Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 2312

Show
Ignore:
Timestamp:
09/23/05 13:29:33 (5 years ago)
Author:
minam
Message:

Add ActiveRecord::SchemaDumper for dumping a DB schema to a pure-ruby file, making it easier to consolidate large migration lists and port database schemas between databases.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r2285 r2312  
    11*SVN* 
     2 
     3* Add ActiveRecord::SchemaDumper for dumping a DB schema to a pure-ruby file, making it easier to consolidate large migration lists and port database schemas between databases. 
    24 
    35* Fixed migrations for Windows when using more than 10 [David Naseby] 
  • trunk/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb

    r2215 r2312  
    153153  module ConnectionAdapters # :nodoc: 
    154154    class Column # :nodoc: 
    155       attr_reader :name, :default, :type, :limit 
     155      attr_reader :name, :default, :type, :limit, :null 
    156156      # The name should contain the name of the column, such as "name" in "name varchar(250)" 
    157157      # The default should contain the type-casted default of the column, such as 1 in "count int(11) DEFAULT 1" 
    158158      # The type parameter should either contain :integer, :float, :datetime, :date, :text, or :string 
    159159      # The sql_type is just used for extracting the limit, such as 10 in "varchar(10)" 
    160       def initialize(name, default, sql_type = nil
    161         @name, @default, @type = name, type_cast(default), simplified_type(sql_type) 
     160      def initialize(name, default, sql_type = nil, null = true
     161        @name, @default, @type, @null = name, type_cast(default), simplified_type(sql_type), null 
    162162        @limit = extract_limit(sql_type) unless sql_type.nil? 
    163163      end 
     
    276276      def select_one(sql, name = nil) end 
    277277 
     278      # Returns an array of table names for the current database. 
     279      def tables(name = nil) end 
     280 
     281      # Returns an array of indexes for the given table. 
     282      def indexes(table_name, name = nil) end 
     283 
    278284      # Returns an array of column objects for the table specified by +table_name+. 
    279285      def columns(table_name, name = nil) end 
     
    424430      end 
    425431 
    426       def add_index(table_name, column_name, index_type = '') 
    427         execute "CREATE #{index_type} INDEX #{table_name}_#{column_name.to_a.first}_index ON #{table_name} (#{column_name.to_a.join(", ")})" 
    428       end 
    429  
    430       def remove_index(table_name, column_name) 
    431         execute "DROP INDEX #{table_name}_#{column_name}_index ON #{table_name}" 
     432      # Create a new index on the given table. By default, it will be named 
     433      # <code>"#{table_name}_#{column_name.to_a.first}_index"</code>, but you 
     434      # can explicitly name the index by passing <code>:name => "..."</code> 
     435      # as the last parameter. Unique indexes may be created by passing 
     436      # <code>:unique => true</code>. 
     437      def add_index(table_name, column_name, options = {}) 
     438        index_name = "#{table_name}_#{column_name.to_a.first}_index" 
     439 
     440        if Hash === options # legacy support, since this param was a string 
     441          index_type = options[:unique] ? "UNIQUE" : "" 
     442          index_name = options[:name] || index_name 
     443        else 
     444          index_type = options 
     445        end 
     446 
     447        execute "CREATE #{index_type} INDEX #{index_name} ON #{table_name} (#{column_name.to_a.join(", ")})" 
     448      end 
     449 
     450      # Remove the given index from the table. 
     451      # 
     452      #   remove_index :my_table, :column => :foo 
     453      #   remove_index :my_table, :name => :my_index_on_foo 
     454      # 
     455      # The first version will remove the index named 
     456      # <code>"#{my_table}_#{column}_index"</code> from the table. The 
     457      # second removes the named column from the table. 
     458      def remove_index(table_name, options = {}) 
     459        if Hash === options # legacy support 
     460          if options[:column] 
     461            index_name = "#{table_name}_#{options[:column]}_index" 
     462          elsif options[:name] 
     463            index_name = options[:name] 
     464          else 
     465            raise ArgumentError, "You must specify the index name" 
     466          end 
     467        else 
     468          index_name = "#{table_name}_#{options}_index" 
     469        end 
     470 
     471        execute "DROP INDEX #{index_name} ON #{table_name}" 
    432472      end 
    433473       
     
    505545    end 
    506546 
     547    class IndexDefinition < Struct.new(:table, :name, :unique, :columns) 
     548    end 
     549 
    507550    class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :default, :null) 
    508551      def to_sql 
  • trunk/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb

    r1912 r2312  
    103103      end 
    104104 
     105      def tables(name = nil) 
     106        tables = [] 
     107        execute("SHOW TABLES", name).each { |field| tables << field[0] } 
     108        tables 
     109      end 
     110 
     111      def indexes(table_name, name = nil) 
     112        indexes = [] 
     113        current_index = nil 
     114        execute("SHOW KEYS FROM #{table_name}", name).each do |row| 
     115          if current_index != row[2] 
     116            next if row[2] == "PRIMARY" # skip the primary key 
     117            current_index = row[2] 
     118            indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", []) 
     119          end 
     120 
     121          indexes.last.columns << row[4] 
     122        end 
     123        indexes 
     124      end 
     125 
    105126      def columns(table_name, name = nil) 
    106127        sql = "SHOW FIELDS FROM #{table_name}" 
    107128        columns = [] 
    108         execute(sql, name).each { |field| columns << Column.new(field[0], field[4], field[1]) } 
     129        execute(sql, name).each { |field| columns << Column.new(field[0], field[4], field[1], field[2] == "YES") } 
    109130        columns 
    110131      end 
  • trunk/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb

    r1955 r2312  
    151151      def rollback_db_transaction() @connection.rollback    end 
    152152 
    153  
    154       def tables 
    155         execute('.table').map { |table| Table.new(table) } 
     153      def tables(name = nil) 
     154        execute("SELECT name FROM sqlite_master WHERE type = 'table'", name).map do |row| 
     155          row[0] 
     156        end 
    156157      end 
    157158 
    158159      def columns(table_name, name = nil) 
    159160        table_structure(table_name).map { |field| 
    160           SQLiteColumn.new(field['name'], field['dflt_value'], field['type']
     161          SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'] == "0"
    161162        } 
     163      end 
     164 
     165      def indexes(table_name, name = nil) 
     166        execute("PRAGMA index_list(#{table_name})", name).map do |row| 
     167          index = IndexDefinition.new(table_name, row['name']) 
     168          index.unique = row['unique'] != '0' 
     169          index.columns = execute("PRAGMA index_info(#{index.name})").map { |col| col['name'] } 
     170          index 
     171        end 
    162172      end 
    163173 
     
    220230          returning structure = execute("PRAGMA table_info(#{table_name})") do 
    221231            raise ActiveRecord::StatementInvalid if structure.empty? 
    222           end 
    223         end 
    224          
    225         def indexes(table_name) 
    226           execute("PRAGMA index_list(#{table_name})").map do |index| 
    227             index_info = execute("PRAGMA index_info(#{index['name']})") 
    228             { 
    229               :name    => index['name'], 
    230               :unique  => index['unique'].to_i == 1, 
    231               :columns => index_info.map {|info| info['name']} 
    232             } 
    233232          end 
    234233        end 
  • trunk/activerecord/test/migration_test.rb

    r1955 r2312  
    3333    def test_add_index 
    3434      Person.connection.add_column "people", "last_name", :string         
     35      Person.connection.add_column "people", "administrator", :boolean 
    3536       
    3637      assert_nothing_raised { Person.connection.add_index("people", "last_name") } 
     
    3940      assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } 
    4041      assert_nothing_raised { Person.connection.remove_index("people", "last_name") } 
     42 
     43      assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") } 
     44      assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") } 
    4145    end 
    4246