From 34ca2da0dc1c17993de4f3633ac1247286cfdb9c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 25 Jun 2010 13:29:17 -0700 Subject: [PATCH] reorganizing adapter specific tests. [#4974 state:resolved] --- activerecord/Rakefile | 5 +- .../test/cases/active_schema_test_mysql.rb | 124 ---------- .../test/cases/active_schema_test_postgresql.rb | 28 --- .../cases/adapters/firebird/connection_test.rb | 8 + .../test/cases/adapters/firebird/default_test.rb | 16 ++ .../test/cases/adapters/firebird/migration_test.rb | 124 ++++++++++ .../cases/adapters/mysql/active_schema_test.rb | 124 ++++++++++ .../test/cases/adapters/mysql/connection_test.rb | 64 +++++ .../cases/adapters/mysql/reserved_word_test.rb | 176 ++++++++++++++ .../test/cases/adapters/oracle/synonym_test.rb | 17 ++ .../adapters/postgresql/active_schema_test.rb | 28 +++ .../cases/adapters/postgresql/datatype_test.rb | 243 ++++++++++++++++++++ .../postgresql/schema_authorization_test.rb | 84 +++++++ .../test/cases/adapters/postgresql/schema_test.rb | 193 ++++++++++++++++ .../test/cases/adapters/sqlite/copy_table_test.rb | 80 +++++++ .../test/cases/connection_test_firebird.rb | 8 - activerecord/test/cases/connection_test_mysql.rb | 64 ----- activerecord/test/cases/copy_table_test_sqlite.rb | 80 ------- .../test/cases/datatype_test_postgresql.rb | 243 -------------------- activerecord/test/cases/default_test_firebird.rb | 16 -- activerecord/test/cases/migration_test_firebird.rb | 124 ---------- .../test/cases/reserved_word_test_mysql.rb | 176 -------------- .../cases/schema_authorization_test_postgresql.rb | 84 ------- activerecord/test/cases/schema_test_postgresql.rb | 193 ---------------- activerecord/test/cases/synonym_test_oracle.rb | 17 -- 25 files changed, 1161 insertions(+), 1158 deletions(-) delete mode 100644 activerecord/test/cases/active_schema_test_mysql.rb delete mode 100644 activerecord/test/cases/active_schema_test_postgresql.rb create mode 100644 activerecord/test/cases/adapters/firebird/connection_test.rb create mode 100644 activerecord/test/cases/adapters/firebird/default_test.rb create mode 100644 activerecord/test/cases/adapters/firebird/migration_test.rb create mode 100644 activerecord/test/cases/adapters/mysql/active_schema_test.rb create mode 100644 activerecord/test/cases/adapters/mysql/connection_test.rb create mode 100644 activerecord/test/cases/adapters/mysql/reserved_word_test.rb create mode 100644 activerecord/test/cases/adapters/oracle/synonym_test.rb create mode 100644 activerecord/test/cases/adapters/postgresql/active_schema_test.rb create mode 100644 activerecord/test/cases/adapters/postgresql/datatype_test.rb create mode 100644 activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb create mode 100644 activerecord/test/cases/adapters/postgresql/schema_test.rb create mode 100644 activerecord/test/cases/adapters/sqlite/copy_table_test.rb delete mode 100644 activerecord/test/cases/connection_test_firebird.rb delete mode 100644 activerecord/test/cases/connection_test_mysql.rb delete mode 100644 activerecord/test/cases/copy_table_test_sqlite.rb delete mode 100644 activerecord/test/cases/datatype_test_postgresql.rb delete mode 100644 activerecord/test/cases/default_test_firebird.rb delete mode 100644 activerecord/test/cases/migration_test_firebird.rb delete mode 100644 activerecord/test/cases/reserved_word_test_mysql.rb delete mode 100644 activerecord/test/cases/schema_authorization_test_postgresql.rb delete mode 100644 activerecord/test/cases/schema_test_postgresql.rb delete mode 100644 activerecord/test/cases/synonym_test_oracle.rb diff --git a/activerecord/Rakefile b/activerecord/Rakefile index 12e094b..22a17a6 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -49,7 +49,10 @@ end connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}" adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/] t.libs << "test" << connection_path - t.test_files=Dir.glob( "test/cases/**/*_test{,_#{adapter_short}}.rb" ).sort + t.test_files = (Dir.glob( "test/cases/**/*_test.rb" ).reject { + |x| x =~ /\/adapters\// + } + Dir.glob("test/cases/adapters/#{adapter_short}/**/*_test.rb")).sort + t.verbose = true t.warning = true } diff --git a/activerecord/test/cases/active_schema_test_mysql.rb b/activerecord/test/cases/active_schema_test_mysql.rb deleted file mode 100644 index d7431e5..0000000 --- a/activerecord/test/cases/active_schema_test_mysql.rb +++ /dev/null @@ -1,124 +0,0 @@ -require "cases/helper" - -class ActiveSchemaTest < ActiveRecord::TestCase - def setup - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_without_stub, :execute - remove_method :execute - def execute(sql, name = nil) return sql end - end - end - - def teardown - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - remove_method :execute - alias_method :execute, :execute_without_stub - end - end - - def test_add_index - # add_index calls index_exists? which can't work since execute is stubbed - ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:define_method, :index_exists?) do |*| - 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}) - ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:remove_method, :index_exists?) - end - - def test_drop_table - assert_equal "DROP TABLE `people`", drop_table(:people) - end - - if current_adapter?(:MysqlAdapter) - 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 do |t| - end - ActiveRecord::Base.connection.add_timestamps :delete_me - 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 - end - ActiveRecord::Base.connection.remove_timestamps :delete_me - 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 - - private - def with_real_execute - #we need to actually modify some data, so we make execute point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_with_stub, :execute - alias_method :execute, :execute_without_stub - end - yield - ensure - #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.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/active_schema_test_postgresql.rb b/activerecord/test/cases/active_schema_test_postgresql.rb deleted file mode 100644 index f106e14..0000000 --- a/activerecord/test/cases/active_schema_test_postgresql.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'cases/helper' - -class PostgresqlActiveSchemaTest < Test::Unit::TestCase - def setup - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do - alias_method :real_execute, :execute - remove_method :execute - def execute(sql, name = nil) sql end - end - end - - def teardown - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do - remove_method :execute - alias_method :execute, :real_execute - end - end - - def test_create_database_with_encoding - assert_equal %(CREATE DATABASE "matt" ENCODING = 'utf8'), create_database(:matt) - assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'latin1'), create_database(:aimonetti, :encoding => :latin1) - end - - private - def method_missing(method_symbol, *arguments) - ActiveRecord::Base.connection.send(method_symbol, *arguments) - end -end diff --git a/activerecord/test/cases/adapters/firebird/connection_test.rb b/activerecord/test/cases/adapters/firebird/connection_test.rb new file mode 100644 index 0000000..f57ea68 --- /dev/null +++ b/activerecord/test/cases/adapters/firebird/connection_test.rb @@ -0,0 +1,8 @@ +require "cases/helper" + +class FirebirdConnectionTest < ActiveRecord::TestCase + def test_charset_properly_set + fb_conn = ActiveRecord::Base.connection.instance_variable_get(:@connection) + assert_equal 'UTF8', fb_conn.database.character_set + end +end diff --git a/activerecord/test/cases/adapters/firebird/default_test.rb b/activerecord/test/cases/adapters/firebird/default_test.rb new file mode 100644 index 0000000..713c7e1 --- /dev/null +++ b/activerecord/test/cases/adapters/firebird/default_test.rb @@ -0,0 +1,16 @@ +require "cases/helper" +require 'models/default' + +class DefaultTest < ActiveRecord::TestCase + def test_default_timestamp + default = Default.new + assert_instance_of(Time, default.default_timestamp) + assert_equal(:datetime, default.column_for_attribute(:default_timestamp).type) + + # Variance should be small; increase if required -- e.g., if test db is on + # remote host and clocks aren't synchronized. + t1 = Time.new + accepted_variance = 1.0 + assert_in_delta(t1.to_f, default.default_timestamp.to_f, accepted_variance) + end +end diff --git a/activerecord/test/cases/adapters/firebird/migration_test.rb b/activerecord/test/cases/adapters/firebird/migration_test.rb new file mode 100644 index 0000000..710661b --- /dev/null +++ b/activerecord/test/cases/adapters/firebird/migration_test.rb @@ -0,0 +1,124 @@ +require "cases/helper" +require 'models/course' + +class FirebirdMigrationTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + # using Course connection for tests -- need a db that doesn't already have a BOOLEAN domain + @connection = Course.connection + @fireruby_connection = @connection.instance_variable_get(:@connection) + end + + def teardown + @connection.drop_table :foo rescue nil + @connection.execute("DROP DOMAIN D_BOOLEAN") rescue nil + end + + def test_create_table_with_custom_sequence_name + assert_nothing_raised do + @connection.create_table(:foo, :sequence => 'foo_custom_seq') do |f| + f.column :bar, :string + end + end + assert !sequence_exists?('foo_seq') + assert sequence_exists?('foo_custom_seq') + + assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') } + assert !sequence_exists?('foo_custom_seq') + ensure + FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil + end + + def test_create_table_without_sequence + assert_nothing_raised do + @connection.create_table(:foo, :sequence => false) do |f| + f.column :bar, :string + end + end + assert !sequence_exists?('foo_seq') + assert_nothing_raised { @connection.drop_table :foo } + + assert_nothing_raised do + @connection.create_table(:foo, :id => false) do |f| + f.column :bar, :string + end + end + assert !sequence_exists?('foo_seq') + assert_nothing_raised { @connection.drop_table :foo } + end + + def test_create_table_with_boolean_column + assert !boolean_domain_exists? + assert_nothing_raised do + @connection.create_table :foo do |f| + f.column :bar, :string + f.column :baz, :boolean + end + end + assert boolean_domain_exists? + end + + def test_add_boolean_column + assert !boolean_domain_exists? + @connection.create_table :foo do |f| + f.column :bar, :string + end + + assert_nothing_raised { @connection.add_column :foo, :baz, :boolean } + assert boolean_domain_exists? + assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "baz" }.type + end + + def test_change_column_to_boolean + assert !boolean_domain_exists? + # Manually create table with a SMALLINT column, which can be changed to a BOOLEAN + @connection.execute "CREATE TABLE foo (bar SMALLINT)" + assert_equal :integer, @connection.columns(:foo).find { |c| c.name == "bar" }.type + + assert_nothing_raised { @connection.change_column :foo, :bar, :boolean } + assert boolean_domain_exists? + assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "bar" }.type + end + + def test_rename_table_with_data_and_index + @connection.create_table :foo do |f| + f.column :baz, :string, :limit => 50 + end + 100.times { |i| @connection.execute "INSERT INTO foo VALUES (GEN_ID(foo_seq, 1), 'record #{i+1}')" } + @connection.add_index :foo, :baz + + assert_nothing_raised { @connection.rename_table :foo, :bar } + assert !@connection.tables.include?("foo") + assert @connection.tables.include?("bar") + assert_equal "index_bar_on_baz", @connection.indexes("bar").first.name + assert_equal 100, FireRuby::Generator.new("bar_seq", @fireruby_connection).last + assert_equal 100, @connection.select_one("SELECT COUNT(*) FROM bar")["count"] + ensure + @connection.drop_table :bar rescue nil + end + + def test_renaming_table_with_fk_constraint_raises_error + @connection.create_table :parent do |p| + p.column :name, :string + end + @connection.create_table :child do |c| + c.column :parent_id, :integer + end + @connection.execute "ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY(parent_id) REFERENCES parent(id)" + assert_raise(ActiveRecord::ActiveRecordError) { @connection.rename_table :child, :descendant } + ensure + @connection.drop_table :child rescue nil + @connection.drop_table :descendant rescue nil + @connection.drop_table :parent rescue nil + end + + private + def boolean_domain_exists? + !@connection.select_one("SELECT 1 FROM rdb$fields WHERE rdb$field_name = 'D_BOOLEAN'").nil? + end + + def sequence_exists?(sequence_name) + FireRuby::Generator.exists?(sequence_name, @fireruby_connection) + end +end diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb new file mode 100644 index 0000000..d7431e5 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb @@ -0,0 +1,124 @@ +require "cases/helper" + +class ActiveSchemaTest < ActiveRecord::TestCase + def setup + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute_without_stub, :execute + remove_method :execute + def execute(sql, name = nil) return sql end + end + end + + def teardown + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + remove_method :execute + alias_method :execute, :execute_without_stub + end + end + + def test_add_index + # add_index calls index_exists? which can't work since execute is stubbed + ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:define_method, :index_exists?) do |*| + 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}) + ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:remove_method, :index_exists?) + end + + def test_drop_table + assert_equal "DROP TABLE `people`", drop_table(:people) + end + + if current_adapter?(:MysqlAdapter) + 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 do |t| + end + ActiveRecord::Base.connection.add_timestamps :delete_me + 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 + end + ActiveRecord::Base.connection.remove_timestamps :delete_me + 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 + + private + def with_real_execute + #we need to actually modify some data, so we make execute point to the original method + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute_with_stub, :execute + alias_method :execute, :execute_without_stub + end + yield + ensure + #before finishing, we restore the alias to the mock-up method + ActiveRecord::ConnectionAdapters::MysqlAdapter.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/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb new file mode 100644 index 0000000..8e4842a --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -0,0 +1,64 @@ +require "cases/helper" + +class MysqlConnectionTest < ActiveRecord::TestCase + 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 + + 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? + 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 + + # Test that MySQL allows multiple results for stored procedures + if 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}" + end + end + + private + + def run_without_connection + original_connection = ActiveRecord::Base.remove_connection + begin + yield original_connection + ensure + ActiveRecord::Base.establish_connection(original_connection) + 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 new file mode 100644 index 0000000..90d8b0d --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb @@ -0,0 +1,176 @@ +require "cases/helper" + +class Group < ActiveRecord::Base + Group.table_name = 'group' + belongs_to :select, :class_name => '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', + 'distincts_selects'=>'distinct_id int, select_id int' + end + + def teardown + drop_tables_directly ['group', 'select', 'values', 'distinct', 'distincts_selects', '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 + + # dump structure of table with reserved word name + def test_structure_dump + assert_nothing_raised { @connection.structure_dump } + 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_fixtures = false + + #fixtures :group + + def test_fixtures + f = create_test_fixtures :select, :distinct, :group, :values, :distincts_selects + + assert_nothing_raised { + f.each do |x| + x.delete_existing_fixtures + end + } + + assert_nothing_raised { + f.each do |x| + x.insert_fixtures + end + } + end + + #activerecord model class with reserved-word table name + def test_activerecord_model + create_test_fixtures :select, :distinct, :group, :values, :distincts_selects + 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 { y = Group.find_by_order('y') } + assert_nothing_raised { y = Group.find(1) } + x = Group.find(1) + end + + # has_one association with reserved-word table name + def test_has_one_associations + create_test_fixtures :select, :distinct, :group, :values, :distincts_selects + 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, :distincts_selects + gs = nil + assert_nothing_raised { gs = Select.find(2).groups } + assert_equal gs.length, 2 + assert(gs.collect{|x| x.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, :distincts_selects + s = nil + assert_nothing_raised { s = Distinct.find(1).selects } + assert_equal s.length, 2 + assert(s.collect{|x|x.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.find(:all, :include => [:groups]) } + end + + #the following functions were added to DRY test cases + + private + # custom fixture loader, uses Fixtures#create_fixtures and appends base_path to the current file's path + def create_test_fixtures(*fixture_names) + Fixtures.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.execute("DROP TABLE IF EXISTS `#{name}`") + 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/oracle/synonym_test.rb b/activerecord/test/cases/adapters/oracle/synonym_test.rb new file mode 100644 index 0000000..b9a422a --- /dev/null +++ b/activerecord/test/cases/adapters/oracle/synonym_test.rb @@ -0,0 +1,17 @@ +require "cases/helper" +require 'models/topic' +require 'models/subject' + +# confirm that synonyms work just like tables; in this case +# the "subjects" table in Oracle (defined in oci.sql) is just +# a synonym to the "topics" table + +class TestOracleSynonym < ActiveRecord::TestCase + + def test_oracle_synonym + topic = Topic.new + subject = Subject.new + assert_equal(topic.attributes, subject.attributes) + end + +end diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb new file mode 100644 index 0000000..f106e14 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -0,0 +1,28 @@ +require 'cases/helper' + +class PostgresqlActiveSchemaTest < Test::Unit::TestCase + def setup + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do + alias_method :real_execute, :execute + remove_method :execute + def execute(sql, name = nil) sql end + end + end + + def teardown + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do + remove_method :execute + alias_method :execute, :real_execute + end + end + + def test_create_database_with_encoding + assert_equal %(CREATE DATABASE "matt" ENCODING = 'utf8'), create_database(:matt) + assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'latin1'), create_database(:aimonetti, :encoding => :latin1) + end + + private + def method_missing(method_symbol, *arguments) + ActiveRecord::Base.connection.send(method_symbol, *arguments) + end +end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb new file mode 100644 index 0000000..3c2d9fb --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -0,0 +1,243 @@ +require "cases/helper" + +class PostgresqlArray < ActiveRecord::Base +end + +class PostgresqlMoney < ActiveRecord::Base +end + +class PostgresqlNumber < ActiveRecord::Base +end + +class PostgresqlTime < ActiveRecord::Base +end + +class PostgresqlNetworkAddress < ActiveRecord::Base +end + +class PostgresqlBitString < ActiveRecord::Base +end + +class PostgresqlOid < ActiveRecord::Base +end + +class PostgresqlTimestampWithZone < ActiveRecord::Base +end + +class PostgresqlDataTypeTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @connection = ActiveRecord::Base.connection + @connection.execute("set lc_monetary = 'C'") + + @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )") + @first_array = PostgresqlArray.find(1) + + @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)") + @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)") + @first_money = PostgresqlMoney.find(1) + @second_money = PostgresqlMoney.find(2) + + @connection.execute("INSERT INTO postgresql_numbers (single, double) VALUES (123.456, 123456.789)") + @first_number = PostgresqlNumber.find(1) + + @connection.execute("INSERT INTO postgresql_times (time_interval) VALUES ('1 year 2 days ago')") + @first_time = PostgresqlTime.find(1) + + @connection.execute("INSERT INTO postgresql_network_addresses (cidr_address, inet_address, mac_address) VALUES('192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')") + @first_network_address = PostgresqlNetworkAddress.find(1) + + @connection.execute("INSERT INTO postgresql_bit_strings (bit_string, bit_string_varying) VALUES (B'00010101', X'15')") + @first_bit_string = PostgresqlBitString.find(1) + + @connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)") + @first_oid = PostgresqlOid.find(1) + + @connection.execute("INSERT INTO postgresql_timestamp_with_zones (time) VALUES ('2010-01-01 10:00:00-1')") + end + + def test_data_type_of_array_types + assert_equal :string, @first_array.column_for_attribute(:commission_by_quarter).type + assert_equal :string, @first_array.column_for_attribute(:nicknames).type + end + + def test_data_type_of_money_types + assert_equal :decimal, @first_money.column_for_attribute(:wealth).type + end + + def test_data_type_of_number_types + assert_equal :float, @first_number.column_for_attribute(:single).type + assert_equal :float, @first_number.column_for_attribute(:double).type + end + + def test_data_type_of_time_types + assert_equal :string, @first_time.column_for_attribute(:time_interval).type + end + + def test_data_type_of_network_address_types + assert_equal :string, @first_network_address.column_for_attribute(:cidr_address).type + assert_equal :string, @first_network_address.column_for_attribute(:inet_address).type + assert_equal :string, @first_network_address.column_for_attribute(:mac_address).type + end + + def test_data_type_of_bit_string_types + assert_equal :string, @first_bit_string.column_for_attribute(:bit_string).type + assert_equal :string, @first_bit_string.column_for_attribute(:bit_string_varying).type + end + + def test_data_type_of_oid_types + assert_equal :integer, @first_oid.column_for_attribute(:obj_id).type + end + + def test_array_values + assert_equal '{35000,21000,18000,17000}', @first_array.commission_by_quarter + assert_equal '{foo,bar,baz}', @first_array.nicknames + end + + def test_money_values + assert_equal 567.89, @first_money.wealth + assert_equal(-567.89, @second_money.wealth) + end + + def test_number_values + assert_equal 123.456, @first_number.single + assert_equal 123456.789, @first_number.double + end + + def test_time_values + assert_equal '-1 years -2 days', @first_time.time_interval + end + + def test_network_address_values + assert_equal '192.168.0.0/24', @first_network_address.cidr_address + assert_equal '172.16.1.254', @first_network_address.inet_address + assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address + end + + def test_bit_string_values + assert_equal '00010101', @first_bit_string.bit_string + assert_equal '00010101', @first_bit_string.bit_string_varying + end + + def test_oid_values + assert_equal 1234, @first_oid.obj_id + end + + def test_update_integer_array + new_value = '{32800,95000,29350,17000}' + assert @first_array.commission_by_quarter = new_value + assert @first_array.save + assert @first_array.reload + assert_equal @first_array.commission_by_quarter, new_value + assert @first_array.commission_by_quarter = new_value + assert @first_array.save + assert @first_array.reload + assert_equal @first_array.commission_by_quarter, new_value + end + + def test_update_text_array + new_value = '{robby,robert,rob,robbie}' + assert @first_array.nicknames = new_value + assert @first_array.save + assert @first_array.reload + assert_equal @first_array.nicknames, new_value + assert @first_array.nicknames = new_value + assert @first_array.save + assert @first_array.reload + assert_equal @first_array.nicknames, new_value + end + + def test_update_money + new_value = BigDecimal.new('123.45') + assert @first_money.wealth = new_value + assert @first_money.save + assert @first_money.reload + assert_equal new_value, @first_money.wealth + end + + def test_update_number + new_single = 789.012 + new_double = 789012.345 + assert @first_number.single = new_single + assert @first_number.double = new_double + assert @first_number.save + assert @first_number.reload + assert_equal @first_number.single, new_single + assert_equal @first_number.double, new_double + end + + def test_update_time + assert @first_time.time_interval = '2 years 3 minutes' + assert @first_time.save + assert @first_time.reload + assert_equal @first_time.time_interval, '2 years 00:03:00' + end + + def test_update_network_address + new_cidr_address = '10.1.2.3/32' + new_inet_address = '10.0.0.0/8' + new_mac_address = 'bc:de:f0:12:34:56' + assert @first_network_address.cidr_address = new_cidr_address + assert @first_network_address.inet_address = new_inet_address + assert @first_network_address.mac_address = new_mac_address + assert @first_network_address.save + assert @first_network_address.reload + assert_equal @first_network_address.cidr_address, new_cidr_address + assert_equal @first_network_address.inet_address, new_inet_address + assert_equal @first_network_address.mac_address, new_mac_address + end + + def test_update_bit_string + new_bit_string = '11111111' + new_bit_string_varying = 'FF' + assert @first_bit_string.bit_string = new_bit_string + assert @first_bit_string.bit_string_varying = new_bit_string_varying + assert @first_bit_string.save + assert @first_bit_string.reload + assert_equal @first_bit_string.bit_string, new_bit_string + assert_equal @first_bit_string.bit_string, @first_bit_string.bit_string_varying + end + + def test_update_oid + new_value = 567890 + assert @first_oid.obj_id = new_value + assert @first_oid.save + assert @first_oid.reload + assert_equal @first_oid.obj_id, new_value + end + + def test_timestamp_with_zone_values_with_rails_time_zone_support + old_tz = ActiveRecord::Base.time_zone_aware_attributes + old_default_tz = ActiveRecord::Base.default_timezone + + ActiveRecord::Base.time_zone_aware_attributes = true + ActiveRecord::Base.default_timezone = :utc + + @connection.reconnect! + + @first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1) + assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time + ensure + ActiveRecord::Base.default_timezone = old_default_tz + ActiveRecord::Base.time_zone_aware_attributes = old_tz + @connection.reconnect! + end + + def test_timestamp_with_zone_values_without_rails_time_zone_support + old_tz = ActiveRecord::Base.time_zone_aware_attributes + old_default_tz = ActiveRecord::Base.default_timezone + + ActiveRecord::Base.time_zone_aware_attributes = false + ActiveRecord::Base.default_timezone = :local + + @connection.reconnect! + + @first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1) + assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time + ensure + ActiveRecord::Base.default_timezone = old_default_tz + ActiveRecord::Base.time_zone_aware_attributes = old_tz + @connection.reconnect! + end +end diff --git a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb new file mode 100644 index 0000000..2860f1a --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -0,0 +1,84 @@ +require "cases/helper" + +class SchemaThing < ActiveRecord::Base +end + +class SchemaAuthorizationTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + TABLE_NAME = 'schema_things' + COLUMNS = [ + 'id serial primary key', + 'name character varying(50)' + ] + USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2'] + + def setup + @connection = ActiveRecord::Base.connection + @connection.execute "SET search_path TO '$user',public" + set_session_auth + USERS.each do |u| + @connection.execute "CREATE USER #{u}" rescue nil + @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" rescue nil + set_session_auth u + @connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" + @connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')" + set_session_auth + end + end + + def teardown + set_session_auth + @connection.execute "RESET search_path" + USERS.each do |u| + @connection.execute "DROP SCHEMA #{u} CASCADE" + @connection.execute "DROP USER #{u}" + end + end + + def test_schema_invisible + assert_raise(ActiveRecord::StatementInvalid) do + set_session_auth + @connection.execute "SELECT * FROM #{TABLE_NAME}" + end + end + + def test_schema_uniqueness + assert_nothing_raised do + set_session_auth + USERS.each do |u| + set_session_auth u + assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1") + set_session_auth + end + end + end + + def test_sequence_schema_caching + assert_nothing_raised do + USERS.each do |u| + set_session_auth u + st = SchemaThing.new :name => 'TEST1' + st.save! + st = SchemaThing.new :id => 5, :name => 'TEST2' + st.save! + set_session_auth + end + end + end + + def test_tables_in_current_schemas + assert !@connection.tables.include?(TABLE_NAME) + USERS.each do |u| + set_session_auth u + assert @connection.tables.include?(TABLE_NAME) + set_session_auth + end + end + + private + def set_session_auth auth = nil + @connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}" + end + +end diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb new file mode 100644 index 0000000..3ed9b19 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -0,0 +1,193 @@ +require "cases/helper" + +class SchemaTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + SCHEMA_NAME = 'test_schema' + SCHEMA2_NAME = 'test_schema2' + TABLE_NAME = 'things' + CAPITALIZED_TABLE_NAME = 'Things' + INDEX_A_NAME = 'a_index_things_on_name' + INDEX_B_NAME = 'b_index_things_on_different_columns_in_each_schema' + INDEX_A_COLUMN = 'name' + INDEX_B_COLUMN_S1 = 'email' + INDEX_B_COLUMN_S2 = 'moment' + COLUMNS = [ + 'id integer', + 'name character varying(50)', + 'email character varying(50)', + 'moment timestamp without time zone default now()' + ] + + class Thing1 < ActiveRecord::Base + set_table_name "test_schema.things" + end + + class Thing2 < ActiveRecord::Base + set_table_name "test_schema2.things" + end + + class Thing3 < ActiveRecord::Base + set_table_name 'test_schema."things.table"' + end + + class Thing4 < ActiveRecord::Base + set_table_name 'test_schema."Things"' + end + + def setup + @connection = ActiveRecord::Base.connection + @connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" + @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{TABLE_NAME}.table\" (#{COLUMNS.join(',')})" + @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{CAPITALIZED_TABLE_NAME}\" (#{COLUMNS.join(',')})" + @connection.execute "CREATE SCHEMA #{SCHEMA2_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" + @connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});" + @connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});" + @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S1});" + @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S2});" + end + + def teardown + @connection.execute "DROP SCHEMA #{SCHEMA2_NAME} CASCADE" + @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE" + end + + def test_table_exists? + [Thing1, Thing2, Thing3, Thing4].each do |klass| + name = klass.table_name + assert @connection.table_exists?(name), "'#{name}' table should exist" + end + end + + def test_table_exists_wrong_schema + assert(!@connection.table_exists?("foo.things"), "table should not exist") + end + + def test_table_exists_quoted_table + assert(@connection.table_exists?('"things.table"'), "table should exist") + end + + def test_with_schema_prefixed_table_name + assert_nothing_raised do + assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}") + end + end + + def test_with_schema_prefixed_capitalized_table_name + assert_nothing_raised do + assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{CAPITALIZED_TABLE_NAME}") + end + end + + def test_with_schema_search_path + assert_nothing_raised do + with_schema_search_path(SCHEMA_NAME) do + assert_equal COLUMNS, columns(TABLE_NAME) + end + end + end + + + def test_proper_encoding_of_table_name + assert_equal '"table_name"', @connection.quote_table_name('table_name') + assert_equal '"table.name"', @connection.quote_table_name('"table.name"') + assert_equal '"schema_name"."table_name"', @connection.quote_table_name('schema_name.table_name') + assert_equal '"schema_name"."table.name"', @connection.quote_table_name('schema_name."table.name"') + assert_equal '"schema.name"."table_name"', @connection.quote_table_name('"schema.name".table_name') + assert_equal '"schema.name"."table.name"', @connection.quote_table_name('"schema.name"."table.name"') + end + + def test_classes_with_qualified_schema_name + assert_equal 0, Thing1.count + assert_equal 0, Thing2.count + assert_equal 0, Thing3.count + assert_equal 0, Thing4.count + + Thing1.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) + assert_equal 1, Thing1.count + assert_equal 0, Thing2.count + assert_equal 0, Thing3.count + assert_equal 0, Thing4.count + + Thing2.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) + assert_equal 1, Thing1.count + assert_equal 1, Thing2.count + assert_equal 0, Thing3.count + assert_equal 0, Thing4.count + + Thing3.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) + assert_equal 1, Thing1.count + assert_equal 1, Thing2.count + assert_equal 1, Thing3.count + assert_equal 0, Thing4.count + + Thing4.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) + assert_equal 1, Thing1.count + assert_equal 1, Thing2.count + assert_equal 1, Thing3.count + assert_equal 1, Thing4.count + end + + def test_raise_on_unquoted_schema_name + assert_raise(ActiveRecord::StatementInvalid) do + with_schema_search_path '$user,public' + end + end + + def test_without_schema_search_path + assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) } + end + + def test_ignore_nil_schema_search_path + assert_nothing_raised { with_schema_search_path nil } + end + + def test_dump_indexes_for_schema_one + do_dump_index_tests_for_schema(SCHEMA_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S1) + end + + def test_dump_indexes_for_schema_two + do_dump_index_tests_for_schema(SCHEMA2_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S2) + end + + def test_with_uppercase_index_name + ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "#{SCHEMA_NAME}.things_Index"} + + ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" + ActiveRecord::Base.connection.schema_search_path = SCHEMA_NAME + assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "things_Index"} + ActiveRecord::Base.connection.schema_search_path = "public" + end + + private + def columns(table_name) + @connection.send(:column_definitions, table_name).map do |name, type, default| + "#{name} #{type}" + (default ? " default #{default}" : '') + 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) + with_schema_search_path(this_schema_name) do + indexes = @connection.indexes(TABLE_NAME).sort_by {|i| i.name} + assert_equal 2,indexes.size + + do_dump_index_assertions_for_one_index(indexes[0], INDEX_A_NAME, first_index_column_name) + do_dump_index_assertions_for_one_index(indexes[1], INDEX_B_NAME, second_index_column_name) + end + end + + def do_dump_index_assertions_for_one_index(this_index, this_index_name, this_index_column) + assert_equal TABLE_NAME, this_index.table + assert_equal 1, this_index.columns.size + assert_equal this_index_column, this_index.columns[0] + assert_equal this_index_name, this_index.name + end +end diff --git a/activerecord/test/cases/adapters/sqlite/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite/copy_table_test.rb new file mode 100644 index 0000000..575b480 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite/copy_table_test.rb @@ -0,0 +1,80 @@ +require "cases/helper" + +class CopyTableTest < ActiveRecord::TestCase + fixtures :customers, :companies, :comments + + def setup + @connection = ActiveRecord::Base.connection + class << @connection + public :copy_table, :table_structure, :indexes + end + end + + def test_copy_table(from = 'customers', to = 'customers2', options = {}) + assert_nothing_raised {copy_table(from, to, options)} + assert_equal row_count(from), row_count(to) + + if block_given? + yield from, to, options + else + assert_equal column_names(from), column_names(to) + end + + @connection.drop_table(to) rescue nil + end + + def test_copy_table_renaming_column + test_copy_table('customers', 'customers2', + :rename => {'name' => 'person_name'}) do |from, to, options| + expected = column_values(from, 'name') + assert_equal expected, column_values(to, 'person_name') + assert expected.any?, "No values in table: #{expected.inspect}" + end + end + + def test_copy_table_with_index + test_copy_table('comments', 'comments_with_index') do + @connection.add_index('comments_with_index', ['post_id', 'type']) + test_copy_table('comments_with_index', 'comments_with_index2') do + assert_equal table_indexes_without_name('comments_with_index'), + table_indexes_without_name('comments_with_index2') + end + end + end + + def test_copy_table_without_primary_key + test_copy_table('developers_projects', 'programmers_projects') + end + + def test_copy_table_with_id_col_that_is_not_primary_key + test_copy_table('goofy_string_id', 'goofy_string_id2') do |from, to, options| + original_id = @connection.columns('goofy_string_id').detect{|col| col.name == 'id' } + copied_id = @connection.columns('goofy_string_id2').detect{|col| col.name == 'id' } + assert_equal original_id.type, copied_id.type + assert_equal original_id.sql_type, copied_id.sql_type + assert_equal original_id.limit, copied_id.limit + assert_equal original_id.primary, copied_id.primary + end + end + +protected + def copy_table(from, to, options = {}) + @connection.copy_table(from, to, {:temporary => true}.merge(options)) + end + + def column_names(table) + @connection.table_structure(table).map {|column| column['name']} + end + + def column_values(table, column) + @connection.select_all("SELECT #{column} FROM #{table} ORDER BY id").map {|row| row[column]} + end + + def table_indexes_without_name(table) + @connection.indexes('comments_with_index').delete(:name) + end + + def row_count(table) + @connection.select_one("SELECT COUNT(*) AS count FROM #{table}")['count'] + end +end diff --git a/activerecord/test/cases/connection_test_firebird.rb b/activerecord/test/cases/connection_test_firebird.rb deleted file mode 100644 index f57ea68..0000000 --- a/activerecord/test/cases/connection_test_firebird.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "cases/helper" - -class FirebirdConnectionTest < ActiveRecord::TestCase - def test_charset_properly_set - fb_conn = ActiveRecord::Base.connection.instance_variable_get(:@connection) - assert_equal 'UTF8', fb_conn.database.character_set - end -end diff --git a/activerecord/test/cases/connection_test_mysql.rb b/activerecord/test/cases/connection_test_mysql.rb deleted file mode 100644 index 8e4842a..0000000 --- a/activerecord/test/cases/connection_test_mysql.rb +++ /dev/null @@ -1,64 +0,0 @@ -require "cases/helper" - -class MysqlConnectionTest < ActiveRecord::TestCase - 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 - - 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? - 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 - - # Test that MySQL allows multiple results for stored procedures - if 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}" - end - end - - private - - def run_without_connection - original_connection = ActiveRecord::Base.remove_connection - begin - yield original_connection - ensure - ActiveRecord::Base.establish_connection(original_connection) - end - end -end diff --git a/activerecord/test/cases/copy_table_test_sqlite.rb b/activerecord/test/cases/copy_table_test_sqlite.rb deleted file mode 100644 index 575b480..0000000 --- a/activerecord/test/cases/copy_table_test_sqlite.rb +++ /dev/null @@ -1,80 +0,0 @@ -require "cases/helper" - -class CopyTableTest < ActiveRecord::TestCase - fixtures :customers, :companies, :comments - - def setup - @connection = ActiveRecord::Base.connection - class << @connection - public :copy_table, :table_structure, :indexes - end - end - - def test_copy_table(from = 'customers', to = 'customers2', options = {}) - assert_nothing_raised {copy_table(from, to, options)} - assert_equal row_count(from), row_count(to) - - if block_given? - yield from, to, options - else - assert_equal column_names(from), column_names(to) - end - - @connection.drop_table(to) rescue nil - end - - def test_copy_table_renaming_column - test_copy_table('customers', 'customers2', - :rename => {'name' => 'person_name'}) do |from, to, options| - expected = column_values(from, 'name') - assert_equal expected, column_values(to, 'person_name') - assert expected.any?, "No values in table: #{expected.inspect}" - end - end - - def test_copy_table_with_index - test_copy_table('comments', 'comments_with_index') do - @connection.add_index('comments_with_index', ['post_id', 'type']) - test_copy_table('comments_with_index', 'comments_with_index2') do - assert_equal table_indexes_without_name('comments_with_index'), - table_indexes_without_name('comments_with_index2') - end - end - end - - def test_copy_table_without_primary_key - test_copy_table('developers_projects', 'programmers_projects') - end - - def test_copy_table_with_id_col_that_is_not_primary_key - test_copy_table('goofy_string_id', 'goofy_string_id2') do |from, to, options| - original_id = @connection.columns('goofy_string_id').detect{|col| col.name == 'id' } - copied_id = @connection.columns('goofy_string_id2').detect{|col| col.name == 'id' } - assert_equal original_id.type, copied_id.type - assert_equal original_id.sql_type, copied_id.sql_type - assert_equal original_id.limit, copied_id.limit - assert_equal original_id.primary, copied_id.primary - end - end - -protected - def copy_table(from, to, options = {}) - @connection.copy_table(from, to, {:temporary => true}.merge(options)) - end - - def column_names(table) - @connection.table_structure(table).map {|column| column['name']} - end - - def column_values(table, column) - @connection.select_all("SELECT #{column} FROM #{table} ORDER BY id").map {|row| row[column]} - end - - def table_indexes_without_name(table) - @connection.indexes('comments_with_index').delete(:name) - end - - def row_count(table) - @connection.select_one("SELECT COUNT(*) AS count FROM #{table}")['count'] - end -end diff --git a/activerecord/test/cases/datatype_test_postgresql.rb b/activerecord/test/cases/datatype_test_postgresql.rb deleted file mode 100644 index 3c2d9fb..0000000 --- a/activerecord/test/cases/datatype_test_postgresql.rb +++ /dev/null @@ -1,243 +0,0 @@ -require "cases/helper" - -class PostgresqlArray < ActiveRecord::Base -end - -class PostgresqlMoney < ActiveRecord::Base -end - -class PostgresqlNumber < ActiveRecord::Base -end - -class PostgresqlTime < ActiveRecord::Base -end - -class PostgresqlNetworkAddress < ActiveRecord::Base -end - -class PostgresqlBitString < ActiveRecord::Base -end - -class PostgresqlOid < ActiveRecord::Base -end - -class PostgresqlTimestampWithZone < ActiveRecord::Base -end - -class PostgresqlDataTypeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - def setup - @connection = ActiveRecord::Base.connection - @connection.execute("set lc_monetary = 'C'") - - @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )") - @first_array = PostgresqlArray.find(1) - - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)") - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)") - @first_money = PostgresqlMoney.find(1) - @second_money = PostgresqlMoney.find(2) - - @connection.execute("INSERT INTO postgresql_numbers (single, double) VALUES (123.456, 123456.789)") - @first_number = PostgresqlNumber.find(1) - - @connection.execute("INSERT INTO postgresql_times (time_interval) VALUES ('1 year 2 days ago')") - @first_time = PostgresqlTime.find(1) - - @connection.execute("INSERT INTO postgresql_network_addresses (cidr_address, inet_address, mac_address) VALUES('192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')") - @first_network_address = PostgresqlNetworkAddress.find(1) - - @connection.execute("INSERT INTO postgresql_bit_strings (bit_string, bit_string_varying) VALUES (B'00010101', X'15')") - @first_bit_string = PostgresqlBitString.find(1) - - @connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)") - @first_oid = PostgresqlOid.find(1) - - @connection.execute("INSERT INTO postgresql_timestamp_with_zones (time) VALUES ('2010-01-01 10:00:00-1')") - end - - def test_data_type_of_array_types - assert_equal :string, @first_array.column_for_attribute(:commission_by_quarter).type - assert_equal :string, @first_array.column_for_attribute(:nicknames).type - end - - def test_data_type_of_money_types - assert_equal :decimal, @first_money.column_for_attribute(:wealth).type - end - - def test_data_type_of_number_types - assert_equal :float, @first_number.column_for_attribute(:single).type - assert_equal :float, @first_number.column_for_attribute(:double).type - end - - def test_data_type_of_time_types - assert_equal :string, @first_time.column_for_attribute(:time_interval).type - end - - def test_data_type_of_network_address_types - assert_equal :string, @first_network_address.column_for_attribute(:cidr_address).type - assert_equal :string, @first_network_address.column_for_attribute(:inet_address).type - assert_equal :string, @first_network_address.column_for_attribute(:mac_address).type - end - - def test_data_type_of_bit_string_types - assert_equal :string, @first_bit_string.column_for_attribute(:bit_string).type - assert_equal :string, @first_bit_string.column_for_attribute(:bit_string_varying).type - end - - def test_data_type_of_oid_types - assert_equal :integer, @first_oid.column_for_attribute(:obj_id).type - end - - def test_array_values - assert_equal '{35000,21000,18000,17000}', @first_array.commission_by_quarter - assert_equal '{foo,bar,baz}', @first_array.nicknames - end - - def test_money_values - assert_equal 567.89, @first_money.wealth - assert_equal(-567.89, @second_money.wealth) - end - - def test_number_values - assert_equal 123.456, @first_number.single - assert_equal 123456.789, @first_number.double - end - - def test_time_values - assert_equal '-1 years -2 days', @first_time.time_interval - end - - def test_network_address_values - assert_equal '192.168.0.0/24', @first_network_address.cidr_address - assert_equal '172.16.1.254', @first_network_address.inet_address - assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address - end - - def test_bit_string_values - assert_equal '00010101', @first_bit_string.bit_string - assert_equal '00010101', @first_bit_string.bit_string_varying - end - - def test_oid_values - assert_equal 1234, @first_oid.obj_id - end - - def test_update_integer_array - new_value = '{32800,95000,29350,17000}' - assert @first_array.commission_by_quarter = new_value - assert @first_array.save - assert @first_array.reload - assert_equal @first_array.commission_by_quarter, new_value - assert @first_array.commission_by_quarter = new_value - assert @first_array.save - assert @first_array.reload - assert_equal @first_array.commission_by_quarter, new_value - end - - def test_update_text_array - new_value = '{robby,robert,rob,robbie}' - assert @first_array.nicknames = new_value - assert @first_array.save - assert @first_array.reload - assert_equal @first_array.nicknames, new_value - assert @first_array.nicknames = new_value - assert @first_array.save - assert @first_array.reload - assert_equal @first_array.nicknames, new_value - end - - def test_update_money - new_value = BigDecimal.new('123.45') - assert @first_money.wealth = new_value - assert @first_money.save - assert @first_money.reload - assert_equal new_value, @first_money.wealth - end - - def test_update_number - new_single = 789.012 - new_double = 789012.345 - assert @first_number.single = new_single - assert @first_number.double = new_double - assert @first_number.save - assert @first_number.reload - assert_equal @first_number.single, new_single - assert_equal @first_number.double, new_double - end - - def test_update_time - assert @first_time.time_interval = '2 years 3 minutes' - assert @first_time.save - assert @first_time.reload - assert_equal @first_time.time_interval, '2 years 00:03:00' - end - - def test_update_network_address - new_cidr_address = '10.1.2.3/32' - new_inet_address = '10.0.0.0/8' - new_mac_address = 'bc:de:f0:12:34:56' - assert @first_network_address.cidr_address = new_cidr_address - assert @first_network_address.inet_address = new_inet_address - assert @first_network_address.mac_address = new_mac_address - assert @first_network_address.save - assert @first_network_address.reload - assert_equal @first_network_address.cidr_address, new_cidr_address - assert_equal @first_network_address.inet_address, new_inet_address - assert_equal @first_network_address.mac_address, new_mac_address - end - - def test_update_bit_string - new_bit_string = '11111111' - new_bit_string_varying = 'FF' - assert @first_bit_string.bit_string = new_bit_string - assert @first_bit_string.bit_string_varying = new_bit_string_varying - assert @first_bit_string.save - assert @first_bit_string.reload - assert_equal @first_bit_string.bit_string, new_bit_string - assert_equal @first_bit_string.bit_string, @first_bit_string.bit_string_varying - end - - def test_update_oid - new_value = 567890 - assert @first_oid.obj_id = new_value - assert @first_oid.save - assert @first_oid.reload - assert_equal @first_oid.obj_id, new_value - end - - def test_timestamp_with_zone_values_with_rails_time_zone_support - old_tz = ActiveRecord::Base.time_zone_aware_attributes - old_default_tz = ActiveRecord::Base.default_timezone - - ActiveRecord::Base.time_zone_aware_attributes = true - ActiveRecord::Base.default_timezone = :utc - - @connection.reconnect! - - @first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1) - assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time - ensure - ActiveRecord::Base.default_timezone = old_default_tz - ActiveRecord::Base.time_zone_aware_attributes = old_tz - @connection.reconnect! - end - - def test_timestamp_with_zone_values_without_rails_time_zone_support - old_tz = ActiveRecord::Base.time_zone_aware_attributes - old_default_tz = ActiveRecord::Base.default_timezone - - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - - @connection.reconnect! - - @first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1) - assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time - ensure - ActiveRecord::Base.default_timezone = old_default_tz - ActiveRecord::Base.time_zone_aware_attributes = old_tz - @connection.reconnect! - end -end diff --git a/activerecord/test/cases/default_test_firebird.rb b/activerecord/test/cases/default_test_firebird.rb deleted file mode 100644 index 713c7e1..0000000 --- a/activerecord/test/cases/default_test_firebird.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "cases/helper" -require 'models/default' - -class DefaultTest < ActiveRecord::TestCase - def test_default_timestamp - default = Default.new - assert_instance_of(Time, default.default_timestamp) - assert_equal(:datetime, default.column_for_attribute(:default_timestamp).type) - - # Variance should be small; increase if required -- e.g., if test db is on - # remote host and clocks aren't synchronized. - t1 = Time.new - accepted_variance = 1.0 - assert_in_delta(t1.to_f, default.default_timestamp.to_f, accepted_variance) - end -end diff --git a/activerecord/test/cases/migration_test_firebird.rb b/activerecord/test/cases/migration_test_firebird.rb deleted file mode 100644 index 710661b..0000000 --- a/activerecord/test/cases/migration_test_firebird.rb +++ /dev/null @@ -1,124 +0,0 @@ -require "cases/helper" -require 'models/course' - -class FirebirdMigrationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - def setup - # using Course connection for tests -- need a db that doesn't already have a BOOLEAN domain - @connection = Course.connection - @fireruby_connection = @connection.instance_variable_get(:@connection) - end - - def teardown - @connection.drop_table :foo rescue nil - @connection.execute("DROP DOMAIN D_BOOLEAN") rescue nil - end - - def test_create_table_with_custom_sequence_name - assert_nothing_raised do - @connection.create_table(:foo, :sequence => 'foo_custom_seq') do |f| - f.column :bar, :string - end - end - assert !sequence_exists?('foo_seq') - assert sequence_exists?('foo_custom_seq') - - assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') } - assert !sequence_exists?('foo_custom_seq') - ensure - FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil - end - - def test_create_table_without_sequence - assert_nothing_raised do - @connection.create_table(:foo, :sequence => false) do |f| - f.column :bar, :string - end - end - assert !sequence_exists?('foo_seq') - assert_nothing_raised { @connection.drop_table :foo } - - assert_nothing_raised do - @connection.create_table(:foo, :id => false) do |f| - f.column :bar, :string - end - end - assert !sequence_exists?('foo_seq') - assert_nothing_raised { @connection.drop_table :foo } - end - - def test_create_table_with_boolean_column - assert !boolean_domain_exists? - assert_nothing_raised do - @connection.create_table :foo do |f| - f.column :bar, :string - f.column :baz, :boolean - end - end - assert boolean_domain_exists? - end - - def test_add_boolean_column - assert !boolean_domain_exists? - @connection.create_table :foo do |f| - f.column :bar, :string - end - - assert_nothing_raised { @connection.add_column :foo, :baz, :boolean } - assert boolean_domain_exists? - assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "baz" }.type - end - - def test_change_column_to_boolean - assert !boolean_domain_exists? - # Manually create table with a SMALLINT column, which can be changed to a BOOLEAN - @connection.execute "CREATE TABLE foo (bar SMALLINT)" - assert_equal :integer, @connection.columns(:foo).find { |c| c.name == "bar" }.type - - assert_nothing_raised { @connection.change_column :foo, :bar, :boolean } - assert boolean_domain_exists? - assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "bar" }.type - end - - def test_rename_table_with_data_and_index - @connection.create_table :foo do |f| - f.column :baz, :string, :limit => 50 - end - 100.times { |i| @connection.execute "INSERT INTO foo VALUES (GEN_ID(foo_seq, 1), 'record #{i+1}')" } - @connection.add_index :foo, :baz - - assert_nothing_raised { @connection.rename_table :foo, :bar } - assert !@connection.tables.include?("foo") - assert @connection.tables.include?("bar") - assert_equal "index_bar_on_baz", @connection.indexes("bar").first.name - assert_equal 100, FireRuby::Generator.new("bar_seq", @fireruby_connection).last - assert_equal 100, @connection.select_one("SELECT COUNT(*) FROM bar")["count"] - ensure - @connection.drop_table :bar rescue nil - end - - def test_renaming_table_with_fk_constraint_raises_error - @connection.create_table :parent do |p| - p.column :name, :string - end - @connection.create_table :child do |c| - c.column :parent_id, :integer - end - @connection.execute "ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY(parent_id) REFERENCES parent(id)" - assert_raise(ActiveRecord::ActiveRecordError) { @connection.rename_table :child, :descendant } - ensure - @connection.drop_table :child rescue nil - @connection.drop_table :descendant rescue nil - @connection.drop_table :parent rescue nil - end - - private - def boolean_domain_exists? - !@connection.select_one("SELECT 1 FROM rdb$fields WHERE rdb$field_name = 'D_BOOLEAN'").nil? - end - - def sequence_exists?(sequence_name) - FireRuby::Generator.exists?(sequence_name, @fireruby_connection) - end -end diff --git a/activerecord/test/cases/reserved_word_test_mysql.rb b/activerecord/test/cases/reserved_word_test_mysql.rb deleted file mode 100644 index 90d8b0d..0000000 --- a/activerecord/test/cases/reserved_word_test_mysql.rb +++ /dev/null @@ -1,176 +0,0 @@ -require "cases/helper" - -class Group < ActiveRecord::Base - Group.table_name = 'group' - belongs_to :select, :class_name => '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', - 'distincts_selects'=>'distinct_id int, select_id int' - end - - def teardown - drop_tables_directly ['group', 'select', 'values', 'distinct', 'distincts_selects', '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 - - # dump structure of table with reserved word name - def test_structure_dump - assert_nothing_raised { @connection.structure_dump } - 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_fixtures = false - - #fixtures :group - - def test_fixtures - f = create_test_fixtures :select, :distinct, :group, :values, :distincts_selects - - assert_nothing_raised { - f.each do |x| - x.delete_existing_fixtures - end - } - - assert_nothing_raised { - f.each do |x| - x.insert_fixtures - end - } - end - - #activerecord model class with reserved-word table name - def test_activerecord_model - create_test_fixtures :select, :distinct, :group, :values, :distincts_selects - 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 { y = Group.find_by_order('y') } - assert_nothing_raised { y = Group.find(1) } - x = Group.find(1) - end - - # has_one association with reserved-word table name - def test_has_one_associations - create_test_fixtures :select, :distinct, :group, :values, :distincts_selects - 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, :distincts_selects - gs = nil - assert_nothing_raised { gs = Select.find(2).groups } - assert_equal gs.length, 2 - assert(gs.collect{|x| x.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, :distincts_selects - s = nil - assert_nothing_raised { s = Distinct.find(1).selects } - assert_equal s.length, 2 - assert(s.collect{|x|x.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.find(:all, :include => [:groups]) } - end - - #the following functions were added to DRY test cases - - private - # custom fixture loader, uses Fixtures#create_fixtures and appends base_path to the current file's path - def create_test_fixtures(*fixture_names) - Fixtures.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.execute("DROP TABLE IF EXISTS `#{name}`") - 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/schema_authorization_test_postgresql.rb b/activerecord/test/cases/schema_authorization_test_postgresql.rb deleted file mode 100644 index 2860f1a..0000000 --- a/activerecord/test/cases/schema_authorization_test_postgresql.rb +++ /dev/null @@ -1,84 +0,0 @@ -require "cases/helper" - -class SchemaThing < ActiveRecord::Base -end - -class SchemaAuthorizationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - TABLE_NAME = 'schema_things' - COLUMNS = [ - 'id serial primary key', - 'name character varying(50)' - ] - USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2'] - - def setup - @connection = ActiveRecord::Base.connection - @connection.execute "SET search_path TO '$user',public" - set_session_auth - USERS.each do |u| - @connection.execute "CREATE USER #{u}" rescue nil - @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" rescue nil - set_session_auth u - @connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" - @connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')" - set_session_auth - end - end - - def teardown - set_session_auth - @connection.execute "RESET search_path" - USERS.each do |u| - @connection.execute "DROP SCHEMA #{u} CASCADE" - @connection.execute "DROP USER #{u}" - end - end - - def test_schema_invisible - assert_raise(ActiveRecord::StatementInvalid) do - set_session_auth - @connection.execute "SELECT * FROM #{TABLE_NAME}" - end - end - - def test_schema_uniqueness - assert_nothing_raised do - set_session_auth - USERS.each do |u| - set_session_auth u - assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1") - set_session_auth - end - end - end - - def test_sequence_schema_caching - assert_nothing_raised do - USERS.each do |u| - set_session_auth u - st = SchemaThing.new :name => 'TEST1' - st.save! - st = SchemaThing.new :id => 5, :name => 'TEST2' - st.save! - set_session_auth - end - end - end - - def test_tables_in_current_schemas - assert !@connection.tables.include?(TABLE_NAME) - USERS.each do |u| - set_session_auth u - assert @connection.tables.include?(TABLE_NAME) - set_session_auth - end - end - - private - def set_session_auth auth = nil - @connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}" - end - -end diff --git a/activerecord/test/cases/schema_test_postgresql.rb b/activerecord/test/cases/schema_test_postgresql.rb deleted file mode 100644 index 3ed9b19..0000000 --- a/activerecord/test/cases/schema_test_postgresql.rb +++ /dev/null @@ -1,193 +0,0 @@ -require "cases/helper" - -class SchemaTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - SCHEMA_NAME = 'test_schema' - SCHEMA2_NAME = 'test_schema2' - TABLE_NAME = 'things' - CAPITALIZED_TABLE_NAME = 'Things' - INDEX_A_NAME = 'a_index_things_on_name' - INDEX_B_NAME = 'b_index_things_on_different_columns_in_each_schema' - INDEX_A_COLUMN = 'name' - INDEX_B_COLUMN_S1 = 'email' - INDEX_B_COLUMN_S2 = 'moment' - COLUMNS = [ - 'id integer', - 'name character varying(50)', - 'email character varying(50)', - 'moment timestamp without time zone default now()' - ] - - class Thing1 < ActiveRecord::Base - set_table_name "test_schema.things" - end - - class Thing2 < ActiveRecord::Base - set_table_name "test_schema2.things" - end - - class Thing3 < ActiveRecord::Base - set_table_name 'test_schema."things.table"' - end - - class Thing4 < ActiveRecord::Base - set_table_name 'test_schema."Things"' - end - - def setup - @connection = ActiveRecord::Base.connection - @connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" - @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{TABLE_NAME}.table\" (#{COLUMNS.join(',')})" - @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{CAPITALIZED_TABLE_NAME}\" (#{COLUMNS.join(',')})" - @connection.execute "CREATE SCHEMA #{SCHEMA2_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" - @connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});" - @connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});" - @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S1});" - @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S2});" - end - - def teardown - @connection.execute "DROP SCHEMA #{SCHEMA2_NAME} CASCADE" - @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE" - end - - def test_table_exists? - [Thing1, Thing2, Thing3, Thing4].each do |klass| - name = klass.table_name - assert @connection.table_exists?(name), "'#{name}' table should exist" - end - end - - def test_table_exists_wrong_schema - assert(!@connection.table_exists?("foo.things"), "table should not exist") - end - - def test_table_exists_quoted_table - assert(@connection.table_exists?('"things.table"'), "table should exist") - end - - def test_with_schema_prefixed_table_name - assert_nothing_raised do - assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}") - end - end - - def test_with_schema_prefixed_capitalized_table_name - assert_nothing_raised do - assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{CAPITALIZED_TABLE_NAME}") - end - end - - def test_with_schema_search_path - assert_nothing_raised do - with_schema_search_path(SCHEMA_NAME) do - assert_equal COLUMNS, columns(TABLE_NAME) - end - end - end - - - def test_proper_encoding_of_table_name - assert_equal '"table_name"', @connection.quote_table_name('table_name') - assert_equal '"table.name"', @connection.quote_table_name('"table.name"') - assert_equal '"schema_name"."table_name"', @connection.quote_table_name('schema_name.table_name') - assert_equal '"schema_name"."table.name"', @connection.quote_table_name('schema_name."table.name"') - assert_equal '"schema.name"."table_name"', @connection.quote_table_name('"schema.name".table_name') - assert_equal '"schema.name"."table.name"', @connection.quote_table_name('"schema.name"."table.name"') - end - - def test_classes_with_qualified_schema_name - assert_equal 0, Thing1.count - assert_equal 0, Thing2.count - assert_equal 0, Thing3.count - assert_equal 0, Thing4.count - - Thing1.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) - assert_equal 1, Thing1.count - assert_equal 0, Thing2.count - assert_equal 0, Thing3.count - assert_equal 0, Thing4.count - - Thing2.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) - assert_equal 1, Thing1.count - assert_equal 1, Thing2.count - assert_equal 0, Thing3.count - assert_equal 0, Thing4.count - - Thing3.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) - assert_equal 1, Thing1.count - assert_equal 1, Thing2.count - assert_equal 1, Thing3.count - assert_equal 0, Thing4.count - - Thing4.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now) - assert_equal 1, Thing1.count - assert_equal 1, Thing2.count - assert_equal 1, Thing3.count - assert_equal 1, Thing4.count - end - - def test_raise_on_unquoted_schema_name - assert_raise(ActiveRecord::StatementInvalid) do - with_schema_search_path '$user,public' - end - end - - def test_without_schema_search_path - assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) } - end - - def test_ignore_nil_schema_search_path - assert_nothing_raised { with_schema_search_path nil } - end - - def test_dump_indexes_for_schema_one - do_dump_index_tests_for_schema(SCHEMA_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S1) - end - - def test_dump_indexes_for_schema_two - do_dump_index_tests_for_schema(SCHEMA2_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S2) - end - - def test_with_uppercase_index_name - ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" - assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "#{SCHEMA_NAME}.things_Index"} - - ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)" - ActiveRecord::Base.connection.schema_search_path = SCHEMA_NAME - assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "things_Index"} - ActiveRecord::Base.connection.schema_search_path = "public" - end - - private - def columns(table_name) - @connection.send(:column_definitions, table_name).map do |name, type, default| - "#{name} #{type}" + (default ? " default #{default}" : '') - 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) - with_schema_search_path(this_schema_name) do - indexes = @connection.indexes(TABLE_NAME).sort_by {|i| i.name} - assert_equal 2,indexes.size - - do_dump_index_assertions_for_one_index(indexes[0], INDEX_A_NAME, first_index_column_name) - do_dump_index_assertions_for_one_index(indexes[1], INDEX_B_NAME, second_index_column_name) - end - end - - def do_dump_index_assertions_for_one_index(this_index, this_index_name, this_index_column) - assert_equal TABLE_NAME, this_index.table - assert_equal 1, this_index.columns.size - assert_equal this_index_column, this_index.columns[0] - assert_equal this_index_name, this_index.name - end -end diff --git a/activerecord/test/cases/synonym_test_oracle.rb b/activerecord/test/cases/synonym_test_oracle.rb deleted file mode 100644 index b9a422a..0000000 --- a/activerecord/test/cases/synonym_test_oracle.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "cases/helper" -require 'models/topic' -require 'models/subject' - -# confirm that synonyms work just like tables; in this case -# the "subjects" table in Oracle (defined in oci.sql) is just -# a synonym to the "topics" table - -class TestOracleSynonym < ActiveRecord::TestCase - - def test_oracle_synonym - topic = Topic.new - subject = Subject.new - assert_equal(topic.attributes, subject.attributes) - end - -end -- 1.7.0.6