require 'DatabaseObjects'


class Schema < DatabaseObject
    obj_table_name "ALL_USERS"
    make_key :owner

    collection :tables, :Table
    collection :views, :View
    collection :triggers, :Trigger
    collection :procedures, :Procedure
    collection_where :sequences, :Sequence, [ "SEQUENCE_OWNER" ]
end

class Table < DatabaseObject

    obj_table_name "ALL_TABLES"
    make_key :owner, :table_name

    collection :columns, :Column
    collection_sql :primary_keys, :Column, "SELECT owner, table_name, column_name FROM ALL_CONS_COLUMNS where owner = ? AND table_name = ? AND NOT POSITION IS NULL"
    collection :constraints, :Constraint
    collection :indices, :Index
    collection_where :triggers, :Trigger, ["table_owner", "table_name" ]

    def column_values
        columns.values.sort
    end

    def column_names
        column_values.collect { |column| column.column_name }
    end

    def primary_key_names
        return [] if not pk_constraint
        pk_constraint.columns.values.sort.collect { |col| col.column_name }
    end

    def pk_constraint
        constraints.values.find { |cons| cons.constraint_type == "P" }
    end
end

class View < DatabaseObject
    obj_table_name "ALL_VIEWS"
    make_key :owner, :view_name

    collection_where :columns, :Column, [ "owner", "table_name" ]
    collection_where :triggers, :Trigger, ["table_owner", "table_name" ]

    db_properties :text, :text_length

    def column_values
        columns.values.sort
    end

    def column_names
        column_values.collect { |column| column.column_name }
    end
end


class Trigger < DatabaseObject
    obj_table_name "ALL_TRIGGERS"
    make_key :owner, :trigger_name

    db_properties :when_clause, :triggering_event, :table_name, :trigger_body, :trigger_type
end

class Constraint < DatabaseObject
    obj_table_name "ALL_CONSTRAINTS"
    make_key   :owner, :constraint_name

    db_properties   :table_name, :constraint_type, :r_owner, :r_constraint_name, :delete_rule, :search_condition, :generated

    collection  :columns, :Column, "ALL_CONS_COLUMNS"
    collection_where  :related_constraints, :Constraint,  { "owner" => :r_owner, "constraint_name" => :r_constraint_name }

    def related_constraint
        related_constraints.values[0]
    end

    def generated?
        generated == "GENERATED NAME"
    end
end


class Column < DatabaseObject
    obj_table_name "ALL_TAB_COLUMNS"
    make_key :owner, :table_name, :column_name
    
    db_properties :data_type, :data_precision, :data_scale, :data_type_owner, :data_length, :nullable, :column_id
end

class Index < DatabaseObject
    obj_table_name "ALL_INDEXES"
    make_key :owner, :index_name

    db_properties :table_name, :uniqueness
    collection :constraints, :Constraint
    collection_sql :columns, :Column, "select table_owner, table_name, column_name FROM ALL_IND_COLUMNS WHERE index_owner = ? AND index_name = ?"

    def has_constraints?
        !constraints.empty?
    end
    
    def unique?
        uniqueness == "UNIQUE"
    end
end

class Procedure < DatabaseObject
    obj_table_name "ALL_PROCEDURES"
    make_key :owner, :object_name

    collection_where :lines, :SourceLine, { "owner" => :owner, "name" => :object_name }

    def body
        lines.values.sort.collect { |line| line.text }.join
    end
    once :body
end

class SourceLine < DatabaseObject
    obj_table_name "ALL_SOURCE"
    make_key :owner, :name, :line

    db_properties :text

    def <=>(other)
        self.line.to_i <=> other.line.to_i
    end
end


class Sequence < DatabaseObject
    obj_table_name "ALL_SEQUENCES"
    make_key :sequence_owner, :sequence_name

    db_properties :min_value, :max_value, :increment_by, :last_number
end


