activerecord-jdbc-adapter 1.3.0.beta1 → 1.3.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +12 -11
- data/.travis.yml +36 -7
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -6
- data/History.txt +64 -0
- data/README.md +8 -1
- data/Rakefile +3 -1
- data/gemfiles/rails23.gemfile +1 -1
- data/gemfiles/rails23.gemfile.lock +6 -5
- data/gemfiles/rails30.gemfile +1 -1
- data/gemfiles/rails30.gemfile.lock +7 -6
- data/gemfiles/rails31.gemfile +1 -1
- data/gemfiles/rails31.gemfile.lock +6 -5
- data/gemfiles/rails32.gemfile +1 -1
- data/gemfiles/rails32.gemfile.lock +6 -5
- data/gemfiles/rails40.gemfile +2 -4
- data/gemfiles/rails40.gemfile.lock +37 -51
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
- data/lib/arel/visitors/db2.rb +5 -1
- data/lib/arel/visitors/hsqldb.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +55 -13
- data/lib/arjdbc/db2/adapter.rb +197 -227
- data/lib/arjdbc/db2/as400.rb +124 -0
- data/lib/arjdbc/db2/connection_methods.rb +20 -1
- data/lib/arjdbc/derby/adapter.rb +17 -85
- data/lib/arjdbc/derby/connection_methods.rb +2 -1
- data/lib/arjdbc/discover.rb +55 -47
- data/lib/arjdbc/h2/adapter.rb +52 -18
- data/lib/arjdbc/h2/connection_methods.rb +10 -2
- data/lib/arjdbc/hsqldb/adapter.rb +33 -9
- data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
- data/lib/arjdbc/informix.rb +2 -1
- data/lib/arjdbc/jdbc.rb +5 -1
- data/lib/arjdbc/jdbc/adapter.rb +167 -89
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/base_ext.rb +25 -3
- data/lib/arjdbc/jdbc/callbacks.rb +9 -8
- data/lib/arjdbc/jdbc/column.rb +8 -20
- data/lib/arjdbc/jdbc/connection.rb +69 -80
- data/lib/arjdbc/jdbc/extension.rb +6 -8
- data/lib/arjdbc/jdbc/jdbc.rake +3 -141
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
- data/lib/arjdbc/mssql/adapter.rb +108 -34
- data/lib/arjdbc/mssql/connection_methods.rb +3 -1
- data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
- data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
- data/lib/arjdbc/mysql/adapter.rb +127 -70
- data/lib/arjdbc/mysql/connection_methods.rb +5 -2
- data/lib/arjdbc/oracle/adapter.rb +124 -94
- data/lib/arjdbc/oracle/connection_methods.rb +2 -1
- data/lib/arjdbc/postgresql/adapter.rb +99 -67
- data/lib/arjdbc/postgresql/column_cast.rb +3 -5
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
- data/lib/arjdbc/railtie.rb +3 -1
- data/lib/arjdbc/sqlite3/adapter.rb +60 -43
- data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
- data/lib/arjdbc/sybase.rb +1 -1
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +50 -0
- data/lib/arjdbc/tasks/databases.rake +89 -0
- data/lib/arjdbc/tasks/databases3.rake +203 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +29 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +11 -12
- data/rails_generators/jdbc_generator.rb +1 -1
- data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
- data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
- data/rakelib/02-test.rake +42 -15
- data/rakelib/compile.rake +29 -2
- data/rakelib/db.rake +2 -1
- data/rakelib/rails.rake +23 -6
- data/src/java/arjdbc/ArJdbcModule.java +175 -0
- data/src/java/arjdbc/db2/DB2Module.java +2 -1
- data/src/java/arjdbc/derby/DerbyModule.java +5 -24
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
- data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
- data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
- data/src/java/arjdbc/oracle/OracleModule.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
- data/test/db/db2.rb +14 -7
- data/test/db/db2/rake_test.rb +82 -0
- data/test/db/db2/rake_test_data.sql +35 -0
- data/test/db/db2/simple_test.rb +20 -0
- data/test/db/db2/unit_test.rb +3 -1
- data/test/db/derby.rb +7 -5
- data/test/db/derby/rake_test.rb +96 -0
- data/test/db/derby/simple_test.rb +10 -2
- data/test/db/h2.rb +6 -8
- data/test/db/h2/identity_column_test.rb +35 -0
- data/test/db/h2/offset_test.rb +49 -0
- data/test/db/h2/rake_test.rb +98 -0
- data/test/db/h2/schema_dump_test.rb +5 -1
- data/test/db/hsqldb.rb +6 -10
- data/test/db/hsqldb/rake_test.rb +101 -0
- data/test/db/hsqldb/schema_dump_test.rb +5 -1
- data/test/db/hsqldb/simple_test.rb +8 -0
- data/test/db/jndi_config.rb +1 -3
- data/test/db/jndi_pooled_config.rb +1 -3
- data/test/db/mssql/limit_offset_test.rb +23 -14
- data/test/db/mssql/rake_test.rb +143 -0
- data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
- data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
- data/test/db/mysql/rake_test.rb +97 -0
- data/test/db/mysql/schema_dump_test.rb +11 -11
- data/test/db/mysql/simple_test.rb +52 -3
- data/test/db/mysql/statement_escaping_test.rb +46 -0
- data/test/db/oracle/rake_test.rb +100 -0
- data/test/db/oracle/simple_test.rb +48 -0
- data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
- data/test/db/postgres/active_schema_unit_test.rb +68 -0
- data/test/db/postgres/connection_test.rb +10 -2
- data/test/db/postgres/data_types_test.rb +2 -2
- data/test/db/postgres/ltree_test.rb +6 -5
- data/test/db/postgres/native_types_test.rb +1 -5
- data/test/db/postgres/rake_test.rb +117 -0
- data/test/db/postgres/schema_dump_test.rb +9 -2
- data/test/db/postgres/schema_test.rb +4 -2
- data/test/db/postgres/simple_test.rb +57 -16
- data/test/db/sqlite3.rb +3 -10
- data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
- data/test/db/sqlite3/rake_test.rb +71 -0
- data/test/db/sqlite3/simple_test.rb +9 -9
- data/test/has_many_through.rb +4 -1
- data/test/jdbc/db2.rb +14 -1
- data/test/jdbc_column_test.rb +23 -0
- data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
- data/test/jndi_callbacks_test.rb +26 -28
- data/test/jndi_test.rb +7 -16
- data/test/models/data_types.rb +2 -1
- data/test/models/thing.rb +1 -0
- data/test/rails/mysql.rb +13 -0
- data/test/rails/sqlite3/version.rb +6 -0
- data/test/rails_stub.rb +31 -0
- data/test/rake_test_support.rb +298 -0
- data/test/serialize.rb +2 -4
- data/test/{helper.rb → shared_helper.rb} +0 -0
- data/test/simple.rb +167 -93
- data/test/test_helper.rb +52 -16
- metadata +388 -354
- data/lib/pg.rb +0 -26
- data/test/abstract_db_create.rb +0 -139
- data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
- data/test/db/mssql/db_create_test.rb +0 -29
- data/test/db/mysql/db_create_test.rb +0 -33
- data/test/db/postgres/db_create_test.rb +0 -44
- data/test/db/postgres/db_drop_test.rb +0 -17
|
@@ -36,9 +36,10 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
|
36
36
|
|
|
37
37
|
public class HSQLDBModule {
|
|
38
38
|
|
|
39
|
-
public static
|
|
39
|
+
public static RubyModule load(final RubyModule arJdbc) {
|
|
40
40
|
RubyModule hsqldb = arJdbc.defineModuleUnder("HSQLDB");
|
|
41
|
-
hsqldb.defineAnnotatedMethods(HSQLDBModule.class);
|
|
41
|
+
hsqldb.defineAnnotatedMethods( HSQLDBModule.class );
|
|
42
|
+
return hsqldb;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
@JRubyMethod(name = "quote_string", required = 1, frame = false)
|
|
@@ -28,60 +28,17 @@ package arjdbc.jdbc;
|
|
|
28
28
|
|
|
29
29
|
import java.io.IOException;
|
|
30
30
|
|
|
31
|
-
import arjdbc.
|
|
32
|
-
import arjdbc.db2.DB2RubyJdbcConnection;
|
|
33
|
-
import arjdbc.derby.DerbyModule;
|
|
34
|
-
import arjdbc.derby.DerbyRubyJdbcConnection;
|
|
35
|
-
import arjdbc.h2.H2RubyJdbcConnection;
|
|
36
|
-
import arjdbc.hsqldb.HSQLDBModule;
|
|
37
|
-
import arjdbc.informix.InformixRubyJdbcConnection;
|
|
38
|
-
import arjdbc.mssql.MSSQLModule;
|
|
39
|
-
import arjdbc.mssql.MSSQLRubyJdbcConnection;
|
|
40
|
-
import arjdbc.mysql.MySQLModule;
|
|
41
|
-
import arjdbc.mysql.MySQLRubyJdbcConnection;
|
|
42
|
-
import arjdbc.oracle.OracleModule;
|
|
43
|
-
import arjdbc.oracle.OracleRubyJdbcConnection;
|
|
44
|
-
import arjdbc.postgresql.PostgreSQLRubyJdbcConnection;
|
|
45
|
-
import arjdbc.sqlite3.SQLite3Module;
|
|
46
|
-
import arjdbc.sqlite3.SQLite3RubyJdbcConnection;
|
|
31
|
+
import arjdbc.ArJdbcModule;
|
|
47
32
|
|
|
48
33
|
import org.jruby.Ruby;
|
|
49
|
-
import org.jruby.RubyClass;
|
|
50
|
-
import org.jruby.RubyModule;
|
|
51
34
|
import org.jruby.runtime.load.BasicLibraryService;
|
|
52
35
|
|
|
53
36
|
public class AdapterJavaService implements BasicLibraryService {
|
|
54
37
|
|
|
55
38
|
public boolean basicLoad(final Ruby runtime) throws IOException {
|
|
56
39
|
// ActiveRecord::ConnectionAdapter-s :
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// MySQL
|
|
60
|
-
MySQLModule.load(arJdbc);
|
|
61
|
-
MySQLRubyJdbcConnection.createMySQLJdbcConnectionClass(runtime, jdbcConnection);
|
|
62
|
-
// PostgreSQL
|
|
63
|
-
PostgreSQLRubyJdbcConnection.createPostgreSQLJdbcConnectionClass(runtime, jdbcConnection);
|
|
64
|
-
// SQLite3
|
|
65
|
-
SQLite3Module.load(arJdbc);
|
|
66
|
-
SQLite3RubyJdbcConnection.createSQLite3JdbcConnectionClass(runtime, jdbcConnection);
|
|
67
|
-
// Oracle
|
|
68
|
-
OracleModule.load(arJdbc);
|
|
69
|
-
OracleRubyJdbcConnection.createOracleJdbcConnectionClass(runtime, jdbcConnection);
|
|
70
|
-
// MS-SQL
|
|
71
|
-
MSSQLModule.load(arJdbc);
|
|
72
|
-
MSSQLRubyJdbcConnection.createMSSQLJdbcConnectionClass(runtime, jdbcConnection);
|
|
73
|
-
// DB2
|
|
74
|
-
DB2Module.load(arJdbc);
|
|
75
|
-
DB2RubyJdbcConnection.createDB2JdbcConnectionClass(runtime, jdbcConnection);
|
|
76
|
-
// Derby
|
|
77
|
-
DerbyModule.load(arJdbc);
|
|
78
|
-
DerbyRubyJdbcConnection.createDerbyJdbcConnectionClass(runtime, jdbcConnection);
|
|
79
|
-
// HSQLDB
|
|
80
|
-
HSQLDBModule.load(arJdbc);
|
|
81
|
-
// H2
|
|
82
|
-
H2RubyJdbcConnection.createH2JdbcConnectionClass(runtime, jdbcConnection);
|
|
83
|
-
// Informix
|
|
84
|
-
InformixRubyJdbcConnection.createInformixJdbcConnectionClass(runtime, jdbcConnection);
|
|
40
|
+
RubyJdbcConnection.createJdbcConnectionClass(runtime);
|
|
41
|
+
ArJdbcModule.load(runtime);
|
|
85
42
|
return true;
|
|
86
43
|
}
|
|
87
44
|
|
|
@@ -28,8 +28,12 @@ package arjdbc.jdbc;
|
|
|
28
28
|
import java.io.ByteArrayInputStream;
|
|
29
29
|
import java.io.IOException;
|
|
30
30
|
import java.io.InputStream;
|
|
31
|
+
import java.io.InputStreamReader;
|
|
31
32
|
import java.io.Reader;
|
|
32
33
|
import java.io.StringReader;
|
|
34
|
+
import java.lang.reflect.InvocationTargetException;
|
|
35
|
+
import java.lang.reflect.Method;
|
|
36
|
+
import java.math.BigDecimal;
|
|
33
37
|
import java.math.BigInteger;
|
|
34
38
|
import java.sql.Array;
|
|
35
39
|
import java.sql.Connection;
|
|
@@ -44,8 +48,6 @@ import java.sql.Date;
|
|
|
44
48
|
import java.sql.Time;
|
|
45
49
|
import java.sql.Timestamp;
|
|
46
50
|
import java.sql.Types;
|
|
47
|
-
import java.text.DateFormat;
|
|
48
|
-
import java.text.SimpleDateFormat;
|
|
49
51
|
import java.util.ArrayList;
|
|
50
52
|
import java.util.Calendar;
|
|
51
53
|
import java.util.List;
|
|
@@ -55,7 +57,10 @@ import org.jruby.RubyArray;
|
|
|
55
57
|
import org.jruby.RubyBignum;
|
|
56
58
|
import org.jruby.RubyBoolean;
|
|
57
59
|
import org.jruby.RubyClass;
|
|
60
|
+
import org.jruby.RubyException;
|
|
61
|
+
import org.jruby.RubyFixnum;
|
|
58
62
|
import org.jruby.RubyHash;
|
|
63
|
+
import org.jruby.RubyIO;
|
|
59
64
|
import org.jruby.RubyInteger;
|
|
60
65
|
import org.jruby.RubyModule;
|
|
61
66
|
import org.jruby.RubyNumeric;
|
|
@@ -67,11 +72,11 @@ import org.jruby.anno.JRubyMethod;
|
|
|
67
72
|
import org.jruby.exceptions.RaiseException;
|
|
68
73
|
import org.jruby.javasupport.JavaEmbedUtils;
|
|
69
74
|
import org.jruby.javasupport.JavaUtil;
|
|
70
|
-
import org.jruby.javasupport.util.RuntimeHelpers;
|
|
71
75
|
import org.jruby.runtime.Arity;
|
|
72
76
|
import org.jruby.runtime.Block;
|
|
73
77
|
import org.jruby.runtime.ObjectAllocator;
|
|
74
78
|
import org.jruby.runtime.ThreadContext;
|
|
79
|
+
import org.jruby.runtime.backtrace.RubyStackTraceElement;
|
|
75
80
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
76
81
|
import org.jruby.util.ByteList;
|
|
77
82
|
|
|
@@ -99,7 +104,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
99
104
|
jdbcConnection.defineAnnotatedMethods(RubyJdbcConnection.class);
|
|
100
105
|
return jdbcConnection;
|
|
101
106
|
}
|
|
102
|
-
|
|
107
|
+
|
|
108
|
+
public static RubyClass getJdbcConnectionClass(final Ruby runtime) {
|
|
109
|
+
return getConnectionAdapters(runtime).getClass("JdbcConnection");
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
/**
|
|
104
113
|
* @param runtime
|
|
105
114
|
* @return <code>ActiveRecord::ConnectionAdapters</code>
|
|
@@ -185,7 +194,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
185
194
|
}
|
|
186
195
|
|
|
187
196
|
@JRubyMethod(name = "supports_transaction_isolation?", optional = 1)
|
|
188
|
-
public IRubyObject supports_transaction_isolation_p(final ThreadContext context,
|
|
197
|
+
public IRubyObject supports_transaction_isolation_p(final ThreadContext context,
|
|
189
198
|
final IRubyObject[] args) throws SQLException {
|
|
190
199
|
final IRubyObject isolation = args.length > 0 ? args[0] : null;
|
|
191
200
|
|
|
@@ -284,14 +293,24 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
284
293
|
return getInstanceVariable("@connection");
|
|
285
294
|
}
|
|
286
295
|
|
|
296
|
+
@JRubyMethod(name = "active?")
|
|
297
|
+
public IRubyObject active_p(final ThreadContext context) {
|
|
298
|
+
IRubyObject connection = getInstanceVariable("@connection");
|
|
299
|
+
if ( connection != null && ! connection.isNil() ) {
|
|
300
|
+
return isConnectionValid(context, getConnection(false)) ?
|
|
301
|
+
context.getRuntime().getTrue() : context.getRuntime().getFalse();
|
|
302
|
+
}
|
|
303
|
+
return context.getRuntime().getFalse();
|
|
304
|
+
}
|
|
305
|
+
|
|
287
306
|
@JRubyMethod(name = "disconnect!")
|
|
288
307
|
public IRubyObject disconnect(final ThreadContext context) {
|
|
289
308
|
// TODO: only here to try resolving multi-thread issues :
|
|
290
309
|
// https://github.com/jruby/activerecord-jdbc-adapter/issues/197
|
|
291
310
|
// https://github.com/jruby/activerecord-jdbc-adapter/issues/198
|
|
292
311
|
if ( Boolean.getBoolean("arjdbc.disconnect.debug") ) {
|
|
312
|
+
final List<?> backtrace = createCallerBacktrace(context);
|
|
293
313
|
final Ruby runtime = context.getRuntime();
|
|
294
|
-
List backtrace = (List) context.createCallerBacktrace(runtime, 0);
|
|
295
314
|
runtime.getOut().println(this + " connection.disconnect! occured: ");
|
|
296
315
|
for ( Object element : backtrace ) {
|
|
297
316
|
runtime.getOut().println(element);
|
|
@@ -300,11 +319,22 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
300
319
|
}
|
|
301
320
|
return setConnection(null);
|
|
302
321
|
}
|
|
303
|
-
|
|
322
|
+
|
|
304
323
|
@JRubyMethod(name = "reconnect!")
|
|
305
324
|
public IRubyObject reconnect(final ThreadContext context) {
|
|
306
325
|
try {
|
|
307
|
-
|
|
326
|
+
final Connection connection = getConnectionFactory().newConnection();
|
|
327
|
+
final IRubyObject result = setConnection( connection );
|
|
328
|
+
final IRubyObject adapter = this.callMethod("adapter");
|
|
329
|
+
if ( ! adapter.isNil() ) {
|
|
330
|
+
if ( adapter.respondsTo("configure_connection") ) {
|
|
331
|
+
adapter.callMethod(context, "configure_connection");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
// NOTE: we should probably warn here about adapter not set ?!?
|
|
336
|
+
}
|
|
337
|
+
return result;
|
|
308
338
|
}
|
|
309
339
|
catch (SQLException e) {
|
|
310
340
|
return handleException(context, e);
|
|
@@ -312,14 +342,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
312
342
|
}
|
|
313
343
|
|
|
314
344
|
@JRubyMethod(name = "database_name")
|
|
315
|
-
public IRubyObject database_name(ThreadContext context) throws SQLException {
|
|
316
|
-
Connection connection = getConnection(true);
|
|
345
|
+
public IRubyObject database_name(final ThreadContext context) throws SQLException {
|
|
346
|
+
final Connection connection = getConnection(true);
|
|
317
347
|
String name = connection.getCatalog();
|
|
318
348
|
|
|
319
|
-
if (
|
|
349
|
+
if (name == null) {
|
|
320
350
|
name = connection.getMetaData().getUserName();
|
|
321
|
-
|
|
322
|
-
if (null == name) name = "db1";
|
|
351
|
+
if (name == null) name = "db1"; // TODO why ?
|
|
323
352
|
}
|
|
324
353
|
|
|
325
354
|
return context.getRuntime().newString(name);
|
|
@@ -332,7 +361,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
332
361
|
Statement statement = null;
|
|
333
362
|
final String query = sql.convertToString().getUnicodeValue();
|
|
334
363
|
try {
|
|
335
|
-
statement =
|
|
364
|
+
statement = createStatement(context, connection);
|
|
336
365
|
if ( doExecute(statement, query) ) {
|
|
337
366
|
return unmarshalResults(context, connection.getMetaData(), statement, false);
|
|
338
367
|
} else {
|
|
@@ -348,6 +377,21 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
348
377
|
});
|
|
349
378
|
}
|
|
350
379
|
|
|
380
|
+
protected Statement createStatement(final ThreadContext context, final Connection connection)
|
|
381
|
+
throws SQLException {
|
|
382
|
+
final Statement statement = connection.createStatement();
|
|
383
|
+
IRubyObject statementEscapeProcessing = getConfigValue(context, "statement_escape_processing");
|
|
384
|
+
// NOTE: disable (driver) escape processing by default, it's not really
|
|
385
|
+
// needed for AR statements ... if users need it they might configure :
|
|
386
|
+
if ( statementEscapeProcessing.isNil() ) {
|
|
387
|
+
statement.setEscapeProcessing(false);
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
statement.setEscapeProcessing(statementEscapeProcessing.isTrue());
|
|
391
|
+
}
|
|
392
|
+
return statement;
|
|
393
|
+
}
|
|
394
|
+
|
|
351
395
|
/**
|
|
352
396
|
* Execute a query using the given statement.
|
|
353
397
|
* @param statement
|
|
@@ -379,58 +423,58 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
379
423
|
key = runtime.getNil();
|
|
380
424
|
}
|
|
381
425
|
return key.isNil() ? runtime.newFixnum( statement.getUpdateCount() ) : key;
|
|
382
|
-
|
|
426
|
+
}
|
|
383
427
|
|
|
384
|
-
@JRubyMethod(name = "
|
|
385
|
-
public IRubyObject
|
|
386
|
-
|
|
428
|
+
@JRubyMethod(name = "execute_insert", required = 1)
|
|
429
|
+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql)
|
|
430
|
+
throws SQLException {
|
|
387
431
|
return withConnection(context, new Callable<IRubyObject>() {
|
|
388
432
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
389
|
-
|
|
433
|
+
Statement statement = null;
|
|
390
434
|
final String insertSQL = sql.convertToString().getUnicodeValue();
|
|
391
435
|
try {
|
|
392
|
-
statement = connection
|
|
393
|
-
statement.
|
|
394
|
-
|
|
436
|
+
statement = createStatement(context, connection);
|
|
437
|
+
statement.executeUpdate(insertSQL, Statement.RETURN_GENERATED_KEYS);
|
|
438
|
+
return unmarshalIdResult(context.getRuntime(), statement);
|
|
395
439
|
}
|
|
396
440
|
catch (final SQLException e) {
|
|
397
441
|
debugErrorSQL(context, insertSQL);
|
|
398
442
|
throw e;
|
|
399
443
|
}
|
|
400
444
|
finally { close(statement); }
|
|
401
|
-
return id;
|
|
402
445
|
}
|
|
403
446
|
});
|
|
404
447
|
}
|
|
405
448
|
|
|
406
|
-
@JRubyMethod(name = "
|
|
407
|
-
public IRubyObject
|
|
449
|
+
@JRubyMethod(name = {"execute_update", "execute_delete"}, required = 1)
|
|
450
|
+
public IRubyObject execute_update(final ThreadContext context, final IRubyObject sql)
|
|
408
451
|
throws SQLException {
|
|
409
|
-
return withConnection(context, new Callable<
|
|
410
|
-
public
|
|
452
|
+
return withConnection(context, new Callable<RubyInteger>() {
|
|
453
|
+
public RubyInteger call(final Connection connection) throws SQLException {
|
|
411
454
|
Statement statement = null;
|
|
412
|
-
final String
|
|
455
|
+
final String updateSQL = sql.convertToString().getUnicodeValue();
|
|
413
456
|
try {
|
|
414
|
-
statement =
|
|
415
|
-
statement.executeUpdate(
|
|
416
|
-
return
|
|
457
|
+
statement = createStatement(context, connection);
|
|
458
|
+
final int rowCount = statement.executeUpdate(updateSQL);
|
|
459
|
+
return context.getRuntime().newFixnum(rowCount);
|
|
417
460
|
}
|
|
418
461
|
catch (final SQLException e) {
|
|
419
|
-
debugErrorSQL(context,
|
|
462
|
+
debugErrorSQL(context, updateSQL);
|
|
420
463
|
throw e;
|
|
421
464
|
}
|
|
422
465
|
finally { close(statement); }
|
|
423
466
|
}
|
|
424
467
|
});
|
|
425
468
|
}
|
|
426
|
-
|
|
469
|
+
|
|
427
470
|
/**
|
|
428
471
|
* NOTE: since 1.3 this behaves like <code>execute_query</code> in AR-JDBC 1.2
|
|
429
472
|
* @param context
|
|
430
473
|
* @param sql
|
|
431
|
-
* @param block
|
|
432
|
-
* @return raw query result
|
|
474
|
+
* @param block (optional) block to yield row values
|
|
475
|
+
* @return raw query result as a name => value Hash (unless block given)
|
|
433
476
|
* @throws SQLException
|
|
477
|
+
* @see #execute_query_raw(ThreadContext, IRubyObject[], Block)
|
|
434
478
|
*/
|
|
435
479
|
@JRubyMethod(name = "execute_query_raw", required = 1) // optional block
|
|
436
480
|
public IRubyObject execute_query_raw(final ThreadContext context,
|
|
@@ -442,20 +486,44 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
442
486
|
/**
|
|
443
487
|
* NOTE: since 1.3 this behaves like <code>execute_query</code> in AR-JDBC 1.2
|
|
444
488
|
* @param context
|
|
445
|
-
* @param
|
|
446
|
-
* @param
|
|
447
|
-
* @
|
|
448
|
-
* @return raw query result in case no block given
|
|
489
|
+
* @param args
|
|
490
|
+
* @param block (optional) block to yield row values
|
|
491
|
+
* @return raw query result as a name => value Hash (unless block given)
|
|
449
492
|
* @throws SQLException
|
|
450
493
|
*/
|
|
451
|
-
@JRubyMethod(name = "execute_query_raw", required = 2)
|
|
494
|
+
@JRubyMethod(name = "execute_query_raw", required = 2, optional = 1)
|
|
495
|
+
// @JRubyMethod(name = "execute_query_raw", required = 1, optional = 2)
|
|
452
496
|
public IRubyObject execute_query_raw(final ThreadContext context,
|
|
453
|
-
final IRubyObject
|
|
454
|
-
|
|
455
|
-
final String query =
|
|
456
|
-
|
|
497
|
+
final IRubyObject[] args, final Block block) throws SQLException {
|
|
498
|
+
// args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
|
|
499
|
+
final String query = args[0].convertToString().getUnicodeValue(); // sql
|
|
500
|
+
IRubyObject max_rows = args.length > 1 ? args[1] : null;
|
|
501
|
+
IRubyObject binds = args.length > 2 ? args[2] : null;
|
|
502
|
+
final int maxRows;
|
|
503
|
+
if ( max_rows == null || max_rows.isNil() ) maxRows = 0;
|
|
504
|
+
else {
|
|
505
|
+
if ( binds instanceof RubyNumeric ) { // (sql, max_rows)
|
|
506
|
+
maxRows = RubyNumeric.fix2int(binds); binds = null;
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
if ( max_rows instanceof RubyNumeric ) {
|
|
510
|
+
maxRows = RubyNumeric.fix2int(max_rows);
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
if ( binds == null ) binds = max_rows; // (sql, binds)
|
|
514
|
+
maxRows = 0;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if ( binds == null || binds.isNil() ) { // no prepared statements
|
|
520
|
+
return executeQueryRaw(context, query, maxRows, block);
|
|
521
|
+
}
|
|
522
|
+
else { // we allow prepared statements with empty binds parameters
|
|
523
|
+
return executePreparedQueryRaw(context, query, (List) binds, maxRows, block);
|
|
524
|
+
}
|
|
457
525
|
}
|
|
458
|
-
|
|
526
|
+
|
|
459
527
|
/**
|
|
460
528
|
* @param context
|
|
461
529
|
* @param query
|
|
@@ -463,20 +531,46 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
463
531
|
* @param block
|
|
464
532
|
* @return raw query result (in case no block was given)
|
|
465
533
|
*
|
|
466
|
-
* @see #
|
|
467
|
-
* @see #execute_raw_query(ThreadContext, IRubyObject, IRubyObject, Block)
|
|
534
|
+
* @see #execute_query_raw(ThreadContext, IRubyObject[], Block)
|
|
468
535
|
*/
|
|
469
|
-
protected IRubyObject executeQueryRaw(final ThreadContext context,
|
|
470
|
-
final
|
|
536
|
+
protected IRubyObject executeQueryRaw(final ThreadContext context,
|
|
537
|
+
final String query, final int maxRows, final Block block) {
|
|
538
|
+
return doExecuteQueryRaw(context, query, maxRows, block, null); // binds == null
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
protected IRubyObject executePreparedQueryRaw(final ThreadContext context,
|
|
542
|
+
final String query, final List<?> binds, final int maxRows, final Block block) {
|
|
543
|
+
return doExecuteQueryRaw(context, query, maxRows, block, binds);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private IRubyObject doExecuteQueryRaw(final ThreadContext context,
|
|
547
|
+
final String query, final int maxRows, final Block block, final List<?> binds) {
|
|
471
548
|
return withConnection(context, new Callable<IRubyObject>() {
|
|
472
549
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
473
550
|
final Ruby runtime = context.getRuntime();
|
|
551
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
552
|
+
|
|
474
553
|
Statement statement = null; ResultSet resultSet = null;
|
|
475
554
|
try {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
555
|
+
if ( binds == null ) { // plain statement
|
|
556
|
+
statement = createStatement(context, connection);
|
|
557
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
|
558
|
+
resultSet = statement.executeQuery(query);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
final PreparedStatement prepStatement;
|
|
562
|
+
statement = prepStatement = connection.prepareStatement(query);
|
|
563
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
|
564
|
+
setStatementParameters(context, connection, prepStatement, binds);
|
|
565
|
+
resultSet = prepStatement.executeQuery();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if ( block != null && block.isGiven() ) {
|
|
569
|
+
// yield(id1, name1) ... row 1 result data
|
|
570
|
+
// yield(id2, name2) ... row 2 result data
|
|
571
|
+
return yieldResultRows(context, runtime, metaData, resultSet, block);
|
|
572
|
+
}
|
|
573
|
+
|
|
480
574
|
return mapToRawResult(context, runtime, metaData, resultSet, false);
|
|
481
575
|
}
|
|
482
576
|
catch (final SQLException e) {
|
|
@@ -487,38 +581,62 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
487
581
|
}
|
|
488
582
|
});
|
|
489
583
|
}
|
|
490
|
-
|
|
584
|
+
|
|
491
585
|
/**
|
|
492
586
|
* Executes a query and returns the (AR) result.
|
|
493
587
|
* @param context
|
|
494
588
|
* @param sql
|
|
495
|
-
* @return
|
|
496
|
-
* @throws SQLException
|
|
497
|
-
*
|
|
498
|
-
* @see #execute_raw_query(ThreadContext, IRubyObject, Block)
|
|
589
|
+
* @return raw query result as a name => value Hash (unless block given)
|
|
590
|
+
* @throws SQLException
|
|
591
|
+
* @see #execute_query(ThreadContext, IRubyObject[], Block)
|
|
499
592
|
*/
|
|
500
593
|
@JRubyMethod(name = "execute_query", required = 1)
|
|
501
|
-
public IRubyObject execute_query(final ThreadContext context,
|
|
502
|
-
throws SQLException {
|
|
594
|
+
public IRubyObject execute_query(final ThreadContext context,
|
|
595
|
+
final IRubyObject sql) throws SQLException {
|
|
503
596
|
final String query = sql.convertToString().getUnicodeValue();
|
|
504
597
|
return executeQuery(context, query, 0);
|
|
505
598
|
}
|
|
506
|
-
|
|
599
|
+
|
|
507
600
|
/**
|
|
508
601
|
* Executes a query and returns the (AR) result.
|
|
509
602
|
* @param context
|
|
510
|
-
* @param
|
|
511
|
-
* @
|
|
512
|
-
* @return
|
|
603
|
+
* @param args
|
|
604
|
+
* @return and <code>ActiveRecord::Result</code>
|
|
513
605
|
* @throws SQLException
|
|
514
606
|
*
|
|
515
|
-
* @see #
|
|
607
|
+
* @see #execute_query(ThreadContext, IRubyObject, IRubyObject, Block)
|
|
516
608
|
*/
|
|
517
|
-
@JRubyMethod(name = "execute_query", required = 2)
|
|
609
|
+
@JRubyMethod(name = "execute_query", required = 2, optional = 1)
|
|
610
|
+
// @JRubyMethod(name = "execute_query", required = 1, optional = 2)
|
|
518
611
|
public IRubyObject execute_query(final ThreadContext context,
|
|
519
|
-
final IRubyObject
|
|
520
|
-
|
|
521
|
-
|
|
612
|
+
final IRubyObject[] args) throws SQLException {
|
|
613
|
+
// args: (sql), (sql, max_rows), (sql, binds), (sql, max_rows, binds)
|
|
614
|
+
final String query = args[0].convertToString().getUnicodeValue(); // sql
|
|
615
|
+
IRubyObject max_rows = args.length > 1 ? args[1] : null;
|
|
616
|
+
IRubyObject binds = args.length > 2 ? args[2] : null;
|
|
617
|
+
final int maxRows;
|
|
618
|
+
if ( max_rows == null || max_rows.isNil() ) maxRows = 0;
|
|
619
|
+
else {
|
|
620
|
+
if ( binds instanceof RubyNumeric ) { // (sql, max_rows)
|
|
621
|
+
maxRows = RubyNumeric.fix2int(binds); binds = null;
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
if ( max_rows instanceof RubyNumeric ) {
|
|
625
|
+
maxRows = RubyNumeric.fix2int(max_rows);
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
if ( binds == null ) binds = max_rows; // (sql, binds)
|
|
629
|
+
maxRows = 0;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if ( binds == null || binds.isNil() ) { // no prepared statements
|
|
635
|
+
return executeQuery(context, query, maxRows);
|
|
636
|
+
}
|
|
637
|
+
else { // we allow prepared statements with empty binds parameters
|
|
638
|
+
return executePreparedQuery(context, query, (List) binds, maxRows);
|
|
639
|
+
}
|
|
522
640
|
}
|
|
523
641
|
|
|
524
642
|
/**
|
|
@@ -537,15 +655,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
537
655
|
protected IRubyObject executeQuery(final ThreadContext context, final String query, final int maxRows) {
|
|
538
656
|
return withConnection(context, new Callable<IRubyObject>() {
|
|
539
657
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
540
|
-
final Ruby runtime = context.getRuntime();
|
|
541
658
|
Statement statement = null; ResultSet resultSet = null;
|
|
542
659
|
try {
|
|
543
|
-
|
|
544
|
-
statement = connection.createStatement();
|
|
660
|
+
statement = createStatement(context, connection);
|
|
545
661
|
statement.setMaxRows(maxRows); // zero means there is no limit
|
|
546
662
|
resultSet = statement.executeQuery(query);
|
|
547
|
-
|
|
548
|
-
return mapToResult(context, runtime, metaData, resultSet, columns);
|
|
663
|
+
return mapQueryResult(context, connection, resultSet);
|
|
549
664
|
}
|
|
550
665
|
catch (final SQLException e) {
|
|
551
666
|
debugErrorSQL(context, query);
|
|
@@ -556,27 +671,57 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
556
671
|
});
|
|
557
672
|
}
|
|
558
673
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
Statement statement = null;
|
|
565
|
-
final String updateSQL = sql.convertToString().getUnicodeValue();
|
|
674
|
+
protected IRubyObject executePreparedQuery(final ThreadContext context, final String query,
|
|
675
|
+
final List<?> binds, final int maxRows) {
|
|
676
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
677
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
678
|
+
PreparedStatement statement = null; ResultSet resultSet = null;
|
|
566
679
|
try {
|
|
567
|
-
statement = connection.
|
|
568
|
-
|
|
569
|
-
|
|
680
|
+
statement = connection.prepareStatement(query);
|
|
681
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
|
682
|
+
setStatementParameters(context, connection, statement, binds);
|
|
683
|
+
resultSet = statement.executeQuery();
|
|
684
|
+
return mapQueryResult(context, connection, resultSet);
|
|
570
685
|
}
|
|
571
686
|
catch (final SQLException e) {
|
|
572
|
-
debugErrorSQL(context,
|
|
687
|
+
debugErrorSQL(context, query);
|
|
573
688
|
throw e;
|
|
574
689
|
}
|
|
575
|
-
finally { close(statement); }
|
|
690
|
+
finally { close(resultSet); close(statement); }
|
|
576
691
|
}
|
|
577
692
|
});
|
|
578
693
|
}
|
|
694
|
+
|
|
695
|
+
private IRubyObject mapQueryResult(final ThreadContext context,
|
|
696
|
+
final Connection connection, final ResultSet resultSet) throws SQLException {
|
|
697
|
+
final Ruby runtime = context.getRuntime();
|
|
698
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
699
|
+
final ColumnData[] columns = setupColumns(runtime, metaData, resultSet.getMetaData(), false);
|
|
700
|
+
return mapToResult(context, runtime, metaData, resultSet, columns);
|
|
701
|
+
}
|
|
579
702
|
|
|
703
|
+
@JRubyMethod(name = "execute_id_insert", required = 2)
|
|
704
|
+
public IRubyObject execute_id_insert(final ThreadContext context,
|
|
705
|
+
final IRubyObject sql, final IRubyObject id) throws SQLException {
|
|
706
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
707
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
708
|
+
PreparedStatement statement = null;
|
|
709
|
+
final String insertSQL = sql.convertToString().getUnicodeValue();
|
|
710
|
+
try {
|
|
711
|
+
statement = connection.prepareStatement(insertSQL);
|
|
712
|
+
statement.setLong(1, RubyNumeric.fix2long(id));
|
|
713
|
+
statement.executeUpdate();
|
|
714
|
+
}
|
|
715
|
+
catch (final SQLException e) {
|
|
716
|
+
debugErrorSQL(context, insertSQL);
|
|
717
|
+
throw e;
|
|
718
|
+
}
|
|
719
|
+
finally { close(statement); }
|
|
720
|
+
return id;
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
580
725
|
@JRubyMethod(name = "native_database_types", frame = false)
|
|
581
726
|
public IRubyObject native_database_types() {
|
|
582
727
|
return getInstanceVariable("@native_database_types");
|
|
@@ -631,7 +776,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
631
776
|
|
|
632
777
|
return runtime.getNil();
|
|
633
778
|
}
|
|
634
|
-
|
|
779
|
+
|
|
635
780
|
@JRubyMethod(name = "tables")
|
|
636
781
|
public IRubyObject tables(ThreadContext context) {
|
|
637
782
|
return tables(context, null, null, null, TABLE_TYPE);
|
|
@@ -670,19 +815,33 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
670
815
|
return TABLE_TYPES;
|
|
671
816
|
}
|
|
672
817
|
|
|
673
|
-
@JRubyMethod(name = "table_exists?"
|
|
674
|
-
public IRubyObject table_exists_p(final ThreadContext context,
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
name = name.callMethod(context, "to_s");
|
|
818
|
+
@JRubyMethod(name = "table_exists?")
|
|
819
|
+
public IRubyObject table_exists_p(final ThreadContext context, IRubyObject table) {
|
|
820
|
+
if ( table.isNil() ) {
|
|
821
|
+
throw context.getRuntime().newArgumentError("nil table name");
|
|
678
822
|
}
|
|
679
|
-
final String tableName =
|
|
680
|
-
|
|
681
|
-
|
|
823
|
+
final String tableName = table.toString();
|
|
824
|
+
|
|
825
|
+
return tableExists(context, null, tableName);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
@JRubyMethod(name = "table_exists?")
|
|
829
|
+
public IRubyObject table_exists_p(final ThreadContext context, IRubyObject table, IRubyObject schema) {
|
|
830
|
+
if ( table.isNil() ) {
|
|
831
|
+
throw context.getRuntime().newArgumentError("nil table name");
|
|
832
|
+
}
|
|
833
|
+
final String tableName = table.toString();
|
|
834
|
+
final String defaultSchema = schema.isNil() ? null : schema.toString();
|
|
682
835
|
|
|
836
|
+
return tableExists(context, defaultSchema, tableName);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
protected IRubyObject tableExists(final ThreadContext context,
|
|
840
|
+
final String defaultSchema, final String tableName) {
|
|
841
|
+
final Ruby runtime = context.getRuntime();
|
|
683
842
|
return withConnection(context, new Callable<RubyBoolean>() {
|
|
684
843
|
public RubyBoolean call(final Connection connection) throws SQLException {
|
|
685
|
-
final TableName components = extractTableName(connection,
|
|
844
|
+
final TableName components = extractTableName(connection, defaultSchema, tableName);
|
|
686
845
|
return runtime.newBoolean( tableExists(runtime, connection, components) );
|
|
687
846
|
}
|
|
688
847
|
});
|
|
@@ -695,7 +854,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
695
854
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
696
855
|
ResultSet columns = null, primaryKeys = null;
|
|
697
856
|
try {
|
|
698
|
-
final String tableName = args[0].
|
|
857
|
+
final String tableName = args[0].toString();
|
|
699
858
|
// optionals (NOTE: catalog argumnet was never used before 1.3.0) :
|
|
700
859
|
final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
|
|
701
860
|
final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
|
|
@@ -724,12 +883,17 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
724
883
|
}
|
|
725
884
|
});
|
|
726
885
|
}
|
|
886
|
+
|
|
887
|
+
@JRubyMethod(name = "indexes")
|
|
888
|
+
public IRubyObject indexes(final ThreadContext context, IRubyObject tableName, IRubyObject name) {
|
|
889
|
+
return indexes(context, toStringOrNull(tableName), toStringOrNull(name), null);
|
|
890
|
+
}
|
|
727
891
|
|
|
728
892
|
@JRubyMethod(name = "indexes")
|
|
729
|
-
public IRubyObject indexes(ThreadContext context, IRubyObject tableName, IRubyObject name, IRubyObject schemaName) {
|
|
893
|
+
public IRubyObject indexes(final ThreadContext context, IRubyObject tableName, IRubyObject name, IRubyObject schemaName) {
|
|
730
894
|
return indexes(context, toStringOrNull(tableName), toStringOrNull(name), toStringOrNull(schemaName));
|
|
731
895
|
}
|
|
732
|
-
|
|
896
|
+
|
|
733
897
|
// NOTE: metaData.getIndexInfo row mappings :
|
|
734
898
|
private static final int INDEX_INFO_TABLE_NAME = 3;
|
|
735
899
|
private static final int INDEX_INFO_NON_UNIQUE = 4;
|
|
@@ -808,7 +972,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
808
972
|
|
|
809
973
|
// NOTE: this seems to be not used ... at all ?!
|
|
810
974
|
/*
|
|
811
|
-
* sql, values, types, name = nil, pk = nil, id_value = nil, sequence_name = nil
|
|
975
|
+
* sql, values (array), types (column.type array), name = nil, pk = nil, id_value = nil, sequence_name = nil
|
|
812
976
|
*/
|
|
813
977
|
@Deprecated
|
|
814
978
|
@JRubyMethod(name = "insert_bind", required = 3, rest = true)
|
|
@@ -820,7 +984,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
820
984
|
PreparedStatement statement = null;
|
|
821
985
|
try {
|
|
822
986
|
statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
|
823
|
-
|
|
987
|
+
setPreparedStatementValues(context, connection, statement, args[1], args[2]);
|
|
824
988
|
statement.executeUpdate();
|
|
825
989
|
return unmarshalIdResult(runtime, statement);
|
|
826
990
|
}
|
|
@@ -831,7 +995,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
831
995
|
|
|
832
996
|
// NOTE: this seems to be not used ... at all ?!
|
|
833
997
|
/*
|
|
834
|
-
* sql, values, types, name = nil
|
|
998
|
+
* sql, values (array), types (column.type array), name = nil
|
|
835
999
|
*/
|
|
836
1000
|
@Deprecated
|
|
837
1001
|
@JRubyMethod(name = "update_bind", required = 3, rest = true)
|
|
@@ -844,7 +1008,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
844
1008
|
PreparedStatement statement = null;
|
|
845
1009
|
try {
|
|
846
1010
|
statement = connection.prepareStatement(sql);
|
|
847
|
-
|
|
1011
|
+
setPreparedStatementValues(context, connection, statement, args[1], args[2]);
|
|
848
1012
|
statement.executeUpdate();
|
|
849
1013
|
}
|
|
850
1014
|
finally { close(statement); }
|
|
@@ -870,10 +1034,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
870
1034
|
throws SQLException {
|
|
871
1035
|
|
|
872
1036
|
final boolean isBinary = args[0].isTrue();
|
|
873
|
-
final
|
|
874
|
-
final
|
|
875
|
-
final
|
|
876
|
-
final
|
|
1037
|
+
final String columnName = args[1].toString();
|
|
1038
|
+
final String tableName = args[2].toString();
|
|
1039
|
+
final String idKey = args[3].toString();
|
|
1040
|
+
final String idVal = args[4].toString();
|
|
877
1041
|
final IRubyObject lobValue = args[5];
|
|
878
1042
|
|
|
879
1043
|
final Ruby runtime = context.getRuntime();
|
|
@@ -951,16 +1115,16 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
951
1115
|
protected IRubyObject config_value(ThreadContext context, String key) {
|
|
952
1116
|
return getConfigValue(context, key);
|
|
953
1117
|
}
|
|
954
|
-
|
|
955
|
-
private static String toStringOrNull(IRubyObject arg) {
|
|
1118
|
+
|
|
1119
|
+
private static String toStringOrNull(final IRubyObject arg) {
|
|
956
1120
|
return arg.isNil() ? null : arg.toString();
|
|
957
1121
|
}
|
|
958
1122
|
|
|
959
|
-
protected IRubyObject getAdapter(ThreadContext context) {
|
|
1123
|
+
protected IRubyObject getAdapter(final ThreadContext context) {
|
|
960
1124
|
return callMethod(context, "adapter");
|
|
961
1125
|
}
|
|
962
1126
|
|
|
963
|
-
protected IRubyObject getJdbcColumnClass(ThreadContext context) {
|
|
1127
|
+
protected IRubyObject getJdbcColumnClass(final ThreadContext context) {
|
|
964
1128
|
return getAdapter(context).callMethod(context, "jdbc_column_class");
|
|
965
1129
|
}
|
|
966
1130
|
|
|
@@ -992,42 +1156,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
992
1156
|
}
|
|
993
1157
|
return new String[] { typeArg.toString() }; // expect a RubyString
|
|
994
1158
|
}
|
|
995
|
-
|
|
996
|
-
private static int jdbcTypeFor(final ThreadContext context, IRubyObject type)
|
|
997
|
-
throws SQLException {
|
|
998
|
-
if ( ! ( type instanceof RubySymbol ) ) {
|
|
999
|
-
if ( type instanceof RubyString ) { // to_sym
|
|
1000
|
-
if ( context.getRuntime().is1_9() ) {
|
|
1001
|
-
type = ( (RubyString) type ).intern19();
|
|
1002
|
-
}
|
|
1003
|
-
else {
|
|
1004
|
-
type = ( (RubyString) type ).intern();
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
else {
|
|
1008
|
-
throw new IllegalArgumentException(
|
|
1009
|
-
"expected a Ruby string/symbol but got: " + type + " (" + type.getMetaClass().getName() + ")"
|
|
1010
|
-
);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
final String internedValue = type.asJavaString();
|
|
1015
|
-
|
|
1016
|
-
if ( internedValue == (Object) "string" ) return Types.VARCHAR;
|
|
1017
|
-
else if ( internedValue == (Object) "text" ) return Types.CLOB;
|
|
1018
|
-
else if ( internedValue == (Object) "integer" ) return Types.INTEGER;
|
|
1019
|
-
else if ( internedValue == (Object) "decimal" ) return Types.DECIMAL;
|
|
1020
|
-
else if ( internedValue == (Object) "float" ) return Types.FLOAT;
|
|
1021
|
-
else if ( internedValue == (Object) "datetime") return Types.TIMESTAMP;
|
|
1022
|
-
else if ( internedValue == (Object) "timestamp" ) return Types.TIMESTAMP;
|
|
1023
|
-
else if ( internedValue == (Object) "time" ) return Types.TIME;
|
|
1024
|
-
else if ( internedValue == (Object) "date" ) return Types.DATE;
|
|
1025
|
-
else if ( internedValue == (Object) "binary" ) return Types.BLOB;
|
|
1026
|
-
else if ( internedValue == (Object) "boolean" ) return Types.BOOLEAN;
|
|
1027
|
-
else if ( internedValue == (Object) "xml" ) return Types.SQLXML;
|
|
1028
|
-
else if ( internedValue == (Object) "array" ) return Types.ARRAY;
|
|
1029
|
-
else return -1;
|
|
1030
|
-
}
|
|
1031
1159
|
|
|
1032
1160
|
/**
|
|
1033
1161
|
* @deprecated this method is no longer used, instead consider overriding
|
|
@@ -1112,14 +1240,14 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1112
1240
|
return booleanToRuby(runtime, resultSet, column);
|
|
1113
1241
|
case Types.SQLXML: // JDBC 4.0
|
|
1114
1242
|
return xmlToRuby(runtime, resultSet, column);
|
|
1243
|
+
case Types.ARRAY: // we handle JDBC Array into (Ruby) []
|
|
1244
|
+
return arrayToRuby(runtime, resultSet, column);
|
|
1115
1245
|
case Types.NULL:
|
|
1116
1246
|
return runtime.getNil();
|
|
1117
1247
|
// NOTE: (JDBC) exotic stuff just cause it's so easy with JRuby :)
|
|
1118
1248
|
case Types.JAVA_OBJECT:
|
|
1119
1249
|
case Types.OTHER:
|
|
1120
1250
|
return objectToRuby(runtime, resultSet, column);
|
|
1121
|
-
case Types.ARRAY: // we handle JDBC Array into (Ruby) []
|
|
1122
|
-
return arrayToRuby(runtime, resultSet, column);
|
|
1123
1251
|
// (default) String
|
|
1124
1252
|
case Types.CHAR:
|
|
1125
1253
|
case Types.VARCHAR:
|
|
@@ -1370,119 +1498,677 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1370
1498
|
finally { xml.free(); }
|
|
1371
1499
|
}
|
|
1372
1500
|
|
|
1373
|
-
protected
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
protected Connection getConnection(boolean error) {
|
|
1378
|
-
final Connection connection = (Connection) dataGetStruct();
|
|
1379
|
-
if ( connection == null && error ) {
|
|
1380
|
-
final RubyClass errorClass = getConnectionNotEstablished( getRuntime() );
|
|
1381
|
-
throw new RaiseException(getRuntime(), errorClass, "no connection available", false);
|
|
1382
|
-
}
|
|
1383
|
-
return connection;
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
private synchronized RubyJdbcConnection setConnection(final Connection connection) {
|
|
1387
|
-
close( getConnection(false) ); // close previously open connection if there is one
|
|
1501
|
+
/* protected */ void setStatementParameters(final ThreadContext context,
|
|
1502
|
+
final Connection connection, final PreparedStatement statement,
|
|
1503
|
+
final List<?> binds) throws SQLException {
|
|
1388
1504
|
|
|
1389
|
-
final
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
Statement statement = null;
|
|
1398
|
-
try {
|
|
1399
|
-
final RubyString aliveSQL = getConfigValue(context, "connection_alive_sql").convertToString();
|
|
1400
|
-
if ( isSelect(aliveSQL) ) { // expect a SELECT/CALL SQL statement
|
|
1401
|
-
statement = connection.createStatement();
|
|
1402
|
-
statement.execute( aliveSQL.toString() );
|
|
1403
|
-
return false; // connection ain't broken
|
|
1505
|
+
final Ruby runtime = context.getRuntime();
|
|
1506
|
+
|
|
1507
|
+
for ( int i = 0; i < binds.size(); i++ ) {
|
|
1508
|
+
// [ [ column1, param1 ], [ column2, param2 ], ... ]
|
|
1509
|
+
Object param = binds.get(i); IRubyObject column = null;
|
|
1510
|
+
if ( param.getClass() == RubyArray.class ) {
|
|
1511
|
+
final RubyArray _param = (RubyArray) param;
|
|
1512
|
+
column = _param.eltInternal(0); param = _param.eltInternal(1);
|
|
1404
1513
|
}
|
|
1405
|
-
else
|
|
1406
|
-
|
|
1514
|
+
else if ( param instanceof List ) {
|
|
1515
|
+
final List<?> _param = (List<?>) param;
|
|
1516
|
+
column = (IRubyObject) _param.get(0); param = _param.get(1);
|
|
1407
1517
|
}
|
|
1518
|
+
else if ( param instanceof Object[] ) {
|
|
1519
|
+
final Object[] _param = (Object[]) param;
|
|
1520
|
+
column = (IRubyObject) _param[0]; param = _param[1];
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
final IRubyObject type;
|
|
1524
|
+
if ( column != null && ! column.isNil() ) {
|
|
1525
|
+
type = column.callMethod(context, "type");
|
|
1526
|
+
}
|
|
1527
|
+
else {
|
|
1528
|
+
type = null;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
setStatementParameter(context, runtime, connection, statement, i + 1, param, type);
|
|
1408
1532
|
}
|
|
1409
|
-
catch (Exception e) {
|
|
1410
|
-
debugMessage(context, "connection considered broken due: " + e.toString());
|
|
1411
|
-
return true;
|
|
1412
|
-
}
|
|
1413
|
-
finally { close(statement); }
|
|
1414
1533
|
}
|
|
1415
|
-
|
|
1416
|
-
private final static DateFormat FORMAT = new SimpleDateFormat("%y-%M-%d %H:%m:%s");
|
|
1417
1534
|
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1535
|
+
/* protected */ void setStatementParameter(final ThreadContext context,
|
|
1536
|
+
final Ruby runtime, final Connection connection,
|
|
1537
|
+
final PreparedStatement statement, final int index,
|
|
1538
|
+
final Object value, final IRubyObject column) throws SQLException {
|
|
1421
1539
|
|
|
1422
|
-
final
|
|
1540
|
+
final RubySymbol columnType = resolveColumnType(context, runtime, column);
|
|
1541
|
+
final int type = jdbcTypeFor(runtime, column, columnType, value);
|
|
1423
1542
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
statement.setString(index, RubyString.objAsString(context, value).toString());
|
|
1433
|
-
break;
|
|
1434
|
-
case Types.INTEGER:
|
|
1435
|
-
statement.setLong(index, RubyNumeric.fix2long(value));
|
|
1436
|
-
break;
|
|
1437
|
-
case Types.FLOAT:
|
|
1438
|
-
statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
|
|
1439
|
-
break;
|
|
1440
|
-
case Types.TIMESTAMP:
|
|
1441
|
-
case Types.TIME:
|
|
1442
|
-
case Types.DATE:
|
|
1443
|
-
if ( ! ( value instanceof RubyTime ) ) {
|
|
1444
|
-
final String stringValue = RubyString.objAsString(context, value).toString();
|
|
1445
|
-
try {
|
|
1446
|
-
Timestamp timestamp = new Timestamp( FORMAT.parse( stringValue ).getTime() );
|
|
1447
|
-
statement.setTimestamp( index, timestamp, Calendar.getInstance() );
|
|
1448
|
-
}
|
|
1449
|
-
catch (Exception e) {
|
|
1450
|
-
statement.setString( index, stringValue );
|
|
1451
|
-
}
|
|
1452
|
-
} else {
|
|
1453
|
-
final RubyTime timeValue = (RubyTime) value;
|
|
1454
|
-
final java.util.Date dateValue = timeValue.getJavaDate();
|
|
1455
|
-
|
|
1456
|
-
long millis = dateValue.getTime();
|
|
1457
|
-
Timestamp timestamp = new Timestamp(millis);
|
|
1458
|
-
Calendar calendar = Calendar.getInstance();
|
|
1459
|
-
calendar.setTime(dateValue);
|
|
1460
|
-
if ( jdbcType != Types.DATE ) {
|
|
1461
|
-
int micros = (int) timeValue.microseconds();
|
|
1462
|
-
timestamp.setNanos( micros * 1000 ); // time.nsec ~ time.usec * 1000
|
|
1543
|
+
// TODO pass column with (JDBC) type to methods :
|
|
1544
|
+
|
|
1545
|
+
switch (type) {
|
|
1546
|
+
case Types.TINYINT:
|
|
1547
|
+
case Types.SMALLINT:
|
|
1548
|
+
case Types.INTEGER:
|
|
1549
|
+
if ( value instanceof RubyBignum ) {
|
|
1550
|
+
setBigIntegerParameter(runtime, connection, statement, index, type, (RubyBignum) value);
|
|
1463
1551
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1552
|
+
setIntegerParameter(runtime, connection, statement, index, type, value);
|
|
1553
|
+
break;
|
|
1554
|
+
case Types.BIGINT:
|
|
1555
|
+
setBigIntegerParameter(runtime, connection, statement, index, type, value);
|
|
1556
|
+
break;
|
|
1557
|
+
case Types.REAL:
|
|
1558
|
+
case Types.FLOAT:
|
|
1559
|
+
case Types.DOUBLE:
|
|
1560
|
+
setDoubleParameter(runtime, connection, statement, index, type, value);
|
|
1561
|
+
break;
|
|
1562
|
+
case Types.NUMERIC:
|
|
1563
|
+
case Types.DECIMAL:
|
|
1564
|
+
setDecimalParameter(runtime, connection, statement, index, type, value);
|
|
1565
|
+
break;
|
|
1566
|
+
case Types.DATE:
|
|
1567
|
+
setDateParameter(runtime, connection, statement, index, type, value);
|
|
1568
|
+
break;
|
|
1569
|
+
case Types.TIME:
|
|
1570
|
+
setTimeParameter(runtime, connection, statement, index, type, value);
|
|
1571
|
+
break;
|
|
1572
|
+
case Types.TIMESTAMP:
|
|
1573
|
+
setTimestampParameter(runtime, connection, statement, index, type, value);
|
|
1574
|
+
break;
|
|
1575
|
+
case Types.BIT:
|
|
1576
|
+
case Types.BOOLEAN:
|
|
1577
|
+
setBooleanParameter(runtime, connection, statement, index, type, value);
|
|
1578
|
+
break;
|
|
1579
|
+
case Types.SQLXML:
|
|
1580
|
+
setXmlParameter(runtime, connection, statement, index, type, value);
|
|
1581
|
+
break;
|
|
1582
|
+
case Types.ARRAY:
|
|
1583
|
+
setArrayParameter(runtime, connection, statement, index, type, value);
|
|
1584
|
+
break;
|
|
1585
|
+
case Types.JAVA_OBJECT:
|
|
1586
|
+
case Types.OTHER:
|
|
1587
|
+
setObjectParameter(runtime, connection, statement, index, type, value);
|
|
1588
|
+
break;
|
|
1589
|
+
case Types.BINARY:
|
|
1590
|
+
case Types.VARBINARY:
|
|
1591
|
+
case Types.LONGVARBINARY:
|
|
1592
|
+
case Types.BLOB:
|
|
1593
|
+
setBlobParameter(runtime, connection, statement, index, type, value);
|
|
1594
|
+
break;
|
|
1595
|
+
case Types.CLOB:
|
|
1596
|
+
case Types.NCLOB: // JDBC 4.0
|
|
1597
|
+
setClobParameter(runtime, connection, statement, index, type, value);
|
|
1598
|
+
break;
|
|
1599
|
+
case Types.CHAR:
|
|
1600
|
+
case Types.VARCHAR:
|
|
1601
|
+
case Types.NCHAR: // JDBC 4.0
|
|
1602
|
+
case Types.NVARCHAR: // JDBC 4.0
|
|
1603
|
+
default:
|
|
1604
|
+
setStringParameter(runtime, connection, statement, index, type, value);
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
@Deprecated
|
|
1609
|
+
private void setPreparedStatementValues(final ThreadContext context,
|
|
1610
|
+
final Connection connection, final PreparedStatement statement,
|
|
1611
|
+
final IRubyObject valuesArg, final IRubyObject typesArg) throws SQLException {
|
|
1612
|
+
final Ruby runtime = context.getRuntime();
|
|
1613
|
+
final RubyArray values = (RubyArray) valuesArg;
|
|
1614
|
+
final RubyArray types = (RubyArray) typesArg; // column types
|
|
1615
|
+
for( int i = 0, j = values.getLength(); i < j; i++ ) {
|
|
1616
|
+
setStatementParameter(
|
|
1617
|
+
context, runtime, connection, statement, i + 1,
|
|
1618
|
+
values.eltInternal(i), types.eltInternal(i)
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
private RubySymbol resolveColumnType(final ThreadContext context, final Ruby runtime,
|
|
1624
|
+
final IRubyObject column) {
|
|
1625
|
+
if ( column instanceof RubySymbol ) { // deprecated behavior
|
|
1626
|
+
return (RubySymbol) column;
|
|
1627
|
+
}
|
|
1628
|
+
if ( column instanceof RubyString) { // deprecated behavior
|
|
1629
|
+
if ( runtime.is1_9() ) {
|
|
1630
|
+
return ( (RubyString) column ).intern19();
|
|
1631
|
+
}
|
|
1632
|
+
else {
|
|
1633
|
+
return ( (RubyString) column ).intern();
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
if ( column == null || column.isNil() ) {
|
|
1638
|
+
throw runtime.newArgumentError("nil column passed");
|
|
1639
|
+
}
|
|
1640
|
+
return (RubySymbol) column.callMethod(context, "type");
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
/* protected */ int jdbcTypeFor(final Ruby runtime, final IRubyObject column,
|
|
1644
|
+
final RubySymbol columnType, final Object value) throws SQLException {
|
|
1645
|
+
|
|
1646
|
+
final String internedType = columnType.asJavaString();
|
|
1647
|
+
|
|
1648
|
+
if ( internedType == (Object) "string" ) return Types.VARCHAR;
|
|
1649
|
+
else if ( internedType == (Object) "text" ) return Types.CLOB;
|
|
1650
|
+
else if ( internedType == (Object) "integer" ) return Types.INTEGER;
|
|
1651
|
+
else if ( internedType == (Object) "decimal" ) return Types.DECIMAL;
|
|
1652
|
+
else if ( internedType == (Object) "float" ) return Types.FLOAT;
|
|
1653
|
+
else if ( internedType == (Object) "date" ) return Types.DATE;
|
|
1654
|
+
else if ( internedType == (Object) "time" ) return Types.TIME;
|
|
1655
|
+
else if ( internedType == (Object) "datetime") return Types.TIMESTAMP;
|
|
1656
|
+
else if ( internedType == (Object) "timestamp" ) return Types.TIMESTAMP;
|
|
1657
|
+
else if ( internedType == (Object) "binary" ) return Types.BLOB;
|
|
1658
|
+
else if ( internedType == (Object) "boolean" ) return Types.BOOLEAN;
|
|
1659
|
+
else if ( internedType == (Object) "xml" ) return Types.SQLXML;
|
|
1660
|
+
else if ( internedType == (Object) "array" ) return Types.ARRAY;
|
|
1661
|
+
else return Types.OTHER; // -1 as well as 0 are used in Types
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
/* protected */ void setIntegerParameter(final Ruby runtime, final Connection connection,
|
|
1665
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1666
|
+
final Object value) throws SQLException {
|
|
1667
|
+
if ( value instanceof IRubyObject ) {
|
|
1668
|
+
setIntegerParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
if ( value == null ) statement.setNull(index, Types.INTEGER);
|
|
1672
|
+
else {
|
|
1673
|
+
statement.setLong(index, ((Number) value).longValue());
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
/* protected */ void setIntegerParameter(final Ruby runtime, final Connection connection,
|
|
1679
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1680
|
+
final IRubyObject value) throws SQLException {
|
|
1681
|
+
if ( value.isNil() ) statement.setNull(index, Types.INTEGER);
|
|
1682
|
+
else {
|
|
1683
|
+
if ( value instanceof RubyFixnum ) {
|
|
1684
|
+
statement.setLong(index, ((RubyFixnum) value).getLongValue());
|
|
1685
|
+
}
|
|
1686
|
+
else {
|
|
1687
|
+
statement.setInt(index, RubyNumeric.fix2int(value));
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
/* protected */ void setBigIntegerParameter(final Ruby runtime, final Connection connection,
|
|
1693
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1694
|
+
final Object value) throws SQLException {
|
|
1695
|
+
if ( value instanceof IRubyObject ) {
|
|
1696
|
+
setBigIntegerParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1697
|
+
}
|
|
1698
|
+
else {
|
|
1699
|
+
if ( value == null ) statement.setNull(index, Types.BIGINT);
|
|
1700
|
+
else {
|
|
1701
|
+
if ( value instanceof BigDecimal ) {
|
|
1702
|
+
statement.setBigDecimal(index, (BigDecimal) value);
|
|
1703
|
+
}
|
|
1704
|
+
else if ( value instanceof BigInteger ) {
|
|
1705
|
+
setLongOrDecimalParameter(statement, index, (BigInteger) value);
|
|
1706
|
+
}
|
|
1707
|
+
else {
|
|
1708
|
+
statement.setLong(index, ((Number) value).longValue());
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
/* protected */ void setBigIntegerParameter(final Ruby runtime, final Connection connection,
|
|
1715
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1716
|
+
final IRubyObject value) throws SQLException {
|
|
1717
|
+
if ( value.isNil() ) statement.setNull(index, Types.INTEGER);
|
|
1718
|
+
else {
|
|
1719
|
+
if ( value instanceof RubyBignum ) {
|
|
1720
|
+
setLongOrDecimalParameter(statement, index, ((RubyBignum) value).getValue());
|
|
1721
|
+
}
|
|
1722
|
+
else {
|
|
1723
|
+
statement.setLong(index, ((RubyInteger) value).getLongValue());
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
|
|
1729
|
+
private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
|
|
1730
|
+
|
|
1731
|
+
/* protected */ static void setLongOrDecimalParameter(final PreparedStatement statement,
|
|
1732
|
+
final int index, final BigInteger value) throws SQLException {
|
|
1733
|
+
if ( value.compareTo(MAX_LONG) <= 0 // -1 intValue < MAX_VALUE
|
|
1734
|
+
&& value.compareTo(MIN_LONG) >= 0 ) {
|
|
1735
|
+
statement.setLong(index, value.longValue());
|
|
1736
|
+
}
|
|
1737
|
+
else {
|
|
1738
|
+
statement.setBigDecimal(index, new BigDecimal(value));
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
/* protected */ void setDoubleParameter(final Ruby runtime, final Connection connection,
|
|
1743
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1744
|
+
final Object value) throws SQLException {
|
|
1745
|
+
if ( value instanceof IRubyObject ) {
|
|
1746
|
+
setDoubleParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1747
|
+
}
|
|
1748
|
+
else {
|
|
1749
|
+
if ( value == null ) statement.setNull(index, Types.DOUBLE);
|
|
1750
|
+
else {
|
|
1751
|
+
statement.setDouble(index, ((Number) value).doubleValue());
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/* protected */ void setDoubleParameter(final Ruby runtime, final Connection connection,
|
|
1757
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1758
|
+
final IRubyObject value) throws SQLException {
|
|
1759
|
+
if ( value.isNil() ) statement.setNull(index, Types.DOUBLE);
|
|
1760
|
+
else {
|
|
1761
|
+
statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
/* protected */ void setDecimalParameter(final Ruby runtime, final Connection connection,
|
|
1766
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1767
|
+
final Object value) throws SQLException {
|
|
1768
|
+
if ( value instanceof IRubyObject ) {
|
|
1769
|
+
setDecimalParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
if ( value == null ) statement.setNull(index, Types.DECIMAL);
|
|
1773
|
+
else {
|
|
1774
|
+
if ( value instanceof BigDecimal ) {
|
|
1775
|
+
statement.setBigDecimal(index, (BigDecimal) value);
|
|
1776
|
+
}
|
|
1777
|
+
else if ( value instanceof BigInteger ) {
|
|
1778
|
+
setLongOrDecimalParameter(statement, index, (BigInteger) value);
|
|
1779
|
+
}
|
|
1780
|
+
else {
|
|
1781
|
+
statement.setDouble(index, ((Number) value).doubleValue());
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
/* protected */ void setDecimalParameter(final Ruby runtime, final Connection connection,
|
|
1788
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1789
|
+
final IRubyObject value) throws SQLException {
|
|
1790
|
+
if ( value.isNil() ) statement.setNull(index, Types.DECIMAL);
|
|
1791
|
+
else {
|
|
1792
|
+
// NOTE: RubyBigDecimal moved into org.jruby.ext.bigdecimal (1.6 -> 1.7)
|
|
1793
|
+
if ( value.getMetaClass().getName().indexOf("BigDecimal") != -1 ) {
|
|
1794
|
+
try { // reflect ((RubyBigDecimal) value).getValue() :
|
|
1795
|
+
BigDecimal decValue = (BigDecimal) value.getClass().
|
|
1796
|
+
getMethod("getValue", (Class<?>[]) null).
|
|
1797
|
+
invoke(value, (Object[]) null);
|
|
1798
|
+
statement.setBigDecimal(index, decValue);
|
|
1799
|
+
}
|
|
1800
|
+
catch (NoSuchMethodException e) {
|
|
1801
|
+
throw new RuntimeException(e);
|
|
1802
|
+
}
|
|
1803
|
+
catch (IllegalAccessException e) {
|
|
1804
|
+
throw new RuntimeException(e);
|
|
1805
|
+
}
|
|
1806
|
+
catch (InvocationTargetException e) {
|
|
1807
|
+
throw new RuntimeException(e.getCause() != null ? e.getCause() : e);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
else {
|
|
1811
|
+
statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
/* protected */ void setTimestampParameter(final Ruby runtime, final Connection connection,
|
|
1817
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1818
|
+
final Object value) throws SQLException {
|
|
1819
|
+
if ( value instanceof IRubyObject ) {
|
|
1820
|
+
setTimestampParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1821
|
+
}
|
|
1822
|
+
else {
|
|
1823
|
+
if ( value == null ) statement.setNull(index, Types.TIMESTAMP);
|
|
1824
|
+
else {
|
|
1825
|
+
if ( value instanceof Timestamp ) {
|
|
1826
|
+
statement.setTimestamp(index, (Timestamp) value);
|
|
1827
|
+
}
|
|
1828
|
+
else if ( value instanceof java.util.Date ) {
|
|
1829
|
+
statement.setTimestamp(index, new Timestamp(((java.util.Date) value).getTime()));
|
|
1830
|
+
}
|
|
1831
|
+
else {
|
|
1832
|
+
statement.setTimestamp(index, Timestamp.valueOf(value.toString()));
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
/* protected */ void setTimestampParameter(final Ruby runtime, final Connection connection,
|
|
1839
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1840
|
+
final IRubyObject value) throws SQLException {
|
|
1841
|
+
if ( value.isNil() ) statement.setNull(index, Types.TIMESTAMP);
|
|
1842
|
+
else {
|
|
1843
|
+
if ( value instanceof RubyTime ) {
|
|
1844
|
+
final RubyTime timeValue = (RubyTime) value;
|
|
1845
|
+
final java.util.Date dateValue = timeValue.getJavaDate();
|
|
1846
|
+
|
|
1847
|
+
long millis = dateValue.getTime();
|
|
1848
|
+
Timestamp timestamp = new Timestamp(millis);
|
|
1849
|
+
Calendar calendar = Calendar.getInstance();
|
|
1850
|
+
calendar.setTime(dateValue);
|
|
1851
|
+
if ( type != Types.DATE ) {
|
|
1852
|
+
int micros = (int) timeValue.microseconds();
|
|
1853
|
+
timestamp.setNanos( micros * 1000 ); // time.nsec ~ time.usec * 1000
|
|
1854
|
+
}
|
|
1855
|
+
statement.setTimestamp( index, timestamp, calendar );
|
|
1856
|
+
}
|
|
1857
|
+
else {
|
|
1858
|
+
final String stringValue = value.convertToString().toString();
|
|
1859
|
+
// yyyy-[m]m-[d]d hh:mm:ss[.f...]
|
|
1860
|
+
final Timestamp timestamp = Timestamp.valueOf( stringValue );
|
|
1861
|
+
statement.setTimestamp( index, timestamp, Calendar.getInstance() );
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
/* protected */ void setTimeParameter(final Ruby runtime, final Connection connection,
|
|
1867
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1868
|
+
final Object value) throws SQLException {
|
|
1869
|
+
if ( value instanceof IRubyObject ) {
|
|
1870
|
+
setTimeParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1871
|
+
}
|
|
1872
|
+
else {
|
|
1873
|
+
if ( value == null ) statement.setNull(index, Types.TIME);
|
|
1874
|
+
else {
|
|
1875
|
+
if ( value instanceof Time ) {
|
|
1876
|
+
statement.setTime(index, (Time) value);
|
|
1877
|
+
}
|
|
1878
|
+
else if ( value instanceof java.util.Date ) {
|
|
1879
|
+
statement.setTime(index, new Time(((java.util.Date) value).getTime()));
|
|
1880
|
+
}
|
|
1881
|
+
else { // hh:mm:ss
|
|
1882
|
+
statement.setTime(index, Time.valueOf(value.toString()));
|
|
1883
|
+
// statement.setString(index, value.toString());
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/* protected */ void setTimeParameter(final Ruby runtime, final Connection connection,
|
|
1890
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1891
|
+
final IRubyObject value) throws SQLException {
|
|
1892
|
+
if ( value.isNil() ) statement.setNull(index, Types.TIME);
|
|
1893
|
+
else {
|
|
1894
|
+
// setTimestampParameter(runtime, connection, statement, index, type, value);
|
|
1895
|
+
if ( value instanceof RubyTime ) {
|
|
1896
|
+
final RubyTime timeValue = (RubyTime) value;
|
|
1897
|
+
final java.util.Date dateValue = timeValue.getJavaDate();
|
|
1898
|
+
|
|
1899
|
+
Time time = new Time(dateValue.getTime());
|
|
1900
|
+
Calendar calendar = Calendar.getInstance();
|
|
1901
|
+
calendar.setTime(dateValue);
|
|
1902
|
+
statement.setTime( index, time, calendar );
|
|
1903
|
+
}
|
|
1904
|
+
else {
|
|
1905
|
+
final String stringValue = value.convertToString().toString();
|
|
1906
|
+
final Time time = Time.valueOf( stringValue );
|
|
1907
|
+
statement.setTime( index, time, Calendar.getInstance() );
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
/* protected */ void setDateParameter(final Ruby runtime, final Connection connection,
|
|
1913
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1914
|
+
final Object value) throws SQLException {
|
|
1915
|
+
if ( value instanceof IRubyObject ) {
|
|
1916
|
+
setDateParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1917
|
+
}
|
|
1918
|
+
else {
|
|
1919
|
+
if ( value == null ) statement.setNull(index, Types.DATE);
|
|
1920
|
+
else {
|
|
1921
|
+
if ( value instanceof Date ) {
|
|
1922
|
+
statement.setDate(index, (Date) value);
|
|
1923
|
+
}
|
|
1924
|
+
else if ( value instanceof java.util.Date ) {
|
|
1925
|
+
statement.setDate(index, new Date(((java.util.Date) value).getTime()));
|
|
1926
|
+
}
|
|
1927
|
+
else { // yyyy-[m]m-[d]d
|
|
1928
|
+
statement.setDate(index, Date.valueOf(value.toString()));
|
|
1929
|
+
// statement.setString(index, value.toString());
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
/* protected */ void setDateParameter(final Ruby runtime, final Connection connection,
|
|
1936
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1937
|
+
final IRubyObject value) throws SQLException {
|
|
1938
|
+
if ( value.isNil() ) statement.setNull(index, Types.DATE);
|
|
1939
|
+
else {
|
|
1940
|
+
// setTimestampParameter(runtime, connection, statement, index, type, value);
|
|
1941
|
+
if ( value instanceof RubyTime ) {
|
|
1942
|
+
final RubyTime timeValue = (RubyTime) value;
|
|
1943
|
+
final java.util.Date dateValue = timeValue.getJavaDate();
|
|
1944
|
+
|
|
1945
|
+
Date date = new Date(dateValue.getTime());
|
|
1946
|
+
Calendar calendar = Calendar.getInstance();
|
|
1947
|
+
calendar.setTime(dateValue);
|
|
1948
|
+
statement.setDate( index, date, calendar );
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
final String stringValue = value.convertToString().toString();
|
|
1952
|
+
final Date date = Date.valueOf( stringValue );
|
|
1953
|
+
statement.setDate( index, date, Calendar.getInstance() );
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
/* protected */ void setBooleanParameter(final Ruby runtime, final Connection connection,
|
|
1959
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1960
|
+
final Object value) throws SQLException {
|
|
1961
|
+
if ( value instanceof IRubyObject ) {
|
|
1962
|
+
setBooleanParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1963
|
+
}
|
|
1964
|
+
else {
|
|
1965
|
+
if ( value == null ) statement.setNull(index, Types.BOOLEAN);
|
|
1966
|
+
else {
|
|
1967
|
+
statement.setBoolean(index, ((Boolean) value).booleanValue());
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
/* protected */ void setBooleanParameter(final Ruby runtime, final Connection connection,
|
|
1973
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1974
|
+
final IRubyObject value) throws SQLException {
|
|
1975
|
+
if ( value.isNil() ) statement.setNull(index, Types.BOOLEAN);
|
|
1976
|
+
else {
|
|
1977
|
+
statement.setBoolean(index, value.isTrue());
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
/* protected */ void setStringParameter(final Ruby runtime, final Connection connection,
|
|
1982
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1983
|
+
final Object value) throws SQLException {
|
|
1984
|
+
if ( value instanceof IRubyObject ) {
|
|
1985
|
+
setStringParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
1986
|
+
}
|
|
1987
|
+
else {
|
|
1988
|
+
if ( value == null ) statement.setNull(index, Types.VARCHAR);
|
|
1989
|
+
else {
|
|
1990
|
+
statement.setString(index, value.toString());
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
/* protected */ void setStringParameter(final Ruby runtime, final Connection connection,
|
|
1996
|
+
final PreparedStatement statement, final int index, final int type,
|
|
1997
|
+
final IRubyObject value) throws SQLException {
|
|
1998
|
+
if ( value.isNil() ) statement.setNull(index, Types.VARCHAR);
|
|
1999
|
+
else {
|
|
2000
|
+
statement.setString(index, value.convertToString().toString());
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
/* protected */ void setArrayParameter(final Ruby runtime, final Connection connection,
|
|
2005
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2006
|
+
final Object value) throws SQLException {
|
|
2007
|
+
if ( value instanceof IRubyObject ) {
|
|
2008
|
+
setArrayParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
2009
|
+
}
|
|
2010
|
+
else {
|
|
2011
|
+
if ( value == null ) statement.setNull(index, Types.ARRAY);
|
|
2012
|
+
else {
|
|
2013
|
+
// TODO get array element type name ?!
|
|
2014
|
+
Array array = connection.createArrayOf(null, (Object[]) value);
|
|
2015
|
+
statement.setArray(index, array);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
/* protected */ void setArrayParameter(final Ruby runtime, final Connection connection,
|
|
2021
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2022
|
+
final IRubyObject value) throws SQLException {
|
|
2023
|
+
if ( value.isNil() ) statement.setNull(index, Types.ARRAY);
|
|
2024
|
+
else {
|
|
2025
|
+
// TODO get array element type name ?!
|
|
2026
|
+
Array array = connection.createArrayOf(null, ((RubyArray) value).toArray());
|
|
2027
|
+
statement.setArray(index, array);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
/* protected */ void setXmlParameter(final Ruby runtime, final Connection connection,
|
|
2032
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2033
|
+
final Object value) throws SQLException {
|
|
2034
|
+
if ( value instanceof IRubyObject ) {
|
|
2035
|
+
setXmlParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
2036
|
+
}
|
|
2037
|
+
else {
|
|
2038
|
+
if ( value == null ) statement.setNull(index, Types.SQLXML);
|
|
2039
|
+
else {
|
|
2040
|
+
SQLXML xml = connection.createSQLXML();
|
|
2041
|
+
xml.setString(value.toString());
|
|
2042
|
+
statement.setSQLXML(index, xml);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
/* protected */ void setXmlParameter(final Ruby runtime, final Connection connection,
|
|
2048
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2049
|
+
final IRubyObject value) throws SQLException {
|
|
2050
|
+
if ( value.isNil() ) statement.setNull(index, Types.SQLXML);
|
|
2051
|
+
else {
|
|
2052
|
+
SQLXML xml = connection.createSQLXML();
|
|
2053
|
+
xml.setString(value.convertToString().toString());
|
|
2054
|
+
statement.setSQLXML(index, xml);
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
/* protected */ void setBlobParameter(final Ruby runtime, final Connection connection,
|
|
2059
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2060
|
+
final Object value) throws SQLException {
|
|
2061
|
+
if ( value instanceof IRubyObject ) {
|
|
2062
|
+
setBlobParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
if ( value == null ) statement.setNull(index, Types.BLOB);
|
|
2066
|
+
else {
|
|
2067
|
+
statement.setBlob(index, (InputStream) value);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
/* protected */ void setBlobParameter(final Ruby runtime, final Connection connection,
|
|
2073
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2074
|
+
final IRubyObject value) throws SQLException {
|
|
2075
|
+
if ( value.isNil() ) statement.setNull(index, Types.BLOB);
|
|
2076
|
+
else {
|
|
2077
|
+
if ( value instanceof RubyString ) {
|
|
2078
|
+
statement.setBlob(index, new ByteArrayInputStream(((RubyString) value).getBytes()));
|
|
2079
|
+
}
|
|
2080
|
+
else { // assume IO/File
|
|
2081
|
+
statement.setBlob(index, ((RubyIO) value).getInStream());
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/* protected */ void setClobParameter(final Ruby runtime, final Connection connection,
|
|
2087
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2088
|
+
final Object value) throws SQLException {
|
|
2089
|
+
if ( value instanceof IRubyObject ) {
|
|
2090
|
+
setClobParameter(runtime, connection, statement, index, type, (IRubyObject) value);
|
|
2091
|
+
}
|
|
2092
|
+
else {
|
|
2093
|
+
if ( value == null ) statement.setNull(index, Types.CLOB);
|
|
2094
|
+
else {
|
|
2095
|
+
statement.setClob(index, (Reader) value);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
/* protected */ void setClobParameter(final Ruby runtime, final Connection connection,
|
|
2101
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2102
|
+
final IRubyObject value) throws SQLException {
|
|
2103
|
+
if ( value.isNil() ) statement.setNull(index, Types.CLOB);
|
|
2104
|
+
else {
|
|
2105
|
+
if ( value instanceof RubyString ) {
|
|
2106
|
+
statement.setClob(index, new StringReader(((RubyString) value).decodeString()));
|
|
2107
|
+
}
|
|
2108
|
+
else { // assume IO/File
|
|
2109
|
+
statement.setClob(index, new InputStreamReader(((RubyIO) value).getInStream()));
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/* protected */ void setObjectParameter(final Ruby runtime, final Connection connection,
|
|
2115
|
+
final PreparedStatement statement, final int index, final int type,
|
|
2116
|
+
Object value) throws SQLException {
|
|
2117
|
+
if (value instanceof IRubyObject) {
|
|
2118
|
+
value = ((IRubyObject) value).toJava(Object.class);
|
|
2119
|
+
}
|
|
2120
|
+
if ( value == null ) statement.setNull(index, Types.JAVA_OBJECT);
|
|
2121
|
+
statement.setObject(index, value);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
protected final Connection getConnection() {
|
|
2125
|
+
return getConnection(false);
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
protected Connection getConnection(boolean error) {
|
|
2129
|
+
final Connection connection = (Connection) dataGetStruct();
|
|
2130
|
+
if ( connection == null && error ) {
|
|
2131
|
+
final RubyClass errorClass = getConnectionNotEstablished( getRuntime() );
|
|
2132
|
+
throw new RaiseException(getRuntime(), errorClass, "no connection available", false);
|
|
2133
|
+
}
|
|
2134
|
+
return connection;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
private synchronized IRubyObject setConnection(final Connection connection) {
|
|
2138
|
+
close( getConnection(false) ); // close previously open connection if there is one
|
|
2139
|
+
|
|
2140
|
+
final IRubyObject rubyConnectionObject =
|
|
2141
|
+
connection != null ? convertJavaToRuby(connection) : getRuntime().getNil();
|
|
2142
|
+
setInstanceVariable( "@connection", rubyConnectionObject );
|
|
2143
|
+
dataWrapStruct(connection);
|
|
2144
|
+
return rubyConnectionObject;
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
protected boolean isConnectionValid(final ThreadContext context, final Connection connection) {
|
|
2148
|
+
if ( connection == null ) return false;
|
|
2149
|
+
final IRubyObject alive_sql = getConfigValue(context, "connection_alive_sql");
|
|
2150
|
+
Statement statement = null;
|
|
2151
|
+
try {
|
|
2152
|
+
RubyString aliveSQL = alive_sql.isNil() ? null : alive_sql.convertToString();
|
|
2153
|
+
if ( aliveSQL != null && isSelect(aliveSQL) ) {
|
|
2154
|
+
// expect a SELECT/CALL SQL statement
|
|
2155
|
+
statement = createStatement(context, connection);
|
|
2156
|
+
statement.execute( aliveSQL.toString() );
|
|
2157
|
+
return true; // connection alive
|
|
2158
|
+
}
|
|
2159
|
+
else { // alive_sql nil (or not a statement we can execute)
|
|
2160
|
+
return connection.isValid(0); // since JDBC 4.0
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
catch (Exception e) {
|
|
2164
|
+
debugMessage(context, "connection considered broken due: " + e.toString());
|
|
2165
|
+
return false;
|
|
2166
|
+
}
|
|
2167
|
+
finally { close(statement); }
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
private boolean tableExists(final Ruby runtime,
|
|
2171
|
+
final Connection connection, final TableName tableName) throws SQLException {
|
|
1486
2172
|
final IRubyObject matchedTables =
|
|
1487
2173
|
matchTables(runtime, connection, tableName.catalog, tableName.schema, tableName.name, getTableTypes(), true);
|
|
1488
2174
|
// NOTE: allow implementers to ignore checkExistsOnly paramater - empty array means does not exists
|
|
@@ -1570,6 +2256,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1570
2256
|
final String catalog, final String schemaPattern,
|
|
1571
2257
|
final String tablePattern, final String[] types) {
|
|
1572
2258
|
return new SQLBlock() {
|
|
2259
|
+
@Override
|
|
1573
2260
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
1574
2261
|
return matchTables(runtime, connection, catalog, schemaPattern, tablePattern, types, false);
|
|
1575
2262
|
}
|
|
@@ -1733,13 +2420,31 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1733
2420
|
final DatabaseMetaData metaData, final ResultSet resultSet,
|
|
1734
2421
|
final boolean downCase) throws SQLException {
|
|
1735
2422
|
|
|
1736
|
-
ColumnData[] columns = extractColumns(runtime, metaData, resultSet, downCase);
|
|
2423
|
+
final ColumnData[] columns = extractColumns(runtime, metaData, resultSet, downCase);
|
|
1737
2424
|
|
|
1738
2425
|
final RubyArray results = runtime.newArray();
|
|
1739
2426
|
// [ { 'col1': 1, 'col2': 2 }, { 'col1': 3, 'col2': 4 } ]
|
|
1740
2427
|
populateFromResultSet(context, runtime, (List<IRubyObject>) results, resultSet, columns);
|
|
1741
2428
|
return results;
|
|
1742
2429
|
}
|
|
2430
|
+
|
|
2431
|
+
private IRubyObject yieldResultRows(final ThreadContext context, final Ruby runtime,
|
|
2432
|
+
final DatabaseMetaData metaData, final ResultSet resultSet,
|
|
2433
|
+
final Block block) throws SQLException {
|
|
2434
|
+
|
|
2435
|
+
final ColumnData[] columns = extractColumns(runtime, metaData, resultSet, false);
|
|
2436
|
+
|
|
2437
|
+
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
|
2438
|
+
while ( resultSet.next() ) {
|
|
2439
|
+
for ( int i = 0; i < columns.length; i++ ) {
|
|
2440
|
+
final ColumnData column = columns[i];
|
|
2441
|
+
blockArgs[i] = jdbcToRuby(runtime, column.index, column.type, resultSet);
|
|
2442
|
+
}
|
|
2443
|
+
block.call( context, blockArgs );
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
return runtime.getNil(); // yielded result rows
|
|
2447
|
+
}
|
|
1743
2448
|
|
|
1744
2449
|
/**
|
|
1745
2450
|
* Extract columns from result set.
|
|
@@ -1797,7 +2502,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1797
2502
|
tries = (int) retryCount.convertToInteger().getLongValue();
|
|
1798
2503
|
if ( tries <= 0 ) tries = 1;
|
|
1799
2504
|
}
|
|
1800
|
-
if (
|
|
2505
|
+
if ( ! isConnectionValid(context, connection) ) {
|
|
1801
2506
|
reconnect(context); continue; // retry connection (block) again
|
|
1802
2507
|
}
|
|
1803
2508
|
break; // connection not broken yet failed
|
|
@@ -1858,10 +2563,9 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
1858
2563
|
exception.getMessage() : exception.toString(); // useful to easily see type on Ruby side
|
|
1859
2564
|
final RaiseException error = wrapException(context, getJDBCError(runtime), exception, message);
|
|
1860
2565
|
final int errorCode = ((SQLException) exception).getErrorCode();
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
"sql_exception=", JavaEmbedUtils.javaToRuby(runtime, exception) );
|
|
2566
|
+
final RubyException self = error.getException();
|
|
2567
|
+
self.getMetaClass().finvoke(context, self, "errno=", runtime.newFixnum(errorCode));
|
|
2568
|
+
self.getMetaClass().finvoke(context, self, "sql_exception=", JavaEmbedUtils.javaToRuby(runtime, exception));
|
|
1865
2569
|
return error;
|
|
1866
2570
|
}
|
|
1867
2571
|
return wrapException(context, getJDBCError(runtime), exception);
|
|
@@ -2055,6 +2759,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
2055
2759
|
this.schema = schema;
|
|
2056
2760
|
this.name = table;
|
|
2057
2761
|
}
|
|
2762
|
+
|
|
2763
|
+
@Override
|
|
2764
|
+
public String toString() {
|
|
2765
|
+
return getClass().getName() +
|
|
2766
|
+
"{catalog=" + catalog + ",schema=" + schema + ",name=" + name + "}";
|
|
2767
|
+
}
|
|
2058
2768
|
|
|
2059
2769
|
}
|
|
2060
2770
|
|
|
@@ -2206,4 +2916,36 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
2206
2916
|
}
|
|
2207
2917
|
}
|
|
2208
2918
|
|
|
2919
|
+
private static RubyArray createCallerBacktrace(final ThreadContext context) {
|
|
2920
|
+
final Ruby runtime = context.getRuntime();
|
|
2921
|
+
runtime.incrementCallerCount();
|
|
2922
|
+
|
|
2923
|
+
Method gatherCallerBacktrace; RubyStackTraceElement[] trace;
|
|
2924
|
+
try {
|
|
2925
|
+
gatherCallerBacktrace = context.getClass().getMethod("gatherCallerBacktrace");
|
|
2926
|
+
trace = (RubyStackTraceElement[]) gatherCallerBacktrace.invoke(context); // 1.6.8
|
|
2927
|
+
}
|
|
2928
|
+
catch (NoSuchMethodException ignore) {
|
|
2929
|
+
try {
|
|
2930
|
+
gatherCallerBacktrace = context.getClass().getMethod("gatherCallerBacktrace", Integer.TYPE);
|
|
2931
|
+
trace = (RubyStackTraceElement[]) gatherCallerBacktrace.invoke(context, 0); // 1.7.4
|
|
2932
|
+
}
|
|
2933
|
+
catch (NoSuchMethodException e) { throw new RuntimeException(e); }
|
|
2934
|
+
catch (IllegalAccessException e) { throw new RuntimeException(e); }
|
|
2935
|
+
catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException()); }
|
|
2936
|
+
}
|
|
2937
|
+
catch (IllegalAccessException e) { throw new RuntimeException(e); }
|
|
2938
|
+
catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException()); }
|
|
2939
|
+
// RubyStackTraceElement[] trace = context.gatherCallerBacktrace(level);
|
|
2940
|
+
|
|
2941
|
+
final RubyArray backtrace = runtime.newArray(trace.length);
|
|
2942
|
+
for (int i = 0; i < trace.length; i++) {
|
|
2943
|
+
RubyStackTraceElement element = trace[i];
|
|
2944
|
+
backtrace.append( RubyString.newString(runtime,
|
|
2945
|
+
element.getFileName() + ":" + element.getLineNumber() + ":in `" + element.getMethodName() + "'"
|
|
2946
|
+
) );
|
|
2947
|
+
}
|
|
2948
|
+
return backtrace;
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2209
2951
|
}
|