activerecord-jdbc-adapter 1.2.5 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +5 -1
  3. data/Appraisals +5 -5
  4. data/Gemfile +9 -1
  5. data/Gemfile.lock +44 -10
  6. data/History.txt +126 -2
  7. data/README.md +246 -0
  8. data/Rakefile +34 -25
  9. data/activerecord-jdbc-adapter.gemspec +1 -1
  10. data/gemfiles/rails23.gemfile +5 -3
  11. data/gemfiles/rails23.gemfile.lock +26 -18
  12. data/gemfiles/rails30.gemfile +4 -2
  13. data/gemfiles/rails30.gemfile.lock +16 -8
  14. data/gemfiles/rails31.gemfile +4 -2
  15. data/gemfiles/rails31.gemfile.lock +16 -9
  16. data/gemfiles/rails32.gemfile +4 -2
  17. data/gemfiles/rails32.gemfile.lock +15 -8
  18. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  19. data/lib/arel/visitors/sql_server.rb +3 -0
  20. data/lib/arjdbc.rb +3 -5
  21. data/lib/arjdbc/db2.rb +1 -0
  22. data/lib/arjdbc/db2/adapter.rb +302 -196
  23. data/lib/arjdbc/db2/connection_methods.rb +18 -0
  24. data/lib/arjdbc/derby/active_record_patch.rb +12 -0
  25. data/lib/arjdbc/derby/adapter.rb +180 -158
  26. data/lib/arjdbc/derby/connection_methods.rb +5 -1
  27. data/lib/arjdbc/firebird/adapter.rb +27 -19
  28. data/lib/arjdbc/h2/adapter.rb +162 -7
  29. data/lib/arjdbc/h2/connection_methods.rb +5 -1
  30. data/lib/arjdbc/hsqldb.rb +1 -1
  31. data/lib/arjdbc/hsqldb/adapter.rb +96 -61
  32. data/lib/arjdbc/hsqldb/connection_methods.rb +5 -1
  33. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  34. data/lib/arjdbc/informix/adapter.rb +56 -55
  35. data/lib/arjdbc/jdbc/adapter.rb +173 -86
  36. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  37. data/lib/arjdbc/jdbc/column.rb +28 -23
  38. data/lib/arjdbc/jdbc/connection.rb +10 -6
  39. data/lib/arjdbc/jdbc/driver.rb +13 -5
  40. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +21 -0
  41. data/lib/arjdbc/mssql.rb +1 -1
  42. data/lib/arjdbc/mssql/adapter.rb +51 -53
  43. data/lib/arjdbc/mssql/connection_methods.rb +8 -1
  44. data/lib/arjdbc/mysql.rb +1 -1
  45. data/lib/arjdbc/mysql/adapter.rb +186 -150
  46. data/lib/arjdbc/mysql/connection_methods.rb +9 -9
  47. data/lib/arjdbc/mysql/explain_support.rb +85 -0
  48. data/lib/arjdbc/oracle.rb +1 -1
  49. data/lib/arjdbc/oracle/adapter.rb +232 -125
  50. data/lib/arjdbc/oracle/connection_methods.rb +2 -2
  51. data/lib/arjdbc/postgresql.rb +1 -1
  52. data/lib/arjdbc/postgresql/adapter.rb +134 -86
  53. data/lib/arjdbc/postgresql/connection_methods.rb +6 -4
  54. data/lib/arjdbc/postgresql/explain_support.rb +55 -0
  55. data/lib/arjdbc/sqlite3.rb +1 -1
  56. data/lib/arjdbc/sqlite3/adapter.rb +176 -108
  57. data/lib/arjdbc/sqlite3/connection_methods.rb +5 -5
  58. data/lib/arjdbc/sqlite3/explain_support.rb +32 -0
  59. data/lib/arjdbc/sybase/adapter.rb +7 -6
  60. data/lib/arjdbc/version.rb +1 -1
  61. data/pom.xml +1 -1
  62. data/rakelib/02-test.rake +9 -11
  63. data/rakelib/rails.rake +18 -10
  64. data/src/java/arjdbc/db2/DB2Module.java +70 -0
  65. data/src/java/arjdbc/derby/DerbyModule.java +24 -5
  66. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +66 -0
  67. data/src/java/arjdbc/jdbc/AdapterJavaService.java +14 -7
  68. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +111 -89
  69. data/src/java/arjdbc/mysql/MySQLModule.java +79 -70
  70. data/src/java/arjdbc/oracle/OracleModule.java +74 -0
  71. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +5 -10
  72. data/src/java/arjdbc/sqlite3/SQLite3Module.java +77 -0
  73. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +127 -0
  74. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +25 -111
  75. data/src/java/arjdbc/util/QuotingUtils.java +104 -0
  76. data/test/abstract_db_create.rb +6 -6
  77. data/test/activerecord/connection_adapters/type_conversion_test.rb +2 -2
  78. data/test/assets/flowers.jpg +0 -0
  79. data/test/binary.rb +67 -0
  80. data/test/db/db2.rb +30 -7
  81. data/test/db/jdbc.rb +4 -2
  82. data/test/db/oracle.rb +18 -27
  83. data/test/db2_binary_test.rb +6 -0
  84. data/test/db2_serialize_test.rb +6 -0
  85. data/test/db2_simple_test.rb +20 -25
  86. data/test/db2_test.rb +71 -0
  87. data/test/derby_binary_test.rb +6 -0
  88. data/test/derby_migration_test.rb +42 -35
  89. data/test/derby_reset_column_information_test.rb +1 -0
  90. data/test/derby_row_locking_test.rb +17 -0
  91. data/test/derby_schema_dump_test.rb +9 -0
  92. data/test/derby_serialize_test.rb +6 -0
  93. data/test/derby_simple_test.rb +59 -17
  94. data/test/generic_jdbc_connection_test.rb +112 -5
  95. data/test/h2_binary_test.rb +6 -0
  96. data/test/h2_change_column_test.rb +1 -1
  97. data/test/h2_schema_dump_test.rb +25 -0
  98. data/test/h2_serialize_test.rb +6 -0
  99. data/test/h2_simple_test.rb +23 -9
  100. data/test/has_many_through.rb +18 -4
  101. data/test/hsqldb_binary_test.rb +6 -0
  102. data/test/hsqldb_schema_dump_test.rb +15 -0
  103. data/test/hsqldb_serialize_test.rb +6 -0
  104. data/test/hsqldb_simple_test.rb +1 -0
  105. data/test/informix_simple_test.rb +1 -1
  106. data/test/jdbc/db2.rb +23 -0
  107. data/test/jdbc/oracle.rb +23 -0
  108. data/test/jdbc_common.rb +3 -110
  109. data/test/jndi_callbacks_test.rb +0 -2
  110. data/test/jndi_test.rb +2 -0
  111. data/test/models/binary.rb +18 -0
  112. data/test/models/custom_pk_name.rb +1 -0
  113. data/test/models/data_types.rb +11 -2
  114. data/test/models/entry.rb +1 -1
  115. data/test/models/string_id.rb +2 -2
  116. data/test/models/thing.rb +1 -1
  117. data/test/models/topic.rb +32 -0
  118. data/test/mssql_legacy_types_test.rb +1 -1
  119. data/test/mssql_limit_offset_test.rb +13 -3
  120. data/test/mssql_serialize_test.rb +6 -0
  121. data/test/mysql_binary_test.rb +6 -0
  122. data/test/mysql_schema_dump_test.rb +220 -0
  123. data/test/mysql_serialize_test.rb +6 -0
  124. data/test/mysql_simple_test.rb +22 -2
  125. data/test/mysql_test.rb +93 -0
  126. data/test/oracle_binary_test.rb +6 -0
  127. data/test/oracle_limit_test.rb +2 -1
  128. data/test/oracle_serialize_test.rb +6 -0
  129. data/test/oracle_simple_test.rb +61 -0
  130. data/test/oracle_specific_test.rb +77 -26
  131. data/test/postgres_binary_test.rb +6 -0
  132. data/test/postgres_native_type_mapping_test.rb +12 -11
  133. data/test/postgres_nonseq_pkey_test.rb +1 -0
  134. data/test/postgres_reserved_test.rb +1 -0
  135. data/test/postgres_reset_column_information_test.rb +1 -0
  136. data/test/postgres_row_locking_test.rb +21 -0
  137. data/test/postgres_schema_dump_test.rb +88 -0
  138. data/test/postgres_schema_search_path_test.rb +1 -0
  139. data/test/postgres_simple_test.rb +62 -89
  140. data/test/postgres_table_alias_length_test.rb +1 -0
  141. data/test/postgres_test.rb +31 -0
  142. data/test/postgres_type_conversion_test.rb +16 -16
  143. data/test/row_locking.rb +69 -64
  144. data/test/schema_dump.rb +168 -0
  145. data/test/serialize.rb +277 -0
  146. data/test/simple.rb +326 -122
  147. data/test/sqlite3_serialize_test.rb +6 -0
  148. data/test/sqlite3_simple_test.rb +51 -84
  149. data/test/sqlite3_type_conversion_test.rb +101 -0
  150. data/test/test_helper.rb +224 -0
  151. metadata +325 -366
  152. data/README.rdoc +0 -214
  153. data/test/db/logger.rb +0 -3
  154. data/test/derby_multibyte_test.rb +0 -11
  155. data/test/mysql_info_test.rb +0 -123
