cmoran92-activerecord-jdbc-adapter 1.2.1

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.
Files changed (202) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +8 -0
  3. data/Gemfile +14 -0
  4. data/Gemfile.lock +42 -0
  5. data/History.txt +469 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.rdoc +199 -0
  8. data/Rakefile +60 -0
  9. data/activerecord-jdbc-adapter.gemspec +23 -0
  10. data/bench/bench_attributes.rb +13 -0
  11. data/bench/bench_attributes_new.rb +14 -0
  12. data/bench/bench_create.rb +12 -0
  13. data/bench/bench_find_all.rb +12 -0
  14. data/bench/bench_find_all_mt.rb +25 -0
  15. data/bench/bench_model.rb +85 -0
  16. data/bench/bench_new.rb +12 -0
  17. data/bench/bench_new_valid.rb +12 -0
  18. data/bench/bench_valid.rb +13 -0
  19. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  31. data/lib/activerecord-jdbc-adapter.rb +8 -0
  32. data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
  33. data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
  34. data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
  35. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
  36. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
  37. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
  38. data/lib/arel/visitors/compat.rb +13 -0
  39. data/lib/arel/visitors/db2.rb +17 -0
  40. data/lib/arel/visitors/derby.rb +25 -0
  41. data/lib/arel/visitors/firebird.rb +24 -0
  42. data/lib/arel/visitors/hsqldb.rb +26 -0
  43. data/lib/arel/visitors/sql_server.rb +44 -0
  44. data/lib/arjdbc.rb +24 -0
  45. data/lib/arjdbc/db2.rb +2 -0
  46. data/lib/arjdbc/db2/adapter.rb +510 -0
  47. data/lib/arjdbc/derby.rb +7 -0
  48. data/lib/arjdbc/derby/adapter.rb +351 -0
  49. data/lib/arjdbc/derby/connection_methods.rb +19 -0
  50. data/lib/arjdbc/discover.rb +92 -0
  51. data/lib/arjdbc/firebird.rb +2 -0
  52. data/lib/arjdbc/firebird/adapter.rb +136 -0
  53. data/lib/arjdbc/h2.rb +4 -0
  54. data/lib/arjdbc/h2/adapter.rb +54 -0
  55. data/lib/arjdbc/h2/connection_methods.rb +13 -0
  56. data/lib/arjdbc/hsqldb.rb +4 -0
  57. data/lib/arjdbc/hsqldb/adapter.rb +184 -0
  58. data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
  59. data/lib/arjdbc/informix.rb +3 -0
  60. data/lib/arjdbc/informix/adapter.rb +138 -0
  61. data/lib/arjdbc/informix/connection_methods.rb +11 -0
  62. data/lib/arjdbc/jdbc.rb +2 -0
  63. data/lib/arjdbc/jdbc/adapter.rb +354 -0
  64. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  65. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  66. data/lib/arjdbc/jdbc/column.rb +47 -0
  67. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  68. data/lib/arjdbc/jdbc/connection.rb +134 -0
  69. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  70. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  71. data/lib/arjdbc/jdbc/discover.rb +18 -0
  72. data/lib/arjdbc/jdbc/driver.rb +35 -0
  73. data/lib/arjdbc/jdbc/extension.rb +47 -0
  74. data/lib/arjdbc/jdbc/java.rb +14 -0
  75. data/lib/arjdbc/jdbc/jdbc.rake +131 -0
  76. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +87 -0
  77. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  78. data/lib/arjdbc/jdbc/railtie.rb +9 -0
  79. data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
  80. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  81. data/lib/arjdbc/jdbc/type_converter.rb +126 -0
  82. data/lib/arjdbc/mimer.rb +2 -0
  83. data/lib/arjdbc/mimer/adapter.rb +142 -0
  84. data/lib/arjdbc/mssql.rb +4 -0
  85. data/lib/arjdbc/mssql/adapter.rb +468 -0
  86. data/lib/arjdbc/mssql/connection_methods.rb +31 -0
  87. data/lib/arjdbc/mssql/limit_helpers.rb +108 -0
  88. data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
  89. data/lib/arjdbc/mysql.rb +4 -0
  90. data/lib/arjdbc/mysql/adapter.rb +505 -0
  91. data/lib/arjdbc/mysql/connection_methods.rb +28 -0
  92. data/lib/arjdbc/oracle.rb +3 -0
  93. data/lib/arjdbc/oracle/adapter.rb +428 -0
  94. data/lib/arjdbc/oracle/connection_methods.rb +12 -0
  95. data/lib/arjdbc/postgresql.rb +4 -0
  96. data/lib/arjdbc/postgresql/adapter.rb +825 -0
  97. data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
  98. data/lib/arjdbc/sqlite3.rb +4 -0
  99. data/lib/arjdbc/sqlite3/adapter.rb +387 -0
  100. data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
  101. data/lib/arjdbc/sybase.rb +2 -0
  102. data/lib/arjdbc/sybase/adapter.rb +46 -0
  103. data/lib/arjdbc/version.rb +8 -0
  104. data/lib/generators/jdbc/USAGE +10 -0
  105. data/lib/generators/jdbc/jdbc_generator.rb +9 -0
  106. data/lib/jdbc_adapter.rb +2 -0
  107. data/lib/jdbc_adapter/rake_tasks.rb +3 -0
  108. data/lib/jdbc_adapter/version.rb +3 -0
  109. data/lib/pg.rb +26 -0
  110. data/pom.xml +57 -0
  111. data/rails_generators/jdbc_generator.rb +15 -0
  112. data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
  113. data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
  114. data/rakelib/bundler_ext.rb +11 -0
  115. data/rakelib/compile.rake +23 -0
  116. data/rakelib/db.rake +39 -0
  117. data/rakelib/rails.rake +41 -0
  118. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +62 -0
  119. data/src/java/arjdbc/derby/DerbyModule.java +324 -0
  120. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
  121. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
  122. data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
  123. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
  124. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1331 -0
  125. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  126. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
  127. data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
  128. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
  129. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
  130. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
  131. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
  132. data/test/abstract_db_create.rb +135 -0
  133. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  134. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  135. data/test/activerecord/jall.sh +7 -0
  136. data/test/activerecord/jtest.sh +3 -0
  137. data/test/db/db2.rb +11 -0
  138. data/test/db/derby.rb +12 -0
  139. data/test/db/h2.rb +11 -0
  140. data/test/db/hsqldb.rb +13 -0
  141. data/test/db/informix.rb +11 -0
  142. data/test/db/jdbc.rb +12 -0
  143. data/test/db/jndi_config.rb +40 -0
  144. data/test/db/logger.rb +3 -0
  145. data/test/db/mssql.rb +9 -0
  146. data/test/db/mysql.rb +10 -0
  147. data/test/db/oracle.rb +34 -0
  148. data/test/db/postgres.rb +9 -0
  149. data/test/db/sqlite3.rb +11 -0
  150. data/test/db2_simple_test.rb +66 -0
  151. data/test/derby_migration_test.rb +68 -0
  152. data/test/derby_multibyte_test.rb +12 -0
  153. data/test/derby_simple_test.rb +99 -0
  154. data/test/generic_jdbc_connection_test.rb +29 -0
  155. data/test/h2_change_column_test.rb +68 -0
  156. data/test/h2_simple_test.rb +41 -0
  157. data/test/has_many_through.rb +79 -0
  158. data/test/helper.rb +85 -0
  159. data/test/hsqldb_simple_test.rb +6 -0
  160. data/test/informix_simple_test.rb +48 -0
  161. data/test/jdbc_common.rb +27 -0
  162. data/test/jndi_callbacks_test.rb +40 -0
  163. data/test/jndi_test.rb +25 -0
  164. data/test/manualTestDatabase.rb +191 -0
  165. data/test/models/add_not_null_column_to_table.rb +9 -0
  166. data/test/models/auto_id.rb +15 -0
  167. data/test/models/data_types.rb +30 -0
  168. data/test/models/entry.rb +40 -0
  169. data/test/models/mixed_case.rb +22 -0
  170. data/test/models/reserved_word.rb +15 -0
  171. data/test/models/string_id.rb +17 -0
  172. data/test/models/thing.rb +16 -0
  173. data/test/models/validates_uniqueness_of_string.rb +19 -0
  174. data/test/mssql_db_create_test.rb +26 -0
  175. data/test/mssql_identity_insert_test.rb +19 -0
  176. data/test/mssql_legacy_types_test.rb +58 -0
  177. data/test/mssql_limit_offset_test.rb +136 -0
  178. data/test/mssql_multibyte_test.rb +18 -0
  179. data/test/mssql_simple_test.rb +55 -0
  180. data/test/mysql_db_create_test.rb +27 -0
  181. data/test/mysql_index_length_test.rb +58 -0
  182. data/test/mysql_info_test.rb +123 -0
  183. data/test/mysql_multibyte_test.rb +10 -0
  184. data/test/mysql_nonstandard_primary_key_test.rb +42 -0
  185. data/test/mysql_simple_test.rb +125 -0
  186. data/test/oracle_simple_test.rb +18 -0
  187. data/test/oracle_specific_test.rb +83 -0
  188. data/test/postgres_db_create_test.rb +32 -0
  189. data/test/postgres_drop_db_test.rb +16 -0
  190. data/test/postgres_information_schema_leak_test.rb +29 -0
  191. data/test/postgres_mixed_case_test.rb +29 -0
  192. data/test/postgres_native_type_mapping_test.rb +89 -0
  193. data/test/postgres_nonseq_pkey_test.rb +38 -0
  194. data/test/postgres_reserved_test.rb +22 -0
  195. data/test/postgres_schema_search_path_test.rb +48 -0
  196. data/test/postgres_simple_test.rb +167 -0
  197. data/test/postgres_table_alias_length_test.rb +15 -0
  198. data/test/postgres_type_conversion_test.rb +34 -0
  199. data/test/simple.rb +658 -0
  200. data/test/sqlite3_simple_test.rb +284 -0
  201. data/test/sybase_jtds_simple_test.rb +28 -0
  202. metadata +261 -0
