activerecord-jdbc-adapter 5.0.pre1 → 51.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.travis.yml +15 -416
  4. data/Gemfile +35 -37
  5. data/README.md +23 -118
  6. data/RUNNING_TESTS.md +31 -26
  7. data/Rakefile +2 -3
  8. data/activerecord-jdbc-adapter.gemspec +1 -2
  9. data/lib/arjdbc/abstract/connection_management.rb +21 -0
  10. data/lib/arjdbc/abstract/core.rb +62 -0
  11. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  12. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  13. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  14. data/lib/arjdbc/derby/adapter.rb +6 -1
  15. data/lib/arjdbc/discover.rb +0 -7
  16. data/lib/arjdbc/firebird/adapter.rb +2 -2
  17. data/lib/arjdbc/jdbc/adapter.rb +10 -252
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/connection.rb +6 -0
  20. data/lib/arjdbc/jdbc.rb +2 -2
  21. data/lib/arjdbc/mysql/adapter.rb +87 -944
  22. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  23. data/lib/arjdbc/postgresql/adapter.rb +288 -1023
  24. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  25. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  26. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  27. data/lib/arjdbc/postgresql/column.rb +10 -599
  28. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  29. data/lib/arjdbc/postgresql/name.rb +24 -0
  30. data/lib/arjdbc/postgresql/oid_types.rb +25 -110
  31. data/lib/arjdbc/sqlite3/adapter.rb +171 -170
  32. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  33. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  34. data/lib/arjdbc/version.rb +1 -1
  35. data/pom.xml +3 -3
  36. data/rakelib/02-test.rake +0 -12
  37. data/rakelib/compile.rake +1 -1
  38. data/rakelib/db.rake +7 -5
  39. data/rakelib/rails.rake +63 -64
  40. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  41. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  42. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  43. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  44. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  45. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  46. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  47. metadata +20 -34
  48. data/Appraisals +0 -41
  49. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  50. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  51. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  52. data/lib/arjdbc/mysql/column.rb +0 -162
  53. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  54. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  55. data/lib/arjdbc/oracle/adapter.rb +0 -952
  56. data/lib/arjdbc/oracle/column.rb +0 -126
  57. data/lib/arjdbc/oracle/connection_methods.rb +0 -21
  58. data/lib/arjdbc/oracle.rb +0 -4
  59. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
  60. data/lib/arjdbc/postgresql/base/oid.rb +0 -412
  61. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  62. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  63. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  64. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  65. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  66. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  67. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  68. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -25,7 +25,6 @@
25
25
  ***** END LICENSE BLOCK *****/
26
26
  package arjdbc.jdbc;
27
27
 
28
- import java.io.ByteArrayInputStream;
29
28
  import java.io.IOException;
30
29
  import java.io.InputStream;
31
30
  import java.io.InputStreamReader;
@@ -80,15 +79,17 @@ import org.jruby.RubySymbol;
80
79
  import org.jruby.RubyTime;
81
80
  import org.jruby.anno.JRubyMethod;
82
81
  import org.jruby.exceptions.RaiseException;
82
+ import org.jruby.ext.bigdecimal.RubyBigDecimal;
83
83
  import org.jruby.javasupport.JavaEmbedUtils;
84
84
  import org.jruby.javasupport.JavaUtil;
85
- import org.jruby.runtime.Arity;
86
85
  import org.jruby.runtime.Block;
86
+ import org.jruby.runtime.Helpers;
87
87
  import org.jruby.runtime.ObjectAllocator;
88
88
  import org.jruby.runtime.ThreadContext;
89
89
  import org.jruby.runtime.backtrace.RubyStackTraceElement;
90
90
  import org.jruby.runtime.builtin.IRubyObject;
91
91
  import org.jruby.util.ByteList;
92
+ import org.jruby.util.TypeConverter;
92
93
 
93
94
  /**
94
95
  * Most of our ActiveRecord::ConnectionAdapters::JdbcConnection implementation.
@@ -121,6 +122,10 @@ public class RubyJdbcConnection extends RubyObject {
121
122
  return getConnectionAdapters(runtime).getClass("JdbcConnection");
122
123
  }
123
124
 
125
+ protected static RubyModule ActiveRecord(ThreadContext context) {
126
+ return context.runtime.getModule("ActiveRecord");
127
+ }
128
+
124
129
  /**
125
130
  * @param runtime
126
131
  * @return <code>ActiveRecord::ConnectionAdapters</code>
@@ -129,22 +134,6 @@ public class RubyJdbcConnection extends RubyObject {
129
134
  return (RubyModule) runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters");
130
135
  }
131
136
 
132
- /**
133
- * @param runtime
134
- * @return <code>ActiveRecord::Result</code>
135
- */
136
- static RubyClass getResult(final Ruby runtime) {
137
- return runtime.getModule("ActiveRecord").getClass("Result");
138
- }
139
-
140
- /**
141
- * @param runtime
142
- * @return <code>ActiveRecord::Base</code>
143
- */
144
- protected static RubyClass getBase(final Ruby runtime) {
145
- return runtime.getModule("ActiveRecord").getClass("Base");
146
- }
147
-
148
137
  /**
149
138
  * @param runtime
150
139
  * @return <code>ActiveRecord::ConnectionAdapters::IndexDefinition</code>
@@ -170,42 +159,6 @@ public class RubyJdbcConnection extends RubyObject {
170
159
  return runtime.getModule("ActiveRecord").getClass("JDBCError");
171
160
  }
172
161
 
173
- /**
174
- * @param runtime
175
- * @return <code>ActiveRecord::ConnectionNotEstablished</code>
176
- */
177
- protected static RubyClass getConnectionNotEstablished(final Ruby runtime) {
178
- return runtime.getModule("ActiveRecord").getClass("ConnectionNotEstablished");
179
- }
180
-
181
- /**
182
- * NOTE: Only available since AR-4.0
183
- * @param runtime
184
- * @return <code>ActiveRecord::TransactionIsolationError</code>
185
- */
186
- protected static RubyClass getTransactionIsolationError(final Ruby runtime) {
187
- return (RubyClass) runtime.getModule("ActiveRecord").getConstant("TransactionIsolationError");
188
- }
189
-
190
- /**
191
- * @param runtime
192
- * @return <code>ActiveRecord::ConnectionAdapters::JdbcTypeConverter</code>
193
- */
194
- private static RubyClass getJdbcTypeConverter(final Ruby runtime) {
195
- return getConnectionAdapters(runtime).getClass("JdbcTypeConverter");
196
- }
197
-
198
- /*
199
- def transaction_isolation_levels
200
- {
201
- read_uncommitted: "READ UNCOMMITTED",
202
- read_committed: "READ COMMITTED",
203
- repeatable_read: "REPEATABLE READ",
204
- serializable: "SERIALIZABLE"
205
- }
206
- end
207
- */
208
-
209
162
  public static int mapTransactionIsolationLevel(IRubyObject isolation) {
210
163
  if ( ! ( isolation instanceof RubySymbol ) ) {
211
164
  isolation = isolation.asString().callMethod("intern");
@@ -244,37 +197,57 @@ public class RubyJdbcConnection extends RubyObject {
244
197
  });
245
198
  }
246
199
 
