activerecord-jdbc-adapter 5.0.pre1 → 51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- 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"},
|
248
|
-
public IRubyObject begin(final ThreadContext context, final IRubyObject
|
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.
|
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
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
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
|
-
|
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.
|
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
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
|
384
|
-
|
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 (
|
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
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
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 (
|
445
|
+
if (getConnection(context, false) == null) {
|
485
446
|
synchronized (this) {
|
486
|
-
if (
|
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
|
-
|
498
|
-
|
499
|
-
|
457
|
+
|
458
|
+
if (connection != null && ! connection.isNil()) {
|
459
|
+
return context.runtime.newBoolean(isConnectionValid(context, getConnection(context, false)));
|
500
460
|
}
|
501
|
-
|
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
|
-
|
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(
|
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
|
-
|
520
|
+
final Connection connection = getConnection(context, false);
|
521
|
+
|
522
|
+
if (connection == null) return context.runtime.getFalse();
|
523
|
+
|
560
524
|
try {
|
561
|
-
|
562
|
-
|
563
|
-
setConnection(null); // does connection.close();
|
564
|
-
|
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.
|
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
|
-
|
599
|
-
|
600
|
-
|
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
|
-
|
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
|
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, (
|
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, (
|
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
|
-
|
688
|
+
final IRubyObject sql, final IRubyObject binds) throws SQLException {
|
707
689
|
|
708
690
|
final String query = sql.convertToString().getUnicodeValue();
|
709
|
-
return executePreparedUpdate(context, query, (
|
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
|
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
|
-
*
|
778
|
-
*
|
779
|
-
* @
|
780
|
-
* @param
|
781
|
-
* @
|
782
|
-
* @
|
783
|
-
* @
|
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(
|
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
|
-
|
807
|
-
IRubyObject binds = args.length > 2 ? args[2] : null;
|
772
|
+
final RubyArray binds;
|
808
773
|
final int maxRows;
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
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
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
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
|
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;
|
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
|
-
|
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
|
-
|
818
|
+
hasResult = prepStatement.execute();
|
871
819
|
}
|
872
820
|
|
873
|
-
if (
|
874
|
-
|
875
|
-
|
876
|
-
|
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 {
|
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
|
-
*
|
893
|
-
*
|
894
|
-
*
|
895
|
-
*
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
*
|
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(
|
913
|
-
|
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
|
-
|
919
|
-
IRubyObject binds = args.length > 2 ? args[2] : null;
|
867
|
+
final RubyArray binds;
|
920
868
|
final int maxRows;
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
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 (
|
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, (
|
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
|
-
|
990
|
-
|
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
|
-
|
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
|
-
|
1000
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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(
|
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 (
|
1763
|
-
resultRows.append(
|
1672
|
+
while (resultSet.next()) {
|
1673
|
+
resultRows.append(mapRow(context, runtime, columns, resultSet, this));
|
1764
1674
|
}
|
1765
1675
|
|
1766
|
-
return
|
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
|
-
|
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
|
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
|
1768
|
+
return runtime.newFloat(value);
|
1873
1769
|
}
|
1874
1770
|
|
1875
|
-
|
1876
|
-
|
1877
|
-
final
|
1878
|
-
|
1879
|
-
|
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
|
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
|
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
|
-
|
1923
|
-
return
|
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, "
|
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
|
-
|
1980
|
-
|
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
|
-
|
2003
|
-
|
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
|
-
|
2026
|
-
|
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.
|
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.
|
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
|
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
|
-
|
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
|
-
//
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
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
|
-
|
2062
|
+
//debugMessage(context, attribute);
|
2063
|
+
int type = jdbcTypeForAttribute(context, attribute);
|
2064
|
+
IRubyObject value = valueForDatabase(context, attribute);
|
2232
2065
|
|
2233
|
-
|
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
|
-
|
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,
|
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,
|
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,
|
2088
|
+
setDecimalParameter(context, connection, statement, index, value, attribute, type);
|
2267
2089
|
break;
|
2268
2090
|
case Types.DATE:
|
2269
|
-
setDateParameter(context, connection, statement, index, value,
|
2091
|
+
setDateParameter(context, connection, statement, index, value, attribute, type);
|
2270
2092
|
break;
|
2271
2093
|
case Types.TIME:
|
2272
|
-
setTimeParameter(context, connection, statement, index, value,
|
2094
|
+
setTimeParameter(context, connection, statement, index, value, attribute, type);
|
2273
2095
|
break;
|
2274
2096
|
case Types.TIMESTAMP:
|
2275
|
-
setTimestampParameter(context, connection, statement, index, value,
|
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,
|
2101
|
+
setBooleanParameter(context, connection, statement, index, value, attribute, type);
|
2280
2102
|
break;
|
2281
2103
|
case Types.SQLXML:
|
2282
|
-
setXmlParameter(context, connection, statement, index, value,
|
2104
|
+
setXmlParameter(context, connection, statement, index, value, attribute, type);
|
2283
2105
|
break;
|
2284
2106
|
case Types.ARRAY:
|
2285
|
-
setArrayParameter(context, connection, statement, index, value,
|
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,
|
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,
|
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,
|
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,
|
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
|
2388
|
-
final IRubyObject
|
2168
|
+
protected int jdbcTypeForAttribute(final ThreadContext context,
|
2169
|
+
final IRubyObject attribute) throws SQLException {
|
2389
2170
|
|
2390
|
-
final String internedType;
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
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
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
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
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
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
|
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
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
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
|
-
|
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
|
2477
|
-
|
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
|
-
|
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
|
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
|
-
|
2536
|
-
|
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
|
-
|
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
|
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
|
-
|
2582
|
-
|
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
|
-
|
2588
|
-
|
2289
|
+
else if ( value instanceof RubyInteger ) {
|
2290
|
+
statement.setBigDecimal(index, new BigDecimal(((RubyInteger) value).getBigIntegerValue()));
|
2589
2291
|
}
|
2590
|
-
|
2591
|
-
|
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
|
-
|
2607
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
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
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
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
|
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
|
-
|
2800
|
-
|
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
|
2818
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
2880
|
-
final
|
2881
|
-
|
2882
|
-
|
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
|
2889
|
-
|
2890
|
-
|
2891
|
-
final
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
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
|
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
|
-
|
2918
|
-
|
2919
|
-
|
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
|
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
|
-
|
2959
|
-
|
2960
|
-
|
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
|
-
|
2967
|
-
|
2968
|
-
|
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
|
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,
|
2994
|
-
final IRubyObject
|
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
|
-
|
3003
|
-
return getConnection(false);
|
2492
|
+
statement.setObject(index, value.toJava(Object.class));
|
3004
2493
|
}
|
3005
2494
|
|
3006
|
-
protected Connection getConnection(boolean
|
3007
|
-
|
3008
|
-
|
3009
|
-
|
3010
|
-
throw new RaiseException(getRuntime(),
|
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(
|
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.
|
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.
|
2718
|
+
final RubyString railsColumnName = RubyString.newInternalFromJavaExternal(runtime, caseConvertIdentifierForRails(metaData, colName));
|
3262
2719
|
final IRubyObject defaultValue = defaultValueFromResultSet( runtime, results );
|
3263
|
-
final RubyString sqlType = RubyString.
|
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
|
-
|
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
|
-
|
3708
|
-
|
3709
|
-
|
3710
|
-
|
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
|
-
|
3722
|
-
|
3723
|
-
|
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
|
-
|
3737
|
-
|
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
|
-
|
3781
|
-
|
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
|
-
|
3084
|
+
return Helpers.invoke(context, result, "new", columnsToArray(context, columns), rows);
|
3085
|
+
}
|
3793
3086
|
|
3794
|
-
|
3087
|
+
private RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
|
3088
|
+
final RubyArray cols = RubyArray.newArray(context.runtime, columns.length);
|
3795
3089
|
|
3796
|
-
|
3797
|
-
|
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
|
-
|
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
|
-
|
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;
|