@@ -0,0 +1,22 @@
1
+ require 'jdbc_common'
2
+ require 'db/postgres'
3
+ require 'models/reserved_word'
4
+
5
+ class PostgresReservedWordsTest < Test::Unit::TestCase
6
+ def setup
7
+ CreateReservedWords.up
8
+ end
9
+ def teardown
10
+ CreateReservedWords.down
11
+ end
12
+
13
+ def test_quote_reserved_word_column
14
+ columns = ReservedWord.column_names - ["id"]
15
+ ReservedWord.connection.add_index :reserved_words, columns
16
+ indexes = ReservedWord.connection.indexes("reserved_words")
17
+ assert_equal 1, indexes.size
18
+ columns.each do |c|
19
+ assert indexes[0].columns.include?(c), "#{indexes[0].columns.inspect} does not include #{c.inspect}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ require 'jdbc_common'
2
+ require 'db/postgres'
3
+
4
+ class CreateSchema < ActiveRecord::Migration
5
+ def self.up
6
+ execute "CREATE SCHEMA test"
7
+ execute "CREATE TABLE test.people (id serial, name text)"
8
+ execute "INSERT INTO test.people (name) VALUES ('Alex')"
9
+ execute "CREATE TABLE public.people (id serial, wrongname text)"
10
+ end
11
+
12
+ def self.down
13
+ execute "DROP SCHEMA test CASCADE"
14
+ execute "DROP TABLE people"
15
+ end
16
+ end
17
+
18
+ class Person < ActiveRecord::Base
19
+ establish_connection POSTGRES_CONFIG.merge(:schema_search_path => 'test,public')
20
+ end
21
+
22
+ class PostgresSchemaSearchPathTest < Test::Unit::TestCase
23
+ def setup
24
+ CreateSchema.up
25
+ end
26
+
27
+ def teardown
28
+ CreateSchema.down
29
+ end
30
+
31
+ def test_columns
32
+ assert_equal(%w{id name}, Person.column_names)
33
+ end
34
+
35
+ def test_find_right
36
+ assert_not_nil Person.find_by_name("Alex")
37
+ end
38
+
39
+ def test_find_wrong
40
+ assert_raise NoMethodError do
41
+ Person.find_by_wrongname("Alex")
42
+ end
43
+ end
44
+ def test_column_information
45
+ assert Person.columns.map{|col| col.name}.include?("name")
46
+ assert !Person.columns.map{|col| col.name}.include?("wrongname")
47
+ end
48
+ end
@@ -0,0 +1,167 @@
1
+ # To run this script, set up the following postgres user and database:
2
+ #
3
+ # sudo -u postgres createuser -D -A -P blog
4
+ # sudo -u postgres createdb -O blog weblog_development
5
+ #
6
+
7
+ require 'jdbc_common'
8
+ require 'db/postgres'
9
+
10
+ class PostgresSimpleTest < Test::Unit::TestCase
11
+ include SimpleTestMethods
12
+ include ActiveRecord3TestMethods
13
+ include ColumnNameQuotingTests
14
+
15
+ def test_adapter_class_name_equals_native_adapter_class_name
16
+ classname = @connection.class.name[/[^:]*$/]
17
+ assert_equal 'PostgreSQLAdapter', classname
18
+ end
19
+
20
+ def test_encoding
21
+ assert_not_nil @connection.encoding
22
+ end
23
+
24
+ def test_multi_statement_support
25
+ results = @connection.execute "SELECT title from entries; SELECT login from users"
26
+ assert_equal 2, results.length
27
+ assert_equal ["title"], results[0].first.keys
28
+ assert_equal ["login"], results[1].first.keys
29
+ end
30
+
31
+ def test_create_xml_column
32
+ assert_nothing_raised do
33
+ @connection.create_table :xml_testings do |t|
34
+ t.column :xml_test, :xml
35
+ end
36
+ end
37
+
38
+ xml_test = @connection.columns(:xml_testings).detect do
39
+ |c| c.name == "xml_test"
40
+ end
41
+
42
+ assert_equal "xml", xml_test.sql_type
43
+ ensure
44
+ @connection.drop_table :xml_testings rescue nil
45
+ end
46
+
47
+ def test_create_table_with_limits
48
+ assert_nothing_raised do
49
+ @connection.create_table :testings do |t|
50
+ t.column :eleven_int, :integer, :limit => 11
51
+ end
52
+ end
53
+
54
+ columns = @connection.columns(:testings)
55
+ eleven = columns.detect { |c| c.name == "eleven_int" }
56
+ assert_equal "integer", eleven.sql_type
57
+ ensure
58
+ @connection.drop_table :testings rescue nil
59
+ end
60
+ end
61
+
62
+ class PostgresTimestampTest < Test::Unit::TestCase
63
+ def setup
64
+ DbTypeMigration.up
65
+ end
66
+
67
+ def teardown
68
+ DbTypeMigration.down
69
+ end
70
+
71
+ def test_string_is_character_varying
72
+ sample_string = DbType.connection.columns(:db_types).detect do |c|
73
+ c.name == "sample_string"
74
+ end
75
+
76
+ assert_match(/^character varying/, sample_string.sql_type)
77
+ end
78
+
79
+ # infinite timestamp tests based on rails tests for postgresql_adapter.rb
80
+ def test_load_infinity_and_beyond
81
+ d = DbType.find_by_sql("select 'infinity'::timestamp as sample_timestamp")
82
+ assert d.first.sample_timestamp.infinite?, 'timestamp should be infinite'
83
+
84
+ d = DbType.find_by_sql "select '-infinity'::timestamp as sample_timestamp"
85
+ time = d.first.sample_timestamp
86
+ assert time.infinite?, "timestamp should be infinte"
87
+ assert_operator time, :<, 0
88
+ end
89
+
90
+ def test_save_infinity_and_beyond
91
+ d = DbType.create!(:sample_timestamp => 1.0 / 0.0)
92
+ assert_equal(1.0 / 0.0, d.sample_timestamp)
93
+
94
+ e = DbType.create!(:sample_timestamp => -1.0 / 0.0)
95
+ assert_equal(-1.0 / 0.0, e.sample_timestamp)
96
+ end
97
+ end
98
+
99
+ class PostgresDeserializationTest < Test::Unit::TestCase
100
+ def setup
101
+ DbTypeMigration.up
102
+ end
103
+
104
+ def teardown
105
+ DbTypeMigration.down
106
+ end
107
+
108
+ def test_should_keep_float_precision
109
+ expected = DbType.create(:sample_float => 7.3)
110
+ actual = DbType.find(expected.id)
111
+
112
+ assert_equal expected.sample_float, actual.sample_float
113
+ end
114
+ end
115
+
116
+ class PostgresSchemaDumperTest < Test::Unit::TestCase
117
+ def setup
118
+ DbTypeMigration.up
119
+ @connection = ActiveRecord::Base.connection
120
+ strio = StringIO.new
121
+ ActiveRecord::SchemaDumper::dump(ActiveRecord::Base.connection, strio)
122
+ @dump = strio.string
123
+ end
124
+
125
+ def teardown
126
+ DbTypeMigration.down
127
+ end
128
+
129
+ # http://kenai.com/jira/browse/ACTIVERECORD_JDBC-135
130
+ def test_schema_dump_should_not_have_limits_on_boolean
131
+ lines = @dump.lines.grep(/boolean/)
132
+ assert !lines.empty?
133
+ lines.each {|line| assert line !~ /limit/ }
134
+ end
135
+
136
+
137
+ def test_schema_dump_should_not_have_limits_on_binaries
138
+ lines = @dump.lines.grep(/binary/)
139
+ assert !lines.empty?, 'no binary type definitions found'
140
+ lines.each {|line| assert line !~ /limit/, 'binary definition contains limit' }
141
+ end
142
+
143
+ # http://kenai.com/jira/browse/ACTIVERECORD_JDBC-139
144
+ def test_schema_dump_should_not_have_limits_on_text_or_date
145
+ lines = @dump.lines.grep(/date|text/)
146
+ assert !lines.empty?
147
+ lines.each {|line| assert line !~ /limit/ }
148
+ end
149
+
150
+ def test_schema_dump_integer_with_no_limit_should_have_no_limit
151
+ lines = @dump.lines.grep(/sample_integer_no_limit/)
152
+ assert !lines.empty?
153
+ lines.each {|line| assert line !~ /:limit/ }
154
+ end
155
+
156
+ def test_schema_dump_integer_with_limit_2_should_have_limit_2
157
+ lines = @dump.lines.grep(/sample_integer_with_limit_2/)
158
+ assert !lines.empty?
159
+ lines.each {|line| assert line =~ /limit => 2/ }
160
+ end
161
+
162
+ def test_schema_dump_integer_with_limit_8_should_have_limit_8
163
+ lines = @dump.lines.grep(/sample_integer_with_limit_8/)
164
+ assert !lines.empty?
165
+ lines.each {|line| assert line =~ /limit => 8/ }
166
+ end
167
+ end
@@ -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
+
@@ -0,0 +1,658 @@
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
+ @connection = ActiveRecord::Base.connection
18
+ end
19
+
20
+ def teardown
21
+ DbTypeMigration.down
22
+ CreateStringIds.down
23
+ CreateEntries.down
24
+ CreateUsers.down
25
+ CreateAutoIds.down
26
+ CreateValidatesUniquenessOf.down
27
+ CreateThings.down
28
+ ActiveRecord::Base.clear_active_connections!
29
+ end
30
+ end
31
+
32
+ module FixtureSetup
33
+ include MigrationSetup
34
+ def setup
35
+ super
36
+ @title = "First post!"
37
+ @content = "Hello from JRuby on Rails!"
38
+ @new_title = "First post updated title"
39
+ @rating = 205.76
40
+ @user = User.create :login=>"something"
41
+ @entry = Entry.create :title => @title, :content => @content, :rating => @rating, :user=>@user
42
+ DbType.create
43
+ end
44
+ end
45
+
46
+ module ColumnNameQuotingTests
47
+ def self.included(base)
48
+ base.class_eval do
49
+ @@column_quote_char = "\""
50
+
51
+ def self.column_quote_char(char)
52
+ @@column_quote_char = char
53
+ end
54
+ end
55
+ end
56
+
57
+ def test_column_names_are_escaped
58
+ conn = ActiveRecord::Base.connection
59
+ quoted = conn.quote_column_name "foo#{column_quote_char}bar"
60
+ assert_equal "#{column_quote_char}foo#{column_quote_char * 2}bar#{column_quote_char}", quoted
61
+ end
62
+
63
+ protected
64
+ def column_quote_char
65
+ @@column_quote_char || "\""
66
+ end
67
+ end
68
+
69
+ module DirtyAttributeTests
70
+ def test_partial_update
71
+ entry = Entry.new(:title => 'foo')
72
+ old_updated_on = 1.hour.ago.beginning_of_day
73
+
74
+ with_partial_updates Entry, false do
75
+ assert_queries(2) { 2.times { entry.save! } }
76
+ Entry.update_all({ :updated_on => old_updated_on }, :id => entry.id)
77
+ end
78
+
79
+ with_partial_updates Entry, true do
80
+ assert_queries(0) { 2.times { entry.save! } }
81
+ assert_equal old_updated_on, entry.reload.updated_on
82
+
83
+ assert_queries(1) { entry.title = 'bar'; entry.save! }
84
+ assert_not_equal old_updated_on, entry.reload.updated_on
85
+ end
86
+ end
87
+
88
+ private
89
+ def with_partial_updates(klass, on = true)
90
+ old = klass.partial_updates?
91
+ klass.partial_updates = on
92
+ yield
93
+ ensure
94
+ klass.partial_updates = old
95
+ end
96
+ end
97
+
98
+ module SimpleTestMethods
99
+ include FixtureSetup
100
+
101
+ def test_substitute_binds_has_no_side_effect_on_binds_parameter
102
+ binds = [[Entry.columns_hash['title'], 'test1']]
103
+ binds2 = binds.dup
104
+ sql = 'select * from entries where title = ?'
105
+ Entry.connection.substitute_binds(sql, binds)
106
+ assert_equal binds2, binds
107
+ end
108
+
109
+ def test_entries_created
110
+ assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^entries$/i}, "entries not created"
111
+ end
112
+
113
+ def test_users_created
114
+ assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^users$/i}, "users not created"
115
+ end
116
+
117
+ def test_entries_empty
118
+ Entry.delete_all
119
+ assert_equal 0, Entry.count
120
+ end
121
+
122
+ def test_find_with_string_slug
123
+ new_entry = Entry.create(:title => "Blah")
124
+ entry = Entry.find(new_entry.to_param)
125
+ assert_equal new_entry.id, entry.id
126
+ end
127
+
128
+ def test_insert_returns_id
129
+ unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
130
+ value = ActiveRecord::Base.connection.insert("INSERT INTO entries (title, content, rating) VALUES('insert_title', 'some content', 1)")
131
+ assert !value.nil?
132
+ entry = Entry.find_by_title('insert_title')
133
+ assert_equal entry.id, value
134
+ end
135
+ end
136
+
137
+ def test_create_new_entry
138
+ Entry.delete_all
139
+
140
+ post = Entry.new
141
+ post.title = @title
142
+ post.content = @content
143
+ post.rating = @rating
144
+ post.save
145
+
146
+ assert_equal 1, Entry.count
147
+ end
148
+
149
+ def test_create_partial_new_entry
150
+ new_entry = Entry.create(:title => "Blah")
151
+ new_entry2 = Entry.create(:title => "Bloh")
152
+ end
153
+
154
+ def test_find_and_update_entry
155
+ post = Entry.find(:first)
156
+ assert_equal @title, post.title
157
+ assert_equal @content, post.content
158
+ assert_equal @rating, post.rating
159
+
160
+ post.title = @new_title
161
+ post.save
162
+
163
+ post = Entry.find(:first)
164
+ assert_equal @new_title, post.title
165
+ end
166
+
167
+ def test_destroy_entry
168
+ prev_count = Entry.count
169
+ post = Entry.find(:first)
170
+ post.destroy
171
+
172
+ assert_equal prev_count - 1, Entry.count
173
+ end
174
+
175
+ if Entry.respond_to?(:limit)
176
+ def test_limit
177
+ Entry.limit(10).to_a
178
+ end
179
+
180
+ def test_count_with_limit
181
+ assert_equal Entry.count, Entry.limit(10).count
182
+ end
183
+ end
184
+
185
+ if Time.respond_to?(:zone)
186
+ def test_save_time_with_utc
187
+ current_zone = Time.zone
188
+ default_zone = ActiveRecord::Base.default_timezone
189
+ ActiveRecord::Base.default_timezone = Time.zone = :utc
190
+ now = Time.now
191
+ my_time = Time.local now.year, now.month, now.day, now.hour, now.min, now.sec
192
+ m = DbType.create! :sample_datetime => my_time
193
+ m.reload
194
+ assert_equal my_time, m.sample_datetime
195
+ rescue
196
+ Time.zone = current_zone
197
+ ActiveRecord::Base.default_timezone = default_zone
198
+ end
199
+
200
+ def test_save_time
201
+ t = Time.now
202
+ #precision will only be expected to the second.
203
+ time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
204
+ e = DbType.find(:first)
205
+ e.sample_datetime = time
206
+ e.save!
207
+ e = DbType.find(:first)
208
+ assert_equal time.in_time_zone, e.sample_datetime
209
+ end
210
+
211
+ def test_save_date_time
212
+ t = Time.now
213
+ #precision will only be expected to the second.
214
+ time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
215
+ datetime = time.to_datetime
216
+ e = DbType.find(:first)
217
+ e.sample_datetime = datetime
218
+ e.save!
219
+ e = DbType.find(:first)
220
+ assert_equal time, e.sample_datetime.localtime
221
+ end
222
+
223
+ def test_save_time_with_zone
224
+ t = Time.now
225
+ #precision will only be expected to the second.
226
+ original_time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
227
+ time = original_time.in_time_zone
228
+ e = DbType.find(:first)
229
+ e.sample_datetime = time
230
+ e.save!
231
+ e = DbType.find(:first)
232
+ assert_equal time, e.sample_datetime
233
+ end
234
+ end
235
+
236
+ def test_save_float
237
+ e = DbType.find(:first)
238
+ e.sample_float = 12.0
239
+ e.save!
240
+
241
+ e = DbType.find(:first)
242
+ assert_equal(12.0, e.sample_float)
243
+ end
244
+
245
+ def test_save_date
246
+ date = Date.new(2007)
247
+ e = DbType.find(:first)
248
+ e.sample_date = date
249
+ e.save!
250
+ e = DbType.find(:first)
251
+ if DbType.columns_hash["sample_date"].type == :datetime
252
+ # Oracle doesn't distinguish btw date/datetime
253
+ assert_equal date, e.sample_date.to_date
254
+ else
255
+ assert_equal date, e.sample_date
256
+ end
257
+ end
258
+
259
+ def test_boolean
260
+ # An unset boolean should default to nil
261
+ e = DbType.find(:first)
262
+ assert_equal(nil, e.sample_boolean)
263
+
264
+ e.sample_boolean = true
265
+ e.save!
266
+
267
+ e = DbType.find(:first)
268
+ assert_equal(true, e.sample_boolean)
269
+ end
270
+
271
+ def test_integer
272
+ # An unset boolean should default to nil
273
+ e = DbType.find(:first)
274
+ assert_equal(nil, e.sample_integer)
275
+
276
+ e.sample_integer = 10
277
+ e.save!
278
+
279
+ e = DbType.find(:first)
280
+ assert_equal(10, e.sample_integer)
281
+ end
282
+
283
+ def test_text
284
+ # An unset boolean should default to nil
285
+ e = DbType.find(:first)
286
+
287
+ # Oracle adapter initializes all CLOB fields with empty_clob() function,
288
+ # so they all have a initial value of an empty string ''
289
+ assert_equal(nil, e.sample_text) unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
290
+
291
+ e.sample_text = "ooop?"
292
+ e.save!
293
+
294
+ e = DbType.find(:first)
295
+ assert_equal("ooop?", e.sample_text)
296
+ end
297
+
298
+ def test_string
299
+ e = DbType.find(:first)
300
+
301
+ # An empty string is treated as a null value in Oracle: http://www.techonthenet.com/oracle/questions/empty_null.php
302
+ assert_equal('', e.sample_string) unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
303
+ e.sample_string = "ooop?"
304
+ e.save!
305
+
306
+ e = DbType.find(:first)
307
+ assert_equal("ooop?", e.sample_string)
308
+ end
309
+
310
+ def test_save_binary
311
+ #string is 60_000 bytes
312
+ binary_string = "\000ABCDEFGHIJKLMNOPQRSTUVWXYZ'\001\003"*1#2_000
313
+ e = DbType.find(:first)
314
+ e.sample_binary = binary_string
315
+ e.save!
316
+ e = DbType.find(:first)
317
+ assert_equal binary_string, e.sample_binary
318
+ end
319
+
320
+ def test_default_decimal_should_keep_fractional_part
321
+ expected = 7.3
322
+ db_type = DbType.new(:sample_small_decimal => expected)
323
+ assert db_type.save
324
+ db_type = DbType.find(db_type.id)
325
+ assert_equal BigDecimal.new(expected.to_s), db_type.sample_small_decimal
326
+ end
327
+
328
+ def test_decimal_with_scale
329
+ test_value = 7.3
330
+ db_type = DbType.new(:sample_small_decimal => test_value)
331
+ assert db_type.save
332
+ db_type = DbType.find(db_type.id)
333
+ assert_kind_of BigDecimal, db_type.sample_small_decimal
334
+ assert_equal BigDecimal.new(test_value.to_s), db_type.sample_small_decimal
335
+ end
336
+
337
+ def test_decimal_with_zero_scale
338
+ test_value = 7000.0
339
+ db_type = DbType.new(:sample_decimal => test_value)
340
+ assert db_type.save
341
+ db_type = DbType.find(db_type.id)
342
+ assert_kind_of Integer, db_type.sample_decimal
343
+ assert_equal test_value.to_i, db_type.sample_decimal
344
+ end
345
+
346
+ def test_negative_default_value
347
+ assert_equal(-1, DbType.columns_hash['sample_integer_neg_default'].default)
348
+ assert_equal(-1, DbType.new.sample_integer_neg_default)
349
+ end
350
+
351
+ def test_indexes
352
+ # Only test indexes if we have implemented it for the particular adapter
353
+ if @connection.respond_to?(:indexes)
354
+ indexes = @connection.indexes(:entries)
355
+ assert_equal(0, indexes.size)
356
+
357
+ index_name = "entries_index"
358
+ @connection.add_index(:entries, :updated_on, :name => index_name)
359
+
360
+ indexes = @connection.indexes(:entries)
361
+ assert_equal(1, indexes.size)
362
+ assert_equal "entries", indexes.first.table.to_s
363
+ assert_equal index_name, indexes.first.name
364
+ assert !indexes.first.unique
365
+ assert_equal ["updated_on"], indexes.first.columns
366
+ end
367
+ end
368
+
369
+ def test_remove_nonexistent_index
370
+ assert_raise(ArgumentError, ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
371
+ @connection.remove_index :entries, :nonexistent_index
372
+ end
373
+ end
374
+
375
+ def test_add_index_with_invalid_name_length
376
+ index_name = 'x' * (@connection.index_name_length + 1)
377
+ assert_raise(ArgumentError) do
378
+ @connection.add_index "entries", "title", :name => index_name
379
+ end
380
+ end
381
+
382
+ def test_dumping_schema
383
+ require 'active_record/schema_dumper'
384
+ @connection.add_index :entries, :title
385
+ StringIO.open do |io|
386
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, io)
387
+ assert_match(/add_index "entries",/, io.string)
388
+ end
389
+ @connection.remove_index :entries, :title
390
+
391
+ end
392
+
393
+ def test_nil_values
394
+ test = AutoId.create('value' => '')
395
+ assert_nil AutoId.find(test.id).value
396
+ end
397
+
398
+ # These should make no difference, but might due to the wacky regexp SQL rewriting we do.
399
+ def test_save_value_containing_sql
400
+ e = DbType.first
401
+ e.save
402
+
403
+ e.sample_string = e.sample_text = "\n\nselect from nothing where id = 'foo'"
404
+ e.save
405
+ end
406
+
407
+ def test_invalid
408
+ e = Entry.new(:title => @title, :content => @content, :rating => ' ')
409
+ assert e.valid?
410
+ end
411
+
412
+ def test_reconnect
413
+ assert_equal 1, Entry.count
414
+ @connection.reconnect!
415
+ assert_equal 1, Entry.count
416
+ end
417
+
418
+ if jruby?
419
+ def test_connection_valid
420
+ assert_raises(ActiveRecord::JDBCError) do
421
+ @connection.raw_connection.with_connection_retry_guard do |c|
422
+ begin
423
+ stmt = c.createStatement
424
+ stmt.execute "bogus sql"
425
+ ensure
426
+ stmt.close rescue nil
427
+ end
428
+ end
429
+ end
430
+ end
431
+
432
+ class Animal < ActiveRecord::Base; end
433
+
434
+ def test_fetching_columns_for_nonexistent_table_should_raise
435
+ assert_raises(ActiveRecord::ActiveRecordError,
436
+ ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
437
+ Animal.columns
438
+ end
439
+ end
440
+ end
441
+
442
+ def test_disconnect
443
+ assert_equal 1, Entry.count
444
+ ActiveRecord::Base.clear_active_connections!
445
+ ActiveRecord::Base.connection_pool.disconnect! if ActiveRecord::Base.respond_to?(:connection_pool)
446
+ assert !ActiveRecord::Base.connected?
447
+ assert_equal 1, Entry.count
448
+ assert ActiveRecord::Base.connected?
449
+ end
450
+
451
+ def test_add_not_null_column_to_table
452
+ AddNotNullColumnToTable.up
453
+ AddNotNullColumnToTable.down
454
+ end
455
+
456
+ def test_add_null_column_with_default
457
+ Entry.connection.add_column :entries, :color, :string, :null => false, :default => "blue"
458
+ created_columns = Entry.connection.columns('entries')
459
+
460
+ color = created_columns.detect { |c| c.name == 'color' }
461
+ assert !color.null
462
+ end
463
+
464
+ def test_add_null_column_with_no_default
465
+ # You must specify a default value with most databases
466
+ if ActiveRecord::Base.connection.adapter_name =~ /mysql/i
467
+ Entry.connection.add_column :entries, :color, :string, :null => false
468
+ created_columns = Entry.connection.columns('entries')
469
+
470
+ color = created_columns.detect { |c| c.name == 'color' }
471
+ assert !color.null
472
+ end
473
+ end
474
+
475
+ def test_add_null_column_with_nil_default
476
+ # You must specify a default value with most databases
477
+ if ActiveRecord::Base.connection.adapter_name =~ /mysql/i
478
+ Entry.connection.add_column :entries, :color, :string, :null => false, :default => nil
479
+ created_columns = Entry.connection.columns('entries')
480
+
481
+ color = created_columns.detect { |c| c.name == 'color' }
482
+ assert !color.null
483
+ end
484
+ end
485
+
486
+ def test_validates_uniqueness_of_strings_case_sensitive
487
+ name_lower = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '1')
488
+ name_lower.save!
489
+
490
+ name_upper = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '2')
491
+ assert_nothing_raised do
492
+ name_upper.save!
493
+ end
494
+
495
+ name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '3')
496
+ assert_raise ActiveRecord::RecordInvalid do
497
+ name_lower_collision.save!
498
+ end
499
+
500
+ name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '4')
501
+ assert_raise ActiveRecord::RecordInvalid do
502
+ name_upper_collision.save!
503
+ end
504
+ end
505
+
506
+ def test_validates_uniqueness_of_strings_case_insensitive
507
+ name_lower = ValidatesUniquenessOfString.new(:cs_string => '1', :ci_string => "name")
508
+ name_lower.save!
509
+
510
+ name_upper = ValidatesUniquenessOfString.new(:cs_string => '2', :ci_string => "NAME")
511
+ assert_raise ActiveRecord::RecordInvalid do
512
+ name_upper.save!
513
+ end
514
+
515
+ name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => '3', :ci_string => "name")
516
+ assert_raise ActiveRecord::RecordInvalid do
517
+ name_lower_collision.save!
518
+ end
519
+
520
+ alternate_name_upper = ValidatesUniquenessOfString.new(:cs_string => '4', :ci_string => "ALTERNATE_NAME")
521
+ assert_nothing_raised do
522
+ alternate_name_upper.save!
523
+ end
524
+
525
+ alternate_name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => '5', :ci_string => "ALTERNATE_NAME")
526
+ assert_raise ActiveRecord::RecordInvalid do
527
+ alternate_name_upper_collision.save!
528
+ end
529
+
530
+ alternate_name_lower = ValidatesUniquenessOfString.new(:cs_string => '6', :ci_string => "alternate_name")
531
+ assert_raise ActiveRecord::RecordInvalid do
532
+ alternate_name_lower.save!
533
+ end
534
+ end
535
+
536
+ class ChangeEntriesTable < ActiveRecord::Migration
537
+ def self.up
538
+ change_table :entries do |t|
539
+ t.string :author
540
+ end if respond_to?(:change_table)
541
+ end
542
+ def self.down
543
+ change_table :entries do |t|
544
+ t.remove :author
545
+ end if respond_to?(:change_table)
546
+ end
547
+ end
548
+ def test_change_table
549
+ ChangeEntriesTable.up
550
+ ChangeEntriesTable.down
551
+ end
552
+
553
+ def test_string_id
554
+ f = StringId.new
555
+ f.id = "some_string"
556
+ f.save
557
+ f = StringId.first #reload is essential
558
+ assert_equal "some_string", f.id
559
+ end
560
+
561
+ def test_model_with_no_id
562
+ assert_nothing_raised do
563
+ Thing.create! :name => "a thing"
564
+ end
565
+ assert_equal 1, Thing.find(:all).size
566
+ end
567
+ end
568
+
569
+ module MultibyteTestMethods
570
+ include MigrationSetup
571
+
572
+ if defined?(JRUBY_VERSION)
573
+ def setup
574
+ super
575
+ config = ActiveRecord::Base.connection.config
576
+ @jdbc_driver = ActiveRecord::ConnectionAdapters::JdbcDriver.new(config[:driver])
577
+ @java_con = @jdbc_driver.connection(config[:url], config[:username], config[:password])
578
+ @java_con.setAutoCommit(true)
579
+ end
580
+
581
+ def teardown
582
+ @java_con.close
583
+ @jdbc_driver = nil
584
+ super
585
+ end
586
+
587
+ def test_select_multibyte_string
588
+ @java_con.createStatement().execute("insert into entries (id, title, content) values (1, 'テスト', '本文')")
589
+ entry = Entry.find(:first)
590
+ assert_equal "テスト", entry.title
591
+ assert_equal "本文", entry.content
592
+ assert_equal entry, Entry.find_by_title("テスト")
593
+ end
594
+
595
+ def test_update_multibyte_string
596
+ Entry.create!(:title => "テスト", :content => "本文")
597
+ rs = @java_con.createStatement().executeQuery("select title, content from entries")
598
+ assert rs.next
599
+ assert_equal "テスト", rs.getString(1)
600
+ assert_equal "本文", rs.getString(2)
601
+ end
602
+ end
603
+
604
+ def test_multibyte_aliasing
605
+ str = "テスト"
606
+ quoted_alias = Entry.connection.quote_column_name(str)
607
+ sql = "SELECT title AS #{quoted_alias} from entries"
608
+ records = Entry.connection.select_all(sql)
609
+ records.each do |rec|
610
+ rec.keys.each do |key|
611
+ assert_equal str, key
612
+ end
613
+ end
614
+ end
615
+
616
+ def test_chinese_word
617
+ chinese_word = '中文'
618
+ new_entry = Entry.create(:title => chinese_word)
619
+ new_entry.reload
620
+ assert_equal chinese_word, new_entry.title
621
+ end
622
+ end
623
+
624
+ module NonUTF8EncodingMethods
625
+ def setup
626
+ @connection = ActiveRecord::Base.remove_connection
627
+ latin2_connection = @connection.dup
628
+ latin2_connection[:encoding] = 'latin2'
629
+ latin2_connection.delete(:url) # pre-gen url gets stashed; remove to re-gen
630
+ ActiveRecord::Base.establish_connection latin2_connection
631
+ CreateEntries.up
632
+ end
633
+
634
+ def teardown
635
+ CreateEntries.down
636
+ ActiveRecord::Base.establish_connection @connection
637
+ end
638
+
639
+ def test_nonutf8_encoding_in_entry
640
+ prague_district = 'hradčany'
641
+ new_entry = Entry.create :title => prague_district
642
+ new_entry.reload
643
+ assert_equal prague_district, new_entry.title
644
+ end
645
+ end
646
+
647
+ module ActiveRecord3TestMethods
648
+ def self.included(base)
649
+ base.send :include, Tests if ActiveRecord::VERSION::MAJOR == 3
650
+ end
651
+
652
+ module Tests
653
+ def test_where
654
+ entries = Entry.where(:title => @entry.title)
655
+ assert_equal @entry, entries.first
656
+ end
657
+ end
658
+ end