diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index eec7efadc2..a848838a4e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -294,19 +294,10 @@ module ActiveRecord # In the simple case, MySQL allows us to place JOINs directly into the UPDATE # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support - # these, we must use a subquery. However, MySQL is too stupid to create a - # temporary table for this automatically, so we have to give it some prompting - # in the form of a subsubquery. Ugh! + # these, we must use a subquery. def join_to_update(update, select) #:nodoc: if select.limit || select.offset || select.orders.any? - subsubselect = select.clone - subsubselect.projections = [update.key] - - subselect = Arel::SelectManager.new(select.engine) - subselect.project Arel.sql(update.key.name) - subselect.from subsubselect.as('__active_record_temp') - - update.where update.key.in(subselect) + super else update.table select.source update.wheres = select.constraints @@ -375,7 +366,7 @@ module ActiveRecord def tables(name = nil, database = nil, like = nil) #:nodoc: sql = "SHOW TABLES " - sql << "IN #{database} " if database + sql << "IN #{quote_table_name(database)} " if database sql << "LIKE #{quote(like)}" if like execute_and_free(sql, 'SCHEMA') do |result| @@ -484,15 +475,26 @@ module ActiveRecord # Maps logical Rails types to MySQL-specific data types. def type_to_sql(type, limit = nil, precision = nil, scale = nil) - return super unless type.to_s == 'integer' - - case limit - when 1; 'tinyint' - when 2; 'smallint' - when 3; 'mediumint' - when nil, 4, 11; 'int(11)' # compatibility with MySQL default - when 5..8; 'bigint' - else raise(ActiveRecordError, "No integer type has byte size #{limit}") + case type.to_s + when 'integer' + case limit + when 1; 'tinyint' + when 2; 'smallint' + when 3; 'mediumint' + when nil, 4, 11; 'int(11)' # compatibility with MySQL default + when 5..8; 'bigint' + else raise(ActiveRecordError, "No integer type has byte size #{limit}") + end + when 'text' + case limit + when 0..0xff; 'tinytext' + when nil, 0x100..0xffff; 'text' + when 0x10000..0xffffff; 'mediumtext' + when 0x1000000..0xffffffff; 'longtext' + else raise(ActiveRecordError, "No text type has character length #{limit}") + end + else + super end end @@ -514,8 +516,8 @@ module ActiveRecord def pk_and_sequence_for(table) execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result| create_table = each_hash(result).first[:"Create Table"] - if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/ - keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") } + if create_table.to_s =~ /PRIMARY KEY\s+(?:USING\s+\w+\s+)?\((.+)\)/ + keys = $1.split(",").map { |key| key.delete('`"') } keys.length == 1 ? [keys.first, nil] : nil else nil @@ -547,6 +549,17 @@ module ActiveRecord protected + # MySQL is too stupid to create a temporary table for use subquery, so we have + # to give it some prompting in the form of a subsubquery. Ugh! + def subquery_for(key, select) + subsubselect = select.clone + subsubselect.projections = [key] + + subselect = Arel::SelectManager.new(select.engine) + subselect.project Arel.sql(key.name) + subselect.from subsubselect.as('__active_record_temp') + end + def add_index_length(option_strings, column_names, options = {}) if options.is_a?(Hash) && length = options[:length] case length |