diff options
Diffstat (limited to 'activerecord/test/cases/adapters')
80 files changed, 1151 insertions, 1452 deletions
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb deleted file mode 100644 index 57eb5d0e18..0000000000 --- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb +++ /dev/null @@ -1,192 +0,0 @@ -require "cases/helper" -require 'support/connection_helper' - -class ActiveSchemaTest < ActiveRecord::TestCase - 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 - - teardown do - reset_connection - end - - def test_add_index - # 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`) " - assert_equal expected, add_index(:people, :last_name, :length => nil) - - expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`(10)) " - assert_equal expected, add_index(:people, :last_name, :length => 10) - - expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15)) " - assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15) - - expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`) " - assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15}) - - expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) " - assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10}) - - %w(SPATIAL FULLTEXT UNIQUE).each do |type| - expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) " - assert_equal expected, add_index(:people, :last_name, :type => type) - end - - %w(btree hash).each do |using| - expected = "CREATE INDEX `index_people_on_last_name` USING #{using} ON `people` (`last_name`) " - assert_equal expected, add_index(:people, :last_name, :using => using) - end - - expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) " - assert_equal expected, add_index(:people, :last_name, :length => 10, :using => :btree) - - expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) ALGORITHM = COPY" - assert_equal expected, add_index(:people, :last_name, :length => 10, using: :btree, algorithm: :copy) - - assert_raise ArgumentError do - add_index(:people, :last_name, algorithm: :coyp) - end - - expected = "CREATE INDEX `index_people_on_last_name_and_first_name` USING btree ON `people` (`last_name`(15), `first_name`(15)) " - assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15, :using => :btree) - end - - def test_index_in_create - def (ActiveRecord::Base.connection).table_exists?(*); false; end - - %w(SPATIAL FULLTEXT UNIQUE).each do |type| - expected = "CREATE TABLE `people` (#{type} INDEX `index_people_on_last_name` (`last_name`) ) ENGINE=InnoDB" - actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t| - t.index :last_name, type: type - end - assert_equal expected, actual - end - - expected = "CREATE TABLE `people` ( INDEX `index_people_on_last_name` USING btree (`last_name`(10)) ) ENGINE=InnoDB" - actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t| - t.index :last_name, length: 10, using: :btree - end - assert_equal expected, actual - end - - def test_index_in_bulk_change - def (ActiveRecord::Base.connection).table_exists?(*); true; end - def (ActiveRecord::Base.connection).index_name_exists?(*); false; end - - %w(SPATIAL FULLTEXT UNIQUE).each do |type| - expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)" - actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t| - t.index :last_name, type: type - end - assert_equal expected, actual - end - - expected = "ALTER TABLE `peaple` ADD INDEX `index_peaple_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY" - actual = ActiveRecord::Base.connection.change_table(:peaple, bulk: true) do |t| - t.index :last_name, length: 10, using: :btree, algorithm: :copy - end - assert_equal expected, actual - end - - def test_drop_table - assert_equal "DROP TABLE `people`", drop_table(:people) - end - - if current_adapter?(:MysqlAdapter, :Mysql2Adapter) - def test_create_mysql_database_with_encoding - assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt) - assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'}) - assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci}) - end - - def test_recreate_mysql_database_with_encoding - create_database(:luca, {:charset => 'latin1'}) - assert_equal "CREATE DATABASE `luca` DEFAULT CHARACTER SET `latin1`", recreate_database(:luca, {:charset => 'latin1'}) - end - end - - def test_add_column - assert_equal "ALTER TABLE `people` ADD `last_name` varchar(255)", add_column(:people, :last_name, :string) - end - - def test_add_column_with_limit - assert_equal "ALTER TABLE `people` ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32) - end - - def test_drop_table_with_specific_database - assert_equal "DROP TABLE `otherdb`.`people`", drop_table('otherdb.people') - end - - def test_add_timestamps - with_real_execute do - begin - ActiveRecord::Base.connection.create_table :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 - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - end - end - end - - def test_remove_timestamps - with_real_execute do - begin - ActiveRecord::Base.connection.create_table :delete_me do |t| - t.timestamps null: true - end - 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 - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - end - 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 - alias_method :execute_with_stub, :execute - remove_method :execute - alias_method :execute, :execute_without_stub - end - - yield - ensure - ActiveRecord::Base.connection.singleton_class.class_eval do - remove_method :execute - alias_method :execute, :execute_with_stub - end - end - - def method_missing(method_symbol, *arguments) - ActiveRecord::Base.connection.send(method_symbol, *arguments) - end - - def column_present?(table_name, column_name, type) - results = ActiveRecord::Base.connection.select_all("SHOW FIELDS FROM #{table_name} LIKE '#{column_name}'") - results.first && results.first['Type'] == type - end -end diff --git a/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb deleted file mode 100644 index 345122b1ad..0000000000 --- a/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb +++ /dev/null @@ -1,54 +0,0 @@ -require "cases/helper" - -class MysqlCaseSensitivityTest < ActiveRecord::TestCase - class CollationTest < ActiveRecord::Base - 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 - end - - def test_case_sensitive - assert !CollationTest.columns_hash['string_ci_column'].case_sensitive? - assert CollationTest.columns_hash['string_cs_column'].case_sensitive? - 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 } - ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) } - assert_no_match(/lower/i, ci_uniqueness_query) - 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/mysql/charset_collation_test.rb b/activerecord/test/cases/adapters/mysql/charset_collation_test.rb deleted file mode 100644 index c8dd49d00a..0000000000 --- a/activerecord/test/cases/adapters/mysql/charset_collation_test.rb +++ /dev/null @@ -1,54 +0,0 @@ -require "cases/helper" -require 'support/schema_dumping_helper' - -class CharsetCollationTest < ActiveRecord::TestCase - include SchemaDumpingHelper - self.use_transactional_tests = false - - setup do - @connection = ActiveRecord::Base.connection - @connection.create_table :charset_collations, force: true do |t| - t.string :string_ascii_bin, charset: 'ascii', collation: 'ascii_bin' - t.text :text_ucs2_unicode_ci, charset: 'ucs2', collation: 'ucs2_unicode_ci' - end - end - - teardown do - @connection.drop_table :charset_collations, if_exists: true - end - - test "string column with charset and collation" do - column = @connection.columns(:charset_collations).find { |c| c.name == 'string_ascii_bin' } - assert_equal :string, column.type - assert_equal 'ascii_bin', column.collation - end - - test "text column with charset and collation" do - column = @connection.columns(:charset_collations).find { |c| c.name == 'text_ucs2_unicode_ci' } - assert_equal :text, column.type - assert_equal 'ucs2_unicode_ci', column.collation - end - - test "add column with charset and collation" do - @connection.add_column :charset_collations, :title, :string, charset: 'utf8', collation: 'utf8_bin' - - column = @connection.columns(:charset_collations).find { |c| c.name == 'title' } - assert_equal :string, column.type - assert_equal 'utf8_bin', column.collation - end - - test "change column with charset and collation" do - @connection.add_column :charset_collations, :description, :string, charset: 'utf8', collation: 'utf8_unicode_ci' - @connection.change_column :charset_collations, :description, :text, charset: 'utf8', collation: 'utf8_general_ci' - - column = @connection.columns(:charset_collations).find { |c| c.name == 'description' } - assert_equal :text, column.type - assert_equal 'utf8_general_ci', column.collation - end - - test "schema dump includes collation" do - output = dump_table_schema("charset_collations") - assert_match %r{t.string\s+"string_ascii_bin",\s+limit: 255,\s+collation: "ascii_bin"$}, output - assert_match %r{t.text\s+"text_ucs2_unicode_ci",\s+limit: 65535,\s+collation: "ucs2_unicode_ci"$}, output - end -end diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb deleted file mode 100644 index 4762ef43b5..0000000000 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ /dev/null @@ -1,182 +0,0 @@ -require "cases/helper" -require 'support/connection_helper' -require 'support/ddl_helper' - -class MysqlConnectionTest < ActiveRecord::TestCase - include ConnectionHelper - include DdlHelper - - class Klass < ActiveRecord::Base - end - - def setup - super - @connection = ActiveRecord::Base.connection - end - - def test_mysql_reconnect_attribute_after_connection_with_reconnect_true - run_without_connection do |orig_connection| - ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true})) - assert ActiveRecord::Base.connection.raw_connection.reconnect - end - end - - unless ARTest.connection_config['arunit']['socket'] - def test_connect_with_url - run_without_connection do - ar_config = ARTest.connection_config['arunit'] - - url = "mysql://#{ar_config["username"]}@localhost/#{ar_config["database"]}" - Klass.establish_connection(url) - assert_equal ar_config['database'], Klass.connection.current_database - end - end - end - - def test_mysql_reconnect_attribute_after_connection_with_reconnect_false - run_without_connection do |orig_connection| - ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => false})) - assert !ActiveRecord::Base.connection.raw_connection.reconnect - end - end - - def test_no_automatic_reconnection_after_timeout - assert @connection.active? - @connection.update('set @@wait_timeout=1') - sleep 2 - assert !@connection.active? - - # Repair all fixture connections so other tests won't break. - @fixture_connections.each(&:verify!) - end - - def test_successful_reconnection_after_timeout_with_manual_reconnect - assert @connection.active? - @connection.update('set @@wait_timeout=1') - sleep 2 - @connection.reconnect! - assert @connection.active? - end - - def test_successful_reconnection_after_timeout_with_verify - assert @connection.active? - @connection.update('set @@wait_timeout=1') - sleep 2 - @connection.verify! - assert @connection.active? - end - - def test_bind_value_substitute - bind_param = @connection.substitute_at('foo') - assert_equal Arel.sql('?'), bind_param.to_sql - end - - def test_exec_no_binds - with_example_table do - result = @connection.exec_query('SELECT id, data FROM ex') - assert_equal 0, result.rows.length - assert_equal 2, result.columns.length - assert_equal %w{ id data }, result.columns - - @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') - - # if there are no bind parameters, it will return a string (due to - # the libmysql api) - result = @connection.exec_query('SELECT id, data FROM ex') - assert_equal 1, result.rows.length - assert_equal 2, result.columns.length - - assert_equal [['1', 'foo']], result.rows - end - end - - def test_exec_with_binds - with_example_table do - @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') - result = @connection.exec_query( - 'SELECT id, data FROM ex WHERE id = ?', nil, [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::Value.new)]) - - assert_equal 1, result.rows.length - assert_equal 2, result.columns.length - - assert_equal [[1, 'foo']], result.rows - end - end - - def test_exec_typecasts_bind_vals - with_example_table do - @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') - bind = ActiveRecord::Relation::QueryAttribute.new("id", "1-fuu", ActiveRecord::Type::Integer.new) - - result = @connection.exec_query( - 'SELECT id, data FROM ex WHERE id = ?', nil, [bind]) - - assert_equal 1, result.rows.length - assert_equal 2, result.columns.length - - assert_equal [[1, 'foo']], result.rows - end - end - - # Test that MySQL allows multiple results for stored procedures - if defined?(Mysql) && Mysql.const_defined?(:CLIENT_MULTI_RESULTS) - def test_multi_results - rows = ActiveRecord::Base.connection.select_rows('CALL ten();') - assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}" - assert @connection.active?, "Bad connection use by 'MysqlAdapter.select_rows'" - end - 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 - - def test_mysql_default_in_strict_mode - result = @connection.exec_query "SELECT @@SESSION.sql_mode" - assert_equal [["STRICT_ALL_TABLES"]], result.rows - end - - def test_mysql_strict_mode_disabled - run_without_connection do |orig_connection| - ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) - result = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" - assert_equal [['']], result.rows - end - end - - def test_mysql_set_session_variable - run_without_connection do |orig_connection| - ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:default_week_format => 3}})) - session_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.DEFAULT_WEEK_FORMAT" - assert_equal 3, session_mode.rows.first.first.to_i - 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}})) - global_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.DEFAULT_WEEK_FORMAT" - session_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.DEFAULT_WEEK_FORMAT" - assert_equal global_mode.rows, session_mode.rows - end - end - - private - - def with_example_table(&block) - definition ||= <<-SQL - `id` int(11) auto_increment PRIMARY KEY, - `data` varchar(255) - SQL - super(@connection, 'ex', definition, &block) - end -end diff --git a/activerecord/test/cases/adapters/mysql/consistency_test.rb b/activerecord/test/cases/adapters/mysql/consistency_test.rb deleted file mode 100644 index ae190b728d..0000000000 --- a/activerecord/test/cases/adapters/mysql/consistency_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -require "cases/helper" - -class MysqlConsistencyTest < ActiveRecord::TestCase - self.use_transactional_tests = false - - class Consistency < ActiveRecord::Base - self.table_name = "mysql_consistency" - end - - setup do - @old_emulate_booleans = ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans - ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false - - @connection = ActiveRecord::Base.connection - @connection.clear_cache! - @connection.create_table("mysql_consistency") do |t| - t.boolean "a_bool" - t.string "a_string" - end - Consistency.reset_column_information - Consistency.create! - end - - teardown do - ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = @old_emulate_booleans - @connection.drop_table "mysql_consistency" - end - - test "boolean columns with random value type cast to 0 when emulate_booleans is false" do - with_new = Consistency.new - with_last = Consistency.last - with_new.a_bool = 'wibble' - with_last.a_bool = 'wibble' - - assert_equal 0, with_new.a_bool - assert_equal 0, with_last.a_bool - end - - test "string columns call #to_s" do - with_new = Consistency.new - with_last = Consistency.last - thing = Object.new - with_new.a_string = thing - with_last.a_string = thing - - assert_equal thing.to_s, with_new.a_string - assert_equal thing.to_s, with_last.a_string - end -end diff --git a/activerecord/test/cases/adapters/mysql/enum_test.rb b/activerecord/test/cases/adapters/mysql/enum_test.rb deleted file mode 100644 index f4e7a3ef0a..0000000000 --- a/activerecord/test/cases/adapters/mysql/enum_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "cases/helper" - -class MysqlEnumTest < ActiveRecord::TestCase - class EnumTest < ActiveRecord::Base - end - - def test_enum_limit - assert_equal 6, EnumTest.columns.first.limit - end -end diff --git a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb b/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb deleted file mode 100644 index 48ceef365e..0000000000 --- a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb +++ /dev/null @@ -1,152 +0,0 @@ - -require "cases/helper" -require 'support/ddl_helper' - -module ActiveRecord - module ConnectionAdapters - class MysqlAdapterTest < ActiveRecord::TestCase - include DdlHelper - - def setup - @conn = ActiveRecord::Base.connection - end - - def test_bad_connection_mysql - assert_raise ActiveRecord::NoDatabaseError do - configuration = ActiveRecord::Base.configurations['arunit'].merge(database: 'inexistent_activerecord_unittest') - connection = ActiveRecord::Base.mysql_connection(configuration) - connection.drop_table 'ex', if_exists: true - end - end - - def test_valid_column - with_example_table do - column = @conn.columns('ex').find { |col| col.name == 'id' } - assert @conn.valid_type?(column.type) - end - end - - def test_invalid_column - assert_not @conn.valid_type?(:foobar) - end - - def test_client_encoding - assert_equal Encoding::UTF_8, @conn.client_encoding - end - - def test_exec_insert_number - with_example_table do - insert(@conn, 'number' => 10) - - result = @conn.exec_query('SELECT number FROM ex WHERE number = 10') - - assert_equal 1, result.rows.length - # if there are no bind parameters, it will return a string (due to - # the libmysql api) - assert_equal '10', result.rows.last.last - end - end - - def test_exec_insert_string - with_example_table do - str = 'いただきます!' - insert(@conn, 'number' => 10, 'data' => str) - - result = @conn.exec_query('SELECT number, data FROM ex WHERE number = 10') - - value = result.rows.last.last - - # FIXME: this should probably be inside the mysql AR adapter? - value.force_encoding(@conn.client_encoding) - - # The strings in this file are utf-8, so transcode to utf-8 - value.encode!(Encoding::UTF_8) - - assert_equal str, value - end - end - - def test_tables_quoting - @conn.tables(nil, "foo-bar", nil) - flunk - rescue => e - # assertion for *quoted* database properly - assert_match(/database 'foo-bar'/, e.inspect) - end - - def test_pk_and_sequence_for - with_example_table do - pk, seq = @conn.pk_and_sequence_for('ex') - assert_equal 'id', pk - assert_equal @conn.default_sequence_name('ex', 'id'), seq - end - end - - def test_pk_and_sequence_for_with_non_standard_primary_key - with_example_table '`code` INT(11) auto_increment, PRIMARY KEY (`code`)' do - pk, seq = @conn.pk_and_sequence_for('ex') - assert_equal 'code', pk - assert_equal @conn.default_sequence_name('ex', 'code'), seq - end - end - - def test_pk_and_sequence_for_with_custom_index_type_pk - with_example_table '`id` INT(11) auto_increment, PRIMARY KEY USING BTREE (`id`)' do - pk, seq = @conn.pk_and_sequence_for('ex') - assert_equal 'id', pk - assert_equal @conn.default_sequence_name('ex', 'id'), seq - end - end - - def test_composite_primary_key - with_example_table '`id` INT(11), `number` INT(11), foo INT(11), PRIMARY KEY (`id`, `number`)' do - assert_nil @conn.primary_key('ex') - end - end - - def test_tinyint_integer_typecasting - with_example_table '`status` TINYINT(4)' do - insert(@conn, { 'status' => 2 }, 'ex') - - result = @conn.exec_query('SELECT status FROM ex') - - assert_equal 2, result.column_types['status'].deserialize(result.last['status']) - end - end - - def test_supports_extensions - assert_not @conn.supports_extensions?, 'does not support extensions' - end - - def test_respond_to_enable_extension - assert @conn.respond_to?(:enable_extension) - end - - def test_respond_to_disable_extension - assert @conn.respond_to?(:disable_extension) - end - - private - def insert(ctx, data, table='ex') - binds = data.map { |name, value| - Relation::QueryAttribute.new(name, value, Type::Value.new) - } - columns = binds.map(&:name) - - sql = "INSERT INTO #{table} (#{columns.join(", ")}) - VALUES (#{(['?'] * columns.length).join(', ')})" - - ctx.exec_insert(sql, 'SQL', binds) - end - - def with_example_table(definition = nil, &block) - definition ||= <<-SQL - `id` int(11) auto_increment PRIMARY KEY, - `number` integer, - `data` varchar(255) - SQL - super(@conn, 'ex', definition, &block) - end - end - end -end diff --git a/activerecord/test/cases/adapters/mysql/quoting_test.rb b/activerecord/test/cases/adapters/mysql/quoting_test.rb deleted file mode 100644 index a2206153e9..0000000000 --- a/activerecord/test/cases/adapters/mysql/quoting_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "cases/helper" - -module ActiveRecord - module ConnectionAdapters - class MysqlAdapter - class QuotingTest < ActiveRecord::TestCase - def setup - @conn = ActiveRecord::Base.connection - end - - def test_type_cast_true - assert_equal 1, @conn.type_cast(true) - end - - def test_type_cast_false - assert_equal 0, @conn.type_cast(false) - end - end - end - end -end diff --git a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb deleted file mode 100644 index ec1c394f40..0000000000 --- a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb +++ /dev/null @@ -1,153 +0,0 @@ -require "cases/helper" - -class Group < ActiveRecord::Base - Group.table_name = 'group' - belongs_to :select - has_one :values -end - -class Select < ActiveRecord::Base - Select.table_name = 'select' - has_many :groups -end - -class Values < ActiveRecord::Base - Values.table_name = 'values' -end - -class Distinct < ActiveRecord::Base - Distinct.table_name = 'distinct' - has_and_belongs_to_many :selects - has_many :values, :through => :groups -end - -# a suite of tests to ensure the ConnectionAdapters#MysqlAdapter can handle tables with -# reserved word names (ie: group, order, values, etc...) -class MysqlReservedWordTest < ActiveRecord::TestCase - def setup - @connection = ActiveRecord::Base.connection - - # we call execute directly here (and do similar below) because ActiveRecord::Base#create_table() - # will fail with these table names if these test cases fail - - create_tables_directly 'group'=>'id int auto_increment primary key, `order` varchar(255), select_id int', - 'select'=>'id int auto_increment primary key', - 'values'=>'id int auto_increment primary key, group_id int', - 'distinct'=>'id int auto_increment primary key', - 'distinct_select'=>'distinct_id int, select_id int' - end - - teardown do - drop_tables_directly ['group', 'select', 'values', 'distinct', 'distinct_select', 'order'] - end - - # create tables with reserved-word names and columns - def test_create_tables - assert_nothing_raised { - @connection.create_table :order do |t| - t.column :group, :string - end - } - end - - # rename tables with reserved-word names - def test_rename_tables - assert_nothing_raised { @connection.rename_table(:group, :order) } - end - - # alter column with a reserved-word name in a table with a reserved-word name - def test_change_columns - assert_nothing_raised { @connection.change_column_default(:group, :order, 'whatever') } - #the quoting here will reveal any double quoting issues in change_column's interaction with the column method in the adapter - assert_nothing_raised { @connection.change_column('group', 'order', :Int, :default => 0) } - assert_nothing_raised { @connection.rename_column(:group, :order, :values) } - end - - # introspect table with reserved word name - def test_introspect - assert_nothing_raised { @connection.columns(:group) } - assert_nothing_raised { @connection.indexes(:group) } - end - - #fixtures - self.use_instantiated_fixtures = true - self.use_transactional_tests = false - - #activerecord model class with reserved-word table name - def test_activerecord_model - create_test_fixtures :select, :distinct, :group, :values, :distinct_select - x = nil - assert_nothing_raised { x = Group.new } - x.order = 'x' - assert_nothing_raised { x.save } - x.order = 'y' - assert_nothing_raised { x.save } - assert_nothing_raised { Group.find_by_order('y') } - assert_nothing_raised { Group.find(1) } - Group.find(1) - end - - # has_one association with reserved-word table name - def test_has_one_associations - create_test_fixtures :select, :distinct, :group, :values, :distinct_select - v = nil - assert_nothing_raised { v = Group.find(1).values } - assert_equal 2, v.id - end - - # belongs_to association with reserved-word table name - def test_belongs_to_associations - create_test_fixtures :select, :distinct, :group, :values, :distinct_select - gs = nil - assert_nothing_raised { gs = Select.find(2).groups } - assert_equal gs.length, 2 - assert(gs.collect(&:id).sort == [2, 3]) - end - - # has_and_belongs_to_many with reserved-word table name - def test_has_and_belongs_to_many - create_test_fixtures :select, :distinct, :group, :values, :distinct_select - s = nil - assert_nothing_raised { s = Distinct.find(1).selects } - assert_equal s.length, 2 - assert(s.collect(&:id).sort == [1, 2]) - end - - # activerecord model introspection with reserved-word table and column names - def test_activerecord_introspection - assert_nothing_raised { Group.table_exists? } - assert_nothing_raised { Group.columns } - end - - # Calculations - def test_calculations_work_with_reserved_words - assert_nothing_raised { Group.count } - end - - def test_associations_work_with_reserved_words - assert_nothing_raised { Select.all.merge!(:includes => [:groups]).to_a } - end - - #the following functions were added to DRY test cases - - private - # custom fixture loader, uses FixtureSet#create_fixtures and appends base_path to the current file's path - def create_test_fixtures(*fixture_names) - ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names) - end - - # custom drop table, uses execute on connection to drop a table if it exists. note: escapes table_name - def drop_tables_directly(table_names, connection = @connection) - table_names.each do |name| - connection.drop_table name, if_exists: true - end - end - - # custom create table, uses execute on connection to create a table, note: escapes table_name, does NOT escape columns - def create_tables_directly (tables, connection = @connection) - tables.each do |table_name, column_properties| - connection.execute("CREATE TABLE `#{table_name}` ( #{column_properties} )") - end - end - -end diff --git a/activerecord/test/cases/adapters/mysql/schema_test.rb b/activerecord/test/cases/adapters/mysql/schema_test.rb deleted file mode 100644 index b7f9c2ce84..0000000000 --- a/activerecord/test/cases/adapters/mysql/schema_test.rb +++ /dev/null @@ -1,100 +0,0 @@ -require "cases/helper" -require 'models/post' -require 'models/comment' - -module ActiveRecord - module ConnectionAdapters - class MysqlSchemaTest < ActiveRecord::TestCase - fixtures :posts - - def setup - @connection = ActiveRecord::Base.connection - db = Post.connection_pool.spec.config[:database] - table = Post.table_name - @db_name = db - - @omgpost = Class.new(ActiveRecord::Base) do - self.table_name = "#{db}.#{table}" - def self.name; 'Post'; end - end - - @connection.create_table "mysql_doubles" - end - - teardown do - @connection.drop_table "mysql_doubles", if_exists: true - end - - class MysqlDouble < ActiveRecord::Base - self.table_name = "mysql_doubles" - end - - def test_float_limits - @connection.add_column :mysql_doubles, :float_no_limit, :float - @connection.add_column :mysql_doubles, :float_short, :float, limit: 5 - @connection.add_column :mysql_doubles, :float_long, :float, limit: 53 - - @connection.add_column :mysql_doubles, :float_23, :float, limit: 23 - @connection.add_column :mysql_doubles, :float_24, :float, limit: 24 - @connection.add_column :mysql_doubles, :float_25, :float, limit: 25 - MysqlDouble.reset_column_information - - column_no_limit = MysqlDouble.columns.find { |c| c.name == 'float_no_limit' } - column_short = MysqlDouble.columns.find { |c| c.name == 'float_short' } - column_long = MysqlDouble.columns.find { |c| c.name == 'float_long' } - - column_23 = MysqlDouble.columns.find { |c| c.name == 'float_23' } - column_24 = MysqlDouble.columns.find { |c| c.name == 'float_24' } - column_25 = MysqlDouble.columns.find { |c| c.name == 'float_25' } - - # Mysql floats are precision 0..24, Mysql doubles are precision 25..53 - assert_equal 24, column_no_limit.limit - assert_equal 24, column_short.limit - assert_equal 53, column_long.limit - - assert_equal 24, column_23.limit - assert_equal 24, column_24.limit - assert_equal 53, column_25.limit - end - - def test_schema - assert @omgpost.first - end - - def test_primary_key - assert_equal 'id', @omgpost.primary_key - end - - def test_table_exists? - name = @omgpost.table_name - assert @connection.table_exists?(name), "#{name} table should exist" - end - - def test_table_exists_wrong_schema - assert(!@connection.table_exists?("#{@db_name}.zomg"), "table should not exist") - end - - def test_dump_indexes - index_a_name = 'index_key_tests_on_snack' - index_b_name = 'index_key_tests_on_pizza' - index_c_name = 'index_key_tests_on_awesome' - - table = 'key_tests' - - indexes = @connection.indexes(table).sort_by(&:name) - assert_equal 3,indexes.size - - index_a = indexes.select{|i| i.name == index_a_name}[0] - index_b = indexes.select{|i| i.name == index_b_name}[0] - index_c = indexes.select{|i| i.name == index_c_name}[0] - assert_equal :btree, index_a.using - assert_nil index_a.type - assert_equal :btree, index_b.using - assert_nil index_b.type - - assert_nil index_c.using - assert_equal :fulltext, index_c.type - end - end - end -end diff --git a/activerecord/test/cases/adapters/mysql/sp_test.rb b/activerecord/test/cases/adapters/mysql/sp_test.rb deleted file mode 100644 index 3ca2917ca4..0000000000 --- a/activerecord/test/cases/adapters/mysql/sp_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "cases/helper" -require 'models/topic' - -class StoredProcedureTest < ActiveRecord::TestCase - fixtures :topics - - # Test that MySQL allows multiple results for stored procedures - if Mysql.const_defined?(:CLIENT_MULTI_RESULTS) - def test_multi_results_from_find_by_sql - topics = Topic.find_by_sql 'CALL topics();' - assert_equal 1, topics.size - assert ActiveRecord::Base.connection.active?, "Bad connection use by 'MysqlAdapter.select'" - end - end -end diff --git a/activerecord/test/cases/adapters/mysql/sql_types_test.rb b/activerecord/test/cases/adapters/mysql/sql_types_test.rb deleted file mode 100644 index 1ddb1b91c9..0000000000 --- a/activerecord/test/cases/adapters/mysql/sql_types_test.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "cases/helper" - -class SqlTypesTest < ActiveRecord::TestCase - def test_binary_types - assert_equal 'varbinary(64)', type_to_sql(:binary, 64) - assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095) - assert_equal 'blob(4096)', type_to_sql(:binary, 4096) - assert_equal 'blob', type_to_sql(:binary) - end - - def type_to_sql(*args) - ActiveRecord::Base.connection.type_to_sql(*args) - end -end diff --git a/activerecord/test/cases/adapters/mysql/statement_pool_test.rb b/activerecord/test/cases/adapters/mysql/statement_pool_test.rb deleted file mode 100644 index 209a0cf464..0000000000 --- a/activerecord/test/cases/adapters/mysql/statement_pool_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'cases/helper' - -module ActiveRecord::ConnectionAdapters - class MysqlAdapter - class StatementPoolTest < ActiveRecord::TestCase - if Process.respond_to?(:fork) - def test_cache_is_per_pid - cache = StatementPool.new nil, 10 - cache['foo'] = 'bar' - assert_equal 'bar', cache['foo'] - - pid = fork { - lookup = cache['foo']; - exit!(!lookup) - } - - Process.waitpid pid - assert $?.success?, 'process should exit successfully' - end - end - end - end -end diff --git a/activerecord/test/cases/adapters/mysql/table_options_test.rb b/activerecord/test/cases/adapters/mysql/table_options_test.rb deleted file mode 100644 index 0e5b0e8aec..0000000000 --- a/activerecord/test/cases/adapters/mysql/table_options_test.rb +++ /dev/null @@ -1,42 +0,0 @@ -require "cases/helper" -require 'support/schema_dumping_helper' - -class MysqlTableOptionsTest < ActiveRecord::TestCase - include SchemaDumpingHelper - - def setup - @connection = ActiveRecord::Base.connection - end - - def teardown - @connection.drop_table "mysql_table_options", if_exists: true - end - - test "table options with ENGINE" do - @connection.create_table "mysql_table_options", force: true, options: "ENGINE=MyISAM" - output = dump_table_schema("mysql_table_options") - options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options] - assert_match %r{ENGINE=MyISAM}, options - end - - test "table options with ROW_FORMAT" do - @connection.create_table "mysql_table_options", force: true, options: "ROW_FORMAT=REDUNDANT" - output = dump_table_schema("mysql_table_options") - options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options] - assert_match %r{ROW_FORMAT=REDUNDANT}, options - end - - test "table options with CHARSET" do - @connection.create_table "mysql_table_options", force: true, options: "CHARSET=utf8mb4" - output = dump_table_schema("mysql_table_options") - options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options] - assert_match %r{CHARSET=utf8mb4}, options - end - - test "table options with COLLATE" do - @connection.create_table "mysql_table_options", force: true, options: "COLLATE=utf8mb4_bin" - output = dump_table_schema("mysql_table_options") - options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options] - assert_match %r{COLLATE=utf8mb4_bin}, options - end -end diff --git a/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb deleted file mode 100644 index e9edc53f93..0000000000 --- a/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "cases/helper" - -class UnsignedTypeTest < ActiveRecord::TestCase - self.use_transactional_tests = 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 diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb index 0ea556d4fa..99f97c7914 100644 --- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/connection_helper' -class ActiveSchemaTest < ActiveRecord::TestCase +class Mysql2ActiveSchemaTest < ActiveRecord::Mysql2TestCase include ConnectionHelper def setup @@ -16,8 +16,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_add_index - # 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 + # add_index calls data_source_exists? and index_name_exists? which can't work since execute is stubbed + def (ActiveRecord::Base.connection).data_source_exists?(*); true; end def (ActiveRecord::Base.connection).index_name_exists?(*); false; end expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`) " @@ -60,7 +60,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_index_in_create - def (ActiveRecord::Base.connection).table_exists?(*); false; end + def (ActiveRecord::Base.connection).data_source_exists?(*); false; end %w(SPATIAL FULLTEXT UNIQUE).each do |type| expected = "CREATE TABLE `people` (#{type} INDEX `index_people_on_last_name` (`last_name`) ) ENGINE=InnoDB" @@ -78,7 +78,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_index_in_bulk_change - def (ActiveRecord::Base.connection).table_exists?(*); true; end + def (ActiveRecord::Base.connection).data_source_exists?(*); true; end def (ActiveRecord::Base.connection).index_name_exists?(*); false; end %w(SPATIAL FULLTEXT UNIQUE).each do |type| @@ -100,17 +100,15 @@ class ActiveSchemaTest < ActiveRecord::TestCase assert_equal "DROP TABLE `people`", drop_table(:people) end - if current_adapter?(:Mysql2Adapter) - def test_create_mysql_database_with_encoding - assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt) - assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'}) - assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci}) - end + def test_create_mysql_database_with_encoding + assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt) + assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'}) + assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci}) + end - def test_recreate_mysql_database_with_encoding - create_database(:luca, {:charset => 'latin1'}) - assert_equal "CREATE DATABASE `luca` DEFAULT CHARACTER SET `latin1`", recreate_database(:luca, {:charset => 'latin1'}) - end + def test_recreate_mysql_database_with_encoding + create_database(:luca, {:charset => 'latin1'}) + assert_equal "CREATE DATABASE `luca` DEFAULT CHARACTER SET `latin1`", recreate_database(:luca, {:charset => 'latin1'}) end def test_add_column @@ -154,7 +152,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_indexes_in_create - ActiveRecord::Base.connection.stubs(:table_exists?).with(:temp).returns(false) + ActiveRecord::Base.connection.stubs(:data_source_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" diff --git a/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb index 5e8065d80d..abdf3dbf5b 100644 --- a/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb @@ -4,7 +4,7 @@ require 'models/topic' module ActiveRecord module ConnectionAdapters class Mysql2Adapter - class BindParameterTest < ActiveRecord::TestCase + class BindParameterTest < ActiveRecord::Mysql2TestCase fixtures :topics def test_update_question_marks diff --git a/activerecord/test/cases/adapters/mysql2/boolean_test.rb b/activerecord/test/cases/adapters/mysql2/boolean_test.rb index 0d81dd6eee..8575df9e43 100644 --- a/activerecord/test/cases/adapters/mysql2/boolean_test.rb +++ b/activerecord/test/cases/adapters/mysql2/boolean_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class Mysql2BooleanTest < ActiveRecord::TestCase +class Mysql2BooleanTest < ActiveRecord::Mysql2TestCase self.use_transactional_tests = false class BooleanType < ActiveRecord::Base diff --git a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb index ccf3d84a44..963116f08a 100644 --- a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb +++ b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class Mysql2CaseSensitivityTest < ActiveRecord::TestCase +class Mysql2CaseSensitivityTest < ActiveRecord::Mysql2TestCase class CollationTest < ActiveRecord::Base end diff --git a/activerecord/test/cases/adapters/mysql2/charset_collation_test.rb b/activerecord/test/cases/adapters/mysql2/charset_collation_test.rb index c8dd49d00a..668c07dacb 100644 --- a/activerecord/test/cases/adapters/mysql2/charset_collation_test.rb +++ b/activerecord/test/cases/adapters/mysql2/charset_collation_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class CharsetCollationTest < ActiveRecord::TestCase +class Mysql2CharsetCollationTest < ActiveRecord::Mysql2TestCase include SchemaDumpingHelper self.use_transactional_tests = false @@ -48,7 +48,7 @@ class CharsetCollationTest < ActiveRecord::TestCase test "schema dump includes collation" do output = dump_table_schema("charset_collations") - assert_match %r{t.string\s+"string_ascii_bin",\s+limit: 255,\s+collation: "ascii_bin"$}, output + assert_match %r{t.string\s+"string_ascii_bin",\s+collation: "ascii_bin"$}, output assert_match %r{t.text\s+"text_ucs2_unicode_ci",\s+limit: 65535,\s+collation: "ucs2_unicode_ci"$}, output end end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index a8b39b21d4..575138eb2a 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/connection_helper' -class MysqlConnectionTest < ActiveRecord::TestCase +class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase include ConnectionHelper fixtures :comments @@ -68,9 +68,6 @@ class MysqlConnectionTest < ActiveRecord::TestCase 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. def test_mysql_default_in_strict_mode result = @connection.exec_query "SELECT @@SESSION.sql_mode" assert_equal [["STRICT_ALL_TABLES"]], result.rows @@ -84,6 +81,29 @@ class MysqlConnectionTest < ActiveRecord::TestCase end end + def test_passing_arbitary_flags_to_adapter + run_without_connection do |orig_connection| + ActiveRecord::Base.establish_connection(orig_connection.merge({flags: Mysql2::Client::COMPRESS})) + assert_equal (Mysql2::Client::COMPRESS | Mysql2::Client::FOUND_ROWS), ActiveRecord::Base.connection.raw_connection.query_options[:flags] + end + end + + def test_passing_flags_by_array_to_adapter + run_without_connection do |orig_connection| + ActiveRecord::Base.establish_connection(orig_connection.merge({flags: ['COMPRESS'] })) + assert_equal ["COMPRESS", "FOUND_ROWS"], ActiveRecord::Base.connection.raw_connection.query_options[:flags] + end + end + + def test_mysql_strict_mode_specified_default + run_without_connection do |orig_connection| + ActiveRecord::Base.establish_connection(orig_connection.merge({strict: :default})) + 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 + end + end + def test_mysql_set_session_variable run_without_connection do |orig_connection| ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:default_week_format => 3}})) @@ -122,4 +142,32 @@ class MysqlConnectionTest < ActiveRecord::TestCase ensure @connection.execute "DROP TABLE `bar_baz`" end + + def test_get_and_release_advisory_lock + lock_name = "test_lock_name" + + got_lock = @connection.get_advisory_lock(lock_name) + assert got_lock, "get_advisory_lock should have returned true but it didn't" + + assert_equal test_lock_free(lock_name), false, + "expected the test advisory lock to be held but it wasn't" + + released_lock = @connection.release_advisory_lock(lock_name) + assert released_lock, "expected release_advisory_lock to return true but it didn't" + + assert test_lock_free(lock_name), 'expected the test lock to be available after releasing' + end + + def test_release_non_existent_advisory_lock + lock_name = "fake_lock_name" + released_non_existent_lock = @connection.release_advisory_lock(lock_name) + assert_equal released_non_existent_lock, false, + 'expected release_advisory_lock to return false when there was no lock to release' + end + + protected + + def test_lock_free(lock_name) + @connection.select_value("SELECT IS_FREE_LOCK('#{lock_name}');") == 1 + end end diff --git a/activerecord/test/cases/adapters/mysql2/enum_test.rb b/activerecord/test/cases/adapters/mysql2/enum_test.rb index 6dd9a5ec87..bb89e893e0 100644 --- a/activerecord/test/cases/adapters/mysql2/enum_test.rb +++ b/activerecord/test/cases/adapters/mysql2/enum_test.rb @@ -1,10 +1,21 @@ require "cases/helper" -class Mysql2EnumTest < ActiveRecord::TestCase +class Mysql2EnumTest < ActiveRecord::Mysql2TestCase class EnumTest < ActiveRecord::Base end def test_enum_limit - assert_equal 6, EnumTest.columns.first.limit + column = EnumTest.columns_hash['enum_column'] + assert_equal 8, column.limit + end + + def test_should_not_be_blob_or_text_column + column = EnumTest.columns_hash['enum_column'] + assert_not column.blob_or_text_column? + end + + def test_should_not_be_unsigned + column = EnumTest.columns_hash['enum_column'] + assert_not column.unsigned? end end diff --git a/activerecord/test/cases/adapters/mysql2/explain_test.rb b/activerecord/test/cases/adapters/mysql2/explain_test.rb index 2b01d941b8..4fc7414b18 100644 --- a/activerecord/test/cases/adapters/mysql2/explain_test.rb +++ b/activerecord/test/cases/adapters/mysql2/explain_test.rb @@ -5,7 +5,7 @@ require 'models/computer' module ActiveRecord module ConnectionAdapters class Mysql2Adapter - class ExplainTest < ActiveRecord::TestCase + class ExplainTest < ActiveRecord::Mysql2TestCase fixtures :developers def test_explain_for_one_query diff --git a/activerecord/test/cases/adapters/mysql2/json_test.rb b/activerecord/test/cases/adapters/mysql2/json_test.rb new file mode 100644 index 0000000000..c8c933af5e --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/json_test.rb @@ -0,0 +1,172 @@ +require 'cases/helper' +require 'support/schema_dumping_helper' + +if ActiveRecord::Base.connection.supports_json? +class Mysql2JSONTest < ActiveRecord::Mysql2TestCase + include SchemaDumpingHelper + self.use_transactional_tests = false + + class JsonDataType < ActiveRecord::Base + self.table_name = 'json_data_type' + + store_accessor :settings, :resolution + end + + def setup + @connection = ActiveRecord::Base.connection + begin + @connection.create_table('json_data_type') do |t| + t.json 'payload' + t.json 'settings' + end + end + end + + def teardown + @connection.drop_table :json_data_type, if_exists: true + JsonDataType.reset_column_information + end + + def test_column + column = JsonDataType.columns_hash["payload"] + assert_equal :json, column.type + assert_equal 'json', column.sql_type + + type = JsonDataType.type_for_attribute("payload") + assert_not type.binary? + end + + def test_change_table_supports_json + @connection.change_table('json_data_type') do |t| + t.json 'users' + end + JsonDataType.reset_column_information + column = JsonDataType.columns_hash['users'] + assert_equal :json, column.type + end + + def test_schema_dumping + output = dump_table_schema("json_data_type") + assert_match(/t\.json\s+"settings"/, output) + end + + def test_cast_value_on_write + x = JsonDataType.new payload: {"string" => "foo", :symbol => :bar} + assert_equal({"string" => "foo", :symbol => :bar}, x.payload_before_type_cast) + assert_equal({"string" => "foo", "symbol" => "bar"}, x.payload) + x.save + assert_equal({"string" => "foo", "symbol" => "bar"}, x.reload.payload) + end + + def test_type_cast_json + type = JsonDataType.type_for_attribute("payload") + + data = "{\"a_key\":\"a_value\"}" + hash = type.deserialize(data) + assert_equal({'a_key' => 'a_value'}, hash) + assert_equal({'a_key' => 'a_value'}, type.deserialize(data)) + + assert_equal({}, type.deserialize("{}")) + assert_equal({'key'=>nil}, type.deserialize('{"key": null}')) + assert_equal({'c'=>'}','"a"'=>'b "a b'}, type.deserialize(%q({"c":"}", "\"a\"":"b \"a b"}))) + end + + def test_rewrite + @connection.execute "insert into json_data_type (payload) VALUES ('{\"k\":\"v\"}')" + x = JsonDataType.first + x.payload = { '"a\'' => 'b' } + assert x.save! + end + + def test_select + @connection.execute "insert into json_data_type (payload) VALUES ('{\"k\":\"v\"}')" + x = JsonDataType.first + assert_equal({'k' => 'v'}, x.payload) + end + + def test_select_multikey + @connection.execute %q|insert into json_data_type (payload) VALUES ('{"k1":"v1", "k2":"v2", "k3":[1,2,3]}')| + x = JsonDataType.first + assert_equal({'k1' => 'v1', 'k2' => 'v2', 'k3' => [1,2,3]}, x.payload) + end + + def test_null_json + @connection.execute %q|insert into json_data_type (payload) VALUES(null)| + x = JsonDataType.first + assert_equal(nil, x.payload) + end + + def test_select_array_json_value + @connection.execute %q|insert into json_data_type (payload) VALUES ('["v0",{"k1":"v1"}]')| + x = JsonDataType.first + assert_equal(['v0', {'k1' => 'v1'}], x.payload) + end + + def test_rewrite_array_json_value + @connection.execute %q|insert into json_data_type (payload) VALUES ('["v0",{"k1":"v1"}]')| + x = JsonDataType.first + x.payload = ['v1', {'k2' => 'v2'}, 'v3'] + assert x.save! + end + + def test_with_store_accessors + x = JsonDataType.new(resolution: "320×480") + assert_equal "320×480", x.resolution + + x.save! + x = JsonDataType.first + assert_equal "320×480", x.resolution + + x.resolution = "640×1136" + x.save! + + x = JsonDataType.first + assert_equal "640×1136", x.resolution + end + + def test_duplication_with_store_accessors + x = JsonDataType.new(resolution: "320×480") + assert_equal "320×480", x.resolution + + y = x.dup + assert_equal "320×480", y.resolution + end + + def test_yaml_round_trip_with_store_accessors + x = JsonDataType.new(resolution: "320×480") + assert_equal "320×480", x.resolution + + y = YAML.load(YAML.dump(x)) + assert_equal "320×480", y.resolution + end + + def test_changes_in_place + json = JsonDataType.new + assert_not json.changed? + + json.payload = { 'one' => 'two' } + assert json.changed? + assert json.payload_changed? + + json.save! + assert_not json.changed? + + json.payload['three'] = 'four' + assert json.payload_changed? + + json.save! + json.reload + + assert_equal({ 'one' => 'two', 'three' => 'four' }, json.payload) + assert_not json.changed? + end + + def test_assigning_invalid_json + json = JsonDataType.new + + json.payload = 'foo' + + assert_nil json.payload + end +end +end diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb new file mode 100644 index 0000000000..4efd728754 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -0,0 +1,44 @@ +require "cases/helper" + +class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase + def setup + @conn = ActiveRecord::Base.connection + end + + def test_columns_for_distinct_zero_orders + assert_equal "posts.id", + @conn.columns_for_distinct("posts.id", []) + end + + def test_columns_for_distinct_one_order + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc"]) + end + + def test_columns_for_distinct_few_orders + assert_equal "posts.id, posts.created_at AS alias_0, posts.position AS alias_1", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "posts.position asc"]) + end + + def test_columns_for_distinct_with_case + assert_equal( + 'posts.id, CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END AS alias_0', + @conn.columns_for_distinct('posts.id', + ["CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END"]) + ) + end + + def test_columns_for_distinct_blank_not_nil_orders + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "", " "]) + end + + def test_columns_for_distinct_with_arel_order + order = Object.new + def order.to_sql + "posts.created_at desc" + end + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", [order]) + end +end diff --git a/activerecord/test/cases/adapters/mysql2/quoting_test.rb b/activerecord/test/cases/adapters/mysql2/quoting_test.rb new file mode 100644 index 0000000000..2de7e1b526 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/quoting_test.rb @@ -0,0 +1,21 @@ +require "cases/helper" + +class Mysql2QuotingTest < ActiveRecord::Mysql2TestCase + setup do + @connection = ActiveRecord::Base.connection + end + + test 'quoted date precision for gte 5.6.4' do + @connection.stubs(:full_version).returns('5.6.4') + @connection.remove_instance_variable(:@version) if @connection.instance_variable_defined?(:@version) + t = Time.now.change(usec: 1) + assert_match(/\.000001\z/, @connection.quoted_date(t)) + end + + test 'quoted date precision for lt 5.6.4' do + @connection.stubs(:full_version).returns('5.6.3') + @connection.remove_instance_variable(:@version) if @connection.instance_variable_defined?(:@version) + t = Time.now.change(usec: 1) + assert_no_match(/\.000001\z/, @connection.quoted_date(t)) + 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 799e60a683..ffb4e2c5cf 100644 --- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb @@ -1,29 +1,29 @@ require "cases/helper" -class Group < ActiveRecord::Base - Group.table_name = 'group' - belongs_to :select - has_one :values -end +# a suite of tests to ensure the ConnectionAdapters#MysqlAdapter can handle tables with +# reserved word names (ie: group, order, values, etc...) +class Mysql2ReservedWordTest < ActiveRecord::Mysql2TestCase + class Group < ActiveRecord::Base + Group.table_name = 'group' + belongs_to :select + has_one :values + end -class Select < ActiveRecord::Base - Select.table_name = 'select' - has_many :groups -end + class Select < ActiveRecord::Base + Select.table_name = 'select' + has_many :groups + end -class Values < ActiveRecord::Base - Values.table_name = 'values' -end + class Values < ActiveRecord::Base + Values.table_name = 'values' + end -class Distinct < ActiveRecord::Base - Distinct.table_name = 'distinct' - has_and_belongs_to_many :selects - has_many :values, :through => :groups -end + class Distinct < ActiveRecord::Base + Distinct.table_name = 'distinct' + has_and_belongs_to_many :selects + has_many :values, :through => :groups + end -# a suite of tests to ensure the ConnectionAdapters#MysqlAdapter can handle tables with -# reserved word names (ie: group, order, values, etc...) -class MysqlReservedWordTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb index 417ccf6d11..396f235e77 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -1,47 +1,42 @@ require "cases/helper" -module ActiveRecord - module ConnectionAdapters - class AbstractMysqlAdapter - class SchemaMigrationsTest < ActiveRecord::TestCase - def test_renaming_index_on_foreign_key - connection.add_index "engines", "car_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.remove_foreign_key :engines, name: "fk_engines_cars" - end - - def test_initializes_schema_migrations_for_encoding_utf8mb4 - smtn = ActiveRecord::Migrator.schema_migrations_table_name - connection.drop_table smtn, if_exists: true - - database_name = connection.current_database - database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'") - - original_charset = database_info["DEFAULT_CHARACTER_SET_NAME"] - original_collation = database_info["DEFAULT_COLLATION_NAME"] - - execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET utf8mb4") - - connection.initialize_schema_migrations_table - - assert connection.column_exists?(smtn, :version, :string, limit: AbstractMysqlAdapter::MAX_INDEX_LENGTH_FOR_CHARSETS_OF_4BYTES_MAXLEN) - ensure - execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET #{original_charset} COLLATE #{original_collation}") - end - - private - def connection - @connection ||= ActiveRecord::Base.connection - end - - def execute(sql) - connection.execute(sql) - end - end - end +class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase + def test_renaming_index_on_foreign_key + connection.add_index "engines", "car_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.remove_foreign_key :engines, name: "fk_engines_cars" + end + + def test_initializes_schema_migrations_for_encoding_utf8mb4 + smtn = ActiveRecord::Migrator.schema_migrations_table_name + connection.drop_table smtn, if_exists: true + + database_name = connection.current_database + database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'") + + original_charset = database_info["DEFAULT_CHARACTER_SET_NAME"] + original_collation = database_info["DEFAULT_COLLATION_NAME"] + + execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET utf8mb4") + + connection.initialize_schema_migrations_table + + limit = ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MAX_INDEX_LENGTH_FOR_CHARSETS_OF_4BYTES_MAXLEN + assert connection.column_exists?(smtn, :version, :string, limit: limit) + ensure + execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET #{original_charset} COLLATE #{original_collation}") + end + + private + def connection + @connection ||= ActiveRecord::Base.connection + end + + def execute(sql) + connection.execute(sql) end end diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb index 47707b7d4f..43957791b1 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb @@ -4,7 +4,7 @@ require 'models/comment' module ActiveRecord module ConnectionAdapters - class Mysql2SchemaTest < ActiveRecord::TestCase + class Mysql2SchemaTest < ActiveRecord::Mysql2TestCase fixtures :posts def setup @@ -14,11 +14,43 @@ module ActiveRecord @db_name = db @omgpost = Class.new(ActiveRecord::Base) do + self.inheritance_column = :disabled self.table_name = "#{db}.#{table}" def self.name; 'Post'; end end end + def test_float_limits + @connection.create_table :mysql_doubles do |t| + t.float :float_no_limit + t.float :float_short, limit: 5 + t.float :float_long, limit: 53 + + t.float :float_23, limit: 23 + t.float :float_24, limit: 24 + t.float :float_25, limit: 25 + end + + column_no_limit = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_no_limit' } + column_short = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_short' } + column_long = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_long' } + + column_23 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_23' } + column_24 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_24' } + column_25 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_25' } + + # Mysql floats are precision 0..24, Mysql doubles are precision 25..53 + assert_equal 24, column_no_limit.limit + assert_equal 24, column_short.limit + assert_equal 53, column_long.limit + + assert_equal 24, column_23.limit + assert_equal 24, column_24.limit + assert_equal 53, column_25.limit + ensure + @connection.drop_table "mysql_doubles", if_exists: true + end + def test_schema assert @omgpost.first end @@ -27,21 +59,13 @@ module ActiveRecord assert_equal 'id', @omgpost.primary_key end - def test_table_exists? + def test_data_source_exists? name = @omgpost.table_name - assert @connection.table_exists?(name), "#{name} table should exist" - end - - def test_table_exists_wrong_schema - assert(!@connection.table_exists?("#{@db_name}.zomg"), "table should not exist") + assert @connection.data_source_exists?(name), "#{name} data_source should exist" end - def test_tables_quoting - @connection.tables(nil, "foo-bar", nil) - flunk - rescue => e - # assertion for *quoted* database properly - assert_match(/database 'foo-bar'/, e.inspect) + def test_data_source_exists_wrong_schema + assert(!@connection.data_source_exists?("#{@db_name}.zomg"), "data_source should not exist") end def test_dump_indexes diff --git a/activerecord/test/cases/adapters/mysql2/sp_test.rb b/activerecord/test/cases/adapters/mysql2/sp_test.rb new file mode 100644 index 0000000000..4197ba45f1 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/sp_test.rb @@ -0,0 +1,36 @@ +require "cases/helper" +require 'models/topic' +require 'models/reply' + +class Mysql2StoredProcedureTest < ActiveRecord::Mysql2TestCase + fixtures :topics + + def setup + @connection = ActiveRecord::Base.connection + unless ActiveRecord::Base.connection.version >= '5.6.0' + skip("no stored procedure support") + end + end + + # Test that MySQL allows multiple results for stored procedures + # + # In MySQL 5.6, CLIENT_MULTI_RESULTS is enabled by default. + # http://dev.mysql.com/doc/refman/5.6/en/call.html + def test_multi_results + rows = @connection.select_rows('CALL ten();') + assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}" + assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_rows'" + end + + def test_multi_results_from_select_one + row = @connection.select_one('CALL topics(1);') + assert_equal 'David', row['author_name'] + assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_one'" + end + + def test_multi_results_from_find_by_sql + topics = Topic.find_by_sql 'CALL topics(3);' + assert_equal 3, topics.size + assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select'" + end +end diff --git a/activerecord/test/cases/adapters/mysql2/sql_types_test.rb b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb index 1ddb1b91c9..4926bc2267 100644 --- a/activerecord/test/cases/adapters/mysql2/sql_types_test.rb +++ b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb @@ -1,10 +1,10 @@ require "cases/helper" -class SqlTypesTest < ActiveRecord::TestCase +class Mysql2SqlTypesTest < ActiveRecord::Mysql2TestCase def test_binary_types assert_equal 'varbinary(64)', type_to_sql(:binary, 64) assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095) - assert_equal 'blob(4096)', type_to_sql(:binary, 4096) + assert_equal 'blob', type_to_sql(:binary, 4096) assert_equal 'blob', type_to_sql(:binary) end diff --git a/activerecord/test/cases/adapters/mysql2/table_options_test.rb b/activerecord/test/cases/adapters/mysql2/table_options_test.rb index 0e5b0e8aec..af121ee7d9 100644 --- a/activerecord/test/cases/adapters/mysql2/table_options_test.rb +++ b/activerecord/test/cases/adapters/mysql2/table_options_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class MysqlTableOptionsTest < ActiveRecord::TestCase +class Mysql2TableOptionsTest < ActiveRecord::Mysql2TestCase include SchemaDumpingHelper def setup diff --git a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb index e9edc53f93..c95a64cc16 100644 --- a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb +++ b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb @@ -1,6 +1,8 @@ require "cases/helper" +require "support/schema_dumping_helper" -class UnsignedTypeTest < ActiveRecord::TestCase +class Mysql2UnsignedTypeTest < ActiveRecord::Mysql2TestCase + include SchemaDumpingHelper self.use_transactional_tests = false class UnsignedType < ActiveRecord::Base @@ -9,12 +11,15 @@ class UnsignedTypeTest < ActiveRecord::TestCase setup do @connection = ActiveRecord::Base.connection @connection.create_table("unsigned_types", force: true) do |t| - t.column :unsigned_integer, "int unsigned" + t.integer :unsigned_integer, unsigned: true + t.bigint :unsigned_bigint, unsigned: true + t.float :unsigned_float, unsigned: true + t.decimal :unsigned_decimal, unsigned: true, precision: 10, scale: 2 end end teardown do - @connection.drop_table "unsigned_types" + @connection.drop_table "unsigned_types", if_exists: true end test "unsigned int max value is in range" do @@ -26,5 +31,35 @@ class UnsignedTypeTest < ActiveRecord::TestCase assert_raise(RangeError) do UnsignedType.create(unsigned_integer: -10) end + assert_raise(RangeError) do + UnsignedType.create(unsigned_bigint: -10) + end + assert_raise(ActiveRecord::StatementInvalid) do + UnsignedType.create(unsigned_float: -10.0) + end + assert_raise(ActiveRecord::StatementInvalid) do + UnsignedType.create(unsigned_decimal: -10.0) + end + end + + test "schema definition can use unsigned as the type" do + @connection.change_table("unsigned_types") do |t| + t.unsigned_integer :unsigned_integer_t + t.unsigned_bigint :unsigned_bigint_t + t.unsigned_float :unsigned_float_t + t.unsigned_decimal :unsigned_decimal_t, precision: 10, scale: 2 + end + + @connection.columns("unsigned_types").select { |c| /^unsigned_/ === c.name }.each do |column| + assert column.unsigned? + end + end + + test "schema dump includes unsigned option" do + schema = dump_table_schema "unsigned_types" + assert_match %r{t.integer\s+"unsigned_integer",\s+unsigned: true$}, schema + assert_match %r{t.integer\s+"unsigned_bigint",\s+limit: 8,\s+unsigned: true$}, schema + assert_match %r{t.float\s+"unsigned_float",\s+limit: 24,\s+unsigned: true$}, schema + assert_match %r{t.decimal\s+"unsigned_decimal",\s+precision: 10,\s+scale: 2,\s+unsigned: true$}, schema end end diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index 3808db5141..ed44bf7362 100644 --- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -1,6 +1,6 @@ require 'cases/helper' -class PostgresqlActiveSchemaTest < ActiveRecord::TestCase +class PostgresqlActiveSchemaTest < ActiveRecord::PostgreSQLTestCase def setup ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do def execute(sql, name = nil) sql end @@ -25,7 +25,7 @@ class PostgresqlActiveSchemaTest < ActiveRecord::TestCase def test_add_index # add_index calls index_name_exists? which can't work since execute is stubbed - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.stubs(:index_name_exists?).returns(false) + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:define_method, :index_name_exists?) { |*| false } expected = %(CREATE UNIQUE INDEX "index_people_on_last_name" ON "people" ("last_name") WHERE state = 'active') assert_equal expected, add_index(:people, :last_name, :unique => true, :where => "state = 'active'") @@ -49,6 +49,24 @@ class PostgresqlActiveSchemaTest < ActiveRecord::TestCase expected = %(CREATE UNIQUE INDEX "index_people_on_last_name" ON "people" USING gist ("last_name") WHERE state = 'active') assert_equal expected, add_index(:people, :last_name, :unique => true, :where => "state = 'active'", :using => :gist) + + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :remove_method, :index_name_exists? + end + + def test_remove_index + # remove_index calls index_name_for_remove which can't work since execute is stubbed + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:define_method, :index_name_for_remove) do |*| + 'index_people_on_last_name' + end + + expected = %(DROP INDEX CONCURRENTLY "index_people_on_last_name") + assert_equal expected, remove_index(:people, name: "index_people_on_last_name", algorithm: :concurrently) + + assert_raise ArgumentError do + add_index(:people, :last_name, algorithm: :copy) + end + + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :remove_method, :index_name_for_remove end private diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index 6edbd9c3a6..380a90d765 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -1,10 +1,9 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlArrayTest < ActiveRecord::TestCase +class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper include InTimeZone - OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID class PgArray < ActiveRecord::Base self.table_name = 'pg_arrays' @@ -212,8 +211,9 @@ class PostgresqlArrayTest < ActiveRecord::TestCase def test_quoting_non_standard_delimiters strings = ["hello,", "world;"] - comma_delim = OID::Array.new(ActiveRecord::Type::String.new, ',') - semicolon_delim = OID::Array.new(ActiveRecord::Type::String.new, ';') + oid = ActiveRecord::ConnectionAdapters::PostgreSQL::OID + comma_delim = oid::Array.new(ActiveRecord::Type::String.new, ',') + semicolon_delim = oid::Array.new(ActiveRecord::Type::String.new, ';') assert_equal %({"hello,",world;}), comma_delim.serialize(strings) assert_equal %({hello,;"world;"}), semicolon_delim.serialize(strings) diff --git a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb index 1a5ff4316c..6f72fa6e0f 100644 --- a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb +++ b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb @@ -2,7 +2,7 @@ require "cases/helper" require 'support/connection_helper' require 'support/schema_dumping_helper' -class PostgresqlBitStringTest < ActiveRecord::TestCase +class PostgresqlBitStringTest < ActiveRecord::PostgreSQLTestCase include ConnectionHelper include SchemaDumpingHelper diff --git a/activerecord/test/cases/adapters/postgresql/bytea_test.rb b/activerecord/test/cases/adapters/postgresql/bytea_test.rb index 16db5ab83d..b6bb1929e6 100644 --- a/activerecord/test/cases/adapters/postgresql/bytea_test.rb +++ b/activerecord/test/cases/adapters/postgresql/bytea_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class PostgresqlByteaTest < ActiveRecord::TestCase +class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase class ByteaDataType < ActiveRecord::Base self.table_name = 'bytea_data_type' end diff --git a/activerecord/test/cases/adapters/postgresql/change_schema_test.rb b/activerecord/test/cases/adapters/postgresql/change_schema_test.rb index 5a9796887c..bc12df668d 100644 --- a/activerecord/test/cases/adapters/postgresql/change_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/change_schema_test.rb @@ -2,7 +2,7 @@ require 'cases/helper' module ActiveRecord class Migration - class PGChangeSchemaTest < ActiveRecord::TestCase + class PGChangeSchemaTest < ActiveRecord::PostgreSQLTestCase attr_reader :connection def setup diff --git a/activerecord/test/cases/adapters/postgresql/cidr_test.rb b/activerecord/test/cases/adapters/postgresql/cidr_test.rb index 6cb11d17b4..52f2a0096c 100644 --- a/activerecord/test/cases/adapters/postgresql/cidr_test.rb +++ b/activerecord/test/cases/adapters/postgresql/cidr_test.rb @@ -3,8 +3,8 @@ require "ipaddr" module ActiveRecord module ConnectionAdapters - class PostgreSQLAdapter - class CidrTest < ActiveRecord::TestCase + class PostgreSQLAdapter < AbstractAdapter + class CidrTest < ActiveRecord::PostgreSQLTestCase test "type casting IPAddr for database" do type = OID::Cidr.new ip = IPAddr.new("255.0.0.0/8") diff --git a/activerecord/test/cases/adapters/postgresql/citext_test.rb b/activerecord/test/cases/adapters/postgresql/citext_test.rb index f706847890..bd62041e79 100644 --- a/activerecord/test/cases/adapters/postgresql/citext_test.rb +++ b/activerecord/test/cases/adapters/postgresql/citext_test.rb @@ -2,7 +2,7 @@ require 'cases/helper' require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_extensions? - class PostgresqlCitextTest < ActiveRecord::TestCase + class PostgresqlCitextTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class Citext < ActiveRecord::Base self.table_name = 'citexts' diff --git a/activerecord/test/cases/adapters/postgresql/collation_test.rb b/activerecord/test/cases/adapters/postgresql/collation_test.rb index 17ef5f304c..8470329c35 100644 --- a/activerecord/test/cases/adapters/postgresql/collation_test.rb +++ b/activerecord/test/cases/adapters/postgresql/collation_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlCollationTest < ActiveRecord::TestCase +class PostgresqlCollationTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper def setup diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb index 16e3f90a47..1de87e5f01 100644 --- a/activerecord/test/cases/adapters/postgresql/composite_test.rb +++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb @@ -40,7 +40,7 @@ end # "unknown OID 5653508: failed to recognize type of 'address'. It will be treated as String." # To take full advantage of composite types, we suggest you register your own +OID::Type+. # See PostgresqlCompositeWithCustomOIDTest -class PostgresqlCompositeTest < ActiveRecord::TestCase +class PostgresqlCompositeTest < ActiveRecord::PostgreSQLTestCase include PostgresqlCompositeBehavior def test_column @@ -77,7 +77,7 @@ class PostgresqlCompositeTest < ActiveRecord::TestCase end end -class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase +class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::PostgreSQLTestCase include PostgresqlCompositeBehavior class FullAddressType < ActiveRecord::Type::Value diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 55ad76c8c0..d559de3e28 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -2,7 +2,7 @@ require "cases/helper" require 'support/connection_helper' module ActiveRecord - class PostgresqlConnectionTest < ActiveRecord::TestCase + class PostgresqlConnectionTest < ActiveRecord::PostgreSQLTestCase include ConnectionHelper class NonExistentTable < ActiveRecord::Base @@ -90,7 +90,7 @@ module ActiveRecord end def test_tables_logs_name - @connection.tables('hello') + ActiveSupport::Deprecation.silence { @connection.tables('hello') } assert_equal 'SCHEMA', @subscriber.logged[0][1] end @@ -100,7 +100,7 @@ module ActiveRecord end def test_table_exists_logs_name - @connection.table_exists?('items') + ActiveSupport::Deprecation.silence { @connection.table_exists?('items') } assert_equal 'SCHEMA', @subscriber.logged[0][1] end @@ -127,7 +127,7 @@ module ActiveRecord def test_statement_key_is_logged bind = Relation::QueryAttribute.new(nil, 1, Type::Value.new) - @connection.exec_query('SELECT $1::integer', 'SQL', [bind]) + @connection.exec_query('SELECT $1::integer', 'SQL', [bind], prepare: true) name = @subscriber.payloads.last[:statement_name] assert name res = @connection.exec_query("EXPLAIN (FORMAT JSON) EXECUTE #{name}(1)") @@ -209,5 +209,47 @@ module ActiveRecord ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:debug_print_plan => :default}})) end end + + def test_get_and_release_advisory_lock + lock_id = 5295901941911233559 + list_advisory_locks = <<-SQL + SELECT locktype, + (classid::bigint << 32) | objid::bigint AS lock_id + FROM pg_locks + WHERE locktype = 'advisory' + SQL + + got_lock = @connection.get_advisory_lock(lock_id) + assert got_lock, "get_advisory_lock should have returned true but it didn't" + + advisory_lock = @connection.query(list_advisory_locks).find {|l| l[1] == lock_id} + assert advisory_lock, + "expected to find an advisory lock with lock_id #{lock_id} but there wasn't one" + + released_lock = @connection.release_advisory_lock(lock_id) + assert released_lock, "expected release_advisory_lock to return true but it didn't" + + advisory_locks = @connection.query(list_advisory_locks).select {|l| l[1] == lock_id} + assert_empty advisory_locks, + "expected to have released advisory lock with lock_id #{lock_id} but it was still held" + end + + def test_release_non_existent_advisory_lock + fake_lock_id = 2940075057017742022 + with_warning_suppression do + released_non_existent_lock = @connection.release_advisory_lock(fake_lock_id) + assert_equal released_non_existent_lock, false, + 'expected release_advisory_lock to return false when there was no lock to release' + end + end + + protected + + def with_warning_suppression + log_level = @connection.client_min_messages + @connection.client_min_messages = 'error' + yield + @connection.client_min_messages = log_level + end end end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 2c14252ae4..232c25cb3b 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -11,7 +11,7 @@ end class PostgresqlLtree < ActiveRecord::Base end -class PostgresqlDataTypeTest < ActiveRecord::TestCase +class PostgresqlDataTypeTest < ActiveRecord::PostgreSQLTestCase self.use_transactional_tests = false def setup @@ -69,7 +69,7 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end end -class PostgresqlInternalDataTypeTest < ActiveRecord::TestCase +class PostgresqlInternalDataTypeTest < ActiveRecord::PostgreSQLTestCase include DdlHelper setup do diff --git a/activerecord/test/cases/adapters/postgresql/domain_test.rb b/activerecord/test/cases/adapters/postgresql/domain_test.rb index 26e064c937..6102ddacd1 100644 --- a/activerecord/test/cases/adapters/postgresql/domain_test.rb +++ b/activerecord/test/cases/adapters/postgresql/domain_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/connection_helper' -class PostgresqlDomainTest < ActiveRecord::TestCase +class PostgresqlDomainTest < ActiveRecord::PostgreSQLTestCase include ConnectionHelper class PostgresqlDomain < ActiveRecord::Base diff --git a/activerecord/test/cases/adapters/postgresql/enum_test.rb b/activerecord/test/cases/adapters/postgresql/enum_test.rb index ed084483bc..6816a6514b 100644 --- a/activerecord/test/cases/adapters/postgresql/enum_test.rb +++ b/activerecord/test/cases/adapters/postgresql/enum_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/connection_helper' -class PostgresqlEnumTest < ActiveRecord::TestCase +class PostgresqlEnumTest < ActiveRecord::PostgreSQLTestCase include ConnectionHelper class PostgresqlEnum < ActiveRecord::Base diff --git a/activerecord/test/cases/adapters/postgresql/explain_test.rb b/activerecord/test/cases/adapters/postgresql/explain_test.rb index 6ffb4c9f33..4d0fd640aa 100644 --- a/activerecord/test/cases/adapters/postgresql/explain_test.rb +++ b/activerecord/test/cases/adapters/postgresql/explain_test.rb @@ -2,25 +2,19 @@ require "cases/helper" require 'models/developer' require 'models/computer' -module ActiveRecord - module ConnectionAdapters - class PostgreSQLAdapter - class ExplainTest < ActiveRecord::TestCase - fixtures :developers +class PostgreSQLExplainTest < ActiveRecord::PostgreSQLTestCase + fixtures :developers - 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 %(QUERY PLAN), explain - end + 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 %(QUERY PLAN), explain + end - def test_explain_with_eager_loading - explain = Developer.where(:id => 1).includes(:audit_logs).explain - assert_match %(QUERY PLAN), explain - assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = $1), explain - assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" = 1), explain - end - end - end + def test_explain_with_eager_loading + explain = Developer.where(:id => 1).includes(:audit_logs).explain + assert_match %(QUERY PLAN), explain + assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = $1), explain + assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" = 1), explain end end diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb index 06d427f464..b2a805333c 100644 --- a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb +++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb @@ -1,15 +1,15 @@ require "cases/helper" -class PostgresqlExtensionMigrationTest < ActiveRecord::TestCase +class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase self.use_transactional_tests = false - class EnableHstore < ActiveRecord::Migration + class EnableHstore < ActiveRecord::Migration::Current def change enable_extension "hstore" end end - class DisableHstore < ActiveRecord::Migration + class DisableHstore < ActiveRecord::Migration::Current def change disable_extension "hstore" end diff --git a/activerecord/test/cases/adapters/postgresql/full_text_test.rb b/activerecord/test/cases/adapters/postgresql/full_text_test.rb index b83063c94e..bde7513339 100644 --- a/activerecord/test/cases/adapters/postgresql/full_text_test.rb +++ b/activerecord/test/cases/adapters/postgresql/full_text_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlFullTextTest < ActiveRecord::TestCase +class PostgresqlFullTextTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class Tsvector < ActiveRecord::Base; end diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 41e9572907..9e250c2b7c 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -2,11 +2,19 @@ require "cases/helper" require 'support/connection_helper' require 'support/schema_dumping_helper' -class PostgresqlPointTest < ActiveRecord::TestCase +class PostgresqlPointTest < ActiveRecord::PostgreSQLTestCase include ConnectionHelper include SchemaDumpingHelper - class PostgresqlPoint < ActiveRecord::Base; end + class PostgresqlPoint < ActiveRecord::Base + attribute :x, :point + attribute :y, :point + attribute :z, :point + attribute :array_of_points, :point, array: true + attribute :legacy_x, :legacy_point + attribute :legacy_y, :legacy_point + attribute :legacy_z, :legacy_point + end def setup @connection = ActiveRecord::Base.connection @@ -14,11 +22,27 @@ class PostgresqlPointTest < ActiveRecord::TestCase t.point :x t.point :y, default: [12.2, 13.3] t.point :z, default: "(14.4,15.5)" + t.point :array_of_points, array: true + t.point :legacy_x + t.point :legacy_y, default: [12.2, 13.3] + t.point :legacy_z, default: "(14.4,15.5)" + end + @connection.create_table('deprecated_points') do |t| + t.point :x end end teardown do @connection.drop_table 'postgresql_points', if_exists: true + @connection.drop_table 'deprecated_points', if_exists: true + end + + class DeprecatedPoint < ActiveRecord::Base; end + + def test_deprecated_legacy_type + assert_deprecated do + DeprecatedPoint.new + end end def test_column @@ -32,11 +56,11 @@ class PostgresqlPointTest < ActiveRecord::TestCase end def test_default - assert_equal [12.2, 13.3], PostgresqlPoint.column_defaults['y'] - assert_equal [12.2, 13.3], PostgresqlPoint.new.y + assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.column_defaults['y'] + assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.new.y - assert_equal [14.4, 15.5], PostgresqlPoint.column_defaults['z'] - assert_equal [14.4, 15.5], PostgresqlPoint.new.z + assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.column_defaults['z'] + assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.new.z end def test_schema_dumping @@ -49,37 +73,112 @@ class PostgresqlPointTest < ActiveRecord::TestCase def test_roundtrip PostgresqlPoint.create! x: [10, 25.2] record = PostgresqlPoint.first - assert_equal [10, 25.2], record.x + assert_equal ActiveRecord::Point.new(10, 25.2), record.x - record.x = [1.1, 2.2] + record.x = ActiveRecord::Point.new(1.1, 2.2) record.save! assert record.reload - assert_equal [1.1, 2.2], record.x + assert_equal ActiveRecord::Point.new(1.1, 2.2), record.x end def test_mutation - p = PostgresqlPoint.create! x: [10, 20] + p = PostgresqlPoint.create! x: ActiveRecord::Point.new(10, 20) - p.x[1] = 25 + p.x.y = 25 p.save! p.reload - assert_equal [10.0, 25.0], p.x + assert_equal ActiveRecord::Point.new(10.0, 25.0), p.x + assert_not p.changed? + end + + def test_array_assignment + p = PostgresqlPoint.new(x: [1, 2]) + + assert_equal ActiveRecord::Point.new(1, 2), p.x + end + + def test_string_assignment + p = PostgresqlPoint.new(x: "(1, 2)") + + assert_equal ActiveRecord::Point.new(1, 2), p.x + end + + def test_array_of_points_round_trip + expected_value = [ + ActiveRecord::Point.new(1, 2), + ActiveRecord::Point.new(2, 3), + ActiveRecord::Point.new(3, 4), + ] + p = PostgresqlPoint.new(array_of_points: expected_value) + + assert_equal expected_value, p.array_of_points + p.save! + p.reload + assert_equal expected_value, p.array_of_points + end + + def test_legacy_column + column = PostgresqlPoint.columns_hash["legacy_x"] + assert_equal :point, column.type + assert_equal "point", column.sql_type + assert_not column.array? + + type = PostgresqlPoint.type_for_attribute("legacy_x") + assert_not type.binary? + end + + def test_legacy_default + assert_equal [12.2, 13.3], PostgresqlPoint.column_defaults['legacy_y'] + assert_equal [12.2, 13.3], PostgresqlPoint.new.legacy_y + + assert_equal [14.4, 15.5], PostgresqlPoint.column_defaults['legacy_z'] + assert_equal [14.4, 15.5], PostgresqlPoint.new.legacy_z + end + + def test_legacy_schema_dumping + output = dump_table_schema("postgresql_points") + assert_match %r{t\.point\s+"legacy_x"$}, output + assert_match %r{t\.point\s+"legacy_y",\s+default: \[12\.2, 13\.3\]$}, output + assert_match %r{t\.point\s+"legacy_z",\s+default: \[14\.4, 15\.5\]$}, output + end + + def test_legacy_roundtrip + PostgresqlPoint.create! legacy_x: [10, 25.2] + record = PostgresqlPoint.first + assert_equal [10, 25.2], record.legacy_x + + record.legacy_x = [1.1, 2.2] + record.save! + assert record.reload + assert_equal [1.1, 2.2], record.legacy_x + end + + def test_legacy_mutation + p = PostgresqlPoint.create! legacy_x: [10, 20] + + p.legacy_x[1] = 25 + p.save! + p.reload + + assert_equal [10.0, 25.0], p.legacy_x assert_not p.changed? end end -class PostgresqlGeometricTest < ActiveRecord::TestCase +class PostgresqlGeometricTest < ActiveRecord::PostgreSQLTestCase + include SchemaDumpingHelper + class PostgresqlGeometric < ActiveRecord::Base; end setup do @connection = ActiveRecord::Base.connection @connection.create_table("postgresql_geometrics") do |t| - t.column :a_line_segment, :lseg - t.column :a_box, :box - t.column :a_path, :path - t.column :a_polygon, :polygon - t.column :a_circle, :circle + t.lseg :a_line_segment + t.box :a_box + t.path :a_path + t.polygon :a_polygon + t.circle :a_circle end end @@ -136,4 +235,144 @@ class PostgresqlGeometricTest < ActiveRecord::TestCase objs = PostgresqlGeometric.find_by_sql "SELECT isclosed(a_path) FROM postgresql_geometrics ORDER BY id ASC" assert_equal [false, true], objs.map(&:isclosed) end + + def test_schema_dumping + output = dump_table_schema("postgresql_geometrics") + assert_match %r{t\.lseg\s+"a_line_segment"$}, output + assert_match %r{t\.box\s+"a_box"$}, output + assert_match %r{t\.path\s+"a_path"$}, output + assert_match %r{t\.polygon\s+"a_polygon"$}, output + assert_match %r{t\.circle\s+"a_circle"$}, output + end +end + +class PostgreSQLGeometricLineTest < ActiveRecord::PostgreSQLTestCase + include SchemaDumpingHelper + + class PostgresqlLine < ActiveRecord::Base; end + + setup do + unless ActiveRecord::Base.connection.send(:postgresql_version) >= 90400 + skip("line type is not fully implemented") + end + @connection = ActiveRecord::Base.connection + @connection.create_table("postgresql_lines") do |t| + t.line :a_line + end + end + + teardown do + if defined?(@connection) + @connection.drop_table 'postgresql_lines', if_exists: true + end + end + + def test_geometric_line_type + g = PostgresqlLine.new( + a_line: '{2.0, 3, 5.5}' + ) + g.save! + + h = PostgresqlLine.find(g.id) + assert_equal '{2,3,5.5}', h.a_line + end + + def test_alternative_format_line_type + g = PostgresqlLine.new( + a_line: '(2.0, 3), (4.0, 6.0)' + ) + g.save! + + h = PostgresqlLine.find(g.id) + assert_equal '{1.5,-1,0}', h.a_line + end + + def test_schema_dumping_for_line_type + output = dump_table_schema("postgresql_lines") + assert_match %r{t\.line\s+"a_line"$}, output + end +end + +class PostgreSQLGeometricTypesTest < ActiveRecord::PostgreSQLTestCase + attr_reader :connection, :table_name + + def setup + super + @connection = ActiveRecord::Base.connection + @table_name = :testings + end + + def test_creating_column_with_point_type + connection.create_table(table_name) do |t| + t.point :foo_point + end + + assert_column_exists(:foo_point) + assert_type_correct(:foo_point, :point) + end + + def test_creating_column_with_line_type + connection.create_table(table_name) do |t| + t.line :foo_line + end + + assert_column_exists(:foo_line) + assert_type_correct(:foo_line, :line) + end + + def test_creating_column_with_lseg_type + connection.create_table(table_name) do |t| + t.lseg :foo_lseg + end + + assert_column_exists(:foo_lseg) + assert_type_correct(:foo_lseg, :lseg) + end + + def test_creating_column_with_box_type + connection.create_table(table_name) do |t| + t.box :foo_box + end + + assert_column_exists(:foo_box) + assert_type_correct(:foo_box, :box) + end + + def test_creating_column_with_path_type + connection.create_table(table_name) do |t| + t.path :foo_path + end + + assert_column_exists(:foo_path) + assert_type_correct(:foo_path, :path) + end + + def test_creating_column_with_polygon_type + connection.create_table(table_name) do |t| + t.polygon :foo_polygon + end + + assert_column_exists(:foo_polygon) + assert_type_correct(:foo_polygon, :polygon) + end + + def test_creating_column_with_circle_type + connection.create_table(table_name) do |t| + t.circle :foo_circle + end + + assert_column_exists(:foo_circle) + assert_type_correct(:foo_circle, :circle) + end + + private + + def assert_column_exists(column_name) + assert connection.column_exists?(table_name, column_name) + end + + def assert_type_correct(column_name, type) + column = connection.columns(table_name).find { |c| c.name == column_name.to_s } + assert_equal type, column.type + end end diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index ad9dd311a6..27cc65a643 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -2,7 +2,7 @@ require "cases/helper" require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_extensions? - class PostgresqlHstoreTest < ActiveRecord::TestCase + class PostgresqlHstoreTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class Hstore < ActiveRecord::Base self.table_name = 'hstores' @@ -86,7 +86,7 @@ if ActiveRecord::Base.connection.supports_extensions? end def test_hstore_migration - hstore_migration = Class.new(ActiveRecord::Migration) do + hstore_migration = Class.new(ActiveRecord::Migration::Current) do def change change_table("hstores") do |t| t.hstore :keys diff --git a/activerecord/test/cases/adapters/postgresql/infinity_test.rb b/activerecord/test/cases/adapters/postgresql/infinity_test.rb index d9d7832094..bfda933fa4 100644 --- a/activerecord/test/cases/adapters/postgresql/infinity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/infinity_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class PostgresqlInfinityTest < ActiveRecord::TestCase +class PostgresqlInfinityTest < ActiveRecord::PostgreSQLTestCase include InTimeZone class PostgresqlInfinity < ActiveRecord::Base diff --git a/activerecord/test/cases/adapters/postgresql/integer_test.rb b/activerecord/test/cases/adapters/postgresql/integer_test.rb index 679a0fc7b3..b4e55964b9 100644 --- a/activerecord/test/cases/adapters/postgresql/integer_test.rb +++ b/activerecord/test/cases/adapters/postgresql/integer_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require "active_support/core_ext/numeric/bytes" -class PostgresqlIntegerTest < ActiveRecord::TestCase +class PostgresqlIntegerTest < ActiveRecord::PostgreSQLTestCase class PgInteger < ActiveRecord::Base end diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb index 6878516aeb..b3b121b4fb 100644 --- a/activerecord/test/cases/adapters/postgresql/json_test.rb +++ b/activerecord/test/cases/adapters/postgresql/json_test.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- require "cases/helper" require 'support/schema_dumping_helper' @@ -188,7 +187,7 @@ module PostgresqlJSONSharedTestCases end end -class PostgresqlJSONTest < ActiveRecord::TestCase +class PostgresqlJSONTest < ActiveRecord::PostgreSQLTestCase include PostgresqlJSONSharedTestCases def column_type @@ -196,7 +195,7 @@ class PostgresqlJSONTest < ActiveRecord::TestCase end end -class PostgresqlJSONBTest < ActiveRecord::TestCase +class PostgresqlJSONBTest < ActiveRecord::PostgreSQLTestCase include PostgresqlJSONSharedTestCases def column_type diff --git a/activerecord/test/cases/adapters/postgresql/ltree_test.rb b/activerecord/test/cases/adapters/postgresql/ltree_test.rb index ce0ad16557..56516c82b4 100644 --- a/activerecord/test/cases/adapters/postgresql/ltree_test.rb +++ b/activerecord/test/cases/adapters/postgresql/ltree_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlLtreeTest < ActiveRecord::TestCase +class PostgresqlLtreeTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class Ltree < ActiveRecord::Base self.table_name = 'ltrees' diff --git a/activerecord/test/cases/adapters/postgresql/money_test.rb b/activerecord/test/cases/adapters/postgresql/money_test.rb index cedd399380..c031178479 100644 --- a/activerecord/test/cases/adapters/postgresql/money_test.rb +++ b/activerecord/test/cases/adapters/postgresql/money_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlMoneyTest < ActiveRecord::TestCase +class PostgresqlMoneyTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class PostgresqlMoney < ActiveRecord::Base; end @@ -56,7 +56,7 @@ class PostgresqlMoneyTest < ActiveRecord::TestCase def test_schema_dumping output = dump_table_schema("postgresql_moneys") assert_match %r{t\.money\s+"wealth",\s+scale: 2$}, output - assert_match %r{t\.money\s+"depth",\s+scale: 2,\s+default: 150\.55$}, output + assert_match %r{t\.money\s+"depth",\s+scale: 2,\s+default: "150\.55"$}, output end def test_create_and_update_money diff --git a/activerecord/test/cases/adapters/postgresql/network_test.rb b/activerecord/test/cases/adapters/postgresql/network_test.rb index 033695518e..fe6ee4e2d9 100644 --- a/activerecord/test/cases/adapters/postgresql/network_test.rb +++ b/activerecord/test/cases/adapters/postgresql/network_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlNetworkTest < ActiveRecord::TestCase +class PostgresqlNetworkTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class PostgresqlNetworkAddress < ActiveRecord::Base; end diff --git a/activerecord/test/cases/adapters/postgresql/numbers_test.rb b/activerecord/test/cases/adapters/postgresql/numbers_test.rb index d8e01e3b89..ba7e7dc9a3 100644 --- a/activerecord/test/cases/adapters/postgresql/numbers_test.rb +++ b/activerecord/test/cases/adapters/postgresql/numbers_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class PostgresqlNumberTest < ActiveRecord::TestCase +class PostgresqlNumberTest < ActiveRecord::PostgreSQLTestCase class PostgresqlNumber < ActiveRecord::Base; end setup do diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index 9a1b889d4d..f1995b243a 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -4,7 +4,7 @@ require 'support/connection_helper' module ActiveRecord module ConnectionAdapters - class PostgreSQLAdapterTest < ActiveRecord::TestCase + class PostgreSQLAdapterTest < ActiveRecord::PostgreSQLTestCase include DdlHelper include ConnectionHelper @@ -123,10 +123,24 @@ module ActiveRecord assert_equal expect.to_i, result.rows.first.first end + def test_exec_insert_default_values_with_returning_disabled_and_no_sequence_name_given + connection = connection_without_insert_returning + result = connection.exec_insert("insert into postgresql_partitioned_table_parent DEFAULT VALUES", nil, [], 'id') + expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first + assert_equal expect.to_i, result.rows.first.first + end + + def test_exec_insert_default_values_quoted_schema_with_returning_disabled_and_no_sequence_name_given + connection = connection_without_insert_returning + result = connection.exec_insert('insert into "public"."postgresql_partitioned_table_parent" DEFAULT VALUES', nil, [], 'id') + expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first + assert_equal expect.to_i, result.rows.first.first + end + def test_sql_for_insert_with_returning_disabled connection = connection_without_insert_returning - result = connection.sql_for_insert('sql', nil, nil, nil, 'binds') - assert_equal ['sql', 'binds'], result + sql, binds = connection.sql_for_insert('sql', nil, nil, nil, 'binds') + assert_equal ['sql', 'binds'], [sql, binds] end def test_serial_sequence @@ -308,11 +322,6 @@ module ActiveRecord end end - def test_substitute_at - bind = @connection.substitute_at(nil) - assert_equal Arel.sql('$1'), bind.to_sql - end - def test_partial_index with_example_table do @connection.add_index 'ex', %w{ id number }, :name => 'partial', :where => "number > 100" diff --git a/activerecord/test/cases/adapters/postgresql/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index e4420d9d13..5e6f4dbbb8 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -4,7 +4,7 @@ require 'ipaddr' module ActiveRecord module ConnectionAdapters class PostgreSQLAdapter - class QuotingTest < ActiveRecord::TestCase + class QuotingTest < ActiveRecord::PostgreSQLTestCase def setup @conn = ActiveRecord::Base.connection end diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index bbf96278b0..0edfa4ed9d 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -1,14 +1,16 @@ require "cases/helper" require 'support/connection_helper' -if ActiveRecord::Base.connection.supports_ranges? +if ActiveRecord::Base.connection.respond_to?(:supports_ranges?) && ActiveRecord::Base.connection.supports_ranges? class PostgresqlRange < ActiveRecord::Base self.table_name = "postgresql_ranges" + self.time_zone_aware_types += [:tsrange, :tstzrange] end - class PostgresqlRangeTest < ActiveRecord::TestCase + class PostgresqlRangeTest < ActiveRecord::PostgreSQLTestCase self.use_transactional_tests = false include ConnectionHelper + include InTimeZone def setup @connection = PostgresqlRange.connection @@ -160,6 +162,26 @@ _SQL assert_nil @empty_range.float_range end + def test_timezone_awareness_tzrange + tz = "Pacific Time (US & Canada)" + + in_time_zone tz do + PostgresqlRange.reset_column_information + time_string = Time.current.to_s + time = Time.zone.parse(time_string) + + record = PostgresqlRange.new(tstz_range: time_string..time_string) + assert_equal time..time, record.tstz_range + assert_equal ActiveSupport::TimeZone[tz], record.tstz_range.begin.time_zone + + record.save! + record.reload + + assert_equal time..time, record.tstz_range + assert_equal ActiveSupport::TimeZone[tz], record.tstz_range.begin.time_zone + end + end + def test_create_tstzrange tstzrange = Time.parse('2010-01-01 14:30:00 +0100')...Time.parse('2011-02-02 14:30:00 CDT') round_trip(@new_range, :tstz_range, tstzrange) @@ -188,6 +210,26 @@ _SQL Time.send(tz, 2010, 1, 1, 14, 30, 0)...Time.send(tz, 2010, 1, 1, 14, 30, 0)) end + def test_timezone_awareness_tsrange + tz = "Pacific Time (US & Canada)" + + in_time_zone tz do + PostgresqlRange.reset_column_information + time_string = Time.current.to_s + time = Time.zone.parse(time_string) + + record = PostgresqlRange.new(ts_range: time_string..time_string) + assert_equal time..time, record.ts_range + assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone + + record.save! + record.reload + + assert_equal time..time, record.ts_range + assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone + end + end + def test_create_numrange assert_equal_round_trip(@new_range, :num_range, BigDecimal.new('0.5')...BigDecimal.new('1')) diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb index 7200ed2771..c895ab9db5 100644 --- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb @@ -1,7 +1,7 @@ require 'cases/helper' require 'support/connection_helper' -class PostgreSQLReferentialIntegrityTest < ActiveRecord::TestCase +class PostgreSQLReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase self.use_transactional_tests = false include ConnectionHelper diff --git a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb index f507328868..bd64bae308 100644 --- a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb +++ b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class PostgresqlRenameTableTest < ActiveRecord::TestCase +class PostgresqlRenameTableTest < ActiveRecord::PostgreSQLTestCase def setup @connection = ActiveRecord::Base.connection @connection.create_table :before_rename, force: true diff --git a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb index 359a45bbd1..a0afd922b2 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -3,7 +3,7 @@ require "cases/helper" class SchemaThing < ActiveRecord::Base end -class SchemaAuthorizationTest < ActiveRecord::TestCase +class SchemaAuthorizationTest < ActiveRecord::PostgreSQLTestCase self.use_transactional_tests = false TABLE_NAME = 'schema_things' @@ -31,7 +31,7 @@ class SchemaAuthorizationTest < ActiveRecord::TestCase set_session_auth @connection.execute "RESET search_path" USERS.each do |u| - @connection.execute "DROP SCHEMA #{u} CASCADE" + @connection.drop_schema u @connection.execute "DROP USER #{u}" end end diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index f925dcad97..4aeca4d709 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -2,7 +2,19 @@ require "cases/helper" require 'models/default' require 'support/schema_dumping_helper' -class SchemaTest < ActiveRecord::TestCase +module PGSchemaHelper + def with_schema_search_path(schema_search_path) + @connection.schema_search_path = schema_search_path + @connection.schema_cache.clear! + yield if block_given? + ensure + @connection.schema_search_path = "'$user', public" + @connection.schema_cache.clear! + end +end + +class SchemaTest < ActiveRecord::PostgreSQLTestCase + include PGSchemaHelper self.use_transactional_tests = false SCHEMA_NAME = 'test_schema' @@ -84,8 +96,8 @@ class SchemaTest < ActiveRecord::TestCase end teardown do - @connection.execute "DROP SCHEMA #{SCHEMA2_NAME} CASCADE" - @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE" + @connection.drop_schema SCHEMA2_NAME, if_exists: true + @connection.drop_schema SCHEMA_NAME, if_exists: true end def test_schema_names @@ -121,10 +133,17 @@ class SchemaTest < ActiveRecord::TestCase assert !@connection.schema_names.include?("test_schema3") end + def test_drop_schema_if_exists + @connection.create_schema "some_schema" + assert_includes @connection.schema_names, "some_schema" + @connection.drop_schema "some_schema", if_exists: true + assert_not_includes @connection.schema_names, "some_schema" + end + def test_habtm_table_name_with_schema + ActiveRecord::Base.connection.drop_schema "music", if_exists: true + ActiveRecord::Base.connection.create_schema "music" ActiveRecord::Base.connection.execute <<-SQL - DROP SCHEMA IF EXISTS music CASCADE; - CREATE SCHEMA music; CREATE TABLE music.albums (id serial primary key); CREATE TABLE music.songs (id serial primary key); CREATE TABLE music.albums_songs (album_id integer, song_id integer); @@ -134,18 +153,22 @@ class SchemaTest < ActiveRecord::TestCase Album.create assert_equal song, Song.includes(:albums).references(:albums).first ensure - ActiveRecord::Base.connection.execute "DROP SCHEMA music CASCADE;" + ActiveRecord::Base.connection.drop_schema "music", if_exists: true end - def test_raise_drop_schema_with_nonexisting_schema + def test_drop_schema_with_nonexisting_schema assert_raises(ActiveRecord::StatementInvalid) do - @connection.drop_schema "test_schema3" + @connection.drop_schema "idontexist" + end + + assert_nothing_raised do + @connection.drop_schema "idontexist", if_exists: true end end def test_raise_wraped_exception_on_bad_prepare assert_raises(ActiveRecord::StatementInvalid) do - @connection.exec_query "select * from developers where id = ?", 'sql', [[nil, 1]] + @connection.exec_query "select * from developers where id = ?", 'sql', [bind_param(1)] end end @@ -161,42 +184,42 @@ class SchemaTest < ActiveRecord::TestCase @connection.exec_query("alter table developers drop column zomg", 'sql', []) if altered end - def test_table_exists? + def test_data_source_exists? [Thing1, Thing2, Thing3, Thing4].each do |klass| name = klass.table_name - assert @connection.table_exists?(name), "'#{name}' table should exist" + assert @connection.data_source_exists?(name), "'#{name}' data_source should exist" end end - def test_table_exists_when_on_schema_search_path + def test_data_source_exists_when_on_schema_search_path with_schema_search_path(SCHEMA_NAME) do - assert(@connection.table_exists?(TABLE_NAME), "table should exist and be found") + assert(@connection.data_source_exists?(TABLE_NAME), "data_source should exist and be found") end end - def test_table_exists_when_not_on_schema_search_path + def test_data_source_exists_when_not_on_schema_search_path with_schema_search_path('PUBLIC') do - assert(!@connection.table_exists?(TABLE_NAME), "table exists but should not be found") + assert(!@connection.data_source_exists?(TABLE_NAME), "data_source exists but should not be found") end end - def test_table_exists_wrong_schema - assert(!@connection.table_exists?("foo.things"), "table should not exist") + def test_data_source_exists_wrong_schema + assert(!@connection.data_source_exists?("foo.things"), "data_source should not exist") end - def test_table_exists_quoted_names + def test_data_source_exists_quoted_names [ %("#{SCHEMA_NAME}"."#{TABLE_NAME}"), %(#{SCHEMA_NAME}."#{TABLE_NAME}"), %(#{SCHEMA_NAME}."#{TABLE_NAME}")].each do |given| - assert(@connection.table_exists?(given), "table should exist when specified as #{given}") + assert(@connection.data_source_exists?(given), "data_source should exist when specified as #{given}") end with_schema_search_path(SCHEMA_NAME) do given = %("#{TABLE_NAME}") - assert(@connection.table_exists?(given), "table should exist when specified as #{given}") + assert(@connection.data_source_exists?(given), "data_source should exist when specified as #{given}") end end - def test_table_exists_quoted_table + def test_data_source_exists_quoted_table with_schema_search_path(SCHEMA_NAME) do - assert(@connection.table_exists?('"things.table"'), "table should exist") + assert(@connection.data_source_exists?('"things.table"'), "data_source should exist") end end @@ -298,16 +321,33 @@ class SchemaTest < ActiveRecord::TestCase do_dump_index_tests_for_schema("public, #{SCHEMA_NAME}", INDEX_A_COLUMN, INDEX_B_COLUMN_S1, INDEX_D_COLUMN, INDEX_E_COLUMN) end + def test_dump_indexes_for_table_with_scheme_specified_in_name + indexes = @connection.indexes("#{SCHEMA_NAME}.#{TABLE_NAME}") + assert_equal 4, indexes.size + end + def test_with_uppercase_index_name @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" - assert_nothing_raised { @connection.remove_index! "things", "#{SCHEMA_NAME}.things_Index"} - @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" with_schema_search_path SCHEMA_NAME do - assert_nothing_raised { @connection.remove_index! "things", "things_Index"} + assert_nothing_raised { @connection.remove_index "things", name: "things_Index"} end end + def test_remove_index_when_schema_specified + @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + assert_nothing_raised { @connection.remove_index "things", name: "#{SCHEMA_NAME}.things_Index" } + + @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + assert_nothing_raised { @connection.remove_index "#{SCHEMA_NAME}.things", name: "things_Index" } + + @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + assert_nothing_raised { @connection.remove_index "#{SCHEMA_NAME}.things", name: "#{SCHEMA_NAME}.things_Index" } + + @connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + assert_raises(ArgumentError) { @connection.remove_index "#{SCHEMA2_NAME}.things", name: "#{SCHEMA_NAME}.things_Index" } + end + def test_primary_key_with_schema_specified [ %("#{SCHEMA_NAME}"."#{PK_TABLE_NAME}"), @@ -404,13 +444,6 @@ class SchemaTest < ActiveRecord::TestCase end end - def with_schema_search_path(schema_search_path) - @connection.schema_search_path = schema_search_path - yield if block_given? - ensure - @connection.schema_search_path = "'$user', public" - end - def do_dump_index_tests_for_schema(this_schema_name, first_index_column_name, second_index_column_name, third_index_column_name, fourth_index_column_name) with_schema_search_path(this_schema_name) do indexes = @connection.indexes(TABLE_NAME).sort_by(&:name) @@ -441,7 +474,7 @@ class SchemaTest < ActiveRecord::TestCase end end -class SchemaForeignKeyTest < ActiveRecord::TestCase +class SchemaForeignKeyTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper setup do @@ -462,14 +495,14 @@ class SchemaForeignKeyTest < ActiveRecord::TestCase ensure @connection.drop_table "wagons", if_exists: true @connection.drop_table "my_schema.trains", if_exists: true - @connection.execute "DROP SCHEMA IF EXISTS my_schema" + @connection.drop_schema "my_schema", if_exists: true end end -class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase +class DefaultsUsingMultipleSchemasAndDomainTest < ActiveRecord::PostgreSQLTestCase setup do @connection = ActiveRecord::Base.connection - @connection.execute "DROP SCHEMA IF EXISTS schema_1 CASCADE" + @connection.drop_schema "schema_1", if_exists: true @connection.execute "CREATE SCHEMA schema_1" @connection.execute "CREATE DOMAIN schema_1.text AS text" @connection.execute "CREATE DOMAIN schema_1.varchar AS varchar" @@ -480,13 +513,14 @@ class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase @connection.create_table "defaults" do |t| t.text "text_col", default: "some value" t.string "string_col", default: "some value" + t.decimal "decimal_col", default: "3.14159265358979323846" end Default.reset_column_information end teardown do @connection.schema_search_path = @old_search_path - @connection.execute "DROP SCHEMA IF EXISTS schema_1 CASCADE" + @connection.drop_schema "schema_1", if_exists: true Default.reset_column_information end @@ -498,6 +532,10 @@ class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase assert_equal "some value", Default.new.string_col, "Default of string column was not correctly parsed" end + def test_decimal_defaults_in_new_schema_when_overriding_domain + assert_equal BigDecimal.new("3.14159265358979323846"), Default.new.decimal_col, "Default of decimal column was not correctly parsed" + end + def test_bpchar_defaults_in_new_schema_when_overriding_domain @connection.execute "ALTER TABLE defaults ADD bpchar_col bpchar DEFAULT 'some value'" Default.reset_column_information @@ -514,3 +552,40 @@ class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase assert_equal "foo'::bar", Default.new.string_col end end + +class SchemaWithDotsTest < ActiveRecord::PostgreSQLTestCase + include PGSchemaHelper + self.use_transactional_tests = false + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_schema "my.schema" + end + + teardown do + @connection.drop_schema "my.schema", if_exists: true + end + + test "rename_table" do + with_schema_search_path('"my.schema"') do + @connection.create_table :posts + @connection.rename_table :posts, :articles + assert_equal ["articles"], @connection.tables + end + end + + test "Active Record basics" do + with_schema_search_path('"my.schema"') do + @connection.create_table :articles do |t| + t.string :title + end + article_class = Class.new(ActiveRecord::Base) do + self.table_name = '"my.schema".articles' + end + + article_class.create!(title: "zOMG, welcome to my blorgh!") + welcome_article = article_class.last + assert_equal "zOMG, welcome to my blorgh!", welcome_article.title + end + end +end diff --git a/activerecord/test/cases/adapters/postgresql/serial_test.rb b/activerecord/test/cases/adapters/postgresql/serial_test.rb index 458a8dae6c..7d30db247b 100644 --- a/activerecord/test/cases/adapters/postgresql/serial_test.rb +++ b/activerecord/test/cases/adapters/postgresql/serial_test.rb @@ -1,7 +1,7 @@ require "cases/helper" require 'support/schema_dumping_helper' -class PostgresqlSerialTest < ActiveRecord::TestCase +class PostgresqlSerialTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class PostgresqlSerial < ActiveRecord::Base; end @@ -30,7 +30,7 @@ class PostgresqlSerialTest < ActiveRecord::TestCase end end -class PostgresqlBigSerialTest < ActiveRecord::TestCase +class PostgresqlBigSerialTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class PostgresqlBigSerial < ActiveRecord::Base; end diff --git a/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb b/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb index 1497b0abc7..5aab246c99 100644 --- a/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb +++ b/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb @@ -13,7 +13,7 @@ module ActiveRecord end end - class StatementPoolTest < ActiveRecord::TestCase + class StatementPoolTest < ActiveRecord::PostgreSQLTestCase if Process.respond_to?(:fork) def test_cache_is_per_pid cache = StatementPool.new nil, 10 diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index a639f98272..4c4866b46b 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -2,7 +2,7 @@ require 'cases/helper' require 'models/developer' require 'models/topic' -class PostgresqlTimestampTest < ActiveRecord::TestCase +class PostgresqlTimestampTest < ActiveRecord::PostgreSQLTestCase class PostgresqlTimestampWithZone < ActiveRecord::Base; end self.use_transactional_tests = false @@ -43,7 +43,7 @@ class PostgresqlTimestampTest < ActiveRecord::TestCase end end -class TimestampTest < ActiveRecord::TestCase +class PostgresqlTimestampFixtureTest < ActiveRecord::PostgreSQLTestCase fixtures :topics def test_group_by_date diff --git a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb index c0907b8f21..77a99ca778 100644 --- a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb +++ b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb @@ -1,6 +1,6 @@ require 'cases/helper' -class PostgresqlTypeLookupTest < ActiveRecord::TestCase +class PostgresqlTypeLookupTest < ActiveRecord::PostgreSQLTestCase setup do @connection = ActiveRecord::Base.connection end diff --git a/activerecord/test/cases/adapters/postgresql/utils_test.rb b/activerecord/test/cases/adapters/postgresql/utils_test.rb index 3fdb6888d9..095c1826e5 100644 --- a/activerecord/test/cases/adapters/postgresql/utils_test.rb +++ b/activerecord/test/cases/adapters/postgresql/utils_test.rb @@ -1,6 +1,7 @@ require 'cases/helper' +require 'active_record/connection_adapters/postgresql/utils' -class PostgreSQLUtilsTest < ActiveSupport::TestCase +class PostgreSQLUtilsTest < ActiveRecord::PostgreSQLTestCase Name = ActiveRecord::ConnectionAdapters::PostgreSQL::Name include ActiveRecord::ConnectionAdapters::PostgreSQL::Utils @@ -20,7 +21,7 @@ class PostgreSQLUtilsTest < ActiveSupport::TestCase end end -class PostgreSQLNameTest < ActiveSupport::TestCase +class PostgreSQLNameTest < ActiveRecord::PostgreSQLTestCase Name = ActiveRecord::ConnectionAdapters::PostgreSQL::Name test "represents itself as schema.name" do diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index e9379a1019..7628075ad2 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -11,7 +11,7 @@ module PostgresqlUUIDHelper end end -class PostgresqlUUIDTest < ActiveRecord::TestCase +class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase include PostgresqlUUIDHelper include SchemaDumpingHelper @@ -20,6 +20,8 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase end setup do + enable_extension!('uuid-ossp', connection) + connection.create_table "uuid_data_type" do |t| t.uuid 'guid' end @@ -135,7 +137,7 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase end end -class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase +class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase include PostgresqlUUIDHelper include SchemaDumpingHelper @@ -144,8 +146,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase end setup do - enable_extension!('uuid-ossp', connection) - connection.create_table('pg_uuids', id: :uuid, default: 'uuid_generate_v1()') do |t| t.string 'name' t.uuid 'other_uuid', default: 'uuid_generate_v4()' @@ -170,7 +170,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase drop_table "pg_uuids" drop_table 'pg_uuids_2' connection.execute 'DROP FUNCTION IF EXISTS my_uuid_generator();' - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? @@ -198,25 +197,23 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase def test_schema_dumper_for_uuid_primary_key schema = dump_table_schema "pg_uuids" - assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: "uuid_generate_v1\(\)"/, schema) - assert_match(/t\.uuid "other_uuid", default: "uuid_generate_v4\(\)"/, schema) + assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: -> { "uuid_generate_v1\(\)" }/, schema) + assert_match(/t\.uuid "other_uuid", default: -> { "uuid_generate_v4\(\)" }/, schema) end def test_schema_dumper_for_uuid_primary_key_with_custom_default schema = dump_table_schema "pg_uuids_2" - assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: "my_uuid_generator\(\)"/, schema) - assert_match(/t\.uuid "other_uuid_2", default: "my_uuid_generator\(\)"/, schema) + assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: -> { "my_uuid_generator\(\)" }/, schema) + assert_match(/t\.uuid "other_uuid_2", default: -> { "my_uuid_generator\(\)" }/, schema) end end end -class PostgresqlUUIDTestNilDefault < ActiveRecord::TestCase +class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase include PostgresqlUUIDHelper include SchemaDumpingHelper setup do - enable_extension!('uuid-ossp', connection) - connection.create_table('pg_uuids', id: false) do |t| t.primary_key :id, :uuid, default: nil t.string 'name' @@ -225,7 +222,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::TestCase teardown do drop_table "pg_uuids" - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? @@ -244,7 +240,7 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::TestCase end end -class PostgresqlUUIDTestInverseOf < ActiveRecord::TestCase +class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase include PostgresqlUUIDHelper class UuidPost < ActiveRecord::Base @@ -258,8 +254,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::TestCase end setup do - enable_extension!('uuid-ossp', connection) - connection.transaction do connection.create_table('pg_uuid_posts', id: :uuid) do |t| t.string 'title' @@ -274,7 +268,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::TestCase teardown do drop_table "pg_uuid_comments" drop_table "pg_uuid_posts" - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? diff --git a/activerecord/test/cases/adapters/postgresql/view_test.rb b/activerecord/test/cases/adapters/postgresql/view_test.rb deleted file mode 100644 index 8a8e1d3b17..0000000000 --- a/activerecord/test/cases/adapters/postgresql/view_test.rb +++ /dev/null @@ -1,63 +0,0 @@ -require "cases/helper" -require "cases/view_test" - -class UpdateableViewTest < ActiveRecord::TestCase - fixtures :books - - class PrintedBook < ActiveRecord::Base - self.primary_key = "id" - end - - setup do - @connection = ActiveRecord::Base.connection - @connection.execute <<-SQL - CREATE VIEW printed_books - AS SELECT id, name, status, format FROM books WHERE format = 'paperback' - SQL - end - - teardown do - @connection.execute "DROP VIEW printed_books" if @connection.table_exists? "printed_books" - end - - def test_update_record - book = PrintedBook.first - book.name = "AWDwR" - book.save! - book.reload - assert_equal "AWDwR", book.name - end - - def test_insert_record - PrintedBook.create! name: "Rails in Action", status: 0, format: "paperback" - - new_book = PrintedBook.last - assert_equal "Rails in Action", new_book.name - end - - def test_update_record_to_fail_view_conditions - book = PrintedBook.first - book.format = "ebook" - book.save! - - assert_raises ActiveRecord::RecordNotFound do - book.reload - end - end -end - -if ActiveRecord::Base.connection.supports_materialized_views? -class MaterializedViewTest < ActiveRecord::TestCase - include ViewBehavior - - private - def create_view(name, query) - @connection.execute "CREATE MATERIALIZED VIEW #{name} AS #{query}" - end - - def drop_view(name) - @connection.execute "DROP MATERIALIZED VIEW #{name}" if @connection.table_exists? name - - end -end -end diff --git a/activerecord/test/cases/adapters/postgresql/xml_test.rb b/activerecord/test/cases/adapters/postgresql/xml_test.rb index b097deb2f4..add32699fa 100644 --- a/activerecord/test/cases/adapters/postgresql/xml_test.rb +++ b/activerecord/test/cases/adapters/postgresql/xml_test.rb @@ -1,7 +1,7 @@ require 'cases/helper' require 'support/schema_dumping_helper' -class PostgresqlXMLTest < ActiveRecord::TestCase +class PostgresqlXMLTest < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper class XmlDataType < ActiveRecord::Base self.table_name = 'xml_data_type' diff --git a/activerecord/test/cases/adapters/sqlite3/collation_test.rb b/activerecord/test/cases/adapters/sqlite3/collation_test.rb new file mode 100644 index 0000000000..58a9469ce5 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/collation_test.rb @@ -0,0 +1,53 @@ +require "cases/helper" +require 'support/schema_dumping_helper' + +class SQLite3CollationTest < ActiveRecord::SQLite3TestCase + include SchemaDumpingHelper + + def setup + @connection = ActiveRecord::Base.connection + @connection.create_table :collation_table_sqlite3, force: true do |t| + t.string :string_nocase, collation: 'NOCASE' + t.text :text_rtrim, collation: 'RTRIM' + end + end + + def teardown + @connection.drop_table :collation_table_sqlite3, if_exists: true + end + + test "string column with collation" do + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == 'string_nocase' } + assert_equal :string, column.type + assert_equal 'NOCASE', column.collation + end + + test "text column with collation" do + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == 'text_rtrim' } + assert_equal :text, column.type + assert_equal 'RTRIM', column.collation + end + + test "add column with collation" do + @connection.add_column :collation_table_sqlite3, :title, :string, collation: 'RTRIM' + + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == 'title' } + assert_equal :string, column.type + assert_equal 'RTRIM', column.collation + end + + test "change column with collation" do + @connection.add_column :collation_table_sqlite3, :description, :string + @connection.change_column :collation_table_sqlite3, :description, :text, collation: 'RTRIM' + + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == 'description' } + assert_equal :text, column.type + assert_equal 'RTRIM', column.collation + end + + test "schema dump includes collation" do + output = dump_table_schema("collation_table_sqlite3") + assert_match %r{t.string\s+"string_nocase",\s+collation: "NOCASE"$}, output + assert_match %r{t.text\s+"text_rtrim",\s+collation: "RTRIM"$}, output + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 13b754d226..34e3b2e023 100644 --- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -1,6 +1,6 @@ require "cases/helper" -class CopyTableTest < ActiveRecord::TestCase +class CopyTableTest < ActiveRecord::SQLite3TestCase fixtures :customers def setup diff --git a/activerecord/test/cases/adapters/sqlite3/explain_test.rb b/activerecord/test/cases/adapters/sqlite3/explain_test.rb index 7d66c44798..2aec322582 100644 --- a/activerecord/test/cases/adapters/sqlite3/explain_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/explain_test.rb @@ -5,7 +5,7 @@ require 'models/computer' module ActiveRecord module ConnectionAdapters class SQLite3Adapter - class ExplainTest < ActiveRecord::TestCase + class ExplainTest < ActiveRecord::SQLite3TestCase fixtures :developers def test_explain_for_one_query diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index 243f65df98..87a892db37 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -6,7 +6,7 @@ require 'securerandom' module ActiveRecord module ConnectionAdapters class SQLite3Adapter - class QuotingTest < ActiveRecord::TestCase + class QuotingTest < ActiveRecord::SQLite3TestCase def setup @conn = Base.sqlite3_connection :database => ':memory:', :adapter => 'sqlite3', diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 27f4ba8eb6..038d9e2d0f 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -5,7 +5,7 @@ require 'support/ddl_helper' module ActiveRecord module ConnectionAdapters - class SQLite3AdapterTest < ActiveRecord::TestCase + class SQLite3AdapterTest < ActiveRecord::SQLite3TestCase include DdlHelper self.use_transactional_tests = false @@ -130,11 +130,6 @@ module ActiveRecord assert_equal 'UTF-8', @conn.encoding end - def test_bind_value_substitute - bind_param = @conn.substitute_at('foo') - assert_equal Arel.sql('?'), bind_param.to_sql - end - def test_exec_no_binds with_example_table 'id int, data string' do result = @conn.exec_query('SELECT id, data FROM ex') @@ -284,9 +279,9 @@ module ActiveRecord def test_tables with_example_table do - assert_equal %w{ ex }, @conn.tables + ActiveSupport::Deprecation.silence { assert_equal %w{ ex }, @conn.tables } with_example_table 'id integer PRIMARY KEY AUTOINCREMENT, number integer', 'people' do - assert_equal %w{ ex people }.sort, @conn.tables.sort + ActiveSupport::Deprecation.silence { assert_equal %w{ ex people }.sort, @conn.tables.sort } end end end @@ -294,10 +289,12 @@ module ActiveRecord def test_tables_logs_name sql = <<-SQL SELECT name FROM sqlite_master - WHERE (type = 'table' OR type = 'view') AND NOT name = 'sqlite_sequence' + WHERE type IN ('table','view') AND name <> 'sqlite_sequence' SQL assert_logged [[sql.squish, 'SCHEMA', []]] do - @conn.tables('hello') + ActiveSupport::Deprecation.silence do + @conn.tables('hello') + end end end @@ -313,11 +310,12 @@ module ActiveRecord with_example_table do sql = <<-SQL SELECT name FROM sqlite_master - WHERE (type = 'table' OR type = 'view') - AND NOT name = 'sqlite_sequence' AND name = \"ex\" + WHERE type IN ('table','view') AND name <> 'sqlite_sequence' AND name = 'ex' SQL assert_logged [[sql.squish, 'SCHEMA', []]] do - assert @conn.table_exists?('ex') + ActiveSupport::Deprecation.silence do + assert @conn.table_exists?('ex') + end end end end @@ -421,17 +419,20 @@ module ActiveRecord end def test_statement_closed - db = SQLite3::Database.new(ActiveRecord::Base. + db = ::SQLite3::Database.new(ActiveRecord::Base. configurations['arunit']['database']) - statement = SQLite3::Statement.new(db, + statement = ::SQLite3::Statement.new(db, 'CREATE TABLE statement_test (number integer not null)') - statement.stubs(:step).raises(SQLite3::BusyException, 'busy') - statement.stubs(:columns).once.returns([]) - statement.expects(:close).once - SQLite3::Statement.stubs(:new).returns(statement) - - assert_raises ActiveRecord::StatementInvalid do - @conn.exec_query 'select * from statement_test' + statement.stub(:step, ->{ raise ::SQLite3::BusyException.new('busy') }) do + assert_called(statement, :columns, returns: []) do + assert_called(statement, :close) do + ::SQLite3::Statement.stub(:new, statement) do + assert_raises ActiveRecord::StatementInvalid do + @conn.exec_query 'select * from statement_test' + end + end + end + end end end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb index deedf67c8e..9b675b804b 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb @@ -3,16 +3,20 @@ require 'models/owner' module ActiveRecord module ConnectionAdapters - class SQLite3CreateFolder < ActiveRecord::TestCase + class SQLite3CreateFolder < ActiveRecord::SQLite3TestCase def test_sqlite_creates_directory Dir.mktmpdir do |dir| - dir = Pathname.new(dir) - @conn = Base.sqlite3_connection :database => dir.join("db/foo.sqlite3"), - :adapter => 'sqlite3', - :timeout => 100 + begin + dir = Pathname.new(dir) + @conn = Base.sqlite3_connection :database => dir.join("db/foo.sqlite3"), + :adapter => 'sqlite3', + :timeout => 100 - assert Dir.exist? dir.join('db') - assert File.exist? dir.join('db/foo.sqlite3') + assert Dir.exist? dir.join('db') + assert File.exist? dir.join('db/foo.sqlite3') + ensure + @conn.disconnect! if @conn + end end end end diff --git a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb index fd0044ac05..559b951109 100644 --- a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb @@ -2,11 +2,11 @@ require 'cases/helper' module ActiveRecord::ConnectionAdapters class SQLite3Adapter - class StatementPoolTest < ActiveRecord::TestCase + class StatementPoolTest < ActiveRecord::SQLite3TestCase if Process.respond_to?(:fork) def test_cache_is_per_pid - cache = StatementPool.new nil, 10 + cache = StatementPool.new(10) cache['foo'] = 'bar' assert_equal 'bar', cache['foo'] @@ -22,4 +22,3 @@ module ActiveRecord::ConnectionAdapters end end end - |