aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/mysql
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/mysql')
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb57
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb69
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb56
3 files changed, 182 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb
new file mode 100644
index 0000000000..1e2c859af9
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb
@@ -0,0 +1,57 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module MySQL
+ class SchemaCreation < AbstractAdapter::SchemaCreation
+ private
+
+ def visit_DropForeignKey(name)
+ "DROP FOREIGN KEY #{name}"
+ end
+
+ def visit_ColumnDefinition(o)
+ o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.unsigned)
+ super
+ end
+
+ def visit_AddColumnDefinition(o)
+ add_column_position!(super, column_options(o.column))
+ end
+
+ def visit_ChangeColumnDefinition(o)
+ change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
+ add_column_position!(change_column_sql, column_options(o.column))
+ end
+
+ def column_options(o)
+ column_options = super
+ column_options[:charset] = o.charset
+ column_options
+ end
+
+ def add_column_options!(sql, options)
+ if options[:charset]
+ sql << " CHARACTER SET #{options[:charset]}"
+ end
+ if options[:collation]
+ sql << " COLLATE #{options[:collation]}"
+ end
+ super
+ end
+
+ def add_column_position!(sql, options)
+ if options[:first]
+ sql << " FIRST"
+ elsif options[:after]
+ sql << " AFTER #{quote_column_name(options[:after])}"
+ end
+ sql
+ end
+
+ def index_in_create(table_name, column_name, options)
+ index_name, index_type, index_columns, _, _, index_using = @conn.add_index_options(table_name, column_name, options)
+ "#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns}) "
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb
new file mode 100644
index 0000000000..29e8c73d46
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb
@@ -0,0 +1,69 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module MySQL
+ module ColumnMethods
+ def primary_key(name, type = :primary_key, **options)
+ options[:auto_increment] = true if type == :bigint
+ super
+ end
+
+ def blob(*args, **options)
+ args.each { |name| column(name, :blob, options) }
+ end
+
+ def json(*args, **options)
+ args.each { |name| column(name, :json, options) }
+ end
+
+ def unsigned_integer(*args, **options)
+ args.each { |name| column(name, :unsigned_integer, options) }
+ end
+
+ def unsigned_bigint(*args, **options)
+ args.each { |name| column(name, :unsigned_bigint, options) }
+ end
+
+ def unsigned_float(*args, **options)
+ args.each { |name| column(name, :unsigned_float, options) }
+ end
+
+ def unsigned_decimal(*args, **options)
+ args.each { |name| column(name, :unsigned_decimal, options) }
+ end
+ end
+
+ class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
+ attr_accessor :charset, :unsigned
+ end
+
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
+ include ColumnMethods
+
+ def new_column_definition(name, type, options) # :nodoc:
+ column = super
+ case column.type
+ when :primary_key
+ column.type = :integer
+ column.auto_increment = true
+ when /\Aunsigned_(?<type>.+)\z/
+ column.type = $~[:type].to_sym
+ column.unsigned = true
+ end
+ column.unsigned ||= options[:unsigned]
+ column.charset = options[:charset]
+ column
+ end
+
+ private
+
+ def create_column_definition(name, type)
+ MySQL::ColumnDefinition.new(name, type)
+ end
+ end
+
+ class Table < ActiveRecord::ConnectionAdapters::Table
+ include ColumnMethods
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb
new file mode 100644
index 0000000000..3c48d0554e
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb
@@ -0,0 +1,56 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module MySQL
+ module ColumnDumper
+ def column_spec_for_primary_key(column)
+ spec = {}
+ if column.auto_increment?
+ spec[:id] = ':bigint' if column.bigint?
+ spec[:unsigned] = 'true' if column.unsigned?
+ return if spec.empty?
+ else
+ spec[:id] = column.type.inspect
+ spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) })
+ end
+ spec
+ end
+
+ def prepare_column_options(column)
+ spec = super
+ spec[:unsigned] = 'true' if column.unsigned?
+ spec
+ end
+
+ def migration_keys
+ super + [:unsigned]
+ end
+
+ private
+
+ def schema_type(column)
+ if column.sql_type == 'tinyblob'
+ 'blob'
+ else
+ super
+ end
+ end
+
+ def schema_limit(column)
+ super unless column.type == :boolean
+ end
+
+ def schema_precision(column)
+ super unless /time/ === column.sql_type && column.precision == 0
+ end
+
+ def schema_collation(column)
+ if column.collation && table_name = column.instance_variable_get(:@table_name)
+ @table_collation_cache ||= {}
+ @table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
+ column.collation.inspect if column.collation != @table_collation_cache[table_name]
+ end
+ end
+ end
+ end
+ end
+end