diff options
Diffstat (limited to 'activerecord/test/cases/adapters/mysql2')
10 files changed, 221 insertions, 48 deletions
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb index 4ccf568406..e87cd3886a 100644 --- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb @@ -1,23 +1,23 @@ require "cases/helper" +require 'support/connection_helper' class ActiveSchemaTest < ActiveRecord::TestCase - def setup - @connection = ActiveRecord::Base.remove_connection - ActiveRecord::Base.establish_connection(@connection) + include ConnectionHelper + def setup ActiveRecord::Base.connection.singleton_class.class_eval do alias_method :execute_without_stub, :execute def execute(sql, name = nil) return sql end end end - def teardown - ActiveRecord::Base.remove_connection - ActiveRecord::Base.establish_connection(@connection) + teardown do + reset_connection 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`) " @@ -92,7 +92,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase with_real_execute do begin ActiveRecord::Base.connection.create_table :delete_me - ActiveRecord::Base.connection.add_timestamps :delete_me + ActiveRecord::Base.connection.add_timestamps :delete_me, null: true assert column_present?('delete_me', 'updated_at', 'datetime') assert column_present?('delete_me', 'created_at', 'datetime') ensure @@ -105,9 +105,9 @@ class ActiveSchemaTest < ActiveRecord::TestCase with_real_execute do begin ActiveRecord::Base.connection.create_table :delete_me do |t| - t.timestamps + t.timestamps null: true end - ActiveRecord::Base.connection.remove_timestamps :delete_me + ActiveRecord::Base.connection.remove_timestamps :delete_me, { null: true } assert !column_present?('delete_me', 'updated_at', 'datetime') assert !column_present?('delete_me', 'created_at', 'datetime') ensure @@ -116,6 +116,18 @@ class ActiveSchemaTest < ActiveRecord::TestCase end end + def test_indexes_in_create + 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 + end + + assert_equal expected, actual + end + private def with_real_execute ActiveRecord::Base.connection.singleton_class.class_eval do diff --git a/activerecord/test/cases/adapters/mysql2/boolean_test.rb b/activerecord/test/cases/adapters/mysql2/boolean_test.rb index 267aa232d9..0e641ba3bf 100644 --- a/activerecord/test/cases/adapters/mysql2/boolean_test.rb +++ b/activerecord/test/cases/adapters/mysql2/boolean_test.rb @@ -9,6 +9,7 @@ class Mysql2BooleanTest < ActiveRecord::TestCase setup do @connection = ActiveRecord::Base.connection + @connection.clear_cache! @connection.create_table("mysql_booleans") do |t| t.boolean "archived" t.string "published", limit: 1 @@ -46,8 +47,7 @@ class Mysql2BooleanTest < ActiveRecord::TestCase assert_equal 1, attributes["archived"] assert_equal "1", attributes["published"] - assert_equal 1, @connection.type_cast(true, boolean_column) - assert_equal 1, @connection.type_cast(true, string_column) + assert_equal 1, @connection.type_cast(true) end test "test type casting without emulated booleans" do @@ -59,8 +59,7 @@ class Mysql2BooleanTest < ActiveRecord::TestCase assert_equal 1, attributes["archived"] assert_equal "1", attributes["published"] - assert_equal 1, @connection.type_cast(true, boolean_column) - assert_equal 1, @connection.type_cast(true, string_column) + assert_equal 1, @connection.type_cast(true) end test "with booleans stored as 1 and 0" do diff --git a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb index 6bcc113482..09bebf3071 100644 --- a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb +++ b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb @@ -3,10 +3,10 @@ require 'models/person' class Mysql2CaseSensitivityTest < ActiveRecord::TestCase class CollationTest < ActiveRecord::Base - validates_uniqueness_of :string_cs_column, :case_sensitive => false - validates_uniqueness_of :string_ci_column, :case_sensitive => false end + repair_validations(CollationTest) + def test_columns_include_collation_different_from_table assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation @@ -18,6 +18,7 @@ class Mysql2CaseSensitivityTest < ActiveRecord::TestCase end def test_case_insensitive_comparison_for_ci_column + CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => false) CollationTest.create!(:string_ci_column => 'A') invalid = CollationTest.new(:string_ci_column => 'a') queries = assert_sql { invalid.save } @@ -26,10 +27,29 @@ class Mysql2CaseSensitivityTest < ActiveRecord::TestCase end def test_case_insensitive_comparison_for_cs_column + CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => false) CollationTest.create!(:string_cs_column => 'A') invalid = CollationTest.new(:string_cs_column => 'a') queries = assert_sql { invalid.save } cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/)} assert_match(/lower/i, cs_uniqueness_query) end + + def test_case_sensitive_comparison_for_ci_column + CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => true) + CollationTest.create!(:string_ci_column => 'A') + invalid = CollationTest.new(:string_ci_column => 'A') + queries = assert_sql { invalid.save } + ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) } + assert_match(/binary/i, ci_uniqueness_query) + end + + def test_case_sensitive_comparison_for_cs_column + CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => true) + CollationTest.create!(:string_cs_column => 'A') + invalid = CollationTest.new(:string_cs_column => 'A') + queries = assert_sql { invalid.save } + cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) } + assert_no_match(/binary/i, cs_uniqueness_query) + end end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 9b7202c915..d261e2db55 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -1,15 +1,20 @@ require "cases/helper" +require 'support/connection_helper' class MysqlConnectionTest < ActiveRecord::TestCase + include ConnectionHelper + + fixtures :comments + def setup super @subscriber = SQLSubscriber.new - ActiveSupport::Notifications.subscribe('sql.active_record', @subscriber) + @subscription = ActiveSupport::Notifications.subscribe('sql.active_record', @subscriber) @connection = ActiveRecord::Base.connection end def teardown - ActiveSupport::Notifications.unsubscribe(@subscriber) + ActiveSupport::Notifications.unsubscribe(@subscription) super end @@ -21,6 +26,17 @@ class MysqlConnectionTest < ActiveRecord::TestCase 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 @connection.active? @connection.update('set @@wait_timeout=1') @@ -28,9 +44,7 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert !@connection.active? # Repair all fixture connections so other tests won't break. - @fixture_connections.each do |c| - c.verify! - end + @fixture_connections.each(&:verify!) end def test_successful_reconnection_after_timeout_with_manual_reconnect @@ -49,6 +63,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert @connection.active? end + def test_mysql_connection_collation_is_configured + assert_equal 'utf8_unicode_ci', @connection.show_variable('collation_connection') + assert_equal 'utf8_general_ci', ARUnit2Model.connection.show_variable('collation_connection') + end + # TODO: Below is a straight up copy/paste from mysql/connection_test.rb # I'm not sure what the correct way is to share these tests between # adapters in minitest. @@ -57,12 +76,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert_equal [["STRICT_ALL_TABLES"]], result.rows end - def test_mysql_strict_mode_disabled_dont_override_global_sql_mode + def test_mysql_strict_mode_disabled run_without_connection do |orig_connection| ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) - global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode" - session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" - assert_equal global_sql_mode.rows, session_sql_mode.rows + result = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" + assert_equal [['']], result.rows end end @@ -74,6 +92,14 @@ class MysqlConnectionTest < ActiveRecord::TestCase end end + def test_mysql_sql_mode_variable_overrides_strict_mode + run_without_connection do |orig_connection| + ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { 'sql_mode' => 'ansi' })) + result = ActiveRecord::Base.connection.exec_query 'SELECT @@SESSION.sql_mode' + assert_not_equal [['STRICT_ALL_TABLES']], result.rows + end + end + def test_mysql_set_session_variable_to_default run_without_connection do |orig_connection| ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:default_week_format => :default}})) @@ -97,14 +123,10 @@ class MysqlConnectionTest < ActiveRecord::TestCase @connection.execute "DROP TABLE `bar_baz`" end - private - - def run_without_connection - original_connection = ActiveRecord::Base.remove_connection - begin - yield original_connection - ensure - ActiveRecord::Base.establish_connection(original_connection) + if mysql_56? + def test_quote_time_usec + assert_equal "'1970-01-01 00:00:00.000000'", @connection.quote(Time.at(0)) + assert_equal "'1970-01-01 00:00:00.000000'", @connection.quote(Time.at(0).to_datetime) end end end diff --git a/activerecord/test/cases/adapters/mysql2/datetime_test.rb b/activerecord/test/cases/adapters/mysql2/datetime_test.rb new file mode 100644 index 0000000000..ae00f4e131 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/datetime_test.rb @@ -0,0 +1,87 @@ +require 'cases/helper' + +if mysql_56? + class DateTimeTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + class Foo < ActiveRecord::Base; end + + def test_default_datetime_precision + ActiveRecord::Base.connection.create_table(:foos, force: true) + ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime + ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime + assert_nil activerecord_column_option('foos', 'created_at', 'precision') + end + + def test_datetime_data_type_with_precision + ActiveRecord::Base.connection.create_table(:foos, force: true) + ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, precision: 1 + ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, precision: 5 + assert_equal 1, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_timestamps_helper_with_custom_precision + ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| + t.timestamps null: true, precision: 4 + end + assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_passing_precision_to_datetime_does_not_set_limit + ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| + t.timestamps null: true, precision: 4 + end + assert_nil activerecord_column_option('foos', 'created_at', 'limit') + assert_nil activerecord_column_option('foos', 'updated_at', 'limit') + end + + def test_invalid_datetime_precision_raises_error + assert_raises ActiveRecord::ActiveRecordError do + ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| + t.timestamps null: true, precision: 7 + end + end + end + + def test_mysql_agrees_with_activerecord_about_precision + ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| + t.timestamps null: true, precision: 4 + end + assert_equal 4, mysql_datetime_precision('foos', 'created_at') + assert_equal 4, mysql_datetime_precision('foos', 'updated_at') + end + + def test_formatting_datetime_according_to_precision + ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| + t.datetime :created_at, precision: 0 + t.datetime :updated_at, precision: 4 + end + date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999) + Foo.create!(created_at: date, updated_at: date) + assert foo = Foo.find_by(created_at: date) + assert_equal date.to_s, foo.created_at.to_s + assert_equal date.to_s, foo.updated_at.to_s + assert_equal 000000, foo.created_at.usec + assert_equal 999900, foo.updated_at.usec + end + + private + + def mysql_datetime_precision(table_name, column_name) + results = ActiveRecord::Base.connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name = '#{table_name}'") + result = results.find do |result_hash| + result_hash["column_name"] == column_name + end + result && result["datetime_precision"] + end + + def activerecord_column_option(tablename, column_name, option) + result = ActiveRecord::Base.connection.columns(tablename).find do |column| + column.name == column_name + end + result && result.send(option) + end + end +end diff --git a/activerecord/test/cases/adapters/mysql2/explain_test.rb b/activerecord/test/cases/adapters/mysql2/explain_test.rb index 1cd356e868..2b01d941b8 100644 --- a/activerecord/test/cases/adapters/mysql2/explain_test.rb +++ b/activerecord/test/cases/adapters/mysql2/explain_test.rb @@ -1,5 +1,6 @@ require "cases/helper" require 'models/developer' +require 'models/computer' module ActiveRecord module ConnectionAdapters @@ -9,15 +10,15 @@ module ActiveRecord def test_explain_for_one_query explain = Developer.where(:id => 1).explain - assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain + assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain assert_match %r(developers |.* const), explain end def test_explain_with_eager_loading explain = Developer.where(:id => 1).includes(:audit_logs).explain - assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain + assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain assert_match %r(developers |.* const), explain - assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` IN (1)), explain + assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` = 1), explain assert_match %r(audit_logs |.* ALL), explain end end diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb index 1a82308176..7f97b454bb 100644 --- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb @@ -37,7 +37,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase 'distinct_select'=>'distinct_id int, select_id int' end - def teardown + teardown do drop_tables_directly ['group', 'select', 'values', 'distinct', 'distinct_select', 'order'] end @@ -100,7 +100,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase gs = nil assert_nothing_raised { gs = Select.find(2).groups } assert_equal gs.length, 2 - assert(gs.collect{|x| x.id}.sort == [2, 3]) + assert(gs.collect(&:id).sort == [2, 3]) end # has_and_belongs_to_many with reserved-word table name @@ -109,7 +109,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase s = nil assert_nothing_raised { s = Distinct.find(1).selects } assert_equal s.length, 2 - assert(s.collect{|x|x.id}.sort == [1, 2]) + assert(s.collect(&:id).sort == [1, 2]) end # activerecord model introspection with reserved-word table and column names diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb index ec73ec35aa..9c49599d34 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -6,12 +6,12 @@ module ActiveRecord class SchemaMigrationsTest < ActiveRecord::TestCase def test_renaming_index_on_foreign_key connection.add_index "engines", "car_id" - connection.execute "ALTER TABLE engines ADD CONSTRAINT fk_engines_cars FOREIGN KEY (car_id) REFERENCES cars(id)" + connection.add_foreign_key :engines, :cars, name: "fk_engines_cars" connection.rename_index("engines", "index_engines_on_car_id", "idx_renamed") assert_equal ["idx_renamed"], connection.indexes("engines").map(&:name) ensure - connection.execute "ALTER TABLE engines DROP FOREIGN KEY fk_engines_cars" + connection.remove_foreign_key :engines, name: "fk_engines_cars" end def test_initializes_schema_migrations_for_encoding_utf8mb4 diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb index 43c9116b5a..47707b7d4f 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb @@ -51,7 +51,7 @@ module ActiveRecord table = 'key_tests' - indexes = @connection.indexes(table).sort_by {|i| i.name} + indexes = @connection.indexes(table).sort_by(&:name) assert_equal 3,indexes.size index_a = indexes.select{|i| i.name == index_a_name}[0] @@ -66,12 +66,14 @@ module ActiveRecord assert_equal :fulltext, index_c.type end - def test_drop_temporary_table - @connection.transaction do - @connection.create_table(:temp_table, temporary: true) - # if it doesn't properly say DROP TEMPORARY TABLE, the transaction commit - # will complain that no transaction is active - @connection.drop_table(:temp_table, temporary: true) + unless mysql_enforcing_gtid_consistency? + def test_drop_temporary_table + @connection.transaction do + @connection.create_table(:temp_table, temporary: true) + # if it doesn't properly say DROP TEMPORARY TABLE, the transaction commit + # will complain that no transaction is active + @connection.drop_table(:temp_table, temporary: true) + end end end end diff --git a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb new file mode 100644 index 0000000000..8f521e9181 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb @@ -0,0 +1,30 @@ +require "cases/helper" + +class UnsignedTypeTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + class UnsignedType < ActiveRecord::Base + end + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table("unsigned_types", force: true) do |t| + t.column :unsigned_integer, "int unsigned" + end + end + + teardown do + @connection.drop_table "unsigned_types" + end + + test "unsigned int max value is in range" do + assert expected = UnsignedType.create(unsigned_integer: 4294967295) + assert_equal expected, UnsignedType.find_by(unsigned_integer: 4294967295) + end + + test "minus value is out of range" do + assert_raise(RangeError) do + UnsignedType.create(unsigned_integer: -10) + end + end +end |