diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2013-03-22 19:41:29 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2013-03-22 19:41:29 -0700 |
commit | 7a872e9d84be2f0205d8ca811698be92195ef0e1 (patch) | |
tree | faceaaedddf84672e014617c57f3698672cacc70 /activerecord/lib/active_record/connection_adapters/abstract | |
parent | db3a6e6a7fc80e85afe239abf5d01aa30685c1c1 (diff) | |
parent | bc8ebefe9825dbff2cffa29ff015a1e7a31f9812 (diff) | |
download | rails-7a872e9d84be2f0205d8ca811698be92195ef0e1.tar.gz rails-7a872e9d84be2f0205d8ca811698be92195ef0e1.tar.bz2 rails-7a872e9d84be2f0205d8ca811698be92195ef0e1.zip |
Merge branch 'schema'
* schema:
add uuid primary key support
separate primary key from column type
push the mysql add_column up to the abstract adapter
allow multiple add columns
pull add_column_options! off the pg connection class
add a pg visitor for dealing with schema modification
push alter table add column sql in to the schema modification visitor
there is no reason to check for an already defined column
push column initialization down to the factory method
@columns list is no longer necessary
keep ivars private, do not manipulate them outside their owner object
factory methods should not alter object state
push SQL generation inside the schema creation object
mostly decouple TableDefinition from the database connection
remove to_sql from TableDefinition
decouple column definition from the database connection
stop depending on sql_type in pg
remove knowledge of SQL from the column definition object
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/abstract')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb | 108 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb | 24 |
2 files changed, 66 insertions, 66 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 902dbd148e..b358d84365 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -15,34 +15,14 @@ module ActiveRecord # are typically created by methods in TableDefinition, and added to the # +columns+ attribute of said TableDefinition object, in order to be used # for generating a number of table creation or table changing SQL statements. - class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc: + class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key) #:nodoc: def string_to_binary(value) value end - def sql_type - base.type_to_sql(type.to_sym, limit, precision, scale) - end - def primary_key? - type.to_sym == :primary_key - end - - def to_sql - column_sql = "#{base.quote_column_name(name)} #{sql_type}" - column_options = {} - column_options[:null] = null unless null.nil? - column_options[:default] = default unless default.nil? - column_options[:column] = self - add_column_options!(column_sql, column_options) unless primary_key? - column_sql + primary_key || type.to_sym == :primary_key end - - private - - def add_column_options!(sql, options) - base.add_column_options!(sql, options) - end end # Represents the schema of an SQL table in an abstract way. This class @@ -68,19 +48,25 @@ module ActiveRecord class TableDefinition # An array of ColumnDefinition objects, representing the column changes # that have been defined. - attr_accessor :columns, :indexes + attr_accessor :indexes + attr_reader :name, :temporary, :options - def initialize(base) - @columns = [] + def initialize(types, name, temporary, options) @columns_hash = {} @indexes = {} - @base = base + @native = types + @temporary = temporary + @options = options + @name = name end + def columns; @columns_hash.values; end + # Appends a primary key definition to the table definition. # Can be called multiple times, but this is probably not a good idea. - def primary_key(name) - column(name, :primary_key) + def primary_key(name, type = :primary_key, options = {}) + options[:primary_key] = true + column(name, type, options) end # Returns a ColumnDefinition for the column with name +name+. @@ -233,20 +219,14 @@ module ActiveRecord raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table." end - column = self[name] || new_column_definition(@base, name, type) - - limit = options.fetch(:limit) do - native[type][:limit] if native[type].is_a?(Hash) - end - - column.limit = limit - column.precision = options[:precision] - column.scale = options[:scale] - column.default = options[:default] - column.null = options[:null] + @columns_hash[name] = new_column_definition(name, type, options) self end + def remove_column(name) + @columns_hash.delete name.to_s + end + [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type| define_method column_type do |*args| options = args.extract_options! @@ -283,23 +263,26 @@ module ActiveRecord end alias :belongs_to :references - # Returns a String whose contents are the column definitions - # concatenated together. This string can then be prepended and appended to - # to generate the final SQL to create the table. - def to_sql - columns.map { |c| c.to_sql } * ', ' - end + def new_column_definition(name, type, options) # :nodoc: + column = create_column_definition name, type + limit = options.fetch(:limit) do + native[type][:limit] if native[type].is_a?(Hash) + end - private - def create_column_definition(base, name, type) - ColumnDefinition.new base, name, type + column.limit = limit + column.precision = options[:precision] + column.scale = options[:scale] + column.default = options[:default] + column.null = options[:null] + column.first = options[:first] + column.after = options[:after] + column.primary_key = type == :primary_key || options[:primary_key] + column end - def new_column_definition(base, name, type) - definition = create_column_definition base, name, type - @columns << definition - @columns_hash[name] = definition - definition + private + def create_column_definition(name, type) + ColumnDefinition.new name, type end def primary_key_column_name @@ -308,7 +291,24 @@ module ActiveRecord end def native - @base.native_database_types + @native + end + end + + class AlterTable # :nodoc: + attr_reader :adds + + def initialize(td) + @td = td + @adds = [] + end + + def name; @td.name; end + + def add_column(name, type, options) + name = name.to_s + type = type.to_sym + @adds << @td.new_column_definition(name, type, options) end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index cd4409295f..a26a0b54ea 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -171,14 +171,14 @@ module ActiveRecord # # See also TableDefinition#column for details on how to create columns. def create_table(table_name, options = {}) - td = create_table_definition + td = create_table_definition table_name, options[:temporary], options[:options] unless options[:id] == false pk = options.fetch(:primary_key) { Base.get_primary_key table_name.to_s.singularize } - td.primary_key pk + td.primary_key pk, options.fetch(:id, :primary_key), options end yield td if block_given? @@ -187,11 +187,7 @@ module ActiveRecord drop_table(table_name, options) end - create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE " - create_sql << "#{quote_table_name(table_name)} (" - create_sql << td.to_sql - create_sql << ") #{options[:options]}" - execute create_sql + execute schema_creation.accept td td.indexes.each_pair { |c,o| add_index table_name, c, o } end @@ -359,9 +355,9 @@ module ActiveRecord # Adds a new column to the named table. # See TableDefinition#column for details of the options you can use. def add_column(table_name, column_name, type, options = {}) - add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" - add_column_options!(add_column_sql, options) - execute(add_column_sql) + at = create_alter_table table_name + at.add_column(column_name, type, options) + execute schema_creation.accept at end # Removes the given columns from the table definition. @@ -829,8 +825,12 @@ module ActiveRecord end private - def create_table_definition - TableDefinition.new(self) + def create_table_definition(name, temporary, options) + TableDefinition.new native_database_types, name, temporary, options + end + + def create_alter_table(name) + AlterTable.new create_table_definition(name, false, {}) end def update_table_definition(table_name, base) |