activerecord-jdbc-adapter-onsite 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +22 -0
- data/.travis.yml +14 -0
- data/Appraisals +16 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +45 -0
- data/History.txt +488 -0
- data/LICENSE.txt +21 -0
- data/README.rdoc +214 -0
- data/Rakefile +62 -0
- data/activerecord-jdbc-adapter.gemspec +23 -0
- data/bench/bench_attributes.rb +13 -0
- data/bench/bench_attributes_new.rb +14 -0
- data/bench/bench_create.rb +12 -0
- data/bench/bench_find_all.rb +12 -0
- data/bench/bench_find_all_mt.rb +25 -0
- data/bench/bench_model.rb +85 -0
- data/bench/bench_new.rb +12 -0
- data/bench/bench_new_valid.rb +12 -0
- data/bench/bench_valid.rb +13 -0
- data/gemfiles/rails23.gemfile +10 -0
- data/gemfiles/rails23.gemfile.lock +38 -0
- data/gemfiles/rails30.gemfile +9 -0
- data/gemfiles/rails30.gemfile.lock +33 -0
- data/gemfiles/rails31.gemfile +9 -0
- data/gemfiles/rails31.gemfile.lock +35 -0
- data/gemfiles/rails32.gemfile +9 -0
- data/gemfiles/rails32.gemfile.lock +35 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +8 -0
- data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
- data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
- data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
- data/lib/arel/visitors/compat.rb +13 -0
- data/lib/arel/visitors/db2.rb +17 -0
- data/lib/arel/visitors/derby.rb +32 -0
- data/lib/arel/visitors/firebird.rb +24 -0
- data/lib/arel/visitors/hsqldb.rb +26 -0
- data/lib/arel/visitors/sql_server.rb +46 -0
- data/lib/arjdbc.rb +24 -0
- data/lib/arjdbc/db2.rb +2 -0
- data/lib/arjdbc/db2/adapter.rb +541 -0
- data/lib/arjdbc/derby.rb +7 -0
- data/lib/arjdbc/derby/adapter.rb +358 -0
- data/lib/arjdbc/derby/connection_methods.rb +19 -0
- data/lib/arjdbc/discover.rb +92 -0
- data/lib/arjdbc/firebird.rb +2 -0
- data/lib/arjdbc/firebird/adapter.rb +140 -0
- data/lib/arjdbc/h2.rb +4 -0
- data/lib/arjdbc/h2/adapter.rb +54 -0
- data/lib/arjdbc/h2/connection_methods.rb +13 -0
- data/lib/arjdbc/hsqldb.rb +4 -0
- data/lib/arjdbc/hsqldb/adapter.rb +184 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
- data/lib/arjdbc/informix.rb +3 -0
- data/lib/arjdbc/informix/adapter.rb +142 -0
- data/lib/arjdbc/informix/connection_methods.rb +11 -0
- data/lib/arjdbc/jdbc.rb +2 -0
- data/lib/arjdbc/jdbc/adapter.rb +356 -0
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/base_ext.rb +15 -0
- data/lib/arjdbc/jdbc/callbacks.rb +44 -0
- data/lib/arjdbc/jdbc/column.rb +47 -0
- data/lib/arjdbc/jdbc/compatibility.rb +51 -0
- data/lib/arjdbc/jdbc/connection.rb +134 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
- data/lib/arjdbc/jdbc/core_ext.rb +24 -0
- data/lib/arjdbc/jdbc/discover.rb +18 -0
- data/lib/arjdbc/jdbc/driver.rb +35 -0
- data/lib/arjdbc/jdbc/extension.rb +47 -0
- data/lib/arjdbc/jdbc/java.rb +14 -0
- data/lib/arjdbc/jdbc/jdbc.rake +131 -0
- data/lib/arjdbc/jdbc/missing_functionality_helper.rb +88 -0
- data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
- data/lib/arjdbc/jdbc/railtie.rb +9 -0
- data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
- data/lib/arjdbc/jdbc/require_driver.rb +16 -0
- data/lib/arjdbc/jdbc/type_converter.rb +126 -0
- data/lib/arjdbc/mimer.rb +2 -0
- data/lib/arjdbc/mimer/adapter.rb +142 -0
- data/lib/arjdbc/mssql.rb +4 -0
- data/lib/arjdbc/mssql/adapter.rb +477 -0
- data/lib/arjdbc/mssql/connection_methods.rb +31 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +101 -0
- data/lib/arjdbc/mssql/lock_helpers.rb +72 -0
- data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
- data/lib/arjdbc/mysql.rb +4 -0
- data/lib/arjdbc/mysql/adapter.rb +505 -0
- data/lib/arjdbc/mysql/connection_methods.rb +28 -0
- data/lib/arjdbc/oracle.rb +3 -0
- data/lib/arjdbc/oracle/adapter.rb +432 -0
- data/lib/arjdbc/oracle/connection_methods.rb +12 -0
- data/lib/arjdbc/postgresql.rb +4 -0
- data/lib/arjdbc/postgresql/adapter.rb +861 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
- data/lib/arjdbc/sqlite3.rb +4 -0
- data/lib/arjdbc/sqlite3/adapter.rb +389 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +46 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/generators/jdbc/USAGE +10 -0
- data/lib/generators/jdbc/jdbc_generator.rb +9 -0
- data/lib/jdbc_adapter.rb +2 -0
- data/lib/jdbc_adapter/rake_tasks.rb +3 -0
- data/lib/jdbc_adapter/version.rb +3 -0
- data/lib/pg.rb +26 -0
- data/pom.xml +57 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/compile.rake +23 -0
- data/rakelib/db.rake +39 -0
- data/rakelib/rails.rake +41 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +69 -0
- data/src/java/arjdbc/derby/DerbyModule.java +324 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1346 -0
- data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
- data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
- data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
- data/test/abstract_db_create.rb +135 -0
- data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
- data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
- data/test/activerecord/jall.sh +7 -0
- data/test/activerecord/jtest.sh +3 -0
- data/test/db/db2.rb +11 -0
- data/test/db/derby.rb +12 -0
- data/test/db/h2.rb +11 -0
- data/test/db/hsqldb.rb +13 -0
- data/test/db/informix.rb +11 -0
- data/test/db/jdbc.rb +12 -0
- data/test/db/jndi_config.rb +40 -0
- data/test/db/logger.rb +3 -0
- data/test/db/mssql.rb +9 -0
- data/test/db/mysql.rb +10 -0
- data/test/db/oracle.rb +34 -0
- data/test/db/postgres.rb +18 -0
- data/test/db/sqlite3.rb +11 -0
- data/test/db2_reset_column_information_test.rb +8 -0
- data/test/db2_simple_test.rb +66 -0
- data/test/derby_migration_test.rb +68 -0
- data/test/derby_multibyte_test.rb +12 -0
- data/test/derby_reset_column_information_test.rb +8 -0
- data/test/derby_row_locking_test.rb +9 -0
- data/test/derby_simple_test.rb +139 -0
- data/test/generic_jdbc_connection_test.rb +29 -0
- data/test/h2_change_column_test.rb +68 -0
- data/test/h2_simple_test.rb +41 -0
- data/test/has_many_through.rb +79 -0
- data/test/helper.rb +108 -0
- data/test/hsqldb_simple_test.rb +6 -0
- data/test/informix_simple_test.rb +48 -0
- data/test/jdbc_common.rb +28 -0
- data/test/jndi_callbacks_test.rb +36 -0
- data/test/jndi_test.rb +25 -0
- data/test/manualTestDatabase.rb +191 -0
- data/test/models/add_not_null_column_to_table.rb +9 -0
- data/test/models/auto_id.rb +15 -0
- data/test/models/custom_pk_name.rb +14 -0
- data/test/models/data_types.rb +30 -0
- data/test/models/entry.rb +40 -0
- data/test/models/mixed_case.rb +22 -0
- data/test/models/reserved_word.rb +15 -0
- data/test/models/string_id.rb +17 -0
- data/test/models/thing.rb +16 -0
- data/test/models/validates_uniqueness_of_string.rb +19 -0
- data/test/mssql_db_create_test.rb +26 -0
- data/test/mssql_identity_insert_test.rb +19 -0
- data/test/mssql_ignore_system_views_test.rb +27 -0
- data/test/mssql_legacy_types_test.rb +58 -0
- data/test/mssql_limit_offset_test.rb +136 -0
- data/test/mssql_multibyte_test.rb +18 -0
- data/test/mssql_null_test.rb +14 -0
- data/test/mssql_reset_column_information_test.rb +8 -0
- data/test/mssql_row_locking_sql_test.rb +159 -0
- data/test/mssql_row_locking_test.rb +9 -0
- data/test/mssql_simple_test.rb +55 -0
- data/test/mysql_db_create_test.rb +27 -0
- data/test/mysql_index_length_test.rb +58 -0
- data/test/mysql_info_test.rb +123 -0
- data/test/mysql_multibyte_test.rb +10 -0
- data/test/mysql_nonstandard_primary_key_test.rb +42 -0
- data/test/mysql_reset_column_information_test.rb +8 -0
- data/test/mysql_simple_test.rb +125 -0
- data/test/oracle_reset_column_information_test.rb +8 -0
- data/test/oracle_simple_test.rb +18 -0
- data/test/oracle_specific_test.rb +83 -0
- data/test/postgres_db_create_test.rb +32 -0
- data/test/postgres_drop_db_test.rb +16 -0
- data/test/postgres_information_schema_leak_test.rb +29 -0
- data/test/postgres_mixed_case_test.rb +29 -0
- data/test/postgres_native_type_mapping_test.rb +93 -0
- data/test/postgres_nonseq_pkey_test.rb +38 -0
- data/test/postgres_reserved_test.rb +22 -0
- data/test/postgres_reset_column_information_test.rb +8 -0
- data/test/postgres_schema_search_path_test.rb +48 -0
- data/test/postgres_simple_test.rb +168 -0
- data/test/postgres_table_alias_length_test.rb +15 -0
- data/test/postgres_type_conversion_test.rb +34 -0
- data/test/row_locking.rb +90 -0
- data/test/simple.rb +731 -0
- data/test/sqlite3_reset_column_information_test.rb +8 -0
- data/test/sqlite3_simple_test.rb +316 -0
- data/test/sybase_jtds_simple_test.rb +28 -0
- data/test/sybase_reset_column_information_test.rb +8 -0
- metadata +288 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'jdbc_common'
|
|
2
|
+
require 'db/postgres'
|
|
3
|
+
|
|
4
|
+
class PostgresTableAliasLengthTest < Test::Unit::TestCase
|
|
5
|
+
def test_table_alias_length
|
|
6
|
+
result = ActiveRecord::Base.connection.select_one("SELECT 1 AS " + "a" * 2048)
|
|
7
|
+
|
|
8
|
+
actual_table_alias_length = result.keys.first.size
|
|
9
|
+
actual_table_alias_length = 0 if actual_table_alias_length == 2048
|
|
10
|
+
|
|
11
|
+
assert_equal(actual_table_alias_length,
|
|
12
|
+
ActiveRecord::Base.connection.table_alias_length)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'jdbc_common'
|
|
2
|
+
require 'db/postgres'
|
|
3
|
+
|
|
4
|
+
class BooleanSchema < ActiveRecord::Migration
|
|
5
|
+
def self.up
|
|
6
|
+
create_table :booleans do |t|
|
|
7
|
+
t.boolean :value, :default => false, :null => false
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.down
|
|
12
|
+
drop_table :booleans
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Boolean < ActiveRecord::Base
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class PostgresTypeConversionTest < Test::Unit::TestCase
|
|
20
|
+
def setup
|
|
21
|
+
BooleanSchema.up
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def teardown
|
|
25
|
+
BooleanSchema.down
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_should_handle_bool_conversion_with_boolean_relation
|
|
29
|
+
assert_nothing_raised do
|
|
30
|
+
ActiveRecord::Base.connection.raw_connection.set_native_database_types
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
data/test/row_locking.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#! /usr/bin/env jruby
|
|
2
|
+
|
|
3
|
+
require 'thread'
|
|
4
|
+
|
|
5
|
+
module RowLockingTestMethods
|
|
6
|
+
|
|
7
|
+
def test_row_locking
|
|
8
|
+
row_locking_test_template
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_row_locking_with_limit
|
|
12
|
+
row_locking_test_template(:limit => 1)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def row_locking_test_template(options={})
|
|
18
|
+
# Create two rows that we will work with
|
|
19
|
+
@row1_id = Entry.create!(:title => "row1").id
|
|
20
|
+
@row2_id = Entry.create!(:title => "row2").id
|
|
21
|
+
|
|
22
|
+
@result_queue = Queue.new
|
|
23
|
+
signal_queue = Queue.new
|
|
24
|
+
t1 = Thread.new { thread_helper { thread1_main(signal_queue, options) } }
|
|
25
|
+
t2 = Thread.new { thread_helper { thread2_main(signal_queue, options) } }
|
|
26
|
+
t1.join
|
|
27
|
+
t2.join
|
|
28
|
+
|
|
29
|
+
result = []
|
|
30
|
+
result << @result_queue.shift until @result_queue.empty? # Convert the queue into an array
|
|
31
|
+
|
|
32
|
+
expected = [
|
|
33
|
+
:t1_locking_row2,
|
|
34
|
+
:t1_locked_row2,
|
|
35
|
+
|
|
36
|
+
:t2_locking_row1,
|
|
37
|
+
:t2_locked_row1,
|
|
38
|
+
|
|
39
|
+
:t2_locking_row2, # thread 2 tries to lock row2 ...
|
|
40
|
+
:t1_committed,
|
|
41
|
+
:t2_locked_row2, # ... but it doesn't succeed until after thread 1 commits its transaction
|
|
42
|
+
|
|
43
|
+
:t2_committed,
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
assert_equal expected, result, "thread2 should lock row1 immediately but wait for thread1 to commit before getting the lock on row2"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def thread1_main(signal_queue, options={})
|
|
50
|
+
Entry.transaction do
|
|
51
|
+
@result_queue << :t1_locking_row2
|
|
52
|
+
Entry.find(@row2_id, {:lock=>true}.merge(options)) # acquire a row lock on r2
|
|
53
|
+
@result_queue << :t1_locked_row2
|
|
54
|
+
signal_queue << :go # signal thread2 to start
|
|
55
|
+
sleep 2.0 # Wait for a few seconds, to allow the other thread to race with this thread.
|
|
56
|
+
@result_queue << :t1_committed
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def thread2_main(signal_queue, options={})
|
|
61
|
+
Entry.transaction do
|
|
62
|
+
signal_queue.shift # wait until we get the signal from thread1
|
|
63
|
+
@result_queue << :t2_locking_row1
|
|
64
|
+
Entry.find(@row1_id, {:lock=>true}.merge(options)) # should return immediately
|
|
65
|
+
@result_queue << :t2_locked_row1
|
|
66
|
+
@result_queue << :t2_locking_row2
|
|
67
|
+
Entry.find(@row2_id, {:lock=>true}.merge(options)) # should block until thread1 commits its transaction
|
|
68
|
+
@result_queue << :t2_locked_row2
|
|
69
|
+
@result_queue << :t2_committed
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def thread_helper
|
|
74
|
+
yield
|
|
75
|
+
rescue Exception => exc
|
|
76
|
+
# Output backtrace, since otherwise we won't see anything until the main thread joins this thread.
|
|
77
|
+
display_exception(exc)
|
|
78
|
+
raise
|
|
79
|
+
ensure
|
|
80
|
+
# This is needed. Otherwise, the database connections aren't returned to the pool and things break.
|
|
81
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def display_exception(exception)
|
|
85
|
+
lines = []
|
|
86
|
+
lines << "#{exception.class.name}: #{exception.message}\n"
|
|
87
|
+
lines += exception.backtrace.map{|line| "\tfrom #{line}"}
|
|
88
|
+
$stderr.puts lines.join("\n")
|
|
89
|
+
end
|
|
90
|
+
end
|
data/test/simple.rb
ADDED
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
ActiveRecord::Schema.verbose = false
|
|
3
|
+
ActiveRecord::Base.time_zone_aware_attributes = true if ActiveRecord::Base.respond_to?(:time_zone_aware_attributes)
|
|
4
|
+
ActiveRecord::Base.default_timezone = :utc
|
|
5
|
+
#just a random zone, unlikely to be local, and not utc
|
|
6
|
+
Time.zone = 'Moscow' if Time.respond_to?(:zone)
|
|
7
|
+
|
|
8
|
+
module MigrationSetup
|
|
9
|
+
def setup
|
|
10
|
+
DbTypeMigration.up
|
|
11
|
+
CreateStringIds.up
|
|
12
|
+
CreateEntries.up
|
|
13
|
+
CreateUsers.up
|
|
14
|
+
CreateAutoIds.up
|
|
15
|
+
CreateValidatesUniquenessOf.up
|
|
16
|
+
CreateThings.up
|
|
17
|
+
CreateCustomPkName.up
|
|
18
|
+
@connection = ActiveRecord::Base.connection
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def teardown
|
|
22
|
+
DbTypeMigration.down
|
|
23
|
+
CreateStringIds.down
|
|
24
|
+
CreateEntries.down
|
|
25
|
+
CreateUsers.down
|
|
26
|
+
CreateAutoIds.down
|
|
27
|
+
CreateValidatesUniquenessOf.down
|
|
28
|
+
CreateThings.down
|
|
29
|
+
CreateCustomPkName.down
|
|
30
|
+
ActiveRecord::Base.clear_active_connections!
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
module FixtureSetup
|
|
35
|
+
include MigrationSetup
|
|
36
|
+
def setup
|
|
37
|
+
super
|
|
38
|
+
@title = "First post!"
|
|
39
|
+
@content = "Hello from JRuby on Rails!"
|
|
40
|
+
@new_title = "First post updated title"
|
|
41
|
+
@rating = 205.76
|
|
42
|
+
@user = User.create :login=>"something"
|
|
43
|
+
@entry = Entry.create :title => @title, :content => @content, :rating => @rating, :user=>@user
|
|
44
|
+
DbType.create
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module ColumnNameQuotingTests
|
|
49
|
+
def self.included(base)
|
|
50
|
+
base.class_eval do
|
|
51
|
+
@@column_quote_char = "\""
|
|
52
|
+
|
|
53
|
+
def self.column_quote_char(char)
|
|
54
|
+
@@column_quote_char = char
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_column_names_are_escaped
|
|
60
|
+
conn = ActiveRecord::Base.connection
|
|
61
|
+
quoted = conn.quote_column_name "foo#{column_quote_char}bar"
|
|
62
|
+
assert_equal "#{column_quote_char}foo#{column_quote_char * 2}bar#{column_quote_char}", quoted
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
def column_quote_char
|
|
67
|
+
@@column_quote_char || "\""
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module DirtyAttributeTests
|
|
72
|
+
def test_partial_update
|
|
73
|
+
entry = Entry.new(:title => 'foo')
|
|
74
|
+
old_updated_on = 1.hour.ago.beginning_of_day
|
|
75
|
+
|
|
76
|
+
with_partial_updates Entry, false do
|
|
77
|
+
assert_queries(2) { 2.times { entry.save! } }
|
|
78
|
+
Entry.update_all({ :updated_on => old_updated_on }, :id => entry.id)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
with_partial_updates Entry, true do
|
|
82
|
+
assert_queries(0) { 2.times { entry.save! } }
|
|
83
|
+
assert_equal old_updated_on, entry.reload.updated_on
|
|
84
|
+
|
|
85
|
+
assert_queries(1) { entry.title = 'bar'; entry.save! }
|
|
86
|
+
assert_not_equal old_updated_on, entry.reload.updated_on
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
def with_partial_updates(klass, on = true)
|
|
92
|
+
old = klass.partial_updates?
|
|
93
|
+
klass.partial_updates = on
|
|
94
|
+
yield
|
|
95
|
+
ensure
|
|
96
|
+
klass.partial_updates = old
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
module SimpleTestMethods
|
|
101
|
+
include FixtureSetup
|
|
102
|
+
|
|
103
|
+
def test_substitute_binds_has_no_side_effect_on_binds_parameter
|
|
104
|
+
binds = [[Entry.columns_hash['title'], 'test1']]
|
|
105
|
+
binds2 = binds.dup
|
|
106
|
+
sql = 'select * from entries where title = ?'
|
|
107
|
+
Entry.connection.substitute_binds(sql, binds)
|
|
108
|
+
assert_equal binds2, binds
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_entries_created
|
|
112
|
+
assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^entries$/i}, "entries not created"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_users_created
|
|
116
|
+
assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^users$/i}, "users not created"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_entries_empty
|
|
120
|
+
Entry.delete_all
|
|
121
|
+
assert_equal 0, Entry.count
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_find_with_string_slug
|
|
125
|
+
new_entry = Entry.create(:title => "Blah")
|
|
126
|
+
entry = Entry.find(new_entry.to_param)
|
|
127
|
+
assert_equal new_entry.id, entry.id
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_insert_returns_id
|
|
131
|
+
unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
|
|
132
|
+
value = ActiveRecord::Base.connection.insert("INSERT INTO entries (title, content, rating) VALUES('insert_title', 'some content', 1)")
|
|
133
|
+
assert !value.nil?
|
|
134
|
+
entry = Entry.find_by_title('insert_title')
|
|
135
|
+
assert_equal entry.id, value
|
|
136
|
+
|
|
137
|
+
# Ensure we get the id even if the PK column is not named 'id'
|
|
138
|
+
1.upto(4) do |i|
|
|
139
|
+
cpn_name = "return id test#{i}"
|
|
140
|
+
cpn = CustomPkName.new
|
|
141
|
+
cpn.name = cpn_name
|
|
142
|
+
cpn.save
|
|
143
|
+
value = cpn.custom_id
|
|
144
|
+
assert !value.nil?
|
|
145
|
+
cpn = CustomPkName.find_by_name(cpn_name)
|
|
146
|
+
assert_equal cpn.custom_id, value
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_create_new_entry
|
|
152
|
+
Entry.delete_all
|
|
153
|
+
|
|
154
|
+
post = Entry.new
|
|
155
|
+
post.title = @title
|
|
156
|
+
post.content = @content
|
|
157
|
+
post.rating = @rating
|
|
158
|
+
post.save
|
|
159
|
+
|
|
160
|
+
assert_equal 1, Entry.count
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def test_create_partial_new_entry
|
|
164
|
+
new_entry = Entry.create(:title => "Blah")
|
|
165
|
+
new_entry2 = Entry.create(:title => "Bloh")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_find_and_update_entry
|
|
169
|
+
post = Entry.find(:first)
|
|
170
|
+
assert_equal @title, post.title
|
|
171
|
+
assert_equal @content, post.content
|
|
172
|
+
assert_equal @rating, post.rating
|
|
173
|
+
|
|
174
|
+
post.title = @new_title
|
|
175
|
+
post.save
|
|
176
|
+
|
|
177
|
+
post = Entry.find(:first)
|
|
178
|
+
assert_equal @new_title, post.title
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def test_destroy_entry
|
|
182
|
+
prev_count = Entry.count
|
|
183
|
+
post = Entry.find(:first)
|
|
184
|
+
post.destroy
|
|
185
|
+
|
|
186
|
+
assert_equal prev_count - 1, Entry.count
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
if Entry.respond_to?(:limit)
|
|
190
|
+
def test_limit
|
|
191
|
+
Entry.limit(10).to_a
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_count_with_limit
|
|
195
|
+
assert_equal Entry.count, Entry.limit(10).count
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
if Time.respond_to?(:zone)
|
|
200
|
+
def test_save_time_with_utc
|
|
201
|
+
current_zone = Time.zone
|
|
202
|
+
default_zone = ActiveRecord::Base.default_timezone
|
|
203
|
+
ActiveRecord::Base.default_timezone = Time.zone = :utc
|
|
204
|
+
now = Time.now
|
|
205
|
+
my_time = Time.local now.year, now.month, now.day, now.hour, now.min, now.sec
|
|
206
|
+
m = DbType.create! :sample_datetime => my_time
|
|
207
|
+
m.reload
|
|
208
|
+
assert_equal my_time, m.sample_datetime
|
|
209
|
+
rescue
|
|
210
|
+
Time.zone = current_zone
|
|
211
|
+
ActiveRecord::Base.default_timezone = default_zone
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def test_save_time
|
|
215
|
+
t = Time.now
|
|
216
|
+
#precision will only be expected to the second.
|
|
217
|
+
time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
|
|
218
|
+
e = DbType.find(:first)
|
|
219
|
+
e.sample_datetime = time
|
|
220
|
+
e.save!
|
|
221
|
+
e = DbType.find(:first)
|
|
222
|
+
assert_equal time.in_time_zone, e.sample_datetime
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def test_save_date_time
|
|
226
|
+
t = Time.now
|
|
227
|
+
#precision will only be expected to the second.
|
|
228
|
+
time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
|
|
229
|
+
datetime = time.to_datetime
|
|
230
|
+
e = DbType.find(:first)
|
|
231
|
+
e.sample_datetime = datetime
|
|
232
|
+
e.save!
|
|
233
|
+
e = DbType.find(:first)
|
|
234
|
+
assert_equal time, e.sample_datetime.localtime
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def test_save_time_with_zone
|
|
238
|
+
t = Time.now
|
|
239
|
+
#precision will only be expected to the second.
|
|
240
|
+
original_time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
|
|
241
|
+
time = original_time.in_time_zone
|
|
242
|
+
e = DbType.find(:first)
|
|
243
|
+
e.sample_datetime = time
|
|
244
|
+
e.save!
|
|
245
|
+
e = DbType.find(:first)
|
|
246
|
+
assert_equal time, e.sample_datetime
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def test_save_float
|
|
251
|
+
e = DbType.find(:first)
|
|
252
|
+
e.sample_float = 12.0
|
|
253
|
+
e.save!
|
|
254
|
+
|
|
255
|
+
e = DbType.find(:first)
|
|
256
|
+
assert_equal(12.0, e.sample_float)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def test_save_date
|
|
260
|
+
date = Date.new(2007)
|
|
261
|
+
e = DbType.find(:first)
|
|
262
|
+
e.sample_date = date
|
|
263
|
+
e.save!
|
|
264
|
+
e = DbType.find(:first)
|
|
265
|
+
if DbType.columns_hash["sample_date"].type == :datetime
|
|
266
|
+
# Oracle doesn't distinguish btw date/datetime
|
|
267
|
+
assert_equal date, e.sample_date.to_date
|
|
268
|
+
else
|
|
269
|
+
assert_equal date, e.sample_date
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def test_boolean
|
|
274
|
+
# An unset boolean should default to nil
|
|
275
|
+
e = DbType.find(:first)
|
|
276
|
+
assert_equal(nil, e.sample_boolean)
|
|
277
|
+
|
|
278
|
+
e.sample_boolean = true
|
|
279
|
+
e.save!
|
|
280
|
+
|
|
281
|
+
e = DbType.find(:first)
|
|
282
|
+
assert_equal(true, e.sample_boolean)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def test_integer
|
|
286
|
+
# An unset boolean should default to nil
|
|
287
|
+
e = DbType.find(:first)
|
|
288
|
+
assert_equal(nil, e.sample_integer)
|
|
289
|
+
|
|
290
|
+
e.sample_integer = 10
|
|
291
|
+
e.save!
|
|
292
|
+
|
|
293
|
+
e = DbType.find(:first)
|
|
294
|
+
assert_equal(10, e.sample_integer)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def test_text
|
|
298
|
+
# An unset boolean should default to nil
|
|
299
|
+
e = DbType.find(:first)
|
|
300
|
+
|
|
301
|
+
# Oracle adapter initializes all CLOB fields with empty_clob() function,
|
|
302
|
+
# so they all have a initial value of an empty string ''
|
|
303
|
+
assert_equal(nil, e.sample_text) unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
|
|
304
|
+
|
|
305
|
+
e.sample_text = "ooop?"
|
|
306
|
+
e.save!
|
|
307
|
+
|
|
308
|
+
e = DbType.find(:first)
|
|
309
|
+
assert_equal("ooop?", e.sample_text)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def test_string
|
|
313
|
+
e = DbType.find(:first)
|
|
314
|
+
|
|
315
|
+
# An empty string is treated as a null value in Oracle: http://www.techonthenet.com/oracle/questions/empty_null.php
|
|
316
|
+
assert_equal('', e.sample_string) unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
|
|
317
|
+
e.sample_string = "ooop?"
|
|
318
|
+
e.save!
|
|
319
|
+
|
|
320
|
+
e = DbType.find(:first)
|
|
321
|
+
assert_equal("ooop?", e.sample_string)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def test_save_binary
|
|
325
|
+
#string is 60_000 bytes
|
|
326
|
+
binary_string = "\000ABCDEFGHIJKLMNOPQRSTUVWXYZ'\001\003"*1#2_000
|
|
327
|
+
e = DbType.find(:first)
|
|
328
|
+
e.sample_binary = binary_string
|
|
329
|
+
e.save!
|
|
330
|
+
e = DbType.find(:first)
|
|
331
|
+
assert_equal binary_string, e.sample_binary
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def test_default_decimal_should_keep_fractional_part
|
|
335
|
+
expected = 7.3
|
|
336
|
+
db_type = DbType.new(:sample_small_decimal => expected)
|
|
337
|
+
assert db_type.save
|
|
338
|
+
db_type = DbType.find(db_type.id)
|
|
339
|
+
assert_equal BigDecimal.new(expected.to_s), db_type.sample_small_decimal
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def test_decimal_with_scale
|
|
343
|
+
test_value = 7.3
|
|
344
|
+
db_type = DbType.new(:sample_small_decimal => test_value)
|
|
345
|
+
assert db_type.save
|
|
346
|
+
db_type = DbType.find(db_type.id)
|
|
347
|
+
assert_kind_of BigDecimal, db_type.sample_small_decimal
|
|
348
|
+
assert_equal BigDecimal.new(test_value.to_s), db_type.sample_small_decimal
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def test_decimal_with_zero_scale
|
|
352
|
+
test_value = 7000.0
|
|
353
|
+
db_type = DbType.new(:sample_decimal => test_value)
|
|
354
|
+
assert db_type.save
|
|
355
|
+
db_type = DbType.find(db_type.id)
|
|
356
|
+
assert_kind_of Integer, db_type.sample_decimal
|
|
357
|
+
assert_equal test_value.to_i, db_type.sample_decimal
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def test_negative_default_value
|
|
361
|
+
assert_equal(-1, DbType.columns_hash['sample_integer_neg_default'].default)
|
|
362
|
+
assert_equal(-1, DbType.new.sample_integer_neg_default)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def test_indexes
|
|
366
|
+
# Only test indexes if we have implemented it for the particular adapter
|
|
367
|
+
if @connection.respond_to?(:indexes)
|
|
368
|
+
indexes = @connection.indexes(:entries)
|
|
369
|
+
assert_equal(0, indexes.size)
|
|
370
|
+
|
|
371
|
+
index_name = "entries_index"
|
|
372
|
+
@connection.add_index(:entries, :updated_on, :name => index_name)
|
|
373
|
+
|
|
374
|
+
indexes = @connection.indexes(:entries)
|
|
375
|
+
assert_equal(1, indexes.size)
|
|
376
|
+
assert_equal "entries", indexes.first.table.to_s
|
|
377
|
+
assert_equal index_name, indexes.first.name
|
|
378
|
+
assert !indexes.first.unique
|
|
379
|
+
assert_equal ["updated_on"], indexes.first.columns
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def test_remove_nonexistent_index
|
|
384
|
+
assert_raise(ArgumentError, ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
|
|
385
|
+
@connection.remove_index :entries, :nonexistent_index
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def test_add_index_with_invalid_name_length
|
|
390
|
+
index_name = 'x' * (@connection.index_name_length + 1)
|
|
391
|
+
assert_raise(ArgumentError) do
|
|
392
|
+
@connection.add_index "entries", "title", :name => index_name
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_dumping_schema
|
|
397
|
+
require 'active_record/schema_dumper'
|
|
398
|
+
@connection.add_index :entries, :title
|
|
399
|
+
StringIO.open do |io|
|
|
400
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, io)
|
|
401
|
+
assert_match(/add_index "entries",/, io.string)
|
|
402
|
+
end
|
|
403
|
+
@connection.remove_index :entries, :title
|
|
404
|
+
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def test_nil_values
|
|
408
|
+
test = AutoId.create('value' => '')
|
|
409
|
+
assert_nil AutoId.find(test.id).value
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# These should make no difference, but might due to the wacky regexp SQL rewriting we do.
|
|
413
|
+
def test_save_value_containing_sql
|
|
414
|
+
e = DbType.first
|
|
415
|
+
e.save
|
|
416
|
+
|
|
417
|
+
e.sample_string = e.sample_text = "\n\nselect from nothing where id = 'foo'"
|
|
418
|
+
e.save
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def test_invalid
|
|
422
|
+
e = Entry.new(:title => @title, :content => @content, :rating => ' ')
|
|
423
|
+
assert e.valid?
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def test_reconnect
|
|
427
|
+
assert_equal 1, Entry.count
|
|
428
|
+
@connection.reconnect!
|
|
429
|
+
assert_equal 1, Entry.count
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
if jruby?
|
|
433
|
+
def test_connection_valid
|
|
434
|
+
assert_raises(ActiveRecord::JDBCError) do
|
|
435
|
+
@connection.raw_connection.with_connection_retry_guard do |c|
|
|
436
|
+
begin
|
|
437
|
+
stmt = c.createStatement
|
|
438
|
+
stmt.execute "bogus sql"
|
|
439
|
+
ensure
|
|
440
|
+
stmt.close rescue nil
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
class Animal < ActiveRecord::Base; end
|
|
447
|
+
|
|
448
|
+
def test_fetching_columns_for_nonexistent_table_should_raise
|
|
449
|
+
assert_raises(ActiveRecord::ActiveRecordError,
|
|
450
|
+
ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
|
|
451
|
+
Animal.columns
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def test_disconnect
|
|
457
|
+
assert_equal 1, Entry.count
|
|
458
|
+
ActiveRecord::Base.clear_active_connections!
|
|
459
|
+
ActiveRecord::Base.connection_pool.disconnect! if ActiveRecord::Base.respond_to?(:connection_pool)
|
|
460
|
+
assert !ActiveRecord::Base.connected?
|
|
461
|
+
assert_equal 1, Entry.count
|
|
462
|
+
assert ActiveRecord::Base.connected?
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def test_add_not_null_column_to_table
|
|
466
|
+
AddNotNullColumnToTable.up
|
|
467
|
+
AddNotNullColumnToTable.down
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def test_add_null_column_with_default
|
|
471
|
+
Entry.connection.add_column :entries, :color, :string, :null => false, :default => "blue"
|
|
472
|
+
created_columns = Entry.connection.columns('entries')
|
|
473
|
+
|
|
474
|
+
color = created_columns.detect { |c| c.name == 'color' }
|
|
475
|
+
assert !color.null
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def test_add_null_column_with_no_default
|
|
479
|
+
# You must specify a default value with most databases
|
|
480
|
+
if ActiveRecord::Base.connection.adapter_name =~ /mysql/i
|
|
481
|
+
Entry.connection.add_column :entries, :color, :string, :null => false
|
|
482
|
+
created_columns = Entry.connection.columns('entries')
|
|
483
|
+
|
|
484
|
+
color = created_columns.detect { |c| c.name == 'color' }
|
|
485
|
+
assert !color.null
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
def test_add_null_column_with_nil_default
|
|
490
|
+
# You must specify a default value with most databases
|
|
491
|
+
if ActiveRecord::Base.connection.adapter_name =~ /mysql/i
|
|
492
|
+
Entry.connection.add_column :entries, :color, :string, :null => false, :default => nil
|
|
493
|
+
created_columns = Entry.connection.columns('entries')
|
|
494
|
+
|
|
495
|
+
color = created_columns.detect { |c| c.name == 'color' }
|
|
496
|
+
assert !color.null
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def test_validates_uniqueness_of_strings_case_sensitive
|
|
501
|
+
name_lower = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '1')
|
|
502
|
+
name_lower.save!
|
|
503
|
+
|
|
504
|
+
name_upper = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '2')
|
|
505
|
+
assert_nothing_raised do
|
|
506
|
+
name_upper.save!
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '3')
|
|
510
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
511
|
+
name_lower_collision.save!
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '4')
|
|
515
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
516
|
+
name_upper_collision.save!
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def test_validates_uniqueness_of_strings_case_insensitive
|
|
521
|
+
name_lower = ValidatesUniquenessOfString.new(:cs_string => '1', :ci_string => "name")
|
|
522
|
+
name_lower.save!
|
|
523
|
+
|
|
524
|
+
name_upper = ValidatesUniquenessOfString.new(:cs_string => '2', :ci_string => "NAME")
|
|
525
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
526
|
+
name_upper.save!
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => '3', :ci_string => "name")
|
|
530
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
531
|
+
name_lower_collision.save!
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
alternate_name_upper = ValidatesUniquenessOfString.new(:cs_string => '4', :ci_string => "ALTERNATE_NAME")
|
|
535
|
+
assert_nothing_raised do
|
|
536
|
+
alternate_name_upper.save!
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
alternate_name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => '5', :ci_string => "ALTERNATE_NAME")
|
|
540
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
541
|
+
alternate_name_upper_collision.save!
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
alternate_name_lower = ValidatesUniquenessOfString.new(:cs_string => '6', :ci_string => "alternate_name")
|
|
545
|
+
assert_raise ActiveRecord::RecordInvalid do
|
|
546
|
+
alternate_name_lower.save!
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
class ChangeEntriesTable < ActiveRecord::Migration
|
|
551
|
+
def self.up
|
|
552
|
+
change_table :entries do |t|
|
|
553
|
+
t.string :author
|
|
554
|
+
end if respond_to?(:change_table)
|
|
555
|
+
end
|
|
556
|
+
def self.down
|
|
557
|
+
change_table :entries do |t|
|
|
558
|
+
t.remove :author
|
|
559
|
+
end if respond_to?(:change_table)
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
def test_change_table
|
|
563
|
+
ChangeEntriesTable.up
|
|
564
|
+
ChangeEntriesTable.down
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def test_string_id
|
|
568
|
+
f = StringId.new
|
|
569
|
+
f.id = "some_string"
|
|
570
|
+
f.save
|
|
571
|
+
f = StringId.first #reload is essential
|
|
572
|
+
assert_equal "some_string", f.id
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def test_model_with_no_id
|
|
576
|
+
assert_nothing_raised do
|
|
577
|
+
Thing.create! :name => "a thing"
|
|
578
|
+
end
|
|
579
|
+
assert_equal 1, Thing.find(:all).size
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
module MultibyteTestMethods
|
|
584
|
+
include MigrationSetup
|
|
585
|
+
|
|
586
|
+
if defined?(JRUBY_VERSION)
|
|
587
|
+
def setup
|
|
588
|
+
super
|
|
589
|
+
config = ActiveRecord::Base.connection.config
|
|
590
|
+
@jdbc_driver = ActiveRecord::ConnectionAdapters::JdbcDriver.new(config[:driver])
|
|
591
|
+
@java_con = @jdbc_driver.connection(config[:url], config[:username], config[:password])
|
|
592
|
+
@java_con.setAutoCommit(true)
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def teardown
|
|
596
|
+
@java_con.close
|
|
597
|
+
@jdbc_driver = nil
|
|
598
|
+
super
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def test_select_multibyte_string
|
|
602
|
+
@java_con.createStatement().execute("insert into entries (id, title, content) values (1, 'テスト', '本文')")
|
|
603
|
+
entry = Entry.find(:first)
|
|
604
|
+
assert_equal "テスト", entry.title
|
|
605
|
+
assert_equal "本文", entry.content
|
|
606
|
+
assert_equal entry, Entry.find_by_title("テスト")
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
def test_update_multibyte_string
|
|
610
|
+
Entry.create!(:title => "テスト", :content => "本文")
|
|
611
|
+
rs = @java_con.createStatement().executeQuery("select title, content from entries")
|
|
612
|
+
assert rs.next
|
|
613
|
+
assert_equal "テスト", rs.getString(1)
|
|
614
|
+
assert_equal "本文", rs.getString(2)
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
def test_multibyte_aliasing
|
|
619
|
+
str = "テスト"
|
|
620
|
+
quoted_alias = Entry.connection.quote_column_name(str)
|
|
621
|
+
sql = "SELECT title AS #{quoted_alias} from entries"
|
|
622
|
+
records = Entry.connection.select_all(sql)
|
|
623
|
+
records.each do |rec|
|
|
624
|
+
rec.keys.each do |key|
|
|
625
|
+
assert_equal str, key
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
def test_chinese_word
|
|
631
|
+
chinese_word = '中文'
|
|
632
|
+
new_entry = Entry.create(:title => chinese_word)
|
|
633
|
+
new_entry.reload
|
|
634
|
+
assert_equal chinese_word, new_entry.title
|
|
635
|
+
end
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
module NonUTF8EncodingMethods
|
|
639
|
+
def setup
|
|
640
|
+
@connection = ActiveRecord::Base.remove_connection
|
|
641
|
+
latin2_connection = @connection.dup
|
|
642
|
+
latin2_connection[:encoding] = 'latin2'
|
|
643
|
+
latin2_connection.delete(:url) # pre-gen url gets stashed; remove to re-gen
|
|
644
|
+
ActiveRecord::Base.establish_connection latin2_connection
|
|
645
|
+
CreateEntries.up
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def teardown
|
|
649
|
+
CreateEntries.down
|
|
650
|
+
ActiveRecord::Base.establish_connection @connection
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
def test_nonutf8_encoding_in_entry
|
|
654
|
+
prague_district = 'hradčany'
|
|
655
|
+
new_entry = Entry.create :title => prague_district
|
|
656
|
+
new_entry.reload
|
|
657
|
+
assert_equal prague_district, new_entry.title
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
module ActiveRecord3TestMethods
|
|
662
|
+
def self.included(base)
|
|
663
|
+
base.send :include, Tests if ActiveRecord::VERSION::MAJOR == 3
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
module Tests
|
|
667
|
+
if ActiveRecord::VERSION::MINOR == 2
|
|
668
|
+
def test_visitor_accessor
|
|
669
|
+
adapter = Entry.connection
|
|
670
|
+
expected_visitors = adapter.config[:adapter_spec].
|
|
671
|
+
arel2_visitors(adapter).values
|
|
672
|
+
assert !adapter.visitor.nil?
|
|
673
|
+
assert expected_visitors.include?(adapter.visitor.class)
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
def test_where
|
|
678
|
+
entries = Entry.where(:title => @entry.title)
|
|
679
|
+
assert_equal @entry, entries.first
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
module ResetColumnInformationTestMethods
|
|
685
|
+
class Fhqwhgad < ActiveRecord::Base
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
def test_reset_column_information
|
|
689
|
+
drop_fhqwhgads_table!
|
|
690
|
+
create_fhqwhgads_table_1!
|
|
691
|
+
Fhqwhgad.reset_column_information
|
|
692
|
+
assert_equal ["id", "come_on"].sort, Fhqwhgad.columns.map{|c| c.name}.sort, "columns should be correct the first time"
|
|
693
|
+
|
|
694
|
+
drop_fhqwhgads_table!
|
|
695
|
+
create_fhqwhgads_table_2!
|
|
696
|
+
Fhqwhgad.reset_column_information
|
|
697
|
+
assert_equal ["id", "to_the_limit"].sort, Fhqwhgad.columns.map{|c| c.name}.sort, "columns should be correct the second time"
|
|
698
|
+
ensure
|
|
699
|
+
drop_fhqwhgads_table!
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
private
|
|
703
|
+
|
|
704
|
+
def drop_fhqwhgads_table!
|
|
705
|
+
ActiveRecord::Schema.define do
|
|
706
|
+
suppress_messages do
|
|
707
|
+
drop_table :fhqwhgads if table_exists? :fhqwhgads
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def create_fhqwhgads_table_1!
|
|
713
|
+
ActiveRecord::Schema.define do
|
|
714
|
+
suppress_messages do
|
|
715
|
+
create_table :fhqwhgads do |t|
|
|
716
|
+
t.string :come_on
|
|
717
|
+
end
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
def create_fhqwhgads_table_2!
|
|
723
|
+
ActiveRecord::Schema.define do
|
|
724
|
+
suppress_messages do
|
|
725
|
+
create_table :fhqwhgads do |t|
|
|
726
|
+
t.string :to_the_limit, :null=>false, :default=>'everybody'
|
|
727
|
+
end
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
end
|