@@ -6,7 +6,24 @@ ActiveRecord::Base.default_timezone = :utc
6
6
  Time.zone = 'Moscow' if Time.respond_to?(:zone)
7
7
 
8
8
  module MigrationSetup
9
- def setup
9
+
10
+ def setup
11
+ setup!
12
+ end
13
+
14
+ def teardown
15
+ teardown!
16
+ end
17
+
18
+ def setup!
19
+ MigrationSetup.setup!
20
+ end
21
+
22
+ def teardown!
23
+ MigrationSetup.teardown!
24
+ end
25
+
26
+ def self.setup!
10
27
  DbTypeMigration.up
11
28
  CreateStringIds.up
12
29
  CreateEntries.up
@@ -15,10 +32,9 @@ module MigrationSetup
15
32
  CreateValidatesUniquenessOf.up
16
33
  CreateThings.up
17
34
  CreateCustomPkName.up
18
- @connection = ActiveRecord::Base.connection
19
35
  end
20
36
 
21
- def teardown
37
+ def self.teardown!
22
38
  DbTypeMigration.down
23
39
  CreateStringIds.down
24
40
  CreateEntries.down
@@ -27,12 +43,13 @@ module MigrationSetup
27
43
  CreateValidatesUniquenessOf.down
28
44
  CreateThings.down