247
- @JRubyMethod(name = {"begin", "transaction"}, optional = 1) // optional isolation argument for AR-4.0
248
- public IRubyObject begin(final ThreadContext context, final IRubyObject[] args) {
249
- final IRubyObject isolation = args.length > 0 ? args[0] : null;
200
+ @JRubyMethod(name = {"begin", "transaction"}, required = 1) // optional isolation argument for AR-4.0
201
+ public IRubyObject begin(final ThreadContext context, final IRubyObject isolation) {
250
202
  try { // handleException == false so we can handle setTXIsolation
251
203
  return withConnection(context, false, new Callable<IRubyObject>() {
252
204
  public IRubyObject call(final Connection connection) throws SQLException {
253
- connection.setAutoCommit(false);
205
+ return beginTransaction(context, connection, isolation.isNil() ? null : isolation);
206
+ }
207
+ });
208
+ } catch (SQLException e) {
209
+ return handleException(context, e);
210
+ }
211
+ }
254
212
 
255
- if ( isolation != null && ! isolation.isNil() ) {
256
- final int level = mapTransactionIsolationLevel(isolation);
257
- try {
258
- connection.setTransactionIsolation(level);
259
- }
260
- catch (SQLException e) {
261
- RubyClass txError = getTransactionIsolationError(context.getRuntime());
262
- if ( txError != null ) throw wrapException(context, txError, e);
263
- throw e; // let it roll - will be wrapped into a JDBCError (non 4.0)
264
- }
265
- }
266
- return context.getRuntime().getNil();
213
+ @JRubyMethod(name = {"begin", "transaction"}) // optional isolation argument for AR-4.0
214
+ public IRubyObject begin(final ThreadContext context) {
215
+ try { // handleException == false so we can handle setTXIsolation
216
+ return withConnection(context, false, new Callable<IRubyObject>() {
217
+ public IRubyObject call(final Connection connection) throws SQLException {
218
+ return beginTransaction(context, connection, null);
267
219
  }
268
220
  });
221
+ } catch (SQLException e) {
222
+ return handleException(context, e);
223
+ }
224
+ }
225
+
226
+ protected IRubyObject beginTransaction(final ThreadContext context, final Connection connection,
227
+ final IRubyObject isolation) throws SQLException {
228
+ if ( isolation != null ) {
229
+ setTransactionIsolation(context, connection, isolation);
230
+ }
231
+ if ( connection.getAutoCommit() ) connection.setAutoCommit(false);
232
+ return context.nil;
233
+ }
234
+
235
+ protected final void setTransactionIsolation(final ThreadContext context, final Connection connection,
236
+ final IRubyObject isolation) throws SQLException {
237
+ final int level = mapTransactionIsolationLevel(isolation);
238
+ try {
239
+ connection.setTransactionIsolation(level);
269
240
  }
270
241
  catch (SQLException e) {
271
- return handleException(context, e);
242
+ RubyClass txError = ActiveRecord(context).getClass("TransactionIsolationError");
243
+ if ( txError != null ) throw wrapException(context, txError, e);
244
+ throw e; // let it roll - will be wrapped into a JDBCError (non 4.0)
272
245
  }
273
246
  }
274
247
 
275
248
  @JRubyMethod(name = "commit")
276
249
  public IRubyObject commit(final ThreadContext context) {
277
- final Connection connection = getConnection(true);
250
+ final Connection connection = getConnection(context, true);
278
251
  try {
279
252
  if ( ! connection.getAutoCommit() ) {
280
253
  try {
@@ -295,13 +268,13 @@ public class RubyJdbcConnection extends RubyObject {
295
268
 
296
269
  @JRubyMethod(name = "rollback")
297
270
  public IRubyObject rollback(final ThreadContext context) {
298
- final Connection connection = getConnection(true);
271
+ final Connection connection = getConnection(context, true);
299
272
  try {
300
273
  if ( ! connection.getAutoCommit() ) {
301
274
  try {
302
275
  connection.rollback();
303
276
  resetSavepoints(context); // if any
304
- return context.getRuntime().newBoolean(true);
277
+ return context.runtime.getTrue();
305
278
  } finally {
306
279
  connection.setAutoCommit(true);
307
280
  }
@@ -326,7 +299,8 @@ public class RubyJdbcConnection extends RubyObject {
326
299
  @JRubyMethod(name = "create_savepoint", optional = 1)
327
300
  public IRubyObject create_savepoint(final ThreadContext context, final IRubyObject[] args) {
328
301
  IRubyObject name = args.length > 0 ? args[0] : null;
329
- final Connection connection = getConnection(true);
302
+ final Connection connection = getConnection(context, true);
303
+
330
304
  try {
331
305
  connection.setAutoCommit(false);
332
306
 
@@ -358,7 +332,7 @@ public class RubyJdbcConnection extends RubyObject {
358
332
  if ( name == null || name.isNil() ) {
359
333
  throw context.getRuntime().newArgumentError("nil savepoint name given");
360
334
  }
361
- final Connection connection = getConnection(true);
335
+ final Connection connection = getConnection(context, true);
362
336
  try {
363
337
  Savepoint savepoint = getSavepoints(context).get(name);
364
338
  if ( savepoint == null ) {
@@ -374,40 +348,27 @@ public class RubyJdbcConnection extends RubyObject {
374
348
 
375
349
  @JRubyMethod(name = "release_savepoint", required = 1)
376
350
  public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
377
- if ( name == null || name.isNil() ) {
378
- throw context.getRuntime().newArgumentError("nil savepoint name given");
379
- }
380
- final Connection connection = getConnection(true);
351
+ Ruby runtime = context.runtime;
352
+
353
+ if ( name == null || name.isNil() ) throw runtime.newArgumentError("nil savepoint name given");
354
+
381
355
  try {
382
356
  Object savepoint = getSavepoints(context).remove(name);
383
- if ( savepoint == null ) {
384
- throw context.getRuntime().newRuntimeError("could not release savepoint: '" + name + "' (not set)");
357
+
358
+ if (savepoint == null) {
359
+ RubyClass invalidStatement = ActiveRecord(context).getClass("StatementInvalid");
360
+ throw runtime.newRaiseException(invalidStatement, "could not release savepoint: '" + name + "' (not set)");
385
361
  }
362
+
386
363
  // NOTE: RubyHash.remove does not convert to Java as get does :
387
- if ( ! ( savepoint instanceof Savepoint ) ) {
364
+ if (!( savepoint instanceof Savepoint )) {
388
365
  savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
389
366
  }
390
- connection.releaseSavepoint((Savepoint) savepoint);
391
- return context.getRuntime().getNil();
392
- }
393
- catch (SQLException e) {
394
- return handleException(context, e);
395
- }
396
- }
397
367
 
398
- // NOTE: this is iternal API - not to be used by user-code !
399
- @JRubyMethod(name = "marked_savepoint_names")
400
- public IRubyObject marked_savepoint_names(final ThreadContext context) {
401
- if ( hasInstanceVariable("@savepoints") ) {
402
- Map<IRubyObject, Savepoint> savepoints = getSavepoints(context);
403
- final RubyArray names = context.getRuntime().newArray();
404
- for ( Map.Entry<IRubyObject, ?> entry : savepoints.entrySet() ) {
405
- names.add( entry.getKey() ); // keys are RubyString instances
406
- }
407
- return names;
408
- }
409
- else {
410
- return context.getRuntime().newEmptyArray();
368
+ getConnection(context, true).releaseSavepoint((Savepoint) savepoint);
369
+ return runtime.getNil();
370
+ } catch (SQLException e) {
371
+ return handleException(context, e);
411
372
  }
412
373
  }
413
374
 
@@ -465,7 +426,7 @@ public class RubyJdbcConnection extends RubyObject {
465
426
  }
466
427
 
467
428
  private IRubyObject initConnection(final ThreadContext context) throws SQLException {
468
- final IRubyObject jdbcConnection = setConnection( newConnection() );
429
+ final IRubyObject jdbcConnection = setConnection(context, newConnection());
469
430
  final IRubyObject adapter = callMethod("adapter"); // self.adapter
470
431
  if ( ! adapter.isNil() ) {
471
432
  if ( adapter.respondsTo("init_connection") ) {
@@ -481,24 +442,24 @@ public class RubyJdbcConnection extends RubyObject {
481
442
 
482
443
  @JRubyMethod(name = "connection")
483
444
  public IRubyObject connection(final ThreadContext context) {
484
- if ( getConnection(false) == null ) {
445
+ if (getConnection(context, false) == null) {
485
446
  synchronized (this) {
486
- if ( getConnection(false) == null ) {
487
- reconnect(context);
488
- }
447
+ if (getConnection(context, false) == null) reconnect(context);
489
448
  }
490
449
  }
450
+
491
451
  return getInstanceVariable("@connection");
492
452
  }
493
453
 
494
454
  @JRubyMethod(name = "active?", alias = "valid?")
495
455
  public IRubyObject active_p(final ThreadContext context) {
496
456
  IRubyObject connection = getInstanceVariable("@connection");
497
- if ( connection != null && ! connection.isNil() ) {
498
- return isConnectionValid(context, getConnection(false)) ?
499
- context.getRuntime().getTrue() : context.getRuntime().getFalse();
457
+
458
+ if (connection != null && ! connection.isNil()) {
459
+ return context.runtime.newBoolean(isConnectionValid(context, getConnection(context, false)));
500
460
  }
501
- return context.getRuntime().getFalse();
461
+
462
+ return context.runtime.getFalse();
502
463
  }
503
464
 
504
465
  @JRubyMethod(name = "disconnect!")
@@ -515,14 +476,14 @@ public class RubyJdbcConnection extends RubyObject {
515
476
  }
516
477
  runtime.getOut().flush();
517
478
  }
518
- return setConnection(null);
479
+ return setConnection(context, null);
519
480
  }
520
481
 
521
482
  @JRubyMethod(name = "reconnect!")
522
483
  public synchronized IRubyObject reconnect(final ThreadContext context) {
523
484
  try {
524
485
  final Connection connection = newConnection();
525
- final IRubyObject result = setConnection( connection );
486
+ final IRubyObject result = setConnection(context, connection);
526
487
  final IRubyObject adapter = callMethod("adapter");
527
488
  if ( ! adapter.isNil() ) {
528
489
  if ( adapter.respondsTo("configure_connection") ) {
@@ -541,37 +502,40 @@ public class RubyJdbcConnection extends RubyObject {
541
502
 
542
503
  @JRubyMethod(name = { "open?" /* "conn?" */ })
543
504
  public IRubyObject open_p(final ThreadContext context) {
544
- final Connection connection = getConnection(false);
545
- if ( connection == null ) return context.getRuntime().getFalse();
505
+ final Connection connection = getConnection(context, false);
506
+
507
+ if (connection == null) return context.runtime.getFalse();
508
+
546
509
  try {
547
510
  // NOTE: isClosed method generally cannot be called to determine
548
511
  // whether a connection to a database is valid or invalid ...
549
- return context.getRuntime().newBoolean( ! connection.isClosed() );
550
- }
551
- catch (SQLException e) {
512
+ return context.getRuntime().newBoolean(!connection.isClosed());
513
+ } catch (SQLException e) {
552
514
  return handleException(context, e);
553
515
  }
554
516
  }
555
517
 
556
518
  @JRubyMethod(name = "close")
557
519
  public IRubyObject close(final ThreadContext context) {
558
- final Connection connection = getConnection(false);
559
- if ( connection == null ) return context.getRuntime().getFalse();
520
+ final Connection connection = getConnection(context, false);
521
+
522
+ if (connection == null) return context.runtime.getFalse();
523
+
560
524
  try {
561
- final boolean closed = connection.isClosed();
562
- if ( closed ) return context.getRuntime().getFalse();
563
- setConnection(null); // does connection.close();
564
- return context.getRuntime().getTrue();
565
- }
566
- catch (Exception e) {
525
+ if (connection.isClosed()) return context.runtime.getFalse();
526
+
527
+ setConnection(context, null); // does connection.close();
528
+ } catch (Exception e) {
567
529
  debugStackTrace(context, e);
568
- return context.getRuntime().getNil();
530
+ return context.runtime.getNil();
569
531
  }
532
+
533
+ return context.runtime.getTrue();
570
534
  }
571
535
 
572
536
  @JRubyMethod(name = "database_name")
573
537
  public IRubyObject database_name(final ThreadContext context) throws SQLException {
574
- final Connection connection = getConnection(true);
538
+ final Connection connection = getConnection(context, true);
575
539
  String name = connection.getCatalog();
576
540
 
577
541
  if (name == null) {
@@ -591,15 +555,41 @@ public class RubyJdbcConnection extends RubyObject {
591
555
 
592
556
  try {
593
557
  statement = createStatement(context, connection);
594
- if ( doExecute(statement, query) ) {
595
- ResultSet resultSet = statement.getResultSet();
596
- ColumnData[] columns = extractColumns(context.runtime, connection, resultSet, false);
597
558
 
598
- return mapToResult(context, context.runtime, connection, resultSet, columns);
599
- } else {
600
- //return context.runtime.newFixnum( statement.getUpdateCount());
559
+ // For DBs that do support multiple statements, lets return the last result set
560
+ // to be consistent with AR
561
+ boolean hasResultSet = doExecute(statement, query);
562
+ int updateCount = statement.getUpdateCount();
563
+
564
+ ColumnData[] columns = null;
565
+ IRubyObject result = null;
566
+ ResultSet resultSet = null;
567
+
568
+ while (hasResultSet || updateCount != -1) {
569
+
570
+ if (hasResultSet) {
571
+ resultSet = statement.getResultSet();
572
+
573
+ // Unfortunately the result set gets closed when getMoreResults()
574
+ // is called, so we have to process the result sets as we get them
575
+ // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
576
+ columns = extractColumns(context.runtime, connection, resultSet, false);
577
+ result = mapToResult(context, context.runtime, connection, resultSet, columns);
578
+ } else {
579
+ resultSet = null;
580
+ }
581
+
582
+ // Check to see if there is another result set
583
+ hasResultSet = statement.getMoreResults();
584
+ updateCount = statement.getUpdateCount();
585
+ }
586
+
587
+ // Need to check resultSet instead of result because result
588
+ // may have been populated in a previous iteration of the loop
589
+ if (resultSet == null) {
601
590
  return context.runtime.newEmptyArray();
602
- //return mapGeneratedKeysOrUpdateCount(context, connection, statement);
591
+ } else {
592
+ return result;
603
593
  }
604
594
  } catch (final SQLException e) {
605
595
  debugErrorSQL(context, query);
@@ -635,15 +625,7 @@ public class RubyJdbcConnection extends RubyObject {
635
625
  * @throws SQLException
636
626
  */
637
627
  protected boolean doExecute(final Statement statement, final String query) throws SQLException {
638
- return genericExecute(statement, query);
639
- }
640
-
641
- /**
642
- * @deprecated renamed to {@link #doExecute(Statement, String)}
643
- */
644
- @Deprecated
645
- protected boolean genericExecute(final Statement statement, final String query) throws SQLException {
646
- return statement.execute(query); // Statement.RETURN_GENERATED_KEYS
628
+ return statement.execute(query);
647
629
  }
648
630
 
649
631
  @JRubyMethod(name = "execute_insert", required = 1)
@@ -661,7 +643,7 @@ public class RubyJdbcConnection extends RubyObject {
661
643
  return executeUpdate(context, query, true);
662
644
  }
663
645
  else { // we allow prepared statements with empty binds parameters
664
- return executePreparedUpdate(context, query, (List) binds, true);
646
+ return executePreparedUpdate(context, query, (RubyArray) binds, true);
665
647
  }
666
648
  }
667
649
 
@@ -697,16 +679,16 @@ public class RubyJdbcConnection extends RubyObject {
697
679
  return executeUpdate(context, query, false);
698
680
  }
699
681
  else { // we allow prepared statements with empty binds parameters
700
- return executePreparedUpdate(context, query, (List) binds, false);
682
+ return executePreparedUpdate(context, query, (RubyArray) binds, false);
701
683
  }
702
684
  }
703
685
 
704
686
  @JRubyMethod(name = {"execute_prepared_update"}, required = 2)
705
687
  public IRubyObject execute_prepared_update(final ThreadContext context,
706
- final IRubyObject sql, final IRubyObject binds) throws SQLException {
688
+ final IRubyObject sql, final IRubyObject binds) throws SQLException {
707
689
 
708
690
  final String query = sql.convertToString().getUnicodeValue();
709
- return executePreparedUpdate(context, query, (List) binds, false);
691
+ return executePreparedUpdate(context, query, (RubyArray) binds, false);
710
692
  }
711
693
 
712
694
  /**
@@ -745,7 +727,7 @@ public class RubyJdbcConnection extends RubyObject {
745
727
  }
746
728
 
747
729
  private IRubyObject executePreparedUpdate(final ThreadContext context, final String query,
748
- final List<?> binds, final boolean returnGeneratedKeys) {
730
+ final RubyArray binds, final boolean returnGeneratedKeys) {
749
731
  return withConnection(context, new Callable<IRubyObject>() {
750
732
  public IRubyObject call(final Connection connection) throws SQLException {
751
733
  PreparedStatement statement = null;
@@ -774,172 +756,143 @@ public class RubyJdbcConnection extends RubyObject {
774
756
  }
775
757
 
776
758
  /**
777
- * NOTE: since 1.3 this behaves like <code>execute_query</code> in AR-JDBC 1.2
778
- * @param context
779
- * @param sql
780
- * @param block (optional) block to yield row values
781
- * @return raw query result as a name => value Hash (unless block given)
782
- * @throws SQLException
783
- * @see #execute_query_raw(ThreadContext, IRubyObject[], Block)
784
- */
785
- @JRubyMethod(name = "execute_query_raw", required = 1) // optional block
786
- public IRubyObject execute_query_raw(final ThreadContext context,
787
- final IRubyObject sql, final Block block) throws SQLException {
788
- final String query = sql.convertToString().getUnicodeValue();
789
- return executeQueryRaw(context, query, 0, block);
790
- }
791
-
792
- /**
793
- * NOTE: since 1.3 this behaves like <code>execute_query</code> in AR-JDBC 1.2
794
- * @param context
795
- * @param args
796
- * @param block (optional) block to yield row values
797
- * @return raw query result as a name => value Hash (unless block given)
798
- * @throws SQLException
759
+ * This is the same as execute_query but it will return a list of hashes.
760
+ *
761
+ * @see RubyJdbcConnection#execute_query(ThreadContext, IRubyObject[])
762
+ * @param context which context this method is executing on.
763
+ * @param args arguments being supplied to this method.
764
+ * @param block (optional) block to yield row values (Hash(name: value))
765
+ * @return List of Hash(name: value) unless block is given.
766
+ * @throws SQLException when a database error occurs<
799
767
  */
800
- @JRubyMethod(name = "execute_query_raw", required = 2, optional = 1)
801
- // @JRubyMethod(name = "execute_query_raw", required = 1, optional = 2)
768
+ @JRubyMethod(required = 1, optional = 2)
802
769
  public IRubyObject execute_query_raw(final ThreadContext context,
803
770
  final IRubyObject[] args, final Block block) throws SQLException {
804
- // args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
805
771
  final String query = args[0].convertToString().getUnicodeValue(); // sql
806
- IRubyObject max_rows = args.length > 1 ? args[1] : null;
807
- IRubyObject binds = args.length > 2 ? args[2] : null;
772
+ final RubyArray binds;
808
773
  final int maxRows;
809
- if ( max_rows == null || max_rows.isNil() ) maxRows = 0;
810
- else {
811
- if ( binds instanceof RubyNumeric ) { // (sql, max_rows)
812
- maxRows = RubyNumeric.fix2int(binds); binds = null;
813
- }
814
- else {
815
- if ( max_rows instanceof RubyNumeric ) {
816
- maxRows = RubyNumeric.fix2int(max_rows);
817
- }
818
- else {
819
- if ( binds == null ) binds = max_rows; // (sql, binds)
774
+
775
+ // args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
776
+ switch (args.length) {
777
+ case 2:
778
+ if (args[1] instanceof RubyNumeric) { // (sql, max_rows)
779
+ maxRows = RubyNumeric.fix2int(args[1]);
780
+ binds = null;
781
+ } else { // (sql, binds)
820
782
  maxRows = 0;
783
+ binds = (RubyArray) TypeConverter.checkArrayType(args[1]);
821
784
  }
822
- }
823
- }
824
-
825
- if ( binds == null || binds.isNil() ) { // no prepared statements
826
- return executeQueryRaw(context, query, maxRows, block);
827
- }
828
- else { // we allow prepared statements with empty binds parameters
829
- return executePreparedQueryRaw(context, query, (List) binds, maxRows, block);
785
+ break;
786
+ case 3: // (sql, max_rows, binds)
787
+ maxRows = RubyNumeric.fix2int(args[1]);
788
+ binds = (RubyArray) TypeConverter.checkArrayType(args[2]);
789
+ break;
790
+ default: // (sql) 1-arg
791
+ maxRows = 0;
792
+ binds = null;
793
+ break;
830
794
  }
831
- }
832
-
833
- /**
834
- * @param context
835
- * @param query
836
- * @param maxRows
837
- * @param block
838
- * @return raw query result (in case no block was given)
839
- *
840
- * @see #execute_query_raw(ThreadContext, IRubyObject[], Block)
841
- */
842
- protected IRubyObject executeQueryRaw(final ThreadContext context,
843
- final String query, final int maxRows, final Block block) {
844
- return doExecuteQueryRaw(context, query, maxRows, block, null); // binds == null
845
- }
846
795
 
847
- protected IRubyObject executePreparedQueryRaw(final ThreadContext context,
848
- final String query, final List<?> binds, final int maxRows, final Block block) {
849
796
  return doExecuteQueryRaw(context, query, maxRows, block, binds);
850
797
  }
851
798
 
852
799
  private IRubyObject doExecuteQueryRaw(final ThreadContext context,
853
- final String query, final int maxRows, final Block block, final List<?> binds) {
800
+ final String query, final int maxRows, final Block block, final RubyArray binds) {
854
801
  return withConnection(context, new Callable<IRubyObject>() {
855
802
  public IRubyObject call(final Connection connection) throws SQLException {
856
803
  final Ruby runtime = context.getRuntime();
857
804
 
858
- Statement statement = null; ResultSet resultSet = null;
805
+ Statement statement = null;
806
+ boolean hasResult = false;
859
807
  try {
860
- if ( binds == null ) { // plain statement
808
+ if ( binds == null || binds.isEmpty()) { // plain statement
861
809
  statement = createStatement(context, connection);
862
810
  statement.setMaxRows(maxRows); // zero means there is no limit
863
- resultSet = statement.executeQuery(query);
811
+ hasResult = statement.execute(query);
864
812
  }
865
813
  else {
866
814
  final PreparedStatement prepStatement;
867
815
  statement = prepStatement = connection.prepareStatement(query);
868
816
  statement.setMaxRows(maxRows); // zero means there is no limit
869
817
  setStatementParameters(context, connection, prepStatement, binds);
870
- resultSet = prepStatement.executeQuery();
818
+ hasResult = prepStatement.execute();
871
819
  }
872
820
 
873
- if ( block != null && block.isGiven() ) {
874
- // yield(id1, name1) ... row 1 result data
875
- // yield(id2, name2) ... row 2 result data
876
- return yieldResultRows(context, runtime, connection, resultSet, block);
821
+ if (block.isGiven()) {
822
+ if (hasResult) {
823
+ // yield(id1, name1) ... row 1 result data
824
+ // yield(id2, name2) ... row 2 result data
825
+ return yieldResultRows(context, runtime, connection, statement.getResultSet(), block);
826
+ } else {
827
+ return runtime.getNil();
828
+ }
829
+ } else if (hasResult) {
830
+ return mapToRawResult(context, runtime, connection, statement.getResultSet(), false);
831
+ } else {
832
+ return runtime.newEmptyArray();
877
833
  }
878
-
879
- return mapToRawResult(context, runtime, connection, resultSet, false);
880
834
  }
881
835
  catch (final SQLException e) {
882
836
  debugErrorSQL(context, query);
883
837
  throw e;
884
838
  }
885
- finally { close(resultSet); close(statement); }
839
+ finally {
840
+ close(statement);
841
+ }
886
842
  }
887
843
  });
888
844
  }
889
845
 
890
846
  /**
891
- * Executes a query and returns the (AR) result.
892
- * @param context
893
- * @param sql
894
- * @return raw query result as a name => value Hash (unless block given)
895
- * @throws SQLException
896
- */
897
- @JRubyMethod(name = "execute_query", required = 1)
898
- public IRubyObject execute_query(final ThreadContext context,
899
- final IRubyObject sql) throws SQLException {
900
- final String query = sql.convertToString().getUnicodeValue();
901
- return executeQuery(context, query, 0);
902
- }
903
-
904
- /**
905
- * Executes a query and returns the (AR) result.
906
- * @param context
907
- * @param args
908
- * @return and <code>ActiveRecord::Result</code>
909
- * @throws SQLException
847
+ * Executes a query and returns the (AR) result. There are three parameters:
848
+ * <ul>
849
+ * <li>sql - String of sql</li>
850
+ * <li>max_rows - Integer of how many rows to return</li>
851
+ * <li>binds - Array of bindings for a prepared statement</li>
852
+ * </ul>
853
+ *
854
+ * In true Ruby fashion if there are only two arguments then the last argument
855
+ * may be either max_rows or binds. Note: If you want to force the query to be
856
+ * done using a prepared statement then you must provide an empty array to binds.
857
+ *
858
+ * @param context which context this method is executing on.
859
+ * @param args arguments being supplied to this method.
860
+ * @return a Ruby <code>ActiveRecord::Result</code> instance
861
+ * @throws SQLException when a database error occurs
910
862
  *
911
863
  */
912
- @JRubyMethod(name = "execute_query", required = 2, optional = 1)
913
- // @JRubyMethod(name = "execute_query", required = 1, optional = 2)
914
- public IRubyObject execute_query(final ThreadContext context,
915
- final IRubyObject[] args) throws SQLException {
916
- // args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
864
+ @JRubyMethod(required = 1, optional = 2)
865
+ public IRubyObject execute_query(final ThreadContext context, final IRubyObject[] args) throws SQLException {
917
866
  final String query = args[0].convertToString().getUnicodeValue(); // sql
918
- IRubyObject max_rows = args.length > 1 ? args[1] : null;
919
- IRubyObject binds = args.length > 2 ? args[2] : null;
867
+ final RubyArray binds;
920
868
  final int maxRows;
921
- if ( max_rows == null || max_rows.isNil() ) maxRows = 0;
922
- else {
923
- if ( binds instanceof RubyNumeric ) { // (sql, max_rows)
924
- maxRows = RubyNumeric.fix2int(binds); binds = null;
925
- }
926
- else {
927
- if ( max_rows instanceof RubyNumeric ) {
928
- maxRows = RubyNumeric.fix2int(max_rows);
929
- }
930
- else {
931
- if ( binds == null ) binds = max_rows; // (sql, binds)
869
+
870
+ // args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
871
+ switch (args.length) {
872
+ case 2:
873
+ if (args[1] instanceof RubyNumeric) { // (sql, max_rows)
874
+ maxRows = RubyNumeric.fix2int(args[1]);
875
+ binds = null;
876
+ } else { // (sql, binds)
932
877
  maxRows = 0;
878
+ binds = (RubyArray) TypeConverter.checkArrayType(args[1]);
933
879
  }
934
- }
880
+ break;
881
+ case 3: // (sql, max_rows, binds)
882
+ maxRows = RubyNumeric.fix2int(args[1]);
883
+ binds = (RubyArray) TypeConverter.checkArrayType(args[2]);
884
+ break;
885
+ default: // (sql) 1-arg
886
+ maxRows = 0;
887
+ binds = null;
888
+ break;
935
889
  }
936
890
 
937
- if ( binds == null || binds.isNil() ) { // no prepared statements
891
+ if (binds != null) { // prepared statement
892
+ return executePreparedQuery(context, query, binds, maxRows);
893
+ } else {
938
894
  return executeQuery(context, query, maxRows);
939
895
  }
940
- else { // we allow prepared statements with empty binds parameters
941
- return executePreparedQuery(context, query, (List) binds, maxRows);
942
- }
943
896
  }
944
897
 
945
898
  @JRubyMethod(name = "execute_prepared_query")
@@ -951,12 +904,10 @@ public class RubyJdbcConnection extends RubyObject {
951
904
  throw context.runtime.newArgumentError("binds exptected to an instance of Array");
952
905
  }
953
906
 
954
- return executePreparedQuery(context, query, (List) binds, 0);
907
+ return executePreparedQuery(context, query, (RubyArray) binds, 0);
955
908
  }
956
909
 
957
910
  /**
958
- * NOTE: This methods behavior changed in AR-JDBC 1.3 the old behavior is
959
- * achievable using {@link #executeQueryRaw(ThreadContext, String, int, Block)}.
960
911
  *
961
912
  * @param context
962
913
  * @param query
@@ -986,42 +937,58 @@ public class RubyJdbcConnection extends RubyObject {
986
937
  });
987
938
  }
988
939
 
989
- @JRubyMethod
990
- public IRubyObject execute_prepared(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
940
+ // Called from exec_query in abstract/database_statements
941
+ @JRubyMethod(required = 3)
942
+ public IRubyObject execute_prepared(final ThreadContext context, final IRubyObject sql,
943
+ final IRubyObject binds, final IRubyObject cachedStatement) {
991
944
  return withConnection(context, new Callable<IRubyObject>() {
992
945
  public IRubyObject call(final Connection connection) throws SQLException {
993
- PreparedStatement statement = null;
946
+ final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
994
947
  final String query = sql.convertToString().getUnicodeValue();
995
-
996
- // FIXME: array type check for binds
948
+ PreparedStatement statement = null;
997
949
 
998
950
  try {
999
- statement = connection.prepareStatement(query);
1000
- setStatementParameters(context, connection, statement, (List) binds);
951
+ if (cached) {
952
+ statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
953
+ } else {
954
+ statement = connection.prepareStatement(query);
955
+ }
956
+
957
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
1001
958
  boolean hasResultSet = statement.execute();
1002
959
 
1003
960
  if (hasResultSet) {
1004
961
  ResultSet resultSet = statement.getResultSet();
1005
962
  ColumnData[] columns = extractColumns(context.runtime, connection, resultSet, false);
1006
963
 
1007
- return mapToResult(context, context.runtime, connection, resultSet, columns);
964
+ IRubyObject results = mapToResult(context, context.runtime, connection, resultSet, columns);
965
+
966
+ if (cached) {
967
+ // Make sure we free the result set if we are caching the statement
968
+ // It gets closed automatically when the statement is closed if we aren't caching
969
+ resultSet.close();
970
+ }
971
+
972
+ return results;
1008
973
  } else {
1009
974
  return context.runtime.newEmptyArray();
1010
- //return context.runtime.newFixnum( statement.getUpdateCount());
1011
- // return mapGeneratedKeysOrUpdateCount(context, connection, statement);
1012
975
  }
1013
976
  } catch (final SQLException e) {
1014
977
  debugErrorSQL(context, query);
1015
978
  throw e;
1016
979
  } finally {
1017
- close(statement);
980
+ if ( cached ) {
981
+ statement.clearParameters();
982
+ } else {
983
+ close(statement);
984
+ }
1018
985
  }
1019
986
  }
1020
987
  });
1021
988
  }
1022
989
 
1023
990
  protected IRubyObject executePreparedQuery(final ThreadContext context, final String query,
1024
- final List<?> binds, final int maxRows) {
991
+ final RubyArray binds, final int maxRows) {
1025
992
  return withConnection(context, new Callable<IRubyObject>() {
1026
993
  public IRubyObject call(final Connection connection) throws SQLException {
1027
994
  PreparedStatement statement = null; ResultSet resultSet = null;
@@ -1081,7 +1048,7 @@ public class RubyJdbcConnection extends RubyObject {
1081
1048
  @JRubyMethod(name = "supported_data_types")
1082
1049
  public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
1083
1050
  final Ruby runtime = context.getRuntime();
1084
- final Connection connection = getConnection(true);
1051
+ final Connection connection = getConnection(context, true);
1085
1052
  final ResultSet typeDesc = connection.getMetaData().getTypeInfo();
1086
1053
  final IRubyObject types;
1087
1054
  try {
@@ -1106,7 +1073,7 @@ public class RubyJdbcConnection extends RubyObject {
1106
1073
  return withConnection(context, new Callable<List<RubyString>>() {
1107
1074
  public List<RubyString> call(final Connection connection) throws SQLException {
1108
1075
  final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1109
- final TableName table = extractTableName(connection, null, _tableName);
1076
+ final TableName table = extractTableName(connection, null, null, _tableName);
1110
1077
  return primaryKeys(context, connection, table);
1111
1078
  }
1112
1079
  });
@@ -1204,7 +1171,7 @@ public class RubyJdbcConnection extends RubyObject {
1204
1171
  final Ruby runtime = context.getRuntime();
1205
1172
  return withConnection(context, new Callable<RubyBoolean>() {
1206
1173
  public RubyBoolean call(final Connection connection) throws SQLException {
1207
- final TableName components = extractTableName(connection, defaultSchema, tableName);
1174
+ final TableName components = extractTableName(connection, null, defaultSchema, tableName);
1208
1175
  return runtime.newBoolean( tableExists(runtime, connection, components) );
1209
1176
  }
1210
1177
  });
@@ -1223,12 +1190,7 @@ public class RubyJdbcConnection extends RubyObject {
1223
1190
  final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
1224
1191
 
1225
1192
  final TableName components;
1226
- if ( catalog == null ) { // backwards-compatibility with < 1.3.0
1227
- components = extractTableName(connection, defaultSchema, tableName);
1228
- }
1229
- else {
1230
- components = extractTableName(connection, catalog, defaultSchema, tableName);
1231
- }
1193
+ components = extractTableName(connection, catalog, defaultSchema, tableName);
1232
1194
 
1233
1195
  if ( ! tableExists(context.getRuntime(), connection, components) ) {
1234
1196
  throw new SQLException("table: " + tableName + " does not exist");
@@ -1277,7 +1239,7 @@ public class RubyJdbcConnection extends RubyObject {
1277
1239
 
1278
1240
  String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1279
1241
  String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1280
- final TableName table = extractTableName(connection, _schemaName, _tableName);
1242
+ final TableName table = extractTableName(connection, null, _schemaName, _tableName);
1281
1243
 
1282
1244
  final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
1283
1245
 
@@ -1451,53 +1413,6 @@ public class RubyJdbcConnection extends RubyObject {
1451
1413
  });
1452
1414
  }
1453
1415
 
1454
- // NOTE: this seems to be not used ... at all ?!
1455
- /*
1456
- * sql, values (array), types (column.type array), name = nil, pk = nil, id_value = nil, sequence_name = nil
1457
- */
1458
- @Deprecated
1459
- @JRubyMethod(name = "insert_bind", required = 3, rest = true)
1460
- public IRubyObject insert_bind(final ThreadContext context, final IRubyObject[] args) throws SQLException {
1461
- final Ruby runtime = context.getRuntime();
1462
- return withConnection(context, new Callable<IRubyObject>() {
1463
- public IRubyObject call(final Connection connection) throws SQLException {
1464
- final String sql = args[0].convertToString().toString();
1465
- PreparedStatement statement = null;
1466
- try {
1467
- statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
1468
- setPreparedStatementValues(context, connection, statement, args[1], args[2]);
1469
- statement.executeUpdate();
1470
- return mapGeneratedKeys(runtime, connection, statement);
1471
- }
1472
- finally { close(statement); }
1473
- }
1474
- });
1475
- }
1476
-
1477
- // NOTE: this seems to be not used ... at all ?!
1478
- /*
1479
- * sql, values (array), types (column.type array), name = nil
1480
- */
1481
- @Deprecated
1482
- @JRubyMethod(name = "update_bind", required = 3, rest = true)
1483
- public IRubyObject update_bind(final ThreadContext context, final IRubyObject[] args) throws SQLException {
1484
- final Ruby runtime = context.getRuntime();
1485
- Arity.checkArgumentCount(runtime, args, 3, 4);
1486
- return withConnection(context, new Callable<IRubyObject>() {
1487
- public IRubyObject call(final Connection connection) throws SQLException {
1488
- final String sql = args[0].convertToString().toString();
1489
- PreparedStatement statement = null;
1490
- try {
1491
- statement = connection.prepareStatement(sql);
1492
- setPreparedStatementValues(context, connection, statement, args[1], args[2]);
1493
- statement.executeUpdate();
1494
- }
1495
- finally { close(statement); }
1496
- return runtime.getNil();
1497
- }
1498
- });
1499
- }
1500
-
1501
1416
  @JRubyMethod(name = "with_connection_retry_guard", frame = true)
1502
1417
  public IRubyObject with_connection_retry_guard(final ThreadContext context, final Block block) {
1503
1418
  return withConnection(context, new Callable<IRubyObject>() {
@@ -1562,11 +1477,15 @@ public class RubyJdbcConnection extends RubyObject {
1562
1477
 
1563
1478
  final String sql = "UPDATE "+ tableName +" SET "+ columnName +" = ? WHERE "+ idKey +" = ?" ;
1564
1479
 
1480
+ // TODO: Fix this, the columns don't have the info needed to handle this anymore
1481
+ // currently commented out so that it will compile
1482
+
1565
1483
  return withConnection(context, new Callable<Integer>() {
1566
1484
  public Integer call(final Connection connection) throws SQLException {
1567
1485
  PreparedStatement statement = null;
1568
1486
  try {
1569
1487
  statement = connection.prepareStatement(sql);
1488
+ /*
1570
1489
  if ( binary ) { // blob
1571
1490
  setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
1572
1491
  }
@@ -1574,6 +1493,7 @@ public class RubyJdbcConnection extends RubyObject {
1574
1493
  setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
1575
1494
  }
1576
1495
  setStatementParameter(context, context.getRuntime(), connection, statement, 2, idValue, idColumn);
1496
+ */
1577
1497
  return statement.executeUpdate();
1578
1498
  }
1579
1499
  finally { close(statement); }
@@ -1672,14 +1592,6 @@ public class RubyJdbcConnection extends RubyObject {
1672
1592
  return config.callMethod(context, "[]", keySym);
1673
1593
  }
1674
1594
 
1675
- /**
1676
- * @deprecated renamed to {@link #getConfigValue(ThreadContext, String)}
1677
- */
1678
- @Deprecated
1679
- protected IRubyObject config_value(ThreadContext context, String key) {
1680
- return getConfigValue(context, key);
1681
- }
1682
-
1683
1595
  private static String toStringOrNull(final IRubyObject arg) {
1684
1596
  return arg.isNil() ? null : arg.toString();
1685
1597
  }
@@ -1736,9 +1648,8 @@ public class RubyJdbcConnection extends RubyObject {
1736
1648
  final ThreadContext context, final Ruby runtime,
1737
1649
  final List<IRubyObject> results, final ResultSet resultSet,
1738
1650
  final ColumnData[] columns) throws SQLException {
1739
- final ResultHandler resultHandler = ResultHandler.getInstance(runtime);
1740
1651
  while ( resultSet.next() ) {
1741
- results.add( resultHandler.mapRawRow(context, runtime, columns, resultSet, this) );
1652
+ results.add(mapRawRow(context, runtime, columns, resultSet, this));
1742
1653
  }
1743
1654
  }
1744
1655
 
@@ -1756,14 +1667,13 @@ public class RubyJdbcConnection extends RubyObject {
1756
1667
  final Connection connection, final ResultSet resultSet,
1757
1668
  final ColumnData[] columns) throws SQLException {
1758
1669
 
1759
- final ResultHandler resultHandler = ResultHandler.getInstance(runtime);
1760
1670
  final RubyArray resultRows = runtime.newArray();
1761
1671
 
1762
- while ( resultSet.next() ) {
1763
- resultRows.append( resultHandler.mapRow(context, runtime, columns, resultSet, this) );
1672
+ while (resultSet.next()) {
1673
+ resultRows.append(mapRow(context, runtime, columns, resultSet, this));
1764
1674
  }
1765
1675
 
1766
- return resultHandler.newResult(context, runtime, columns, resultRows);
1676
+ return newResult(context, columns, resultRows);
1767
1677
  }
1768
1678
 
1769
1679
  @Deprecated
@@ -1790,12 +1700,7 @@ public class RubyJdbcConnection extends RubyObject {
1790
1700
  return readerToRuby(context, runtime, resultSet, column);
1791
1701
  case Types.LONGVARCHAR:
1792
1702
  case Types.LONGNVARCHAR: // JDBC 4.0
1793
- if ( runtime.is1_9() ) {
1794
- return readerToRuby(context, runtime, resultSet, column);
1795
- }
1796
- else {
1797
- return streamToRuby(context, runtime, resultSet, column);
1798
- }
1703
+ return readerToRuby(context, runtime, resultSet, column);
1799
1704
  case Types.TINYINT:
1800
1705
  case Types.SMALLINT:
1801
1706
  case Types.INTEGER:
@@ -1852,16 +1757,7 @@ public class RubyJdbcConnection extends RubyObject {
1852
1757
  throws SQLException {
1853
1758
  final long value = resultSet.getLong(column);
1854
1759
  if ( value == 0 && resultSet.wasNull() ) return runtime.getNil();
1855
- return integerToRuby(runtime, resultSet, value);
1856
- }
1857
-
1858
- @Deprecated
1859
- protected IRubyObject integerToRuby(
1860
- final Ruby runtime, final ResultSet resultSet, final long longValue)
1861
- throws SQLException {
1862
- if ( longValue == 0 && resultSet.wasNull() ) return runtime.getNil();
1863
-
1864
- return runtime.newFixnum(longValue);
1760
+ return runtime.newFixnum(value);
1865
1761
  }
1866
1762
 
1867
1763
  protected IRubyObject doubleToRuby(final ThreadContext context,
@@ -1869,58 +1765,29 @@ public class RubyJdbcConnection extends RubyObject {
1869
1765
  throws SQLException {
1870
1766
  final double value = resultSet.getDouble(column);
1871
1767
  if ( value == 0 && resultSet.wasNull() ) return runtime.getNil();
1872
- return doubleToRuby(runtime, resultSet, value);
1768
+ return runtime.newFloat(value);
1873
1769
  }
1874
1770
 
1875
- @Deprecated
1876
- protected IRubyObject doubleToRuby(
1877
- final Ruby runtime, final ResultSet resultSet, double doubleValue)
1878
- throws SQLException {
1879
- if ( doubleValue == 0 && resultSet.wasNull() ) return runtime.getNil();
1880
- return runtime.newFloat(doubleValue);
1771
+ protected IRubyObject stringToRuby(final ThreadContext context,
1772
+ final Ruby runtime, final ResultSet resultSet, final int column) throws SQLException {
1773
+ final String value = resultSet.getString(column);
1774
+ if ( value == null && resultSet.wasNull() ) return runtime.getNil();
1775
+ return RubyString.newInternalFromJavaExternal(runtime, value);
1881
1776
  }
1882
1777
 
1883
- protected IRubyObject stringToRuby(final ThreadContext context,
1884
- final Ruby runtime, final ResultSet resultSet, final int column)
1885
- throws SQLException {
1778
+ protected IRubyObject bigIntegerToRuby(final ThreadContext context,
1779
+ final Ruby runtime, final ResultSet resultSet, final int column) throws SQLException {
1886
1780
  final String value = resultSet.getString(column);
1887
1781
  if ( value == null && resultSet.wasNull() ) return runtime.getNil();
1888
- return stringToRuby(runtime, resultSet, value);
1889
- }
1890
-
1891
- @Deprecated
1892
- protected IRubyObject stringToRuby(
1893
- final Ruby runtime, final ResultSet resultSet, final String string)
1894
- throws SQLException {
1895
- if ( string == null && resultSet.wasNull() ) return runtime.getNil();
1896
-
1897
- return RubyString.newUnicodeString(runtime, string);
1898
- }
1899
-
1900
- protected IRubyObject bigIntegerToRuby(final ThreadContext context,
1901
- final Ruby runtime, final ResultSet resultSet, final int column)
1902
- throws SQLException {
1903
- final String value = resultSet.getString(column);
1904
- if ( value == null && resultSet.wasNull() ) return runtime.getNil();
1905
- return bigIntegerToRuby(runtime, resultSet, value);
1906
- }
1907
-
1908
- @Deprecated
1909
- protected IRubyObject bigIntegerToRuby(
1910
- final Ruby runtime, final ResultSet resultSet, final String intValue)
1911
- throws SQLException {
1912
- if ( intValue == null && resultSet.wasNull() ) return runtime.getNil();
1913
-
1914
- return RubyBignum.bignorm(runtime, new BigInteger(intValue));
1782
+ return RubyBignum.bignorm(runtime, new BigInteger(value));
1915
1783
  }
1916
1784
 
1917
1785
  protected IRubyObject decimalToRuby(final ThreadContext context,
1918
- final Ruby runtime, final ResultSet resultSet, final int column)
1919
- throws SQLException {
1786
+ final Ruby runtime, final ResultSet resultSet, final int column) throws SQLException {
1920
1787
  final String value = resultSet.getString(column);
1921
1788
  if ( value == null && resultSet.wasNull() ) return runtime.getNil();
1922
- // NOTE: JRuby 1.6 -> 1.7 API change : moved org.jruby.RubyBigDecimal
1923
- return runtime.getKernel().callMethod("BigDecimal", runtime.newString(value));
1789
+
1790
+ return RubyBigDecimal.newInstance(context, runtime.getModule("BigDecimal"), runtime.newString(value));
1924
1791
  }
1925
1792
 
1926
1793
  protected static Boolean rawDateTime;
@@ -1957,7 +1824,7 @@ public class RubyJdbcConnection extends RubyObject {
1957
1824
  protected static IRubyObject typeCastFromDatabase(final ThreadContext context,
1958
1825
  final IRubyObject adapter, final RubySymbol typeName, final RubyString value) {
1959
1826
  final IRubyObject type = adapter.callMethod(context, "lookup_cast_type", typeName);
1960
- return type.callMethod(context, "type_cast_from_database", value);
1827
+ return type.callMethod(context, "deserialize", value);
1961
1828
  }
1962
1829
 
1963
1830
  protected IRubyObject dateToRuby(final ThreadContext context,
@@ -1976,11 +1843,8 @@ public class RubyJdbcConnection extends RubyObject {
1976
1843
  final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
1977
1844
  if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
1978
1845
 
1979
- if ( usesType(runtime) ) {
1980
- // NOTE: this CAN NOT be 100% correct - as :date is just a type guess!
1981
- return typeCastFromDatabase(context, adapter, runtime.newSymbol("date"), strValue);
1982
- }
1983
- return adapter.callMethod(context, "_string_to_date", strValue);
1846
+ // NOTE: this CAN NOT be 100% correct - as :date is just a type guess!
1847
+ return typeCastFromDatabase(context, adapter, runtime.newSymbol("date"), strValue);
1984
1848
  }
1985
1849
 
1986
1850
  protected IRubyObject timeToRuby(final ThreadContext context,
@@ -1999,11 +1863,8 @@ public class RubyJdbcConnection extends RubyObject {
1999
1863
  final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
2000
1864
  if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
2001
1865
 
2002
- if ( usesType(runtime) ) {
2003
- // NOTE: this CAN NOT be 100% correct - as :time is just a type guess!
2004
- return typeCastFromDatabase(context, adapter, runtime.newSymbol("time"), strValue);
2005
- }
2006
- return adapter.callMethod(context, "_string_to_time", strValue);
1866
+ // NOTE: this CAN NOT be 100% correct - as :time is just a type guess!
1867
+ return typeCastFromDatabase(context, adapter, runtime.newSymbol("time"), strValue);
2007
1868
  }
2008
1869
 
2009
1870
  protected IRubyObject timestampToRuby(final ThreadContext context, // TODO
@@ -2022,11 +1883,8 @@ public class RubyJdbcConnection extends RubyObject {
2022
1883
  final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
2023
1884
  if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
2024
1885
 
2025
- if ( usesType(runtime) ) {
2026
- // NOTE: this CAN NOT be 100% correct - as :timestamp is just a type guess!
2027
- return typeCastFromDatabase(context, adapter, runtime.newSymbol("timestamp"), strValue);
2028
- }
2029
- return adapter.callMethod(context, "_string_to_timestamp", strValue);
1886
+ // NOTE: this CAN NOT be 100% correct - as :timestamp is just a type guess!
1887
+ return typeCastFromDatabase(context, adapter, runtime.newSymbol("timestamp"), strValue);
2030
1888
  }
2031
1889
 
2032
1890
  protected static RubyString timestampToRubyString(final Ruby runtime, String value) {
@@ -2041,14 +1899,6 @@ public class RubyJdbcConnection extends RubyObject {
2041
1899
  return RubyString.newUnicodeString(runtime, value);
2042
1900
  }
2043
1901
 
2044
- @Deprecated
2045
- protected IRubyObject timestampToRuby(
2046
- final Ruby runtime, final ResultSet resultSet, final Timestamp value)
2047
- throws SQLException {
2048
- if ( value == null && resultSet.wasNull() ) return runtime.getNil();
2049
-
2050
- return timestampToRubyString(runtime, value.toString());
2051
- }
2052
1902
 
2053
1903
  protected static Boolean rawBoolean;
2054
1904
  static {
@@ -2151,7 +2001,7 @@ public class RubyJdbcConnection extends RubyObject {
2151
2001
  string.append(buf, 0, len);
2152
2002
  }
2153
2003
 
2154
- return RubyString.newUnicodeString(runtime, string.toString());
2004
+ return RubyString.newInternalFromJavaExternal(runtime, string.toString());
2155
2005
  }
2156
2006
 
2157
2007
  protected IRubyObject objectToRuby(final ThreadContext context,
@@ -2190,161 +2040,93 @@ public class RubyJdbcConnection extends RubyObject {
2190
2040
  try {
2191
2041
  if ( xml == null || resultSet.wasNull() ) return runtime.getNil();
2192
2042
 
2193
- return RubyString.newUnicodeString(runtime, xml.getString());
2043
+ return RubyString.newInternalFromJavaExternal(runtime, xml.getString());
2194
2044
  }
2195
2045
  finally { if ( xml != null ) xml.free(); }
2196
2046
  }
2197
2047
 
2198
2048
  protected void setStatementParameters(final ThreadContext context,
2199
2049
  final Connection connection, final PreparedStatement statement,
2200
- final List<?> binds) throws SQLException {
2201
-
2202
- final Ruby runtime = context.getRuntime();
2203
-
2204
- for ( int i = 0; i < binds.size(); i++ ) {
2205
- // [ [ column1, param1 ], [ column2, param2 ], ... ]
2206
- Object param = binds.get(i); IRubyObject column = null;
2207
- if ( param instanceof RubyArray ) {
2208
- final RubyArray _param = (RubyArray) param;
2209
- column = _param.eltInternal(0); param = _param.eltInternal(1);
2210
- }
2211
- else if ( param instanceof List ) {
2212
- final List<?> _param = (List<?>) param;
2213
- column = (IRubyObject) _param.get(0); param = _param.get(1);
2214
- }
2215
- else if ( param instanceof Object[] ) {
2216
- final Object[] _param = (Object[]) param;
2217
- column = (IRubyObject) _param[0]; param = _param[1];
2218
- }
2050
+ final RubyArray binds) throws SQLException {
2219
2051
 
2220
- setStatementParameter(context, runtime, connection, statement, i + 1, param, column);
2052
+ for ( int i = 0; i < binds.getLength(); i++ ) {
2053
+ setStatementParameter(context, connection, statement, i + 1, binds.eltInternal(i));
2221
2054
  }
2222
2055
  }
2223
2056
 
2224
- // So far we have only examined the needs to Sqlite3 but for that adapter (and it is old JDBC adapter)
2225
- // we can pass all tests but binary column types with just the supplied value. So we will leave it
2226
- // this way until we upgrade Sqlite adapter and get some more databases supported.
2227
- protected int typeHack(ThreadContext context, IRubyObject column, Object value) throws SQLException {
2228
- if (column != null) {
2229
- String columnType = column.asString().toString();
2057
+ // Set the prepared statement attributes based on the passed in Attribute object
2058
+ protected void setStatementParameter(final ThreadContext context,
2059
+ final Connection connection, final PreparedStatement statement,
2060
+ final int index, IRubyObject attribute) throws SQLException {
2230
2061
 
2231
- if (columnType.equals("binary")) return jdbcTypeFor(context, context.runtime, column, value);
2062
+ //debugMessage(context, attribute);
2063
+ int type = jdbcTypeForAttribute(context, attribute);
2064
+ IRubyObject value = valueForDatabase(context, attribute);
2232
2065
 
2233
- column = null;
2066
+ // All the set methods were calling this first so save a method call in the nil case
2067
+ if ( value.isNil() ) {
2068
+ statement.setNull(index, type);
2069
+ return;
2234
2070
  }
2235
2071
 
2236
- return jdbcTypeFor(context, context.runtime, column, value);
2237
- }
2238
-
2239
- protected void setStatementParameter(final ThreadContext context,
2240
- final Ruby runtime, final Connection connection,
2241
- final PreparedStatement statement, final int index,
2242
- final Object value, IRubyObject column) throws SQLException {
2243
- int type = typeHack(context, column, value);
2244
-
2245
2072
  switch (type) {
2246
2073
  case Types.TINYINT:
2247
2074
  case Types.SMALLINT:
2248
2075
  case Types.INTEGER:
2249
- if ( value instanceof RubyBignum ) { // e.g. HSQLDB / H2 report JDBC type 4
2250
- setBigIntegerParameter(context, connection, statement, index, (RubyBignum) value, column, type);
2251
- }
2252
- else {
2253
- setIntegerParameter(context, connection, statement, index, value, column, type);
2254
- }
2076
+ setIntegerParameter(context, connection, statement, index, value, attribute, type);
2255
2077
  break;
2256
2078
  case Types.BIGINT:
2257
- setBigIntegerParameter(context, connection, statement, index, value, column, type);
2079
+ setBigIntegerParameter(context, connection, statement, index, value, attribute, type);
2258
2080
  break;
2259
2081
  case Types.REAL:
2260
2082
  case Types.FLOAT:
2261
2083
  case Types.DOUBLE:
2262
- setDoubleParameter(context, connection, statement, index, value, column, type);
2084
+ setDoubleParameter(context, connection, statement, index, value, attribute, type);
2263
2085
  break;
2264
2086
  case Types.NUMERIC:
2265
2087
  case Types.DECIMAL:
2266
- setDecimalParameter(context, connection, statement, index, value, column, type);
2088
+ setDecimalParameter(context, connection, statement, index, value, attribute, type);
2267
2089
  break;
2268
2090
  case Types.DATE:
2269
- setDateParameter(context, connection, statement, index, value, column, type);
2091
+ setDateParameter(context, connection, statement, index, value, attribute, type);
2270
2092
  break;
2271
2093
  case Types.TIME:
2272
- setTimeParameter(context, connection, statement, index, value, column, type);
2094
+ setTimeParameter(context, connection, statement, index, value, attribute, type);
2273
2095
  break;
2274
2096
  case Types.TIMESTAMP:
2275
- setTimestampParameter(context, connection, statement, index, value, column, type);
2097
+ setTimestampParameter(context, connection, statement, index, value, attribute, type);
2276
2098
  break;
2277
2099
  case Types.BIT:
2278
2100
  case Types.BOOLEAN:
2279
- setBooleanParameter(context, connection, statement, index, value, column, type);
2101
+ setBooleanParameter(context, connection, statement, index, value, attribute, type);
2280
2102
  break;
2281
2103
  case Types.SQLXML:
2282
- setXmlParameter(context, connection, statement, index, value, column, type);
2104
+ setXmlParameter(context, connection, statement, index, value, attribute, type);
2283
2105
  break;
2284
2106
  case Types.ARRAY:
2285
- setArrayParameter(context, connection, statement, index, value, column, type);
2107
+ setArrayParameter(context, connection, statement, index, value, attribute, type);
2286
2108
  break;
2287
2109
  case Types.JAVA_OBJECT:
2288
2110
  case Types.OTHER:
2289
- setObjectParameter(context, connection, statement, index, value, column, type);
2111
+ setObjectParameter(context, connection, statement, index, value, attribute, type);
2290
2112
  break;
2291
2113
  case Types.BINARY:
2292
2114
  case Types.VARBINARY:
2293
2115
  case Types.LONGVARBINARY:
2294
2116
  case Types.BLOB:
2295
- setBlobParameter(context, connection, statement, index, value, column, type);
2117
+ setBlobParameter(context, connection, statement, index, value, attribute, type);
2296
2118
  break;
2297
2119
  case Types.CLOB:
2298
2120
  case Types.NCLOB: // JDBC 4.0
2299
- setClobParameter(context, connection, statement, index, value, column, type);
2121
+ setClobParameter(context, connection, statement, index, value, attribute, type);
2300
2122
  break;
2301
2123
  case Types.CHAR:
2302
2124
  case Types.VARCHAR:
2303
2125
  case Types.NCHAR: // JDBC 4.0
2304
2126
  case Types.NVARCHAR: // JDBC 4.0
2305
2127
  default:
2306
- setStringParameter(context, connection, statement, index, value, column, type);
2307
- }
2308
- }
2309
-
2310
- @Deprecated // NOTE: only used from deprecated methods
2311
- private void setPreparedStatementValues(final ThreadContext context,
2312
- final Connection connection, final PreparedStatement statement,
2313
- final IRubyObject valuesArg, final IRubyObject typesArg) throws SQLException {
2314
- final Ruby runtime = context.getRuntime();
2315
- final RubyArray values = (RubyArray) valuesArg;
2316
- final RubyArray types = (RubyArray) typesArg; // column types
2317
- for( int i = 0, j = values.getLength(); i < j; i++ ) {
2318
- setStatementParameter(
2319
- context, runtime, connection, statement, i + 1,
2320
- values.eltInternal(i), types.eltInternal(i)
2321
- );
2322
- }
2323
- }
2324
-
2325
- private RubySymbol resolveColumnType(final ThreadContext context, final Ruby runtime,
2326
- final IRubyObject column) {
2327
- if ( column instanceof RubySymbol ) { // deprecated behavior
2328
- return (RubySymbol) column;
2329
- }
2330
- if ( column instanceof RubyString) { // deprecated behavior
2331
- if ( runtime.is1_9() ) {
2332
- return ( (RubyString) column ).intern19();
2333
- }
2334
- else {
2335
- return ( (RubyString) column ).intern();
2336
- }
2337
- }
2338
-
2339
- if ( column == null || column.isNil() ) {
2340
- throw runtime.newArgumentError("nil column passed");
2341
- }
2342
-
2343
- final IRubyObject type = column.callMethod(context, "type");
2344
- if ( type.isNil() || ! (type instanceof RubySymbol) ) {
2345
- throw new IllegalStateException("unexpected type = " + type.inspect() + " for " + column.inspect());
2128
+ setStringParameter(context, connection, statement, index, value, attribute, type);
2346
2129
  }
2347
- return (RubySymbol) type;
2348
2130
  }
2349
2131
 
2350
2132
  protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<String, Integer>(32, 1);
@@ -2359,7 +2141,6 @@ public class RubyJdbcConnection extends RubyObject {
2359
2141
  JDBC_TYPE_FOR.put("time", Types.TIME);
2360
2142
  JDBC_TYPE_FOR.put("datetime", Types.TIMESTAMP);
2361
2143
  JDBC_TYPE_FOR.put("timestamp", Types.TIMESTAMP);
2362
- JDBC_TYPE_FOR.put("binary", Types.BLOB);
2363
2144
  JDBC_TYPE_FOR.put("boolean", Types.BOOLEAN);
2364
2145
  JDBC_TYPE_FOR.put("array", Types.ARRAY);
2365
2146
  JDBC_TYPE_FOR.put("xml", Types.SQLXML);
@@ -2384,107 +2165,89 @@ public class RubyJdbcConnection extends RubyObject {
2384
2165
  JDBC_TYPE_FOR.put("nclob", Types.NCLOB);
2385
2166
  }
2386
2167
 
2387
- protected int jdbcTypeFor(final ThreadContext context, final Ruby runtime,
2388
- final IRubyObject column, final Object value) throws SQLException {
2168
+ protected int jdbcTypeForAttribute(final ThreadContext context,
2169
+ final IRubyObject attribute) throws SQLException {
2389
2170
 
2390
- final String internedType;
2391
- if ( column != null && ! column.isNil() ) {
2392
- // NOTE: there's no ActiveRecord "convention" really for this ...
2393
- // this is based on Postgre's initial support for arrays :
2394
- // `column.type` contains the base type while there's `column.array?`
2395
- if ( column.respondsTo("array?") && column.callMethod(context, "array?").isTrue() ) {
2396
- internedType = "array";
2397
- }
2398
- else {
2399
- internedType = resolveColumnType(context, runtime, column).asJavaString();
2400
- }
2171
+ final String internedType = internedTypeFor(context, attribute);
2172
+ final Integer sqlType = jdbcTypeFor(internedType);
2173
+ if ( sqlType != null ) {
2174
+ return sqlType.intValue();
2401
2175
  }
2402
- else {
2403
- if ( value instanceof RubyInteger ) internedType = "integer";
2404
- else if ( value instanceof RubyNumeric ) internedType = "float";
2405
- else if ( value instanceof RubyTime ) internedType = "timestamp";
2406
- else internedType = "string";
2407
- }
2408
-
2409
- final Integer sqlType = JDBC_TYPE_FOR.get(internedType);
2410
- if ( sqlType != null ) return sqlType.intValue();
2411
2176
 
2412
2177
  return Types.OTHER; // -1 as well as 0 are used in Types
2413
2178
  }
2414
2179
 
2415
- protected void setIntegerParameter(final ThreadContext context,
2416
- final Connection connection, final PreparedStatement statement,
2417
- final int index, final Object value,
2418
- final IRubyObject column, final int type) throws SQLException {
2419
- if ( value instanceof IRubyObject ) {
2420
- setIntegerParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2180
+ protected Integer jdbcTypeFor(final String type) {
2181
+ return JDBC_TYPE_FOR.get(type);
2182
+ }
2183
+
2184
+ protected IRubyObject attributeType(final ThreadContext context, final IRubyObject attribute) {
2185
+ return attribute.callMethod(context, "type");
2186
+ }
2187
+
2188
+ protected IRubyObject attributeSQLType(final ThreadContext context, final IRubyObject attribute) {
2189
+ return attributeType(context, attribute).callMethod(context, "type");
2190
+ }
2191
+
2192
+ protected String internedTypeFor(final ThreadContext context, final IRubyObject attribute) throws SQLException {
2193
+
2194
+ final IRubyObject type = attributeSQLType(context, attribute);
2195
+
2196
+ if ( !type.isNil() ) {
2197
+ return type.asJavaString();
2421
2198
  }
2422
- else {
2423
- if ( value == null ) statement.setNull(index, Types.INTEGER);
2424
- else {
2425
- statement.setLong(index, ((Number) value).longValue());
2426
- }
2199
+
2200
+ final IRubyObject value = attribute.callMethod(context, "value");
2201
+
2202
+ if ( value instanceof RubyInteger ) {
2203
+ return "integer";
2204
+ }
2205
+
2206
+ if ( value instanceof RubyNumeric ) {
2207
+ return "float";
2427
2208
  }
2209
+
2210
+ if ( value instanceof RubyTime ) {
2211
+ return "timestamp";
2212
+ }
2213
+
2214
+ return "string";
2428
2215
  }
2429
2216
 
2430
2217
  protected void setIntegerParameter(final ThreadContext context,
2431
2218
  final Connection connection, final PreparedStatement statement,
2432
2219
  final int index, final IRubyObject value,
2433
- final IRubyObject column, final int type) throws SQLException {
2434
- if ( value.isNil() ) statement.setNull(index, Types.INTEGER);
2435
- else {
2436
- if ( value instanceof RubyFixnum ) {
2437
- statement.setLong(index, ((RubyFixnum) value).getLongValue());
2438
- }
2439
- else if ( value instanceof RubyNumeric ) {
2440
- // NOTE: fix2int will call value.convertToIngeter for non-numeric
2441
- // types which won't work for Strings since it uses `to_int` ...
2442
- statement.setInt(index, RubyNumeric.fix2int(value));
2443
- }
2444
- else {
2445
- statement.setLong(index, value.convertToInteger("to_i").getLongValue());
2446
- }
2447
- }
2448
- }
2220
+ final IRubyObject attribute, final int type) throws SQLException {
2449
2221
 
2450
- protected void setBigIntegerParameter(final ThreadContext context,
2451
- final Connection connection, final PreparedStatement statement,
2452
- final int index, final Object value,
2453
- final IRubyObject column, final int type) throws SQLException {
2454
- if ( value instanceof IRubyObject ) {
2455
- setBigIntegerParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2222
+ if ( value instanceof RubyBignum ) { // e.g. HSQLDB / H2 report JDBC type 4
2223
+ setBigIntegerParameter(context, connection, statement, index, (RubyBignum) value, attribute, type);
2224
+ }
2225
+ else if ( value instanceof RubyFixnum ) {
2226
+ statement.setLong(index, ((RubyFixnum) value).getLongValue());
2227
+ }
2228
+ else if ( value instanceof RubyNumeric ) {
2229
+ // NOTE: fix2int will call value.convertToInteger for non-numeric
2230
+ // types which won't work for Strings since it uses `to_int` ...
2231
+ statement.setInt(index, RubyNumeric.fix2int(value));
2456
2232
  }
2457
2233
  else {
2458
- if ( value == null ) statement.setNull(index, Types.BIGINT);
2459
- else {
2460
- if ( value instanceof BigDecimal ) {
2461
- statement.setBigDecimal(index, (BigDecimal) value);
2462
- }
2463
- else if ( value instanceof BigInteger ) {
2464
- setLongOrDecimalParameter(statement, index, (BigInteger) value);
2465
- }
2466
- else {
2467
- statement.setLong(index, ((Number) value).longValue());
2468
- }
2469
- }
2234
+ statement.setLong(index, value.convertToInteger("to_i").getLongValue());
2470
2235
  }
2471
2236
  }
2472
2237
 
2473
2238
  protected void setBigIntegerParameter(final ThreadContext context,
2474
2239
  final Connection connection, final PreparedStatement statement,
2475
2240
  final int index, final IRubyObject value,
2476
- final IRubyObject column, final int type) throws SQLException {
2477
- if ( value.isNil() ) statement.setNull(index, Types.INTEGER);
2241
+ final IRubyObject attribute, final int type) throws SQLException {
2242
+
2243
+ if ( value instanceof RubyBignum ) {
2244
+ setLongOrDecimalParameter(statement, index, ((RubyBignum) value).getValue());
2245
+ }
2246
+ else if ( value instanceof RubyInteger ) {
2247
+ statement.setLong(index, ((RubyInteger) value).getLongValue());
2248
+ }
2478
2249
  else {
2479
- if ( value instanceof RubyBignum ) {
2480
- setLongOrDecimalParameter(statement, index, ((RubyBignum) value).getValue());
2481
- }
2482
- else if ( value instanceof RubyInteger ) {
2483
- statement.setLong(index, ((RubyInteger) value).getLongValue());
2484
- }
2485
- else {
2486
- setLongOrDecimalParameter(statement, index, value.convertToInteger("to_i").getBigIntegerValue());
2487
- }
2250
+ setLongOrDecimalParameter(statement, index, value.convertToInteger("to_i").getBigIntegerValue());
2488
2251
  }
2489
2252
  }
2490
2253
 
@@ -2502,153 +2265,63 @@ public class RubyJdbcConnection extends RubyObject {
2502
2265
  }
2503
2266
  }
2504
2267
 
2505
- protected void setDoubleParameter(final ThreadContext context,
2506
- final Connection connection, final PreparedStatement statement,
2507
- final int index, final Object value,
2508
- final IRubyObject column, final int type) throws SQLException {
2509
- if ( value instanceof IRubyObject ) {
2510
- setDoubleParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2511
- }
2512
- else {
2513
- if ( value == null ) statement.setNull(index, Types.DOUBLE);
2514
- else {
2515
- statement.setDouble(index, ((Number) value).doubleValue());
2516
- }
2517
- }
2518
- }
2519
-
2520
2268
  protected void setDoubleParameter(final ThreadContext context,
2521
2269
  final Connection connection, final PreparedStatement statement,
2522
2270
  final int index, final IRubyObject value,
2523
- final IRubyObject column, final int type) throws SQLException {
2524
- if ( value.isNil() ) statement.setNull(index, Types.DOUBLE);
2525
- else {
2526
- if ( value instanceof RubyNumeric ) {
2527
- statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
2528
- }
2529
- else {
2530
- statement.setDouble(index, value.convertToFloat().getDoubleValue());
2531
- }
2532
- }
2533
- }
2271
+ final IRubyObject attribute, final int type) throws SQLException {
2534
2272
 
2535
- protected void setDecimalParameter(final ThreadContext context,
2536
- final Connection connection, final PreparedStatement statement,
2537
- final int index, final Object value,
2538
- final IRubyObject column, final int type) throws SQLException {
2539
- if ( value instanceof IRubyObject ) {
2540
- setDecimalParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2273
+ if ( value instanceof RubyNumeric ) {
2274
+ statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
2541
2275
  }
2542
2276
  else {
2543
- if ( value == null ) statement.setNull(index, Types.DECIMAL);
2544
- else {
2545
- if ( value instanceof BigDecimal ) {
2546
- statement.setBigDecimal(index, (BigDecimal) value);
2547
- }
2548
- else if ( value instanceof BigInteger ) {
2549
- setLongOrDecimalParameter(statement, index, (BigInteger) value);
2550
- }
2551
- else {
2552
- statement.setDouble(index, ((Number) value).doubleValue());
2553
- }
2554
- }
2277
+ statement.setDouble(index, value.convertToFloat().getDoubleValue());
2555
2278
  }
2556
2279
  }
2557
2280
 
2558
2281
  protected void setDecimalParameter(final ThreadContext context,
2559
2282
  final Connection connection, final PreparedStatement statement,
2560
2283
  final int index, final IRubyObject value,
2561
- final IRubyObject column, final int type) throws SQLException {
2562
- if ( value.isNil() ) statement.setNull(index, Types.DECIMAL);
2563
- else {
2564
- // NOTE: RubyBigDecimal moved into org.jruby.ext.bigdecimal (1.6 -> 1.7)
2565
- if ( value.getMetaClass().getName().indexOf("BigDecimal") != -1 ) {
2566
- statement.setBigDecimal(index, getBigDecimalValue(value));
2567
- }
2568
- else if ( value instanceof RubyInteger ) {
2569
- statement.setBigDecimal(index, new BigDecimal(((RubyInteger) value).getBigIntegerValue()));
2570
- }
2571
- else if ( value instanceof RubyNumeric ) {
2572
- statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
2573
- }
2574
- else { // e.g. `BigDecimal '42.00000000000000000001'`
2575
- IRubyObject v = callMethod(context, "BigDecimal", value);
2576
- statement.setBigDecimal(index, getBigDecimalValue(v));
2577
- }
2578
- }
2579
- }
2284
+ final IRubyObject attribute, final int type) throws SQLException {
2580
2285
 
2581
- private static BigDecimal getBigDecimalValue(final IRubyObject value) {
2582
- try { // reflect ((RubyBigDecimal) value).getValue() :
2583
- return (BigDecimal) value.getClass().
2584
- getMethod("getValue", (Class<?>[]) null).
2585
- invoke(value, (Object[]) null);
2286
+ if (value instanceof RubyBigDecimal) {
2287
+ statement.setBigDecimal(index, ((RubyBigDecimal) value).getValue());
2586
2288
  }
2587
- catch (NoSuchMethodException e) {
2588
- throw new RuntimeException(e);
2289
+ else if ( value instanceof RubyInteger ) {
2290
+ statement.setBigDecimal(index, new BigDecimal(((RubyInteger) value).getBigIntegerValue()));
2589
2291
  }
2590
- catch (IllegalAccessException e) {
2591
- throw new RuntimeException(e);
2592
- }
2593
- catch (InvocationTargetException e) {
2594
- throw new RuntimeException(e.getCause() != null ? e.getCause() : e);
2595
- }
2596
- }
2597
-
2598
- protected void setTimestampParameter(final ThreadContext context,
2599
- final Connection connection, final PreparedStatement statement,
2600
- final int index, final Object value,
2601
- final IRubyObject column, final int type) throws SQLException {
2602
- if ( value instanceof IRubyObject ) {
2603
- setTimestampParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2292
+ else if ( value instanceof RubyNumeric ) {
2293
+ statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
2604
2294
  }
2605
- else {
2606
- if ( value == null ) statement.setNull(index, Types.TIMESTAMP);
2607
- else {
2608
- if ( value instanceof Timestamp ) {
2609
- statement.setTimestamp(index, (Timestamp) value);
2610
- }
2611
- else if ( value instanceof java.util.Date ) {
2612
- statement.setTimestamp(index, new Timestamp(((java.util.Date) value).getTime()));
2613
- }
2614
- else {
2615
- statement.setTimestamp(index, Timestamp.valueOf(value.toString()));
2616
- }
2617
- }
2295
+ else { // e.g. `BigDecimal '42.00000000000000000001'`
2296
+ statement.setBigDecimal(index,
2297
+ RubyBigDecimal.newInstance(context, context.runtime.getModule("BigDecimal"), value).getValue());
2618
2298
  }
2619
2299
  }
2620
2300
 
2621
2301
  protected void setTimestampParameter(final ThreadContext context,
2622
2302
  final Connection connection, final PreparedStatement statement,
2623
2303
  final int index, IRubyObject value,
2624
- final IRubyObject column, final int type) throws SQLException {
2625
- if ( value.isNil() ) statement.setNull(index, Types.TIMESTAMP);
2626
- else {
2627
- value = getTimeInDefaultTimeZone(context, value);
2628
- if ( value instanceof RubyTime ) {
2629
- final RubyTime timeValue = (RubyTime) value;
2630
- final DateTime dateTime = timeValue.getDateTime();
2631
-
2632
- final Timestamp timestamp = new Timestamp( dateTime.getMillis() );
2633
- if ( type != Types.DATE ) { // 1942-11-30T01:02:03.123_456
2634
- // getMillis already set nanos to: 123_000_000
2635
- final int usec = (int) timeValue.getUSec(); // 456 on JRuby
2636
- if ( usec >= 0 ) {
2637
- timestamp.setNanos( timestamp.getNanos() + usec * 1000 );
2638
- }
2639
- }
2640
- statement.setTimestamp( index, timestamp, getTimeZoneCalendar(dateTime.getZone().getID()) );
2641
- }
2642
- else if ( value instanceof RubyString ) { // yyyy-[m]m-[d]d hh:mm:ss[.f...]
2643
- final Timestamp timestamp = Timestamp.valueOf( value.toString() );
2644
- statement.setTimestamp( index, timestamp ); // assume local time-zone
2645
- }
2646
- else { // DateTime ( ActiveSupport::TimeWithZone.to_time )
2647
- final RubyFloat timeValue = value.convertToFloat(); // to_f
2648
- final Timestamp timestamp = convertToTimestamp(timeValue);
2304
+ final IRubyObject attribute, final int type) throws SQLException {
2649
2305
 
2650
- statement.setTimestamp( index, timestamp, getTimeZoneCalendar("GMT") );
2651
- }
2306
+ value = callMethod(context, "time_in_default_timezone", value);
2307
+
2308
+ if (value instanceof RubyTime) {
2309
+ final RubyTime timeValue = (RubyTime) value;
2310
+ final DateTime dateTime = timeValue.getDateTime();
2311
+ final Timestamp timestamp = new Timestamp(dateTime.getMillis());
2312
+
2313
+ // 1942-11-30T01:02:03.123_456
2314
+ if (type != Types.DATE && timeValue.getNSec() >= 0) timestamp.setNanos((int) (timestamp.getNanos() + timeValue.getNSec()));
2315
+
2316
+ statement.setTimestamp(index, timestamp, getTimeZoneCalendar(dateTime.getZone().getID()));
2317
+ } else if ( value instanceof RubyString ) { // yyyy-[m]m-[d]d hh:mm:ss[.f...]
2318
+ final Timestamp timestamp = Timestamp.valueOf(value.toString());
2319
+ statement.setTimestamp(index, timestamp); // assume local time-zone
2320
+ } else { // DateTime ( ActiveSupport::TimeWithZone.to_time )
2321
+ final RubyFloat timeValue = value.convertToFloat(); // to_f
2322
+ final Timestamp timestamp = convertToTimestamp(timeValue);
2323
+
2324
+ statement.setTimestamp( index, timestamp, getTimeZoneCalendar("GMT") );
2652
2325
  }
2653
2326
  }
2654
2327
 
@@ -2663,7 +2336,7 @@ public class RubyJdbcConnection extends RubyObject {
2663
2336
  final int len = strValue.getRealSize() - strValue.getBegin();
2664
2337
  if ( dot1 > 0 && dot4 < len ) { // skip .123 but handle .1234
2665
2338
  final int end = Math.min( len - dot4, 3 );
2666
- CharSequence usecSeq = strValue.subSequence(dot4, end);
2339
+ CharSequence usecSeq = strValue.subSequence(dot4, dot4 + end);
2667
2340
  final int usec = Integer.parseInt( usecSeq.toString() );
2668
2341
  if ( usec < 10 ) { // 0.1234 ~> 4
2669
2342
  timestamp.setNanos( timestamp.getNanos() + usec * 100 );
@@ -2679,301 +2352,124 @@ public class RubyJdbcConnection extends RubyObject {
2679
2352
  return timestamp;
2680
2353
  }
2681
2354
 
2682
- protected static IRubyObject getTimeInDefaultTimeZone(final ThreadContext context, IRubyObject value) {
2683
- if ( value.respondsTo("to_time") ) {
2684
- value = value.callMethod(context, "to_time");
2685
- }
2686
- final String method = isDefaultTimeZoneUTC(context) ? "getutc" : "getlocal";
2687
- if ( value.respondsTo(method) ) {
2688
- value = value.callMethod(context, method);
2689
- }
2690
- return value;
2691
- }
2692
-
2693
- protected static boolean isDefaultTimeZoneUTC(final ThreadContext context) {
2694
- final RubyClass base = getBase(context.getRuntime());
2695
- final String tz = base.callMethod(context, "default_timezone").toString(); // :utc
2696
- return "utc".equalsIgnoreCase(tz);
2697
- }
2698
-
2699
2355
  private static Calendar getTimeZoneCalendar(final String ID) {
2700
2356
  return Calendar.getInstance( TimeZone.getTimeZone(ID) );
2701
2357
  }
2702
2358
 
2703
- protected void setTimeParameter(final ThreadContext context,
2704
- final Connection connection, final PreparedStatement statement,
2705
- final int index, final Object value,
2706
- final IRubyObject column, final int type) throws SQLException {
2707
- if ( value instanceof IRubyObject ) {
2708
- setTimeParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2709
- }
2710
- else {
2711
- if ( value == null ) statement.setNull(index, Types.TIME);
2712
- else {
2713
- if ( value instanceof Time ) {
2714
- statement.setTime(index, (Time) value);
2715
- }
2716
- else if ( value instanceof java.util.Date ) {
2717
- statement.setTime(index, new Time(((java.util.Date) value).getTime()));
2718
- }
2719
- else { // hh:mm:ss
2720
- statement.setTime(index, Time.valueOf(value.toString()));
2721
- // statement.setString(index, value.toString());
2722
- }
2723
- }
2724
- }
2725
- }
2726
-
2727
2359
  protected void setTimeParameter(final ThreadContext context,
2728
2360
  final Connection connection, final PreparedStatement statement,
2729
2361
  final int index, IRubyObject value,
2730
- final IRubyObject column, final int type) throws SQLException {
2731
- if ( value.isNil() ) statement.setNull(index, Types.TIME);
2732
- else {
2733
- value = getTimeInDefaultTimeZone(context, value);
2734
- if ( value instanceof RubyTime ) {
2735
- final RubyTime timeValue = (RubyTime) value;
2736
- final DateTime dateTime = timeValue.getDateTime();
2362
+ final IRubyObject attribute, final int type) throws SQLException {
2737
2363
 
2738
- final Time time = new Time( dateTime.getMillis() );
2739
- statement.setTime( index, time, getTimeZoneCalendar(dateTime.getZone().getID()) );
2740
- }
2741
- else if ( value instanceof RubyString ) {
2742
- final Time time = Time.valueOf( value.toString() );
2743
- statement.setTime( index, time ); // assume local time-zone
2744
- }
2745
- else { // DateTime ( ActiveSupport::TimeWithZone.to_time )
2746
- final RubyFloat timeValue = value.convertToFloat(); // to_f
2747
- final Time time = new Time(timeValue.getLongValue() * 1000); // millis
2748
- // java.sql.Time is expected to be only up to second precision
2749
- statement.setTime( index, time, getTimeZoneCalendar("GMT") );
2750
- }
2751
- }
2752
- }
2364
+ value = callMethod(context, "time_in_default_timezone", value);
2753
2365
 
2754
- protected void setDateParameter(final ThreadContext context,
2755
- final Connection connection, final PreparedStatement statement,
2756
- final int index, final Object value,
2757
- final IRubyObject column, final int type) throws SQLException {
2758
- if ( value instanceof IRubyObject ) {
2759
- setDateParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2366
+ if ( value instanceof RubyTime ) {
2367
+ final DateTime dateTime = ((RubyTime) value).getDateTime();
2368
+ final Time time = new Time(dateTime.getMillis());
2369
+
2370
+ statement.setTime(index, time, getTimeZoneCalendar(dateTime.getZone().getID()));
2760
2371
  }
2761
- else {
2762
- if ( value == null ) statement.setNull(index, Types.DATE);
2763
- else {
2764
- if ( value instanceof Date ) {
2765
- statement.setDate(index, (Date) value);
2766
- }
2767
- else if ( value instanceof java.util.Date ) {
2768
- statement.setDate(index, new Date(((java.util.Date) value).getTime()));
2769
- }
2770
- else { // yyyy-[m]m-[d]d
2771
- statement.setDate(index, Date.valueOf(value.toString()));
2772
- // statement.setString(index, value.toString());
2773
- }
2774
- }
2372
+ else if ( value instanceof RubyString ) {
2373
+ final Time time = Time.valueOf(value.toString());
2374
+ statement.setTime(index, time); // assume local time-zone
2375
+ }
2376
+ else { // DateTime ( ActiveSupport::TimeWithZone.to_time )
2377
+ final RubyFloat timeValue = value.convertToFloat(); // to_f
2378
+ final Time time = new Time(timeValue.getLongValue() * 1000); // millis
2379
+ // java.sql.Time is expected to be only up to second precision
2380
+ statement.setTime(index, time, getTimeZoneCalendar("GMT"));
2775
2381
  }
2776
2382
  }
2777
2383
 
2778
2384
  protected void setDateParameter(final ThreadContext context,
2779
2385
  final Connection connection, final PreparedStatement statement,
2780
2386
  final int index, IRubyObject value,
2781
- final IRubyObject column, final int type) throws SQLException {
2782
- if ( value.isNil() ) statement.setNull(index, Types.DATE);
2783
- else {
2784
- //if ( value instanceof RubyString ) {
2785
- // final Date date = Date.valueOf( value.toString() );
2786
- // statement.setDate( index, date ); // assume local time-zone
2787
- // return;
2788
- //}
2789
- if ( ! "Date".equals( value.getMetaClass().getName() ) ) {
2790
- if ( value.respondsTo("to_date") ) {
2791
- value = value.callMethod(context, "to_date");
2792
- }
2793
- }
2794
- final Date date = Date.valueOf( value.asString().toString() ); // to_s
2795
- statement.setDate( index, date /*, getTimeZoneCalendar("GMT") */ );
2796
- }
2797
- }
2387
+ final IRubyObject attribute, final int type) throws SQLException {
2798
2388
 
2799
- protected void setBooleanParameter(final ThreadContext context,
2800
- final Connection connection, final PreparedStatement statement,
2801
- final int index, final Object value,
2802
- final IRubyObject column, final int type) throws SQLException {
2803
- if ( value instanceof IRubyObject ) {
2804
- setBooleanParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2805
- }
2806
- else {
2807
- if ( value == null ) statement.setNull(index, Types.BOOLEAN);
2808
- else {
2809
- statement.setBoolean(index, ((Boolean) value).booleanValue());
2810
- }
2389
+ if ( ! "Date".equals(value.getMetaClass().getName()) && value.respondsTo("to_date") ) {
2390
+ value = value.callMethod(context, "to_date");
2811
2391
  }
2392
+ final Date date = Date.valueOf(value.asString().toString()); // to_s
2393
+ statement.setDate(index, date);
2812
2394
  }
2813
2395
 
2814
2396
  protected void setBooleanParameter(final ThreadContext context,
2815
2397
  final Connection connection, final PreparedStatement statement,
2816
2398
  final int index, final IRubyObject value,
2817
- final IRubyObject column, final int type) throws SQLException {
2818
- if ( value.isNil() ) statement.setNull(index, Types.BOOLEAN);
2819
- else {
2820
- statement.setBoolean(index, value.isTrue());
2821
- }
2822
- }
2823
-
2824
- protected void setStringParameter(final ThreadContext context,
2825
- final Connection connection, final PreparedStatement statement,
2826
- final int index, final Object value,
2827
- final IRubyObject column, final int type) throws SQLException {
2828
- if ( value instanceof IRubyObject ) {
2829
- setStringParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2830
- }
2831
- else {
2832
- if ( value == null ) statement.setNull(index, Types.VARCHAR);
2833
- else {
2834
- statement.setString(index, value.toString());
2835
- }
2836
- }
2399
+ final IRubyObject attribute, final int type) throws SQLException {
2400
+ statement.setBoolean(index, value.isTrue());
2837
2401
  }
2838
2402
 
2839
2403
  protected void setStringParameter(final ThreadContext context,
2840
2404
  final Connection connection, final PreparedStatement statement,
2841
2405
  final int index, final IRubyObject value,
2842
- final IRubyObject column, final int type) throws SQLException {
2843
- if ( value.isNil() ) statement.setNull(index, Types.VARCHAR);
2844
- else {
2845
- statement.setString(index, value.asString().toString());
2846
- }
2847
- }
2406
+ final IRubyObject attribute, final int type) throws SQLException {
2848
2407
 
2849
- protected void setArrayParameter(final ThreadContext context,
2850
- final Connection connection, final PreparedStatement statement,
2851
- final int index, final Object value,
2852
- final IRubyObject column, final int type) throws SQLException {
2853
- if ( value instanceof IRubyObject ) {
2854
- setArrayParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2855
- } else {
2856
- if ( value == null ) {
2857
- statement.setNull(index, Types.ARRAY);
2858
- } else {
2859
- String typeName = resolveArrayBaseTypeName(context, value, column, type);
2860
- Array array = connection.createArrayOf(typeName, (Object[]) value);
2861
- statement.setArray(index, array);
2862
- }
2863
- }
2408
+ statement.setString(index, value.asString().toString());
2864
2409
  }
2865
2410
 
2866
2411
  protected void setArrayParameter(final ThreadContext context,
2867
2412
  final Connection connection, final PreparedStatement statement,
2868
2413
  final int index, final IRubyObject value,
2869
- final IRubyObject column, final int type) throws SQLException {
2870
- if ( value.isNil() ) {
2871
- statement.setNull(index, Types.ARRAY);
2872
- } else {
2873
- String typeName = resolveArrayBaseTypeName(context, value, column, type);
2874
- Array array = connection.createArrayOf(typeName, ((RubyArray) value).toArray());
2875
- statement.setArray(index, array);
2876
- }
2877
- }
2414
+ final IRubyObject attribute, final int type) throws SQLException {
2878
2415
 
2879
- protected String resolveArrayBaseTypeName(final ThreadContext context,
2880
- final Object value, final IRubyObject column, final int type) {
2881
- // return column.callMethod(context, "sql_type").toString();
2882
- String sqlType = column.callMethod(context, "sql_type").toString();
2883
- final int index = sqlType.indexOf('('); // e.g. "character varying(255)"
2884
- if ( index > 0 ) sqlType = sqlType.substring(0, index);
2885
- return sqlType;
2416
+ final String typeName = resolveArrayBaseTypeName(context, attribute);
2417
+ final IRubyObject valueForDB = value.callMethod(context, "values");
2418
+ Array array = connection.createArrayOf(typeName, ((RubyArray) valueForDB).toArray());
2419
+ statement.setArray(index, array);
2886
2420
  }
2887
2421
 
2888
- protected void setXmlParameter(final ThreadContext context,
2889
- final Connection connection, final PreparedStatement statement,
2890
- final int index, final Object value,
2891
- final IRubyObject column, final int type) throws SQLException {
2892
- if ( value instanceof IRubyObject ) {
2893
- setXmlParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2894
- }
2895
- else {
2896
- if ( value == null ) statement.setNull(index, Types.SQLXML);
2897
- else {
2898
- SQLXML xml = connection.createSQLXML();
2899
- xml.setString(value.toString());
2900
- statement.setSQLXML(index, xml);
2901
- }
2422
+ protected String resolveArrayBaseTypeName(final ThreadContext context, final IRubyObject attribute) throws SQLException {
2423
+
2424
+ // This shouldn't return nil at this point because we know we have an array typed attribute
2425
+ final RubySymbol type = (RubySymbol) attributeSQLType(context, attribute);
2426
+
2427
+ // For some reason the driver doesn't like "character varying" as a type
2428
+ if ( type.eql(context.runtime.newSymbol("string")) ){
2429
+ return "text";
2902
2430
  }
2431
+
2432
+ final IRubyObject adapter = callMethod("adapter");
2433
+ final RubyHash nativeTypes = (RubyHash) adapter.callMethod(context, "native_database_types");
2434
+ final RubyHash typeInfo = (RubyHash) nativeTypes.op_aref(context, type);
2435
+
2436
+ return typeInfo.op_aref(context, context.runtime.newSymbol("name")).asString().toString();
2903
2437
  }
2904
2438
 
2905
2439
  protected void setXmlParameter(final ThreadContext context,
2906
2440
  final Connection connection, final PreparedStatement statement,
2907
2441
  final int index, final IRubyObject value,
2908
- final IRubyObject column, final int type) throws SQLException {
2909
- if ( value.isNil() ) statement.setNull(index, Types.SQLXML);
2910
- else {
2911
- SQLXML xml = connection.createSQLXML();
2912
- xml.setString(value.asString().toString());
2913
- statement.setSQLXML(index, xml);
2914
- }
2915
- }
2442
+ final IRubyObject attribute, final int type) throws SQLException {
2916
2443
 
2917
- protected void setBlobParameter(final ThreadContext context,
2918
- final Connection connection, final PreparedStatement statement,
2919
- final int index, final Object value,
2920
- final IRubyObject column, final int type) throws SQLException {
2921
- if ( value instanceof IRubyObject ) {
2922
- setBlobParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2923
- }
2924
- else {
2925
- if ( value == null ) statement.setNull(index, Types.BLOB);
2926
- else {
2927
- //statement.setBlob(index, (InputStream) value);
2928
- statement.setBinaryStream(index, (InputStream) value);
2929
- }
2930
- }
2444
+ SQLXML xml = connection.createSQLXML();
2445
+ xml.setString(value.asString().toString());
2446
+ statement.setSQLXML(index, xml);
2931
2447
  }
2932
2448
 
2933
2449
  protected void setBlobParameter(final ThreadContext context,
2934
2450
  final Connection connection, final PreparedStatement statement,
2935
2451
  final int index, final IRubyObject value,
2936
- final IRubyObject column, final int type) throws SQLException {
2937
- if ( value.isNil() ) statement.setNull(index, Types.BLOB);
2938
- else {
2939
- if ( value instanceof RubyIO ) { // IO/File
2940
- //statement.setBlob(index, ((RubyIO) value).getInStream());
2941
- statement.setBinaryStream(index, ((RubyIO) value).getInStream());
2942
- }
2943
- else { // should be a RubyString
2944
- final ByteList blob = value.asString().getByteList();
2945
- statement.setBytes(index, blob.bytes());
2946
- //statement.setBinaryStream(index,
2947
- // new ByteArrayInputStream(blob.unsafeBytes(), blob.getBegin(), blob.getRealSize()),
2948
- // blob.getRealSize() // length
2949
- // );
2950
- // JDBC 4.0 :
2951
- //statement.setBlob(index,
2952
- // new ByteArrayInputStream(bytes.unsafeBytes(), bytes.getBegin(), bytes.getRealSize())
2953
- //);
2954
- }
2955
- }
2956
- }
2452
+ final IRubyObject attribute, final int type) throws SQLException {
2957
2453
 
2958
- protected void setClobParameter(final ThreadContext context,
2959
- final Connection connection, final PreparedStatement statement,
2960
- final int index, final Object value,
2961
- final IRubyObject column, final int type) throws SQLException {
2962
- if ( value instanceof IRubyObject ) {
2963
- setClobParameter(context, connection, statement, index, (IRubyObject) value, column, type);
2454
+ if ( value instanceof RubyIO ) { // IO/File
2455
+ // JDBC 4.0: statement.setBlob(index, ((RubyIO) value).getInStream());
2456
+ statement.setBinaryStream(index, ((RubyIO) value).getInStream());
2964
2457
  }
2965
- else {
2966
- if ( value == null ) statement.setNull(index, Types.CLOB);
2967
- else {
2968
- statement.setClob(index, (Reader) value);
2969
- }
2458
+ else { // should be a RubyString
2459
+ final ByteList blob = value.asString().getByteList();
2460
+ statement.setBytes(index, blob.bytes());
2461
+
2462
+ // JDBC 4.0 :
2463
+ //statement.setBlob(index,
2464
+ // new ByteArrayInputStream(bytes.unsafeBytes(), bytes.getBegin(), bytes.getRealSize())
2465
+ //);
2970
2466
  }
2971
2467
  }
2972
2468
 
2973
2469
  protected void setClobParameter(final ThreadContext context,
2974
2470
  final Connection connection, final PreparedStatement statement,
2975
2471
  final int index, final IRubyObject value,
2976
- final IRubyObject column, final int type) throws SQLException {
2472
+ final IRubyObject attribute, final int type) throws SQLException {
2977
2473
  if ( value.isNil() ) statement.setNull(index, Types.CLOB);
2978
2474
  else {
2979
2475
  if ( value instanceof RubyIO ) { // IO/File
@@ -2990,35 +2486,32 @@ public class RubyJdbcConnection extends RubyObject {
2990
2486
 
2991
2487
  protected void setObjectParameter(final ThreadContext context,
2992
2488
  final Connection connection, final PreparedStatement statement,
2993
- final int index, Object value,
2994
- final IRubyObject column, final int type) throws SQLException {
2995
- if (value instanceof IRubyObject) {
2996
- value = ((IRubyObject) value).toJava(Object.class);
2997
- }
2998
- if ( value == null ) statement.setNull(index, Types.JAVA_OBJECT);
2999
- statement.setObject(index, value);
3000
- }
2489
+ final int index, IRubyObject value,
2490
+ final IRubyObject attribute, final int type) throws SQLException {
3001
2491
 
3002
- protected final Connection getConnection() {
3003
- return getConnection(false);
2492
+ statement.setObject(index, value.toJava(Object.class));
3004
2493
  }
3005
2494
 
3006
- protected Connection getConnection(boolean error) {
3007
- final Connection connection = (Connection) dataGetStruct(); // synchronized
3008
- if ( connection == null && error ) {
3009
- final RubyClass errorClass = getConnectionNotEstablished( getRuntime() );
3010
- throw new RaiseException(getRuntime(), errorClass, "no connection available", false);
2495
+ protected Connection getConnection(ThreadContext context, boolean reportMissingConnection) {
2496
+ Connection connection = (Connection) dataGetStruct(); // synchronized
2497
+
2498
+ if (connection == null && reportMissingConnection) {
2499
+ throw new RaiseException(getRuntime(), ActiveRecord(context).getClass("ConnectionNotEstablished"),
2500
+ "no connection available", false);
3011
2501
  }
2502
+
3012
2503
  return connection;
3013
2504
  }
3014
2505
 
3015
- private IRubyObject setConnection(final Connection connection) {
3016
- close( getConnection(false) ); // close previously open connection if there is one
2506
+ private IRubyObject setConnection(ThreadContext context, final Connection connection) {
2507
+ close(getConnection(context, false)); // close previously open connection if there is one
2508
+
2509
+ final IRubyObject rubyConnectionObject = connection != null ?
2510
+ convertJavaToRuby(connection) : context.runtime.getNil();
3017
2511
 
3018
- final IRubyObject rubyConnectionObject =
3019
- connection != null ? convertJavaToRuby(connection) : getRuntime().getNil();
3020
2512
  setInstanceVariable( "@connection", rubyConnectionObject );
3021
2513
  dataWrapStruct(connection);
2514
+
3022
2515
  return rubyConnectionObject;
3023
2516
  }
3024
2517
 
@@ -3152,25 +2645,6 @@ public class RubyJdbcConnection extends RubyObject {
3152
2645
  return tables;
3153
2646
  }
3154
2647
 
3155
- /**
3156
- * NOTE: since 1.3.0 only present for binary compatibility (with extensions).
3157
- *
3158
- * @depreacated no longer used - replaced with
3159
- * {@link #matchTables(Ruby, Connection, String, String, String, String[], boolean)}
3160
- * please update your sub-class esp. if you're overriding this method !
3161
- */
3162
- @Deprecated
3163
- protected SQLBlock tableLookupBlock(final Ruby runtime,
3164
- final String catalog, final String schemaPattern,
3165
- final String tablePattern, final String[] types) {
3166
- return new SQLBlock() {
3167
- @Override
3168
- public IRubyObject call(final Connection connection) throws SQLException {
3169
- return matchTables(runtime, connection, catalog, schemaPattern, tablePattern, types, false);
3170
- }
3171
- };
3172
- }
3173
-
3174
2648
  protected static final int COLUMN_NAME = 4;
3175
2649
  protected static final int DATA_TYPE = 5;
3176
2650
  protected static final int TYPE_NAME = 6;
@@ -3212,24 +2686,7 @@ public class RubyJdbcConnection extends RubyObject {
3212
2686
  private static IRubyObject defaultValueFromResultSet(final Ruby runtime, final ResultSet resultSet)
3213
2687
  throws SQLException {
3214
2688
  final String defaultValue = resultSet.getString(COLUMN_DEF);
3215
- return defaultValue == null ? runtime.getNil() : RubyString.newUnicodeString(runtime, defaultValue);
3216
- }
3217
-
3218
- /**
3219
- * Internal API that might be subject to change!
3220
- * @since 1.3.18
3221
- */
3222
- protected static boolean usesType(final Ruby runtime) { // AR 4.2
3223
- return runtime.getModule("ActiveRecord").getConstantAt("Type") != null;
3224
- }
3225
-
3226
- /**
3227
- * This method is considered internal and is not part of AR-JDBC's Java ext
3228
- * API and thus might be subject to change in the future.
3229
- * Please copy it to your own class if you rely on it to avoid issues.
3230
- */
3231
- protected static boolean isAr42(IRubyObject column) {
3232
- return column.respondsTo("cast_type");
2689
+ return defaultValue == null ? runtime.getNil() : RubyString.newInternalFromJavaExternal(runtime, defaultValue);
3233
2690
  }
3234
2691
 
3235
2692
  protected RubyArray mapColumnsResult(final ThreadContext context,
@@ -3258,9 +2715,9 @@ public class RubyJdbcConnection extends RubyObject {
3258
2715
  final IRubyObject config = getConfig(context);
3259
2716
  while ( results.next() ) {
3260
2717
  final String colName = results.getString(COLUMN_NAME);
3261
- final RubyString railsColumnName = RubyString.newUnicodeString(runtime, caseConvertIdentifierForRails(metaData, colName));
2718
+ final RubyString railsColumnName = RubyString.newInternalFromJavaExternal(runtime, caseConvertIdentifierForRails(metaData, colName));
3262
2719
  final IRubyObject defaultValue = defaultValueFromResultSet( runtime, results );
3263
- final RubyString sqlType = RubyString.newUnicodeString( runtime, typeFromResultSet(results) );
2720
+ final RubyString sqlType = RubyString.newInternalFromJavaExternal( runtime, typeFromResultSet(results) );
3264
2721
  final RubyBoolean nullable = runtime.newBoolean( ! results.getString(IS_NULLABLE).trim().equals("NO") );
3265
2722
  final IRubyObject[] args;
3266
2723
  if ( lookupCastType ) {
@@ -3355,22 +2812,8 @@ public class RubyJdbcConnection extends RubyObject {
3355
2812
  return keys;
3356
2813
  }
3357
2814
 
3358
- protected IRubyObject mapGeneratedKey(final Ruby runtime, final ResultSet genKeys)
3359
- throws SQLException {
3360
- return runtime.newFixnum( genKeys.getLong(1) );
3361
- }
3362
-
3363
- protected IRubyObject mapGeneratedKeysOrUpdateCount(final ThreadContext context,
3364
- final Connection connection, final Statement statement) throws SQLException {
3365
- final Ruby runtime = context.getRuntime();
3366
- final IRubyObject key = mapGeneratedKeys(runtime, connection, statement);
3367
- return ( key == null || key.isNil() ) ? runtime.newFixnum( statement.getUpdateCount() ) : key;
3368
- }
3369
-
3370
- @Deprecated
3371
- protected IRubyObject unmarshalKeysOrUpdateCount(final ThreadContext context,
3372
- final Connection connection, final Statement statement) throws SQLException {
3373
- return mapGeneratedKeysOrUpdateCount(context, connection, statement);
2815
+ protected IRubyObject mapGeneratedKey(final Ruby runtime, final ResultSet genKeys) throws SQLException {
2816
+ return runtime.newFixnum(genKeys.getLong(1));
3374
2817
  }
3375
2818
 
3376
2819
  private Boolean supportsGeneratedKeys;
@@ -3386,64 +2829,6 @@ public class RubyJdbcConnection extends RubyObject {
3386
2829
  return supportsGeneratedKeys.booleanValue();
3387
2830
  }
3388
2831
 
3389
- /**
3390
- * @deprecated no longer used - kept for binary compatibility, this method
3391
- * is confusing since it closes the result set it receives and thus was
3392
- * replaced with {@link #mapGeneratedKeys(Ruby, Connection, Statement)}
3393
- */
3394
- @Deprecated
3395
- public static IRubyObject unmarshal_id_result(
3396
- final Ruby runtime, final ResultSet genKeys) throws SQLException {
3397
- try {
3398
- if (genKeys.next() && genKeys.getMetaData().getColumnCount() > 0) {
3399
- return runtime.newFixnum( genKeys.getLong(1) );
3400
- }
3401
- return runtime.getNil();
3402
- }
3403
- finally { close(genKeys); }
3404
- }
3405
-
3406
- protected IRubyObject mapResults(final ThreadContext context,
3407
- final Connection connection, final Statement statement,
3408
- final boolean downCase) throws SQLException {
3409
-
3410
- final Ruby runtime = context.getRuntime();
3411
- IRubyObject result;
3412
- ResultSet resultSet = statement.getResultSet();
3413
- try {
3414
- result = mapToRawResult(context, runtime, connection, resultSet, downCase);
3415
- }
3416
- finally { close(resultSet); }
3417
-
3418
- if ( ! statement.getMoreResults() ) return result;
3419
-
3420
- final List<IRubyObject> results = new ArrayList<IRubyObject>();
3421
- results.add(result);
3422
-
3423
- do {
3424
- resultSet = statement.getResultSet();
3425
- try {
3426
- result = mapToRawResult(context, runtime, connection, resultSet, downCase);
3427
- }
3428
- finally { close(resultSet); }
3429
-
3430
- results.add(result);
3431
- }
3432
- while ( statement.getMoreResults() );
3433
-
3434
- return runtime.newArray(results);
3435
- }
3436
-
3437
- /**
3438
- * @deprecated no longer used but kept for binary compatibility
3439
- */
3440
- @Deprecated
3441
- protected IRubyObject unmarshalResult(final ThreadContext context,
3442
- final DatabaseMetaData metaData, final ResultSet resultSet,
3443
- final boolean downCase) throws SQLException {
3444
- return mapToRawResult(context, context.getRuntime(), metaData, resultSet, downCase);
3445
- }
3446
-
3447
2832
  /**
3448
2833
  * Converts a JDBC result set into an array (rows) of hashes (row).
3449
2834
  *
@@ -3462,20 +2847,6 @@ public class RubyJdbcConnection extends RubyObject {
3462
2847
  return results;
3463
2848
  }
3464
2849
 
3465
- @Deprecated
3466
- @SuppressWarnings("unchecked")
3467
- private IRubyObject mapToRawResult(final ThreadContext context, final Ruby runtime,
3468
- final DatabaseMetaData metaData, final ResultSet resultSet,
3469
- final boolean downCase) throws SQLException {
3470
-
3471
- final ColumnData[] columns = extractColumns(runtime, metaData, resultSet, downCase);
3472
-
3473
- final RubyArray results = runtime.newArray();
3474
- // [ { 'col1': 1, 'col2': 2 }, { 'col1': 3, 'col2': 4 } ]
3475
- populateFromResultSet(context, runtime, (List<IRubyObject>) results, resultSet, columns);
3476
- return results;
3477
- }
3478
-
3479
2850
  private IRubyObject yieldResultRows(final ThreadContext context, final Ruby runtime,
3480
2851
  final Connection connection, final ResultSet resultSet,
3481
2852
  final Block block) throws SQLException {
@@ -3509,23 +2880,6 @@ public class RubyJdbcConnection extends RubyObject {
3509
2880
  return setupColumns(runtime, connection, resultSet.getMetaData(), downCase);
3510
2881
  }
3511
2882
 
3512
- @Deprecated
3513
- protected ColumnData[] extractColumns(final Ruby runtime,
3514
- final DatabaseMetaData metaData, final ResultSet resultSet,
3515
- final boolean downCase) throws SQLException {
3516
- return setupColumns(runtime, metaData, resultSet.getMetaData(), downCase);
3517
- }
3518
-
3519
- /**
3520
- * @deprecated renamed and parameterized to {@link #withConnection(ThreadContext, boolean, Callable)}
3521
- */
3522
- @Deprecated
3523
- @SuppressWarnings("unchecked")
3524
- protected Object withConnectionAndRetry(final ThreadContext context, final SQLBlock block)
3525
- throws RaiseException {
3526
- return withConnection(context, block);
3527
- }
3528
-
3529
2883
  protected <T> T withConnection(final ThreadContext context, final Callable<T> block)
3530
2884
  throws RaiseException {
3531
2885
  try {
@@ -3544,7 +2898,7 @@ public class RubyJdbcConnection extends RubyObject {
3544
2898
  do {
3545
2899
  if ( retry > 0 ) reconnect(context); // we're retrying running block
3546
2900
 
3547
- final Connection connection = getConnection(true);
2901
+ final Connection connection = getConnection(context, true);
3548
2902
  boolean autoCommit = true; // retry in-case getAutoCommit throws
3549
2903
  try {
3550
2904
  autoCommit = connection.getAutoCommit();
@@ -3607,15 +2961,6 @@ public class RubyJdbcConnection extends RubyObject {
3607
2961
  throw wrapException(context, exception);
3608
2962
  }
3609
2963
 
3610
- /**
3611
- * @deprecated use {@link #wrapException(ThreadContext, Throwable)} instead
3612
- * for overriding how exceptions are handled use {@link #handleException(ThreadContext, Throwable)}
3613
- */
3614
- @Deprecated
3615
- protected RuntimeException wrap(final ThreadContext context, final Throwable exception) {
3616
- return wrapException(context, exception);
3617
- }
3618
-
3619
2964
  protected RaiseException wrapException(final ThreadContext context, final Throwable exception) {
3620
2965
  final Ruby runtime = context.getRuntime();
3621
2966
  if ( exception instanceof SQLException ) {
@@ -3703,63 +3048,19 @@ public class RubyJdbcConnection extends RubyObject {
3703
3048
  return end;
3704
3049
  }
3705
3050
 
3706
- /**
3707
- * JDBC connection helper that handles mapping results to
3708
- * <code>ActiveRecord::Result</code> (available since AR-3.1).
3709
- *
3710
- * @see #populateFromResultSet(ThreadContext, Ruby, List, ResultSet, RubyJdbcConnection.ColumnData[])
3711
- * @author kares
3712
- */
3713
- protected static class ResultHandler {
3714
-
3715
- protected static Boolean USE_RESULT;
3716
-
3717
- // AR-3.2 : initialize(columns, rows)
3718
- // AR-4.0 : initialize(columns, rows, column_types = {})
3719
- protected static Boolean INIT_COLUMN_TYPES = Boolean.FALSE;
3051
+ // maps a AR::Result row
3052
+ protected IRubyObject mapRow(final ThreadContext context, final Ruby runtime,
3053
+ final ColumnData[] columns, final ResultSet resultSet,
3054
+ final RubyJdbcConnection connection) throws SQLException {
3055
+ final RubyArray row = runtime.newArray(columns.length);
3720
3056
 
3721
- protected static Boolean FORCE_HASH_ROWS = Boolean.FALSE;
3722
-
3723
- private static volatile ResultHandler instance;
3724
-
3725
- public static ResultHandler getInstance(final Ruby runtime) {
3726
- if ( instance == null ) {
3727
- synchronized(ResultHandler.class) {
3728
- if ( instance == null ) { // fine to initialize twice
3729
- setInstance( new ResultHandler(runtime) );
3730
- }
3731
- }
3732
- }
3733
- return instance;
3057
+ for (int i = 0; i < columns.length; i++) {
3058
+ final ColumnData column = columns[i];
3059
+ row.append(connection.jdbcToRuby(context, runtime, column.index, column.type, resultSet));
3734
3060
  }
3735
3061
 
3736
- protected static synchronized void setInstance(final ResultHandler instance) {
3737
- ResultHandler.instance = instance;
3738
- }
3739
-
3740
- protected ResultHandler(final Ruby runtime) {
3741
- final RubyClass result = getResult(runtime);
3742
- USE_RESULT = result != null && result != runtime.getNilClass();
3743
- }
3744
-
3745
- public IRubyObject mapRow(final ThreadContext context, final Ruby runtime,
3746
- final ColumnData[] columns, final ResultSet resultSet,
3747
- final RubyJdbcConnection connection) throws SQLException {
3748
-
3749
- if ( USE_RESULT ) { // maps a AR::Result row
3750
- final RubyArray row = runtime.newArray(columns.length);
3751
-
3752
- for ( int i = 0; i < columns.length; i++ ) {
3753
- final ColumnData column = columns[i];
3754
- row.append( connection.jdbcToRuby(context, runtime, column.index, column.type, resultSet) );
3755
- }
3756
-
3757
- return row;
3758
- }
3759
- else {
3760
- return mapRawRow(context, runtime, columns, resultSet, connection);
3761
- }
3762
- }
3062
+ return row;
3063
+ }
3763
3064
 
3764
3065
  IRubyObject mapRawRow(final ThreadContext context, final Ruby runtime,
3765
3066
  final ColumnData[] columns, final ResultSet resultSet,
@@ -3777,37 +3078,20 @@ public class RubyJdbcConnection extends RubyObject {
3777
3078
  return row;
3778
3079
  }
3779
3080
 
3780
- public IRubyObject newResult(final ThreadContext context, final Ruby runtime,
3781
- final ColumnData[] columns, final IRubyObject rows) { // rows array
3782
- if ( USE_RESULT ) { // ActiveRecord::Result.new(columns, rows)
3783
- final RubyClass result = getResult(runtime);
3784
- return result.callMethod( context, "new", initArgs(runtime, columns, rows), Block.NULL_BLOCK );
3785
- }
3786
- return rows; // contains { 'col1' => 1, ... } Hash-es
3787
- }
3788
-
3789
- private IRubyObject[] initArgs(final Ruby runtime,
3790
- final ColumnData[] columns, final IRubyObject rows) {
3081
+ protected IRubyObject newResult(final ThreadContext context, ColumnData[] columns, IRubyObject rows) {
3082
+ RubyClass result = ActiveRecord(context).getClass("Result");
3791
3083
 
3792
- final IRubyObject[] args;
3084
+ return Helpers.invoke(context, result, "new", columnsToArray(context, columns), rows);
3085
+ }
3793
3086
 
3794
- final RubyArray cols = RubyArray.newArray(runtime, columns.length);
3087
+ private RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
3088
+ final RubyArray cols = RubyArray.newArray(context.runtime, columns.length);
3795
3089
 
3796
- if ( INIT_COLUMN_TYPES ) { // NOTE: NOT IMPLEMENTED
3797
- for ( int i = 0; i < columns.length; i++ ) {
3798
- cols.append( columns[i].name );
3799
- }
3800
- args = new IRubyObject[] { cols, rows };
3801
- }
3802
- else {
3803
- for ( int i = 0; i < columns.length; i++ ) {
3804
- cols.append( columns[i].name );
3805
- }
3806
- args = new IRubyObject[] { cols, rows };
3807
- }
3808
- return args;
3090
+ for ( int i = 0; i < columns.length; i++ ) {
3091
+ cols.append( columns[i].name );
3809
3092
  }
3810
3093
 
3094
+ return cols;
3811
3095
  }
3812
3096
 
3813
3097
 
@@ -3876,14 +3160,8 @@ public class RubyJdbcConnection extends RubyObject {
3876
3160
  return new TableName(catalog, schema, name);
3877
3161
  }
3878
3162
 
3879
- /**
3880
- * @deprecated use {@link #extractTableName(Connection, String, String, String)}
3881
- */
3882
- @Deprecated
3883
- protected TableName extractTableName(
3884
- final Connection connection, final String schema,
3885
- final String tableName) throws IllegalArgumentException, SQLException {
3886
- return extractTableName(connection, null, schema, tableName);
3163
+ protected IRubyObject valueForDatabase(final ThreadContext context, final IRubyObject attribute) {
3164
+ return attribute.callMethod(context, "value_for_database");
3887
3165
  }
3888
3166
 
3889
3167
  protected static final class ColumnData {
@@ -3921,32 +3199,8 @@ public class RubyJdbcConnection extends RubyObject {
3921
3199
  } else {
3922
3200
  name = caseConvertIdentifierForRails(connection, name);
3923
3201
  }
3924
- final RubyString columnName = RubyString.newUnicodeString(runtime, name);
3925
- final int columnType = resultMetaData.getColumnType(i);
3926
- columns[i - 1] = new ColumnData(columnName, columnType, i);
3927
- }
3928
-
3929
- return columns;
3930
- }
3931
-
3932
- @Deprecated
3933
- private ColumnData[] setupColumns(
3934
- final Ruby runtime,
3935
- final DatabaseMetaData metaData,
3936
- final ResultSetMetaData resultMetaData,
3937
- final boolean downCase) throws SQLException {
3938
3202
 
3939
- final int columnCount = resultMetaData.getColumnCount();
3940
- final ColumnData[] columns = new ColumnData[columnCount];
3941
-
3942
- for ( int i = 1; i <= columnCount; i++ ) { // metadata is one-based
3943
- String name = resultMetaData.getColumnLabel(i);
3944
- if ( downCase ) {
3945
- name = name.toLowerCase();
3946
- } else {
3947
- name = caseConvertIdentifierForRails(metaData, name);
3948
- }
3949
- final RubyString columnName = RubyString.newUnicodeString(runtime, name);
3203
+ final RubyString columnName = RubyString.newInternalFromJavaExternal(runtime, name);
3950
3204
  final int columnType = resultMetaData.getColumnType(i);
3951
3205
  columns[i - 1] = new ColumnData(columnName, columnType, i);
3952
3206
  }
@@ -3998,6 +3252,10 @@ public class RubyJdbcConnection extends RubyObject {
3998
3252
  }
3999
3253
  }
4000
3254
 
3255
+ public static void debugMessage(final ThreadContext context, final IRubyObject item) {
3256
+ debugMessage(context, item.callMethod(context, "inspect").asString().toString());
3257
+ }
3258
+
4001
3259
  protected static void debugErrorSQL(final ThreadContext context, final String sql) {
4002
3260
  if ( debug || ( context != null && context.runtime.isDebug() ) ) {
4003
3261
  final PrintStream out = context != null ? context.runtime.getOut() : System.out;