aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorSteve Rice <steve@steverice.org>2014-03-25 21:13:29 -0700
committerSteve Rice <steve@pagerduty.com>2014-03-25 22:10:43 -0700
commit63c94efccb20c0b398dd90c0d209d6894eb22d92 (patch)
tree2717390d594069f6c82e8c9eb7f98eecebe7c07f /activerecord
parentafa148a4f0ac5e2a446b5fe87881a130e8a24f3d (diff)
downloadrails-63c94efccb20c0b398dd90c0d209d6894eb22d92.tar.gz
rails-63c94efccb20c0b398dd90c0d209d6894eb22d92.tar.bz2
rails-63c94efccb20c0b398dd90c0d209d6894eb22d92.zip
Fixes bugs for using indexes in CREATE TABLE by adding checks for table existence
Also: - updates tests by stubbing table_exists? method - adds entry for creating indexes in CREATE TABLE to changelog
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md15
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb6
-rw-r--r--activerecord/test/cases/adapters/mysql2/active_schema_test.rb6
5 files changed, 25 insertions, 6 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 6e77493de9..ccd07ce248 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,18 @@
+* Create indexes inline in CREATE TABLE for MySQL
+
+ This is important, because adding an index on a temporary table after it has been created
+ would commit the transaction.
+ It also allows creating and dropping indexed tables with fewer queries and fewer permissions required.
+
+ Example:
+
+ create_table :temp, temporary: true, as: "SELECT id, name, zip FROM a_really_complicated_query" do |t|
+ t.index :zip
+ end
+ # => CREATE TEMPORARY TABLE temp (INDEX (zip)) AS SELECT id, name, zip FROM a_really_complicated_query
+
+ *Cody Cutrer*, *Steve Rice*
+
* Save `has_one` association even if the record doesn't changed.
Fixes #14407.
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 59210c345f..23404a5c48 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -795,7 +795,7 @@ module ActiveRecord
if index_name.length > max_index_length
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
end
- if index_name_exists?(table_name, index_name, false)
+ if table_exists?(table_name) && index_name_exists?(table_name, index_name, false)
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
end
index_columns = quoted_columns_for_index(column_names, options).join(", ")
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 96c7d5d7eb..a1748c9261 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -12,7 +12,7 @@ module ActiveRecord
statements = []
statements.concat(o.columns.map { |c| accept c })
statements.concat(o.indexes.map { |(column_name, options)| index_in_create(o.name, column_name, options) })
- create_sql << "(#{statements.join(', ')}) "
+ create_sql << "(#{statements.join(', ')}) " if statements.present?
create_sql << "#{o.options}"
create_sql << " AS #{@conn.to_sql(o.as)}" if o.as
create_sql
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index 072aa65000..35681fb5ae 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -17,7 +17,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase
end
def test_add_index
- # add_index calls index_name_exists? which can't work since execute is stubbed
+ # add_index calls table_exists? and index_name_exists? which can't work since execute is stubbed
+ def (ActiveRecord::Base.connection).table_exists?(*); true; end
def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`) "
@@ -118,7 +119,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase
def test_indexes_in_create
begin
- ActiveRecord::Base.connection.stubs(:index_name_exists?).returns(false)
+ ActiveRecord::Base.connection.stubs(:table_exists?).with(:temp).returns(false)
+ ActiveRecord::Base.connection.stubs(:index_name_exists?).with(:index_temp_on_zip).returns(false)
expected = "CREATE TEMPORARY TABLE `temp` (INDEX `index_temp_on_zip` (`zip`)) ENGINE=InnoDB AS SELECT id, name, zip FROM a_really_complicated_query"
actual = ActiveRecord::Base.connection.create_table(:temp, temporary: true, as: "SELECT id, name, zip FROM a_really_complicated_query") do |t|
t.index :zip
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
index 91d880e5ae..925b9c1bd1 100644
--- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
@@ -17,7 +17,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase
end
def test_add_index
- # add_index calls index_name_exists? which can't work since execute is stubbed
+ # add_index calls table_exists? and index_name_exists? which can't work since execute is stubbed
+ def (ActiveRecord::Base.connection).table_exists?(*); true; end
def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`) "
@@ -118,7 +119,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase
def test_indexes_in_create
begin
- ActiveRecord::Base.connection.stubs(:index_name_exists?).returns(false)
+ ActiveRecord::Base.connection.stubs(:table_exists?).with(:temp).returns(false)
+ ActiveRecord::Base.connection.stubs(:index_name_exists?).with(:index_temp_on_zip).returns(false)
expected = "CREATE TEMPORARY TABLE `temp` (INDEX `index_temp_on_zip` (`zip`)) ENGINE=InnoDB AS SELECT id, name, zip FROM a_really_complicated_query"
actual = ActiveRecord::Base.connection.create_table(:temp, temporary: true, as: "SELECT id, name, zip FROM a_really_complicated_query") do |t|
t.index :zip