29
45
  CreateCustomPkName.down
30
- ActiveRecord::Base.clear_active_connections!
31
46
  end
47
+
32
48
  end
33
49
 
34
50
  module FixtureSetup
35
51
  include MigrationSetup
52
+
36
53
  def setup
37
54
  super
38
55
  @title = "First post!"
@@ -80,7 +97,7 @@ module DirtyAttributeTests
80
97
 
81
98
  with_partial_updates Entry, true do
82
99
  assert_queries(0) { 2.times { entry.save! } }
83
- assert_equal old_updated_on, entry.reload.updated_on
100
+ assert_datetime_equal old_updated_on, entry.reload.updated_on
84
101
 
85
102
  assert_queries(1) { entry.title = 'bar'; entry.save! }
86
103
  assert_not_equal old_updated_on, entry.reload.updated_on
@@ -100,14 +117,6 @@ end
100
117
  module SimpleTestMethods
101
118
  include FixtureSetup
102
119
 
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
120
  def test_entries_created
112
121
  assert ActiveRecord::Base.connection.tables.find{|t| t =~ /^entries$/i}, "entries not created"
113
122
  end
@@ -161,12 +170,12 @@ module SimpleTestMethods
161
170
  end
162
171
 
163
172
  def test_create_partial_new_entry
164
- new_entry = Entry.create(:title => "Blah")
165
- new_entry2 = Entry.create(:title => "Bloh")
173
+ Entry.create(:title => "Blah")
174
+ Entry.create(:title => "Bloh")
166
175
  end
167
176
 
168
177
  def test_find_and_update_entry
169
- post = Entry.find(:first)
178
+ post = Entry.first
170
179
  assert_equal @title, post.title
171
180
  assert_equal @content, post.content
172
181
  assert_equal @rating, post.rating
@@ -174,13 +183,13 @@ module SimpleTestMethods
174
183
  post.title = @new_title
175
184
  post.save
176
185
 
177
- post = Entry.find(:first)
186
+ post = Entry.first
178
187
  assert_equal @new_title, post.title
179
188
  end
180
189
 
181
190
  def test_destroy_entry
182
191
  prev_count = Entry.count
183
- post = Entry.find(:first)
192
+ post = Entry.first
184
193
  post.destroy
185
194
 
186
195
  assert_equal prev_count - 1, Entry.count
@@ -197,6 +206,7 @@ module SimpleTestMethods
197
206
  end
198
207
 
199
208
  if Time.respond_to?(:zone)
209
+
200
210
  def test_save_time_with_utc
201
211
  current_zone = Time.zone
202
212
  default_zone = ActiveRecord::Base.default_timezone
@@ -205,21 +215,24 @@ module SimpleTestMethods
205
215
  my_time = Time.local now.year, now.month, now.day, now.hour, now.min, now.sec
206
216
  m = DbType.create! :sample_datetime => my_time
207
217
  m.reload
218
+
208
219
  assert_equal my_time, m.sample_datetime
209
220
  rescue
210
221
  Time.zone = current_zone
211
222
  ActiveRecord::Base.default_timezone = default_zone
212
223
  end
213
224
 
214
- def test_save_time
225
+ def test_save_time_with_zone
215
226
  t = Time.now
216
227
  #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)
228
+ original_time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
229
+ time = original_time.in_time_zone
230
+ e = DbType.first
219
231
  e.sample_datetime = time
220
232
  e.save!
221
- e = DbType.find(:first)
222
- assert_equal time.in_time_zone, e.sample_datetime
233
+ e = DbType.first
234
+
235
+ assert_equal time, e.sample_datetime
223
236
  end
