diff options
Diffstat (limited to 'activerecord/lib')
5 files changed, 106 insertions, 11 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb new file mode 100644 index 0000000000..4118ea7b31 --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb @@ -0,0 +1,57 @@ +module ActiveRecord + module ConnectionAdapters # :nodoc: + module DatabaseLimits + + # the maximum length of a table alias + def table_alias_length + 255 + end + + # the maximum length of a column name + def column_name_length + 64 + end + + # the maximum length of a table name + def table_name_length + 64 + end + + # the maximum length of an index name + def index_name_length + 64 + end + + # the maximum number of columns per table + def columns_per_table + 1024 + end + + # the maximum number of indexes per table + def indexes_per_table + 16 + end + + # the maximum number of columns in a multicolumn index + def columns_per_multicolumn_index + 16 + end + + # the maximum number of elements in an IN (x,y,z) clause + def in_clause_length + 65535 + end + + # the maximum length of a SQL query + def sql_query_length + 1048575 + end + + # maximum number of joins in a single query + def joins_per_query + 256 + end + + end + 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 1255ef09be..d3499cea72 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -10,11 +10,6 @@ module ActiveRecord {} end - # This is the maximum length a table alias can be - def table_alias_length - 255 - end - # Truncates a table alias according to the limits of the current adapter. def table_alias_for(table_name) table_name[0..table_alias_length-1].gsub(/\./, '_') @@ -293,6 +288,14 @@ module ActiveRecord index_type = options end + if index_name.length > index_name_length + @logger.warn("Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters. Skipping.") + return + end + if index_exists?(table_name, index_name, false) + @logger.warn("Index name '#{index_name}' on table '#{table_name}' already exists. Skipping.") + return + end quoted_column_names = quoted_columns_for_index(column_names, options).join(", ") execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})" @@ -309,7 +312,28 @@ module ActiveRecord # Remove the index named by_branch_party in the accounts table. # remove_index :accounts, :name => :by_branch_party def remove_index(table_name, options = {}) - execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{quote_table_name(table_name)}" + index_name = index_name(table_name, options) + unless index_exists?(table_name, index_name, true) + @logger.warn("Index name '#{index_name}' on table '#{table_name}' does not exist. Skipping.") + return + end + remove_index!(table_name, index_name) + end + + def remove_index!(table_name, index_name) #:nodoc: + execute "DROP INDEX #{quote_column_name(index_name)} ON #{table_name}" + end + + # Rename an index. + # + # Rename the index_people_on_last_name index to index_users_on_last_name + # rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name' + def rename_index(table_name, old_name, new_name) + # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance) + old_index_def = indexes(table_name).detect { |i| i.name == old_name } + return unless old_index_def + remove_index(table_name, :name => old_name) + add_index(table_name, old_index_def.columns, :name => new_name, :unique => old_index_def.unique) end def index_name(table_name, options) #:nodoc: @@ -326,6 +350,15 @@ module ActiveRecord end end + # Verify the existence of an index. + # + # The default argument is returned if the underlying implementation does not define the indexes method, + # as there's no way to determine the correct answer in that case. + def index_exists?(table_name, index_name, default) + return default unless respond_to?(:indexes) + indexes(table_name).detect { |i| i.name == index_name } + end + # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the # entire structure of the database. def structure_dump diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 28a59c1e62..fecd4d590e 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -11,6 +11,7 @@ require 'active_record/connection_adapters/abstract/quoting' require 'active_record/connection_adapters/abstract/connection_pool' require 'active_record/connection_adapters/abstract/connection_specification' require 'active_record/connection_adapters/abstract/query_cache' +require 'active_record/connection_adapters/abstract/database_limits' module ActiveRecord module ConnectionAdapters # :nodoc: @@ -29,6 +30,7 @@ module ActiveRecord # notably, the instance methods provided by SchemaStatement are very useful. class AbstractAdapter include Quoting, DatabaseStatements, SchemaStatements + include DatabaseLimits include QueryCache include ActiveSupport::Callbacks diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 6389094b8a..34aaff2b49 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -819,9 +819,12 @@ module ActiveRecord execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}" end - # Drops an index from a table. - def remove_index(table_name, options = {}) - execute "DROP INDEX #{quote_table_name(index_name(table_name, options))}" + def remove_index!(table_name, index_name) #:nodoc: + execute "DROP INDEX #{quote_table_name(index_name)}" + end + + def index_name_length + 63 end # Maps logical Rails types to PostgreSQL-specific data types. diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 29225b83c5..e8a45bb3c6 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -217,8 +217,8 @@ module ActiveRecord column ? column['name'] : nil end - def remove_index(table_name, options={}) #:nodoc: - execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}" + def remove_index!(table_name, index_name) #:nodoc: + execute "DROP INDEX #{quote_column_name(index_name)}" end def rename_table(name, new_name) |