diff options
Diffstat (limited to 'activerecord/test/cases/adapters/mysql2')
4 files changed, 166 insertions, 15 deletions
diff --git a/activerecord/test/cases/adapters/mysql2/annotate_test.rb b/activerecord/test/cases/adapters/mysql2/annotate_test.rb new file mode 100644 index 0000000000..b512540073 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/annotate_test.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/post" + +class Mysql2AnnotateTest < ActiveRecord::Mysql2TestCase + fixtures :posts + + def test_annotate_wraps_content_in_an_inline_comment + assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do + posts = Post.select(:id).annotate("foo") + assert posts.first + end + end + + def test_annotate_is_sanitized + assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do + posts = Post.select(:id).annotate("*/foo/*") + assert posts.first + end + + assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do + posts = Post.select(:id).annotate("**//foo//**") + assert posts.first + end + + assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/ /\* bar \*/}) do + posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar") + assert posts.first + end + + assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* \+ MAX_EXECUTION_TIME\(1\) \*/}) do + posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)") + assert posts.first + end + end +end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 3103589186..9c6566106a 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -28,17 +28,6 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase end end - def test_truncate - rows = ActiveRecord::Base.connection.exec_query("select count(*) from comments") - count = rows.first.values.first - assert_operator count, :>, 0 - - ActiveRecord::Base.connection.truncate("comments") - rows = ActiveRecord::Base.connection.exec_query("select count(*) from comments") - count = rows.first.values.first - assert_equal 0, count - end - def test_no_automatic_reconnection_after_timeout assert_predicate @connection, :active? @connection.update("set @@wait_timeout=1") diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 7bc86476b6..6ade2eec24 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -56,7 +56,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.columns_for_distinct("posts.id", [order]) end - def test_errors_for_bigint_fks_on_integer_pk_table + def test_errors_for_bigint_fks_on_integer_pk_table_in_alter_table # table old_cars has primary key of integer error = assert_raises(ActiveRecord::MismatchedForeignKey) do @@ -64,9 +64,86 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.add_foreign_key :engines, :old_cars end - assert_match "Column `old_car_id` on table `engines` has a type of `bigint(20)`", error.message + assert_includes error.message, <<~MSG.squish + Column `old_car_id` on table `engines` does not match column `id` on `old_cars`, + which has type `int(11)`. To resolve this issue, change the type of the `old_car_id` + column on `engines` to be :integer. (For example `t.integer :old_car_id`). + MSG assert_not_nil error.cause - @conn.exec_query("ALTER TABLE engines DROP COLUMN old_car_id") + ensure + @conn.execute("ALTER TABLE engines DROP COLUMN old_car_id") rescue nil + end + + def test_errors_for_bigint_fks_on_integer_pk_table_in_create_table + # table old_cars has primary key of integer + + error = assert_raises(ActiveRecord::MismatchedForeignKey) do + @conn.execute(<<~SQL) + CREATE TABLE activerecord_unittest.foos ( + id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, + old_car_id bigint, + INDEX index_foos_on_old_car_id (old_car_id), + CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (old_car_id) REFERENCES old_cars (id) + ) + SQL + end + + assert_includes error.message, <<~MSG.squish + Column `old_car_id` on table `foos` does not match column `id` on `old_cars`, + which has type `int(11)`. To resolve this issue, change the type of the `old_car_id` + column on `foos` to be :integer. (For example `t.integer :old_car_id`). + MSG + assert_not_nil error.cause + ensure + @conn.drop_table :foos, if_exists: true + end + + def test_errors_for_integer_fks_on_bigint_pk_table_in_create_table + # table old_cars has primary key of bigint + + error = assert_raises(ActiveRecord::MismatchedForeignKey) do + @conn.execute(<<~SQL) + CREATE TABLE activerecord_unittest.foos ( + id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, + car_id int, + INDEX index_foos_on_car_id (car_id), + CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (car_id) REFERENCES cars (id) + ) + SQL + end + + assert_includes error.message, <<~MSG.squish + Column `car_id` on table `foos` does not match column `id` on `cars`, + which has type `bigint(20)`. To resolve this issue, change the type of the `car_id` + column on `foos` to be :bigint. (For example `t.bigint :car_id`). + MSG + assert_not_nil error.cause + ensure + @conn.drop_table :foos, if_exists: true + end + + def test_errors_for_bigint_fks_on_string_pk_table_in_create_table + # table old_cars has primary key of string + + error = assert_raises(ActiveRecord::MismatchedForeignKey) do + @conn.execute(<<~SQL) + CREATE TABLE activerecord_unittest.foos ( + id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, + subscriber_id bigint, + INDEX index_foos_on_subscriber_id (subscriber_id), + CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (subscriber_id) REFERENCES subscribers (nick) + ) + SQL + end + + assert_includes error.message, <<~MSG.squish + Column `subscriber_id` on table `foos` does not match column `nick` on `subscribers`, + which has type `varchar(255)`. To resolve this issue, change the type of the `subscriber_id` + column on `foos` to be :string. (For example `t.string :subscriber_id`). + MSG + assert_not_nil error.cause + ensure + @conn.drop_table :foos, if_exists: true end def test_errors_when_an_insert_query_is_called_while_preventing_writes @@ -123,7 +200,15 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase def test_doesnt_error_when_a_set_query_is_called_while_preventing_writes @conn.while_preventing_writes do - assert_nil @conn.execute("SET NAMES utf8") + assert_nil @conn.execute("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci") + end + end + + def test_doesnt_error_when_a_read_query_with_leading_chars_is_called_while_preventing_writes + @conn.execute("INSERT INTO `engines` (`car_id`) VALUES ('138853948594')") + + @conn.while_preventing_writes do + assert_equal 1, @conn.execute("(\n( SELECT `engines`.* FROM `engines` WHERE `engines`.`car_id` = '138853948594' ) )").entries.count end end diff --git a/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb new file mode 100644 index 0000000000..b9794c5710 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/post" + +if supports_optimizer_hints? + class Mysql2OptimzerHintsTest < ActiveRecord::Mysql2TestCase + fixtures :posts + + def test_optimizer_hints + assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do + posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)") + posts = posts.select(:id).where(author_id: [0, 1]) + assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |" + end + end + + def test_optimizer_hints_is_sanitized + assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do + posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */") + posts = posts.select(:id).where(author_id: [0, 1]) + assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |" + end + + assert_sql(%r{\ASELECT /\*\+ `posts`\.\*, \*/}) do + posts = Post.optimizer_hints("**// `posts`.*, //**") + posts = posts.select(:id).where(author_id: [0, 1]) + assert_equal({ "id" => 1 }, posts.first.as_json) + end + end + + def test_optimizer_hints_with_unscope + assert_sql(%r{\ASELECT `posts`\.`id`}) do + posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */") + posts = posts.select(:id).where(author_id: [0, 1]) + posts.unscope(:optimizer_hints).load + end + end + end +end |