224
237
 
225
238
  def test_save_date_time
@@ -227,136 +240,148 @@ module SimpleTestMethods
227
240
  #precision will only be expected to the second.
228
241
  time = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec)
229
242
  datetime = time.to_datetime
230
- e = DbType.find(:first)
243
+ e = DbType.first
231
244
  e.sample_datetime = datetime
232
245
  e.save!
233
- e = DbType.find(:first)
246
+ e = DbType.first
234
247
  assert_equal time, e.sample_datetime.localtime
235
248
  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
249
+
248
250
  end
249
251
 
250
- def test_save_float
251
- e = DbType.find(:first)
252
- e.sample_float = 12.0
252
+ def test_save_time
253
+ # Ruby doesn't have a plain Time class without a date.
254
+ time = Time.utc(2012, 12, 18, 21, 10, 15, 0)
255
+ e = DbType.first
256
+ e.sample_time = time
253
257
  e.save!
258
+ e = DbType.first
254
259
 
255
- e = DbType.find(:first)
256
- assert_equal(12.0, e.sample_float)
260
+ assert_time_equal time, e.sample_time
257
261
  end
262
+
263
+ def test_save_timestamp
264
+ timestamp = Time.utc(2012, 12, 18, 21, 10, 15, 0)
265
+ e = DbType.first
266
+ e.sample_timestamp = timestamp
267
+ e.save!
268
+ e = DbType.first
269
+ assert_timestamp_equal timestamp, e.sample_timestamp
270
+ end
271
+
272
+ # TODO we do not support precision beyond seconds !
273
+ # def test_save_timestamp_with_usec
274
+ # timestamp = Time.utc(1942, 11, 30, 01, 53, 59, 123_456)
275
+ # e = DbType.first
276
+ # e.sample_timestamp = timestamp
277
+ # e.save!
278
+ # e = DbType.first
279
+ # assert_timestamp_equal timestamp, e.sample_timestamp
280
+ # end
258
281
 
259
282
  def test_save_date
260
283
  date = Date.new(2007)
261
- e = DbType.find(:first)
284
+ e = DbType.first
262
285
  e.sample_date = date
263
286
  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
287
+ e = DbType.first
288
+ assert_date_type e.sample_date
289
+ assert_date_equal date, e.sample_date
290
+ end
291
+
292
+ def test_save_float
293
+ e = DbType.first
294
+ e.sample_float = 12.0
295
+ e.save!
296
+
297
+ e = DbType.first
298
+ assert_equal(12.0, e.sample_float)
271
299
  end
272
300
 
273
301
  def test_boolean
274
302
  # An unset boolean should default to nil
275
- e = DbType.find(:first)
303
+ e = DbType.first
276
304
  assert_equal(nil, e.sample_boolean)
277
305
 
278
306
  e.sample_boolean = true
279
307
  e.save!
280
308
 
281
- e = DbType.find(:first)
309
+ e = DbType.first
282
310
  assert_equal(true, e.sample_boolean)
283
311
  end
284
312
 
285
313
  def test_integer
286
314
  # An unset boolean should default to nil
287
- e = DbType.find(:first)
315
+ e = DbType.first
288
316
  assert_equal(nil, e.sample_integer)
289
317
 
290
318
  e.sample_integer = 10
291
319
  e.save!
292
320
 
293
- e = DbType.find(:first)
321
+ e = DbType.first
294
322
  assert_equal(10, e.sample_integer)
295
323
  end
296
324
 
297
325
  def test_text
298
326
  # An unset boolean should default to nil
299
- e = DbType.find(:first)
327
+ e = DbType.first
300
328
 
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
329
+ assert_null_text e.sample_text
304
330
 
305
331
  e.sample_text = "ooop?"
306
332
  e.save!
307
333
 
308
- e = DbType.find(:first)
334
+ e = DbType.first
309
335
  assert_equal("ooop?", e.sample_text)
310
336
  end
311
337
 
312
338
  def test_string
313
- e = DbType.find(:first)
339
+ e = DbType.first
340
+
341
+ assert_empty_string e.sample_string
314
342
 
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
343
  e.sample_string = "ooop?"
318
344
  e.save!
319
345
 
320
- e = DbType.find(:first)
346
+ e = DbType.first
321
347
  assert_equal("ooop?", e.sample_string)
322
348
  end
323
349
 
324
350
  def test_save_binary
325
351
  #string is 60_000 bytes
326
- binary_string = "\000ABCDEFGHIJKLMNOPQRSTUVWXYZ'\001\003"*1#2_000
327
- e = DbType.find(:first)
352
+ binary_string = "\000ABCDEFGHIJKLMNOPQRSTUVWXYZ'\001\003" * 1 # 2_000
353
+ e = DbType.first
328
354
  e.sample_binary = binary_string
329
355
  e.save!
330
- e = DbType.find(:first)
356
+ e = DbType.first
331
357
  assert_equal binary_string, e.sample_binary
332
358
  end
333
359
 
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
360
+ def test_small_decimal
343
361
  test_value = 7.3
344
362
  db_type = DbType.new(:sample_small_decimal => test_value)
345
- assert db_type.save
363
+ db_type.save!
346
364
  db_type = DbType.find(db_type.id)
347
365
  assert_kind_of BigDecimal, db_type.sample_small_decimal
348
366
  assert_equal BigDecimal.new(test_value.to_s), db_type.sample_small_decimal
349
367
  end
350
368
 
351
- def test_decimal_with_zero_scale
369
+ def test_decimal # _with_zero_scale
352
370
  test_value = 7000.0
353
- db_type = DbType.new(:sample_decimal => test_value)
354
- assert db_type.save
371
+ db_type = DbType.create!(:sample_decimal => test_value)
355
372
  db_type = DbType.find(db_type.id)
356
373
  assert_kind_of Integer, db_type.sample_decimal
357
374
  assert_equal test_value.to_i, db_type.sample_decimal
358
375
  end
359
376
 
377
+ def test_big_decimal
378
+ test_value = 9876543210_9876543210_9876543210.0
379
+ db_type = DbType.create!(:big_decimal => test_value)
380
+ db_type = DbType.find(db_type.id)
381
+ assert_kind_of Bignum, db_type.big_decimal
382
+ assert_equal test_value, db_type.big_decimal
383
+ end
384
+
360
385
  def test_negative_default_value
361
386
  assert_equal(-1, DbType.columns_hash['sample_integer_neg_default'].default)
362
387
  assert_equal(-1, DbType.new.sample_integer_neg_default)
@@ -364,33 +389,24 @@ module SimpleTestMethods
364
389
 
365
390
  def test_indexes
366
391
  # Only test indexes if we have implemented it for the particular adapter
367
- if @connection.respond_to?(:indexes)
368
- indexes = @connection.indexes(:entries)
392
+ if connection.respond_to?(:indexes)
393
+ indexes = connection.indexes(:entries)
369
394
  assert_equal(0, indexes.size)
370
395
 
371
396
  index_name = "entries_index"
372
- @connection.add_index(:entries, :updated_on, :name => index_name)
397
+ connection.add_index(:entries, :updated_on, :name => index_name)
373
398
 
374
- indexes = @connection.indexes(:entries)
399
+ indexes = connection.indexes(:entries)
375
400
  assert_equal(1, indexes.size)
376
401
  assert_equal "entries", indexes.first.table.to_s
377
402
  assert_equal index_name, indexes.first.name
378
403
  assert !indexes.first.unique
379
404
  assert_equal ["updated_on"], indexes.first.columns
405
+ else
406
+ puts "indexes not implemented for adapter: #{connection}"
380
407
  end
381
408
  end
382
409
 
383
- def test_dumping_schema
384
- require 'active_record/schema_dumper'
385
- @connection.add_index :entries, :title
386
- StringIO.open do |io|
387
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, io)
388
- assert_match(/add_index "entries",/, io.string)
389
- end
390
- @connection.remove_index :entries, :title
391
-
392
- end
393
-
394
410
  def test_nil_values
395
411
  test = AutoId.create('value' => '')
396
412
  assert_nil AutoId.find(test.id).value
@@ -412,14 +428,15 @@ module SimpleTestMethods
412
428
 
413
429
  def test_reconnect
414
430
  assert_equal 1, Entry.count
415
- @connection.reconnect!
431
+ ActiveRecord::Base.connection.reconnect!
416
432
  assert_equal 1, Entry.count
417
433
  end
418
434
 
419
- if jruby?
435
+ if defined?(JRUBY_VERSION)
420
436
  def test_connection_valid
421
- assert_raises(ActiveRecord::JDBCError) do
422
- @connection.raw_connection.with_connection_retry_guard do |c|
437
+ assert_raise(ActiveRecord::JDBCError) do
438
+ connection = ActiveRecord::Base.connection
439
+ connection.raw_connection.with_connection_retry_guard do |c|
423
440
  begin
424
441
  stmt = c.createStatement
425
442
  stmt.execute "bogus sql"
@@ -433,7 +450,7 @@ module SimpleTestMethods
433
450
  class Animal < ActiveRecord::Base; end
434
451
 
435
452
  def test_fetching_columns_for_nonexistent_table_should_raise
436
- assert_raises(ActiveRecord::ActiveRecordError,
453
+ assert_raise(ActiveRecord::ActiveRecordError,
437
454
  ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
438
455
  Animal.columns
439
456
  end
@@ -534,22 +551,132 @@ module SimpleTestMethods
534
551
  end
535
552
  end
536
553
 
554
+ def test_substitute_binds_has_no_side_effect_on_binds_parameter
555
+ binds = [ [ Entry.columns_hash['title'], 'test1' ] ]
556
+ binds_dup = binds.dup
557
+ sql = 'SELECT * FROM entries WHERE title = ?'
558
+ Entry.connection.send :substitute_binds, sql, binds
559
+ assert_equal binds_dup, binds
560
+ end
561
+
562
+ def test_find_by_sql_with_binds
563
+ Entry.create!(:title => 'qqq', :content => '', :rating => 4)
564
+ Entry.create!(:title => 'www', :content => '', :rating => 5)
565
+ Entry.create!(:title => 'www', :content => '', :rating => 6)
566
+ #ActiveRecord::Base.logger.level = Logger::DEBUG
567
+ sql = 'SELECT * FROM entries WHERE ( title = ? OR title = ? ) AND rating < ? AND rating > ?'
568
+ entries = Entry.find_by_sql [ sql, 'qqq', 'www', 6, 4 ]
569
+ assert_equal 1, entries.size
570
+ ensure
571
+ #ActiveRecord::Base.logger.level = Logger::WARN
572
+ end
573
+
574
+ def test_find_by_sql_with_named_binds
575
+ Entry.create!(:title => 'qqq', :content => '', :rating => 4)
576
+ Entry.create!(:title => 'www', :content => '', :rating => 5)
577
+ Entry.create!(:title => 'www', :content => '', :rating => 6)
578
+ #ActiveRecord::Base.logger.level = Logger::DEBUG
579
+ sql = 'SELECT * FROM entries WHERE ( title = :title OR title = :title ) AND rating < :upper AND rating > :lower'
580
+ entries = Entry.find_by_sql [ sql, { :title => 'www', :upper => 6, :lower => 4 } ]
581
+ assert_equal 1, entries.size
582
+ ensure
583
+ #ActiveRecord::Base.logger.level = Logger::WARN
584
+ end
585
+
586
+ def test_create_bind_param_with_q_mark
587
+ str = "Don' botharrr talkin' like one, savvy? Right?!?"
588
+ db_type = DbType.create! :sample_string => str.dup
589
+ assert_equal str, db_type.reload.sample_string
590
+
591
+ entry = Entry.create! :title => 'foo!', :content => 'bar?'
592
+ assert_equal 'foo!', entry.reload.title
593
+ assert_equal 'bar?', entry.content
594
+ end
595
+
596
+ def test_exec_update_bind_param_with_q_mark
597
+ entry = Entry.create! :title => 'foo!'
598
+
599
+ sql = "UPDATE entries SET title = ? WHERE id = #{entry.id}"
600
+ connection.exec_update sql, 'UPDATE(with_q_mark)', [ [ nil, "bar?" ] ]
601
+ assert_equal 'bar?', entry.reload.title
602
+ end
603
+
604
+ def test_exec_insert_bind_param_with_q_mark
605
+ sql = "INSERT INTO entries(title) VALUES (?)"
606
+ connection.exec_insert sql, 'INSERT(with_q_mark)', [ [ nil, "bar?!?" ] ]
607
+
608
+ entries = Entry.find_by_sql "SELECT * FROM entries WHERE title = 'bar?!?'"
609
+ assert entries.first
610
+ end
611
+
612
+ def test_raw_insert_bind_param_with_q_mark
613
+ sql = "INSERT INTO entries(title) VALUES (?)"
614
+ name = "INSERT(raw_with_q_mark)"
615
+ pk = nil; id_value = nil; sequence_name = nil
616
+ connection.insert sql, name, pk, id_value, sequence_name, [ [ nil, "?!huu!?" ] ]
617
+ assert Entry.exists?([ 'title LIKE ?', "%?!huu!?%" ])
618
+ end if Test::Unit::TestCase.ar_version('3.1') # no binds argument for <= 3.0
619
+
620
+ def test_raw_update_bind_param_with_q_mark
621
+ entry = Entry.create! :title => 'foo!'
622
+
623
+ sql = "UPDATE entries SET title = ? WHERE id = #{entry.id}"
624
+ name = "UPDATE(raw_with_q_mark)"
625
+ connection.update sql, name, [ [ nil, "bar?" ] ]
626
+ assert_equal 'bar?', entry.reload.title
627
+
628
+ sql = "UPDATE entries SET title = ? WHERE id = ?"
629
+ connection.update sql, name, [ [ nil, "?baz?!?" ], [ nil, entry.id ] ]
630
+ assert_equal '?baz?!?', entry.reload.title
631
+ end if Test::Unit::TestCase.ar_version('3.1') # no binds argument for <= 3.0
632
+
633
+ def test_raw_delete_bind_param_with_q_mark
634
+ entry = Entry.create! :title => 'foo?!?'
635
+
636
+ sql = "DELETE FROM entries WHERE title = ?"
637
+ name = "DELETE(raw_with_q_mark)"
638
+ connection.delete sql, name, [ [ nil, "foo?!?" ] ]
639
+ assert ! Entry.exists?(entry.id)
640
+ end if Test::Unit::TestCase.ar_version('3.1') # no binds argument for <= 3.0
641
+
537
642
  class ChangeEntriesTable < ActiveRecord::Migration
538
643
  def self.up
539
644
  change_table :entries do |t|
540
645
  t.string :author
541
- end if respond_to?(:change_table)
646
+ end
542
647
  end
543
648
  def self.down
544
649
  change_table :entries do |t|
545
650
  t.remove :author
546
- end if respond_to?(:change_table)
651
+ end
547
652
  end
548
653
  end
654
+
549
655
  def test_change_table
656
+ attributes = {
657
+ :title => 'welcome to the real world',
658
+ :content => '... TO BE CONTINUED ...',
659
+ :author => 'kares'
660
+ }
661
+ assert_raise ActiveRecord::UnknownAttributeError do
662
+ Entry.create! attributes
663
+ end
664
+
550
665
  ChangeEntriesTable.up
551
- ChangeEntriesTable.down
552
- end
666
+ Entry.reset_column_information
667
+ begin
668
+ Entry.create! attributes
669
+ if Entry.respond_to?(:where)
670
+ e = Entry.where :author => 'kares'
671
+ else # 2.3
672
+ e = Entry.all :conditions => { :author => 'kares' }
673
+ end
674
+ assert e.first
675
+ ensure
676
+ ChangeEntriesTable.down # rescue nil
677
+ Entry.reset_column_information
678
+ end
679
+ end # if Test::Unit::TestCase.ar_version('3.0')
553
680
 
554
681
  def test_string_id
555
682
  f = StringId.new
@@ -558,6 +685,28 @@ module SimpleTestMethods
558
685
  f = StringId.first #reload is essential
559
686
  assert_equal "some_string", f.id
560
687
  end
688
+
689
+ def test_handles_quotes_inside_of_strings
690
+ content_json = {
691
+ "comments" => [
692
+ "First I was like, \"What, you've got crazy pants\"",
693
+ "And then he was like, \"Yeah dude, total crazy pantalones\""
694
+ ]
695
+ }.to_json
696
+
697
+ post = Entry.new :title => 'comment entry'
698
+ post.content = content_json
699
+ post.save!
700
+
701
+ assert_equal content_json, post.reload.content
702
+ end
703
+
704
+ protected
705
+
706
+ def assert_date_type(value)
707
+ assert_instance_of Date, value
708
+ end
709
+
561
710
  end
562
711
 
563
712
  module MultibyteTestMethods
@@ -567,20 +716,20 @@ module MultibyteTestMethods
567
716
  def setup
568
717
  super
569
718
  config = ActiveRecord::Base.connection.config
570
- @jdbc_driver = ActiveRecord::ConnectionAdapters::JdbcDriver.new(config[:driver])
571
- @java_con = @jdbc_driver.connection(config[:url], config[:username], config[:password])
572
- @java_con.setAutoCommit(true)
719
+ jdbc_driver = ActiveRecord::ConnectionAdapters::JdbcDriver.new(config[:driver])
720
+ @java_connection = jdbc_driver.connection(config[:url], config[:username], config[:password])
721
+ @java_connection.setAutoCommit(true)
573
722
  end
574
723
 
575
724
  def teardown
576
- @java_con.close
577
- @jdbc_driver = nil
725
+ @java_connection.close
578
726
  super
579
727
  end
580
728
 
581
729
  def test_select_multibyte_string
582
- @java_con.createStatement().execute("insert into entries (id, title, content) values (1, 'テスト', '本文')")
583
- entry = Entry.find(:first)
730
+ @java_connection.createStatement().
731
+ execute("insert into entries (id, title, content) values (1, 'テスト', '本文')")
732
+ entry = Entry.first
584
733
  assert_equal "テスト", entry.title
585
734
  assert_equal "本文", entry.content
586
735
  assert_equal entry, Entry.find_by_title("テスト")
@@ -588,7 +737,8 @@ module MultibyteTestMethods
588
737
 
589
738
  def test_update_multibyte_string
590
739
  Entry.create!(:title => "テスト", :content => "本文")
591
- rs = @java_con.createStatement().executeQuery("select title, content from entries")
740
+ rs = @java_connection.createStatement().
741
+ executeQuery("select title, content from entries")
592
742
  assert rs.next
593
743
  assert_equal "テスト", rs.getString(1)
594
744
  assert_equal "本文", rs.getString(2)
@@ -639,29 +789,40 @@ module NonUTF8EncodingMethods
639
789
  end
640
790
 
641
791
  module XmlColumnTests
792
+
642
793
  def self.included(base)
643
794
  base.send :include, Tests if ActiveRecord::VERSION::MAJOR > 3 ||
644
795
  (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR >= 1)
645
796
  end
797
+
646
798
  module Tests
799
+
647
800
  def test_create_xml_column
648
- assert_nothing_raised do
649
- @connection.create_table :xml_testings do |t|
650
- t.xml :xml_test
651
- end
801
+ connection.create_table :xml_testings do |t|
802
+ t.xml :xml_test
652
803
  end
653
804
 
654
- xml_test = @connection.columns(:xml_testings).detect do |c|
805
+ xml_column = connection.columns(:xml_testings).detect do |c|
655
806
  c.name == "xml_test"
656
807
  end
657
-
658
- assert_equal "text", xml_test.sql_type
808
+
809
+ assert_equal xml_sql_type, xml_column.sql_type
659
810
  ensure
660
- @connection.drop_table :xml_testings rescue nil
811
+ connection.drop_table :xml_testings rescue nil
812
+ end
813
+
814
+ protected
815
+
816
+ def xml_sql_type
817
+ 'text'
661
818
  end
819
+
662
820
  end
821
+
663
822
  end
823
+
664
824
  module ActiveRecord3TestMethods
825
+
665
826
  def self.included(base)
666
827
  base.send :include, Tests if ActiveRecord::VERSION::MAJOR == 3
667
828
  end
@@ -684,14 +845,14 @@ module ActiveRecord3TestMethods
684
845
 
685
846
  def test_remove_nonexistent_index
686
847
  assert_raise(ArgumentError, ActiveRecord::StatementInvalid, ActiveRecord::JDBCError) do
687
- @connection.remove_index :entries, :nonexistent_index
848
+ connection.remove_index :entries, :nonexistent_index
688
849
  end
689
850
  end
690
851
 
691
852
  def test_add_index_with_invalid_name_length
692
- index_name = 'x' * (@connection.index_name_length + 1)
853
+ index_name = 'x' * (connection.index_name_length + 1)
693
854
  assert_raise(ArgumentError) do
694
- @connection.add_index "entries", "title", :name => index_name
855
+ connection.add_index "entries", "title", :name => index_name
695
856
  end
696
857
  end
697
858
 
@@ -702,6 +863,7 @@ module ActiveRecord3TestMethods
702
863
  assert_equal 1, Thing.find(:all).size
703
864
  end
704
865
  end
866
+
705
867
  end
706
868
 
707
869
  module ResetColumnInformationTestMethods
@@ -752,3 +914,45 @@ module ResetColumnInformationTestMethods
752
914
  end
753
915
  end
754
916
  end
917
+
918
+ module ExplainSupportTestMethods
919
+
920
+ PRINT_EXPLAIN_OUTPUT = java.lang.Boolean.getBoolean('explain.support.output')
921
+
922
+ def test_supports_explain
923
+ assert ActiveRecord::Base.connection.supports_explain?
924
+ end
925
+
926
+ def test_explain_without_binds
927
+ create_explain_data
928
+
929
+ pp = ActiveRecord::Base.connection.explain(
930
+ "SELECT * FROM entries JOIN users on entries.user_id = users.id WHERE entries.rating > 0"
931
+ )
932
+ puts "\n"; puts pp if PRINT_EXPLAIN_OUTPUT
933
+ assert_instance_of String, pp
934
+ end
935
+
936
+ def test_explain_with_binds
937
+ create_explain_data
938
+
939
+ binds = [ [ Entry.columns.find { |col| col.name.to_s == 'rating' }, 0 ] ]
940
+ pp = ActiveRecord::Base.connection.explain(
941
+ "SELECT * FROM entries JOIN users on entries.user_id = users.id WHERE entries.rating > ?", binds
942
+ )
943
+ puts "\n"; puts pp if PRINT_EXPLAIN_OUTPUT
944
+ assert_instance_of String, pp
945
+ end
946
+
947
+ private
948
+ def create_explain_data
949
+ user_1 = User.create :login => 'user_1'
950
+ user_2 = User.create :login => 'user_2'
951
+
952
+ Entry.create :title => 'title_1', :content => 'content_1', :rating => 1, :user_id => user_1.id
953
+ Entry.create :title => 'title_2', :content => 'content_2', :rating => 2, :user_id => user_2.id
954
+ Entry.create :title => 'title_3', :content => 'content', :rating => 0, :user_id => user_1.id
955
+ Entry.create :title => 'title_4', :content => 'content', :rating => 0, :user_id => user_1.id
956
+ end
957
+
958
+ end