activerecord-jdbc-adapter 52.7-java → 60.0-java
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 +4 -4
- data/.gitignore +1 -2
- data/.travis.yml +58 -37
- data/Gemfile +9 -2
- data/README.md +25 -9
- data/Rakefile +1 -1
- data/Rakefile.jdbc +8 -1
- data/activerecord-jdbc-adapter.gemspec +5 -8
- data/lib/arjdbc/abstract/connection_management.rb +7 -0
- data/lib/arjdbc/abstract/core.rb +16 -23
- data/lib/arjdbc/abstract/database_statements.rb +26 -2
- data/lib/arjdbc/abstract/statement_cache.rb +2 -5
- data/lib/arjdbc/abstract/transaction_support.rb +5 -3
- data/lib/arjdbc/db2/column.rb +0 -39
- data/lib/arjdbc/derby/adapter.rb +1 -20
- data/lib/arjdbc/firebird/adapter.rb +0 -21
- data/lib/arjdbc/h2/adapter.rb +0 -15
- data/lib/arjdbc/hsqldb/adapter.rb +0 -14
- data/lib/arjdbc/informix/adapter.rb +0 -23
- data/lib/arjdbc/jdbc/adapter.rb +3 -1
- data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
- data/lib/arjdbc/jdbc/base_ext.rb +3 -1
- data/lib/arjdbc/jdbc/callbacks.rb +2 -0
- data/lib/arjdbc/jdbc/column.rb +2 -0
- data/lib/arjdbc/jdbc/connection.rb +2 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +2 -0
- data/lib/arjdbc/jdbc/error.rb +2 -0
- data/lib/arjdbc/jdbc/extension.rb +2 -0
- data/lib/arjdbc/jdbc/java.rb +3 -1
- data/lib/arjdbc/jdbc/railtie.rb +3 -1
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -1
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -1
- data/lib/arjdbc/jdbc/type_cast.rb +2 -0
- data/lib/arjdbc/jdbc/type_converter.rb +2 -0
- data/lib/arjdbc/mysql/adapter.rb +47 -18
- data/lib/arjdbc/mysql/connection_methods.rb +0 -1
- data/lib/arjdbc/postgresql/adapter.rb +220 -213
- data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
- data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
- data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
- data/lib/arjdbc/postgresql/column.rb +6 -4
- data/lib/arjdbc/postgresql/connection_methods.rb +0 -1
- data/lib/arjdbc/postgresql/name.rb +2 -0
- data/lib/arjdbc/postgresql/oid_types.rb +2 -0
- data/lib/arjdbc/sqlite3/adapter.rb +175 -180
- data/lib/arjdbc/sqlite3/connection_methods.rb +15 -5
- data/lib/arjdbc/tasks/databases.rake +13 -10
- data/lib/arjdbc/util/quoted_cache.rb +3 -1
- data/lib/arjdbc/util/serialized_attributes.rb +3 -1
- data/lib/arjdbc/util/table_copier.rb +3 -1
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +4 -4
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/ArJdbcModule.java +5 -5
- data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +434 -701
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +0 -51
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +31 -24
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +94 -99
- metadata +8 -10
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
3
3
|
def sqlite3_connection(config)
|
4
|
-
config = config.deep_dup
|
5
4
|
config[:adapter_spec] ||= ::ArJdbc::SQLite3
|
6
5
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
|
7
6
|
|
@@ -23,17 +22,27 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
23
22
|
raise
|
24
23
|
end
|
25
24
|
end
|
26
|
-
|
25
|
+
|
26
|
+
config[:properties] ||= {}
|
27
|
+
|
27
28
|
database = config[:database] # NOTE: "jdbc:sqlite::memory:" syntax is supported
|
28
29
|
config[:url] ||= "jdbc:sqlite:#{database == ':memory:' ? '' : database}"
|
29
30
|
config[:connection_alive_sql] ||= 'SELECT 1'
|
30
31
|
|
32
|
+
if config[:readonly]
|
33
|
+
# See
|
34
|
+
# * http://sqlite.org/c3ref/open.html
|
35
|
+
# * http://sqlite.org/c3ref/c_open_autoproxy.html
|
36
|
+
# => 0x01 = readonly, 0x40 = uri (default in JDBC)
|
37
|
+
config[:properties][:open_mode] = 0x01 | 0x40
|
38
|
+
end
|
39
|
+
|
31
40
|
timeout = config[:timeout]
|
32
41
|
if timeout && timeout.to_s !~ /\A\d+\Z/
|
33
42
|
raise TypeError.new "Timeout must be nil or a number (got: #{timeout})."
|
34
43
|
end
|
35
44
|
|
36
|
-
options =
|
45
|
+
options = config[:properties]
|
37
46
|
options['busy_timeout'] ||= timeout unless timeout.nil?
|
38
47
|
|
39
48
|
jdbc_connection(config)
|
@@ -51,8 +60,9 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
51
60
|
def parse_sqlite3_config!(config)
|
52
61
|
database = ( config[:database] ||= config[:dbfile] )
|
53
62
|
if ':memory:' != database
|
54
|
-
|
55
|
-
|
63
|
+
# make sure to have an absolute path. Ruby and Java don't agree on working directory
|
64
|
+
config[:database] = File.expand_path(database, defined?(Rails.root) ? Rails.root : nil)
|
65
|
+
dirname = File.dirname(config[:database])
|
56
66
|
Dir.mkdir(dirname) unless File.directory?(dirname)
|
57
67
|
end
|
58
68
|
end
|
@@ -5,25 +5,28 @@ module ActiveRecord::Tasks
|
|
5
5
|
DatabaseTasks.module_eval do
|
6
6
|
|
7
7
|
# @override patched to adapt jdbc configuration
|
8
|
-
def each_current_configuration(environment)
|
8
|
+
def each_current_configuration(environment, spec_name = nil)
|
9
9
|
environments = [environment]
|
10
10
|
environments << 'test' if environment == 'development'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
environments.each do |env|
|
13
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
|
14
|
+
next if spec_name && spec_name != db_config.spec_name
|
15
|
+
|
16
|
+
yield adapt_jdbc_config(db_config.config), db_config.spec_name, env unless db_config.config['database'].blank?
|
17
|
+
end
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
21
|
# @override patched to adapt jdbc configuration
|
19
22
|
def each_local_configuration
|
20
|
-
ActiveRecord::Base.configurations.
|
21
|
-
next unless config['database']
|
23
|
+
ActiveRecord::Base.configurations.configs_for.each do |db_config|
|
24
|
+
next unless db_config.config['database']
|
22
25
|
|
23
|
-
if local_database?(config)
|
24
|
-
yield adapt_jdbc_config(config)
|
26
|
+
if local_database?(db_config.config)
|
27
|
+
yield adapt_jdbc_config(db_config.config)
|
25
28
|
else
|
26
|
-
$stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
|
29
|
+
$stderr.puts "This task only modifies local databases. #{db_config.config['database']} is on a remote host."
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
@@ -45,4 +48,4 @@ module ActiveRecord::Tasks
|
|
45
48
|
|
46
49
|
end if const_defined?(:MySQLDatabaseTasks)
|
47
50
|
|
48
|
-
end
|
51
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ArJdbc
|
2
4
|
module Util
|
3
5
|
# Gets included into `ActiveRecord::Base` to support sending LOB values
|
@@ -95,4 +97,4 @@ module ArJdbc
|
|
95
97
|
end
|
96
98
|
# @private only due backwards compatibility
|
97
99
|
SerializedAttributesHelper = Util::SerializedAttributes
|
98
|
-
end
|
100
|
+
end
|
data/lib/arjdbc/version.rb
CHANGED
data/pom.xml
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
<url>http://github.com/jruby/activerecord-jdbc-adapter/wiki</url>
|
13
13
|
|
14
14
|
<properties>
|
15
|
-
<jruby.version>9.
|
15
|
+
<jruby.version>9.2.6.0</jruby.version>
|
16
16
|
</properties>
|
17
17
|
|
18
18
|
<issueManagement>
|
@@ -75,7 +75,7 @@
|
|
75
75
|
<dependency>
|
76
76
|
<groupId>org.postgresql</groupId>
|
77
77
|
<artifactId>postgresql</artifactId>
|
78
|
-
<version>42.1.4
|
78
|
+
<version>42.1.4</version>
|
79
79
|
</dependency>
|
80
80
|
</dependencies>
|
81
81
|
|
@@ -103,8 +103,8 @@
|
|
103
103
|
<artifactId>maven-compiler-plugin</artifactId>
|
104
104
|
<version>2.5.1</version>
|
105
105
|
<configuration>
|
106
|
-
<source>1.
|
107
|
-
<target>1.
|
106
|
+
<source>1.8</source>
|
107
|
+
<target>1.8</target>
|
108
108
|
</configuration>
|
109
109
|
</plugin>
|
110
110
|
</plugins>
|
data/rakelib/01-tomcat.rake
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
2
2
|
|
3
|
-
TOMCAT_MAVEN_REPO = '
|
3
|
+
TOMCAT_MAVEN_REPO = 'http://repo2.maven.org/maven2/org/apache/tomcat'
|
4
4
|
TOMCAT_VERSION = '7.0.54'
|
5
5
|
|
6
6
|
DOWNLOAD_DIR = File.expand_path('../test/jars', File.dirname(__FILE__))
|
@@ -48,4 +48,4 @@ namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
|
48
48
|
rm jar_path if File.exist?(jar_path)
|
49
49
|
end
|
50
50
|
|
51
|
-
end
|
51
|
+
end
|
data/rakelib/rails.rake
CHANGED
@@ -51,7 +51,7 @@ namespace :rails do
|
|
51
51
|
ruby_opts_string += " -C \"#{ar_path}\""
|
52
52
|
ruby_opts_string += " -rbundler/setup"
|
53
53
|
ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
|
54
|
-
file_list = ENV["TEST"] ? FileList[ ENV["TEST"]
|
54
|
+
file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
|
55
55
|
file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
|
56
56
|
# test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
|
57
57
|
option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )
|
@@ -151,7 +151,7 @@ public class ArJdbcModule {
|
|
151
151
|
throw newNativeException(runtime, e);
|
152
152
|
}
|
153
153
|
|
154
|
-
return
|
154
|
+
return context.tru;
|
155
155
|
}
|
156
156
|
|
157
157
|
/**
|
@@ -191,7 +191,7 @@ public class ArJdbcModule {
|
|
191
191
|
}
|
192
192
|
|
193
193
|
// NOTE: probably useless - only to be useful for the pooled runtime mode when jar at WEB-INF/lib
|
194
|
-
static final Map<Ruby, Map<String, Boolean>> loadedDrivers = new WeakHashMap
|
194
|
+
static final Map<Ruby, Map<String, Boolean>> loadedDrivers = new WeakHashMap<>(8);
|
195
195
|
|
196
196
|
private static IRubyObject loadDriver(final ThreadContext context, final IRubyObject self,
|
197
197
|
final String constName) {
|
@@ -202,7 +202,7 @@ public class ArJdbcModule {
|
|
202
202
|
synchronized (ArJdbcModule.class) {
|
203
203
|
loadedMap = loadedDrivers.get(runtime);
|
204
204
|
if ( loadedMap == null ) {
|
205
|
-
loadedMap = new HashMap
|
205
|
+
loadedMap = new HashMap<>(4);
|
206
206
|
loadedDrivers.put(runtime, loadedMap);
|
207
207
|
}
|
208
208
|
}
|
@@ -210,8 +210,8 @@ public class ArJdbcModule {
|
|
210
210
|
|
211
211
|
final Boolean driverLoaded = loadedMap.get(constName);
|
212
212
|
if ( driverLoaded != null ) {
|
213
|
-
if (
|
214
|
-
return
|
213
|
+
if (driverLoaded) return context.fals;
|
214
|
+
return context.nil;
|
215
215
|
}
|
216
216
|
|
217
217
|
try { // require 'jdbc/mysql'
|
@@ -60,15 +60,7 @@ public class DriverWrapper {
|
|
60
60
|
|
61
61
|
private Driver allocateDriver(final Class<? extends Driver> driverClass)
|
62
62
|
throws InstantiationException, IllegalAccessException {
|
63
|
-
|
64
|
-
return driverClass.newInstance();
|
65
|
-
}
|
66
|
-
catch (InstantiationException e) {
|
67
|
-
throw e;
|
68
|
-
}
|
69
|
-
catch (IllegalAccessException e) {
|
70
|
-
throw e;
|
71
|
-
}
|
63
|
+
return driverClass.newInstance();
|
72
64
|
}
|
73
65
|
|
74
66
|
protected static Class<? extends Driver> loadDriver(final Ruby runtime, final String name)
|
@@ -73,7 +73,6 @@ import org.jruby.RubyBoolean;
|
|
73
73
|
import org.jruby.RubyClass;
|
74
74
|
import org.jruby.RubyException;
|
75
75
|
import org.jruby.RubyFixnum;
|
76
|
-
import org.jruby.RubyFloat;
|
77
76
|
import org.jruby.RubyHash;
|
78
77
|
import org.jruby.RubyIO;
|
79
78
|
import org.jruby.RubyInteger;
|
@@ -86,6 +85,7 @@ import org.jruby.RubyTime;
|
|
86
85
|
import org.jruby.anno.JRubyMethod;
|
87
86
|
import org.jruby.exceptions.RaiseException;
|
88
87
|
import org.jruby.ext.bigdecimal.RubyBigDecimal;
|
88
|
+
import org.jruby.ext.date.RubyDate;
|
89
89
|
import org.jruby.javasupport.JavaEmbedUtils;
|
90
90
|
import org.jruby.javasupport.JavaUtil;
|
91
91
|
import org.jruby.runtime.Block;
|
@@ -147,11 +147,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
147
147
|
return JdbcConnection;
|
148
148
|
}
|
149
149
|
|
150
|
-
@Deprecated
|
151
|
-
public static RubyClass getJdbcConnectionClass(final Ruby runtime) {
|
152
|
-
return getConnectionAdapters(runtime).getClass("JdbcConnection");
|
153
|
-
}
|
154
|
-
|
155
150
|
public static RubyClass getJdbcConnection(final Ruby runtime) {
|
156
151
|
return (RubyClass) getConnectionAdapters(runtime).getConstantAt("JdbcConnection");
|
157
152
|
}
|
@@ -231,34 +226,30 @@ public class RubyJdbcConnection extends RubyObject {
|
|
231
226
|
|
232
227
|
@JRubyMethod(name = "transaction_isolation", alias = "get_transaction_isolation")
|
233
228
|
public IRubyObject get_transaction_isolation(final ThreadContext context) {
|
234
|
-
return withConnection(context,
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
return context.runtime.newSymbol(isolationSymbol);
|
240
|
-
}
|
229
|
+
return withConnection(context, connection -> {
|
230
|
+
final int level = connection.getTransactionIsolation();
|
231
|
+
final String isolationSymbol = formatTransactionIsolationLevel(level);
|
232
|
+
if ( isolationSymbol == null ) return context.nil;
|
233
|
+
return context.runtime.newSymbol(isolationSymbol);
|
241
234
|
});
|
242
235
|
}
|
243
236
|
|
244
237
|
@JRubyMethod(name = "transaction_isolation=", alias = "set_transaction_isolation")
|
245
238
|
public IRubyObject set_transaction_isolation(final ThreadContext context, final IRubyObject isolation) {
|
246
|
-
return withConnection(context,
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
}
|
239
|
+
return withConnection(context, connection -> {
|
240
|
+
final int level;
|
241
|
+
if ( isolation.isNil() ) {
|
242
|
+
level = connection.getMetaData().getDefaultTransactionIsolation();
|
243
|
+
}
|
244
|
+
else {
|
245
|
+
level = mapTransactionIsolationLevel(isolation);
|
246
|
+
}
|
255
247
|
|
256
|
-
|
248
|
+
connection.setTransactionIsolation(level);
|
257
249
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
}
|
250
|
+
final String isolationSymbol = formatTransactionIsolationLevel(level);
|
251
|
+
if ( isolationSymbol == null ) return context.nil;
|
252
|
+
return context.runtime.newSymbol(isolationSymbol);
|
262
253
|
});
|
263
254
|
}
|
264
255
|
|
@@ -306,31 +297,25 @@ public class RubyJdbcConnection extends RubyObject {
|
|
306
297
|
final IRubyObject[] args) throws SQLException {
|
307
298
|
final IRubyObject isolation = args.length > 0 ? args[0] : null;
|
308
299
|
|
309
|
-
return withConnection(context,
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
supported = level > Connection.TRANSACTION_NONE; // > 0
|
320
|
-
}
|
321
|
-
return context.runtime.newBoolean(supported);
|
300
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
301
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
302
|
+
final boolean supported;
|
303
|
+
if ( isolation != null && ! isolation.isNil() ) {
|
304
|
+
final int level = mapTransactionIsolationLevel(isolation);
|
305
|
+
supported = metaData.supportsTransactionIsolationLevel(level);
|
306
|
+
}
|
307
|
+
else {
|
308
|
+
final int level = metaData.getDefaultTransactionIsolation();
|
309
|
+
supported = level > Connection.TRANSACTION_NONE; // > 0
|
322
310
|
}
|
311
|
+
return context.runtime.newBoolean(supported);
|
323
312
|
});
|
324
313
|
}
|
325
314
|
|
326
315
|
@JRubyMethod(name = {"begin", "transaction"}, required = 1) // optional isolation argument for AR-4.0
|
327
316
|
public IRubyObject begin(final ThreadContext context, final IRubyObject isolation) {
|
328
317
|
try { // handleException == false so we can handle setTXIsolation
|
329
|
-
return withConnection(context, false,
|
330
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
331
|
-
return beginTransaction(context, connection, isolation == context.nil ? null : isolation);
|
332
|
-
}
|
333
|
-
});
|
318
|
+
return withConnection(context, false, connection -> beginTransaction(context, connection, isolation == context.nil ? null : isolation));
|
334
319
|
} catch (SQLException e) {
|
335
320
|
return handleException(context, e);
|
336
321
|
}
|
@@ -339,11 +324,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
339
324
|
@JRubyMethod(name = {"begin", "transaction"}) // optional isolation argument for AR-4.0
|
340
325
|
public IRubyObject begin(final ThreadContext context) {
|
341
326
|
try { // handleException == false so we can handle setTXIsolation
|
342
|
-
return withConnection(context, false,
|
343
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
344
|
-
return beginTransaction(context, connection, null);
|
345
|
-
}
|
346
|
-
});
|
327
|
+
return withConnection(context, false, connection -> beginTransaction(context, connection, null));
|
347
328
|
} catch (SQLException e) {
|
348
329
|
return handleException(context, e);
|
349
330
|
}
|
@@ -373,8 +354,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
373
354
|
|
374
355
|
@JRubyMethod(name = "commit")
|
375
356
|
public IRubyObject commit(final ThreadContext context) {
|
376
|
-
final Connection connection = getConnection(true);
|
377
357
|
try {
|
358
|
+
final Connection connection = getConnectionInternal(true);
|
378
359
|
if ( ! connection.getAutoCommit() ) {
|
379
360
|
try {
|
380
361
|
connection.commit();
|
@@ -394,13 +375,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
394
375
|
|
395
376
|
@JRubyMethod(name = "rollback")
|
396
377
|
public IRubyObject rollback(final ThreadContext context) {
|
397
|
-
final Connection connection = getConnection(true);
|
398
378
|
try {
|
379
|
+
final Connection connection = getConnectionInternal(true);
|
399
380
|
if ( ! connection.getAutoCommit() ) {
|
400
381
|
try {
|
401
382
|
connection.rollback();
|
402
383
|
resetSavepoints(context); // if any
|
403
|
-
return context.
|
384
|
+
return context.tru;
|
404
385
|
} finally {
|
405
386
|
connection.setAutoCommit(true);
|
406
387
|
}
|
@@ -414,11 +395,9 @@ public class RubyJdbcConnection extends RubyObject {
|
|
414
395
|
|
415
396
|
@JRubyMethod(name = "supports_savepoints?")
|
416
397
|
public IRubyObject supports_savepoints_p(final ThreadContext context) throws SQLException {
|
417
|
-
return withConnection(context,
|
418
|
-
|
419
|
-
|
420
|
-
return context.runtime.newBoolean( metaData.supportsSavepoints() );
|
421
|
-
}
|
398
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
399
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
400
|
+
return context.runtime.newBoolean( metaData.supportsSavepoints() );
|
422
401
|
});
|
423
402
|
}
|
424
403
|
|
@@ -429,8 +408,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
429
408
|
|
430
409
|
@JRubyMethod(name = "create_savepoint", required = 1)
|
431
410
|
public IRubyObject create_savepoint(final ThreadContext context, IRubyObject name) {
|
432
|
-
final Connection connection = getConnection(true);
|
433
411
|
try {
|
412
|
+
final Connection connection = getConnectionInternal(true);
|
434
413
|
connection.setAutoCommit(false);
|
435
414
|
|
436
415
|
final Savepoint savepoint ;
|
@@ -458,8 +437,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
458
437
|
public IRubyObject rollback_savepoint(final ThreadContext context, final IRubyObject name) {
|
459
438
|
if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
|
460
439
|
|
461
|
-
final Connection connection = getConnection(true);
|
462
440
|
try {
|
441
|
+
final Connection connection = getConnectionInternal(true);
|
463
442
|
Savepoint savepoint = getSavepoints(context).get(name);
|
464
443
|
if ( savepoint == null ) {
|
465
444
|
throw context.runtime.newRuntimeError("could not rollback savepoint: '" + name + "' (not set)");
|
@@ -476,7 +455,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
476
455
|
public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
|
477
456
|
if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
|
478
457
|
|
479
|
-
final Connection connection = getConnection(true);
|
480
458
|
try {
|
481
459
|
Object savepoint = getSavepoints(context).remove(name);
|
482
460
|
|
@@ -487,6 +465,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
487
465
|
savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
|
488
466
|
}
|
489
467
|
|
468
|
+
final Connection connection = getConnectionInternal(true);
|
490
469
|
releaseSavepoint(connection, (Savepoint) savepoint);
|
491
470
|
return context.nil;
|
492
471
|
}
|
@@ -525,7 +504,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
525
504
|
}
|
526
505
|
|
527
506
|
@SuppressWarnings("unchecked")
|
528
|
-
private
|
507
|
+
private Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
|
529
508
|
if ( hasInternalVariable("savepoints") ) {
|
530
509
|
return (Map<IRubyObject, Savepoint>) getInternalVariable("savepoints");
|
531
510
|
}
|
@@ -545,13 +524,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
545
524
|
return false;
|
546
525
|
}
|
547
526
|
|
548
|
-
@Deprecated // second argument is now mandatory - only kept for compatibility
|
549
|
-
@JRubyMethod(required = 1)
|
550
|
-
public final IRubyObject initialize(final ThreadContext context, final IRubyObject config) {
|
551
|
-
doInitialize(context, config, context.nil);
|
552
|
-
return this;
|
553
|
-
}
|
554
|
-
|
555
527
|
@JRubyMethod(required = 2)
|
556
528
|
public final IRubyObject initialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
|
557
529
|
doInitialize(context, config, adapter);
|
@@ -559,12 +531,17 @@ public class RubyJdbcConnection extends RubyObject {
|
|
559
531
|
}
|
560
532
|
|
561
533
|
protected void doInitialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
|
562
|
-
this.config = config;
|
534
|
+
this.config = config;
|
535
|
+
this.adapter = adapter;
|
563
536
|
|
564
537
|
this.jndi = setupConnectionFactory(context);
|
565
538
|
this.lazy = jndi; // JNDIs are lazy by default otherwise eager
|
566
539
|
try {
|
567
|
-
|
540
|
+
if (adapter == null || adapter == context.nil) {
|
541
|
+
warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
|
542
|
+
}
|
543
|
+
|
544
|
+
if (!lazy) setConnection(newConnection());
|
568
545
|
}
|
569
546
|
catch (SQLException e) {
|
570
547
|
String message = e.getMessage();
|
@@ -575,7 +552,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
575
552
|
IRubyObject value = getConfigValue(context, "configure_connection");
|
576
553
|
if ( value == context.nil ) this.configureConnection = true;
|
577
554
|
else {
|
578
|
-
this.configureConnection = value != context.
|
555
|
+
this.configureConnection = value != context.fals;
|
579
556
|
}
|
580
557
|
|
581
558
|
IRubyObject jdbcFetchSize = getConfigValue(context, "jdbc_fetch_size");
|
@@ -586,7 +563,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
586
563
|
|
587
564
|
@JRubyMethod(name = "adapter")
|
588
565
|
public IRubyObject adapter(final ThreadContext context) {
|
589
|
-
final IRubyObject adapter = getAdapter();
|
590
566
|
return adapter == null ? context.nil : adapter;
|
591
567
|
}
|
592
568
|
|
@@ -601,43 +577,9 @@ public class RubyJdbcConnection extends RubyObject {
|
|
601
577
|
return factory;
|
602
578
|
}
|
603
579
|
|
604
|
-
/**
|
605
|
-
* Called during <code>initialize</code> after the connection factory
|
606
|
-
* has been set to check if we can connect and/or perform any initialization
|
607
|
-
* necessary.
|
608
|
-
* <br/>
|
609
|
-
* NOTE: connection has not been configured at this point,
|
610
|
-
* nor should we retry - we're creating a brand new JDBC connection
|
611
|
-
*
|
612
|
-
* @param context
|
613
|
-
* @return connection
|
614
|
-
*/
|
615
|
-
@Deprecated
|
616
|
-
@JRubyMethod(name = "init_connection")
|
617
|
-
public synchronized IRubyObject init_connection(final ThreadContext context) {
|
618
|
-
try {
|
619
|
-
return initConnection(context);
|
620
|
-
}
|
621
|
-
catch (SQLException e) {
|
622
|
-
return handleException(context, e); // throws
|
623
|
-
}
|
624
|
-
}
|
625
|
-
|
626
|
-
private IRubyObject initConnection(final ThreadContext context) throws SQLException {
|
627
|
-
final IRubyObject adapter = getAdapter(); // self.adapter
|
628
|
-
if ( adapter == null || adapter == context.nil ) {
|
629
|
-
warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
|
630
|
-
}
|
631
|
-
|
632
|
-
if ( ! lazy ) setConnection( newConnection() );
|
633
|
-
|
634
|
-
return context.nil;
|
635
|
-
}
|
636
|
-
|
637
580
|
private void configureConnection() {
|
638
581
|
if ( ! configureConnection ) return; // return false;
|
639
582
|
|
640
|
-
final IRubyObject adapter = getAdapter(); // self.adapter
|
641
583
|
if ( adapter != null && ! adapter.isNil() ) {
|
642
584
|
if ( adapter.respondsTo("configure_connection") ) {
|
643
585
|
final ThreadContext context = getRuntime().getCurrentContext();
|
@@ -659,7 +601,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
659
601
|
|
660
602
|
@JRubyMethod(name = "jdbc_connection", alias = "connection", required = 1)
|
661
603
|
public final IRubyObject connection(final ThreadContext context, final IRubyObject unwrap) {
|
662
|
-
if ( unwrap == context.nil || unwrap == context.
|
604
|
+
if ( unwrap == context.nil || unwrap == context.fals ) {
|
663
605
|
return connection(context);
|
664
606
|
}
|
665
607
|
Connection connection = connectionImpl(context);
|
@@ -695,18 +637,25 @@ public class RubyJdbcConnection extends RubyObject {
|
|
695
637
|
|
696
638
|
@JRubyMethod(name = "active?", alias = "valid?")
|
697
639
|
public RubyBoolean active_p(final ThreadContext context) {
|
698
|
-
if ( ! connected ) return context.
|
699
|
-
if (
|
640
|
+
if ( ! connected ) return context.fals;
|
641
|
+
if (jndi) {
|
700
642
|
// for JNDI the data-source / pool is supposed to
|
701
643
|
// manage connections for us thus no valid check!
|
702
644
|
boolean active = getConnectionFactory() != null;
|
703
645
|
return context.runtime.newBoolean( active );
|
704
646
|
}
|
705
|
-
final Connection connection = getConnection();
|
706
|
-
if ( connection == null ) return context.
|
647
|
+
final Connection connection = getConnection(false);
|
648
|
+
if ( connection == null ) return context.fals; // unlikely
|
707
649
|
return context.runtime.newBoolean( isConnectionValid(context, connection) );
|
708
650
|
}
|
709
651
|
|
652
|
+
@JRubyMethod(name = "really_valid?")
|
653
|
+
public RubyBoolean really_valid_p(final ThreadContext context) {
|
654
|
+
final Connection connection = getConnection(true);
|
655
|
+
if (connection == null) return context.fals;
|
656
|
+
return context.runtime.newBoolean(isConnectionValid(context, connection));
|
657
|
+
}
|
658
|
+
|
710
659
|
@JRubyMethod(name = "disconnect!")
|
711
660
|
public synchronized IRubyObject disconnect(final ThreadContext context) {
|
712
661
|
setConnection(null); connected = false;
|
@@ -727,41 +676,40 @@ public class RubyJdbcConnection extends RubyObject {
|
|
727
676
|
|
728
677
|
private void connectImpl(final boolean forceConnection) throws SQLException {
|
729
678
|
setConnection( forceConnection ? newConnection() : null );
|
730
|
-
if (forceConnection)
|
731
|
-
if (getConnectionImpl() == null) throw new SQLException("Didn't get a connection. Wrong URL?");
|
732
|
-
configureConnection();
|
733
|
-
}
|
679
|
+
if ( forceConnection ) configureConnection();
|
734
680
|
}
|
735
681
|
|
736
682
|
@JRubyMethod(name = "read_only?")
|
737
683
|
public IRubyObject is_read_only(final ThreadContext context) {
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
return context.runtime.newBoolean(
|
684
|
+
try {
|
685
|
+
final Connection connection = getConnectionInternal(false);
|
686
|
+
if (connection != null) {
|
687
|
+
return context.runtime.newBoolean(connection.isReadOnly());
|
742
688
|
}
|
743
|
-
|
689
|
+
} catch (SQLException e) {
|
690
|
+
return handleException(context, e);
|
744
691
|
}
|
745
692
|
return context.nil;
|
746
693
|
}
|
747
694
|
|
748
695
|
@JRubyMethod(name = "read_only=")
|
749
696
|
public IRubyObject set_read_only(final ThreadContext context, final IRubyObject flag) {
|
750
|
-
final Connection connection = getConnection(true);
|
751
697
|
try {
|
698
|
+
final Connection connection = getConnectionInternal(true);
|
752
699
|
connection.setReadOnly( flag.isTrue() );
|
753
700
|
return context.runtime.newBoolean( connection.isReadOnly() );
|
701
|
+
} catch (SQLException e) {
|
702
|
+
return handleException(context, e);
|
754
703
|
}
|
755
|
-
catch (SQLException e) { return handleException(context, e); }
|
756
704
|
}
|
757
705
|
|
758
706
|
@JRubyMethod(name = { "open?" /* "conn?" */ })
|
759
707
|
public IRubyObject open_p(final ThreadContext context) {
|
760
|
-
|
708
|
+
try {
|
709
|
+
final Connection connection = getConnectionInternal(false);
|
761
710
|
|
762
|
-
|
711
|
+
if (connection == null) return context.fals;
|
763
712
|
|
764
|
-
try {
|
765
713
|
// NOTE: isClosed method generally cannot be called to determine
|
766
714
|
// whether a connection to a database is valid or invalid ...
|
767
715
|
return context.runtime.newBoolean(!connection.isClosed());
|
@@ -774,10 +722,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
774
722
|
public IRubyObject close(final ThreadContext context) {
|
775
723
|
final Connection connection = getConnection(false);
|
776
724
|
|
777
|
-
if (connection == null) return context.
|
725
|
+
if (connection == null) return context.fals;
|
778
726
|
|
779
727
|
try {
|
780
|
-
if (connection.isClosed()) return context.
|
728
|
+
if (connection.isClosed()) return context.fals;
|
781
729
|
|
782
730
|
setConnection(null); // does connection.close();
|
783
731
|
} catch (Exception e) {
|
@@ -787,69 +735,65 @@ public class RubyJdbcConnection extends RubyObject {
|
|
787
735
|
|
788
736
|
// ActiveRecord expects a closed connection to not try and re-open a connection
|
789
737
|
// whereas JNDI expects that.
|
790
|
-
if (!
|
738
|
+
if (!jndi) disconnect(context);
|
791
739
|
|
792
|
-
return context.
|
740
|
+
return context.tru;
|
793
741
|
}
|
794
742
|
|
795
743
|
@JRubyMethod(name = "database_name")
|
796
744
|
public IRubyObject database_name(final ThreadContext context) {
|
797
|
-
return withConnection(context,
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
if ( name == null ) return context.nil;
|
803
|
-
}
|
804
|
-
return context.runtime.newString(name);
|
745
|
+
return withConnection(context, connection -> {
|
746
|
+
String name = connection.getCatalog();
|
747
|
+
if ( name == null ) {
|
748
|
+
name = connection.getMetaData().getUserName();
|
749
|
+
if ( name == null ) return context.nil;
|
805
750
|
}
|
751
|
+
return context.runtime.newString(name);
|
806
752
|
});
|
807
753
|
}
|
808
754
|
|
809
755
|
@JRubyMethod(name = "execute", required = 1)
|
810
756
|
public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
|
811
757
|
final String query = sqlString(sql);
|
812
|
-
return withConnection(context,
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
statement = createStatement(context, connection);
|
817
|
-
|
818
|
-
// For DBs that do support multiple statements, lets return the last result set
|
819
|
-
// to be consistent with AR
|
820
|
-
boolean hasResultSet = doExecute(statement, query);
|
821
|
-
int updateCount = statement.getUpdateCount();
|
758
|
+
return withConnection(context, connection -> {
|
759
|
+
Statement statement = null;
|
760
|
+
try {
|
761
|
+
statement = createStatement(context, connection);
|
822
762
|
|
823
|
-
|
824
|
-
|
763
|
+
// For DBs that do support multiple statements, lets return the last result set
|
764
|
+
// to be consistent with AR
|
765
|
+
boolean hasResultSet = doExecute(statement, query);
|
766
|
+
int updateCount = statement.getUpdateCount();
|
825
767
|
|
826
|
-
|
768
|
+
IRubyObject result = context.nil; // If no results, return nil
|
769
|
+
ResultSet resultSet;
|
827
770
|
|
828
|
-
|
829
|
-
resultSet = statement.getResultSet();
|
771
|
+
while (hasResultSet || updateCount != -1) {
|
830
772
|
|
831
|
-
|
832
|
-
|
833
|
-
// this shouldn't be an issue in most cases since we're only getting 1 result set anyways
|
834
|
-
result = mapExecuteResult(context, connection, resultSet);
|
835
|
-
resultSet.close();
|
836
|
-
} else {
|
837
|
-
result = context.runtime.newFixnum(updateCount);
|
838
|
-
}
|
773
|
+
if (hasResultSet) {
|
774
|
+
resultSet = statement.getResultSet();
|
839
775
|
|
840
|
-
//
|
841
|
-
|
842
|
-
|
776
|
+
// Unfortunately the result set gets closed when getMoreResults()
|
777
|
+
// is called, so we have to process the result sets as we get them
|
778
|
+
// this shouldn't be an issue in most cases since we're only getting 1 result set anyways
|
779
|
+
result = mapExecuteResult(context, connection, resultSet);
|
780
|
+
resultSet.close();
|
781
|
+
} else {
|
782
|
+
result = context.runtime.newFixnum(updateCount);
|
843
783
|
}
|
844
784
|
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
debugErrorSQL(context, query);
|
849
|
-
throw e;
|
850
|
-
} finally {
|
851
|
-
close(statement);
|
785
|
+
// Check to see if there is another result set
|
786
|
+
hasResultSet = statement.getMoreResults();
|
787
|
+
updateCount = statement.getUpdateCount();
|
852
788
|
}
|
789
|
+
|
790
|
+
return result;
|
791
|
+
|
792
|
+
} catch (final SQLException e) {
|
793
|
+
debugErrorSQL(context, query);
|
794
|
+
throw e;
|
795
|
+
} finally {
|
796
|
+
close(statement);
|
853
797
|
}
|
854
798
|
});
|
855
799
|
}
|
@@ -888,106 +832,62 @@ public class RubyJdbcConnection extends RubyObject {
|
|
888
832
|
return mapQueryResult(context, connection, resultSet);
|
889
833
|
}
|
890
834
|
|
891
|
-
private static String[] createStatementPk(IRubyObject pk) {
|
892
|
-
String[] statementPk;
|
893
|
-
if (pk instanceof RubyArray) {
|
894
|
-
RubyArray ary = (RubyArray) pk;
|
895
|
-
int size = ary.size();
|
896
|
-
statementPk = new String[size];
|
897
|
-
for (int i = 0; i < size; i++) {
|
898
|
-
statementPk[i] = sqlString(ary.eltInternal(i));
|
899
|
-
}
|
900
|
-
} else {
|
901
|
-
statementPk = new String[] { sqlString(pk) };
|
902
|
-
}
|
903
|
-
return statementPk;
|
904
|
-
}
|
905
|
-
|
906
835
|
/**
|
907
836
|
* Executes an INSERT SQL statement
|
908
837
|
* @param context
|
909
838
|
* @param sql
|
910
|
-
* @param pk Rails PK
|
911
839
|
* @return ActiveRecord::Result
|
912
840
|
* @throws SQLException
|
913
841
|
*/
|
914
|
-
@JRubyMethod(name = "
|
915
|
-
public IRubyObject
|
916
|
-
return withConnection(context,
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
try {
|
921
|
-
|
922
|
-
statement = createStatement(context, connection);
|
923
|
-
|
924
|
-
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
|
925
|
-
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
|
926
|
-
} else {
|
927
|
-
statement.executeUpdate(query, createStatementPk(pk));
|
928
|
-
}
|
842
|
+
@JRubyMethod(name = "execute_insert", required = 1)
|
843
|
+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
|
844
|
+
return withConnection(context, connection -> {
|
845
|
+
Statement statement = null;
|
846
|
+
final String query = sqlString(sql);
|
847
|
+
try {
|
929
848
|
|
930
|
-
|
849
|
+
statement = createStatement(context, connection);
|
850
|
+
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
|
851
|
+
return mapGeneratedKeys(context, connection, statement);
|
931
852
|
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
}
|
853
|
+
} catch (final SQLException e) {
|
854
|
+
debugErrorSQL(context, query);
|
855
|
+
throw e;
|
856
|
+
} finally {
|
857
|
+
close(statement);
|
938
858
|
}
|
939
859
|
});
|
940
860
|
}
|
941
861
|
|
942
|
-
@Deprecated
|
943
|
-
@JRubyMethod(name = "execute_insert", required = 1)
|
944
|
-
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
|
945
|
-
return execute_insert_pk(context, sql, context.nil);
|
946
|
-
}
|
947
|
-
|
948
862
|
/**
|
949
863
|
* Executes an INSERT SQL statement using a prepared statement
|
950
864
|
* @param context
|
951
865
|
* @param sql
|
952
866
|
* @param binds RubyArray of values to be bound to the query
|
953
|
-
* @param pk Rails PK
|
954
867
|
* @return ActiveRecord::Result
|
955
868
|
* @throws SQLException
|
956
869
|
*/
|
957
|
-
@JRubyMethod(name = "
|
958
|
-
public IRubyObject
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
final String query = sqlString(sql);
|
964
|
-
try {
|
965
|
-
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
|
966
|
-
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
|
967
|
-
} else {
|
968
|
-
statement = connection.prepareStatement(query, createStatementPk(pk));
|
969
|
-
}
|
870
|
+
@JRubyMethod(name = "execute_insert", required = 2)
|
871
|
+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
|
872
|
+
return withConnection(context, connection -> {
|
873
|
+
PreparedStatement statement = null;
|
874
|
+
final String query = sqlString(sql);
|
875
|
+
try {
|
970
876
|
|
971
|
-
|
972
|
-
|
973
|
-
|
877
|
+
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
|
878
|
+
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
879
|
+
statement.executeUpdate();
|
880
|
+
return mapGeneratedKeys(context, connection, statement);
|
974
881
|
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
}
|
882
|
+
} catch (final SQLException e) {
|
883
|
+
debugErrorSQL(context, query);
|
884
|
+
throw e;
|
885
|
+
} finally {
|
886
|
+
close(statement);
|
981
887
|
}
|
982
888
|
});
|
983
889
|
}
|
984
890
|
|
985
|
-
@Deprecated
|
986
|
-
@JRubyMethod(name = "execute_insert", required = 2)
|
987
|
-
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject binds, final IRubyObject sql) {
|
988
|
-
return execute_insert_pk(context, sql, binds, context.nil);
|
989
|
-
}
|
990
|
-
|
991
891
|
/**
|
992
892
|
* Executes an UPDATE (DELETE) SQL statement
|
993
893
|
* @param context
|
@@ -997,22 +897,20 @@ public class RubyJdbcConnection extends RubyObject {
|
|
997
897
|
*/
|
998
898
|
@JRubyMethod(name = {"execute_update", "execute_delete"}, required = 1)
|
999
899
|
public IRubyObject execute_update(final ThreadContext context, final IRubyObject sql) {
|
1000
|
-
return withConnection(context,
|
1001
|
-
|
1002
|
-
|
1003
|
-
final String query = sqlString(sql);
|
900
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
901
|
+
Statement statement = null;
|
902
|
+
final String query = sqlString(sql);
|
1004
903
|
|
1005
|
-
|
1006
|
-
|
904
|
+
try {
|
905
|
+
statement = createStatement(context, connection);
|
1007
906
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
}
|
907
|
+
final int rowCount = statement.executeUpdate(query);
|
908
|
+
return context.runtime.newFixnum(rowCount);
|
909
|
+
} catch (final SQLException e) {
|
910
|
+
debugErrorSQL(context, query);
|
911
|
+
throw e;
|
912
|
+
} finally {
|
913
|
+
close(statement);
|
1016
914
|
}
|
1017
915
|
});
|
1018
916
|
}
|
@@ -1028,21 +926,19 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1028
926
|
*/
|
1029
927
|
@JRubyMethod(name = {"execute_prepared_update", "execute_prepared_delete"}, required = 2)
|
1030
928
|
public IRubyObject execute_prepared_update(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
|
1031
|
-
return withConnection(context,
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
close(statement);
|
1045
|
-
}
|
929
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
930
|
+
PreparedStatement statement = null;
|
931
|
+
final String query = sqlString(sql);
|
932
|
+
try {
|
933
|
+
statement = connection.prepareStatement(query);
|
934
|
+
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
935
|
+
final int rowCount = statement.executeUpdate();
|
936
|
+
return context.runtime.newFixnum(rowCount);
|
937
|
+
} catch (final SQLException e) {
|
938
|
+
debugErrorSQL(context, query);
|
939
|
+
throw e;
|
940
|
+
} finally {
|
941
|
+
close(statement);
|
1046
942
|
}
|
1047
943
|
});
|
1048
944
|
}
|
@@ -1089,50 +985,48 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1089
985
|
|
1090
986
|
private IRubyObject doExecuteQueryRaw(final ThreadContext context,
|
1091
987
|
final String query, final int maxRows, final Block block, final RubyArray binds) {
|
1092
|
-
return withConnection(context,
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
}
|
988
|
+
return withConnection(context, connection -> {
|
989
|
+
Statement statement = null; boolean hasResult;
|
990
|
+
try {
|
991
|
+
if ( binds == null || binds.isEmpty()) { // plain statement
|
992
|
+
statement = createStatement(context, connection);
|
993
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
994
|
+
hasResult = statement.execute(query);
|
995
|
+
}
|
996
|
+
else {
|
997
|
+
final PreparedStatement prepStatement;
|
998
|
+
statement = prepStatement = connection.prepareStatement(query);
|
999
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1000
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
1001
|
+
setStatementParameters(context, connection, prepStatement, binds);
|
1002
|
+
hasResult = prepStatement.execute();
|
1003
|
+
}
|
1109
1004
|
|
1110
|
-
|
1111
|
-
if (hasResult) {
|
1112
|
-
// yield(id1, name1) ... row 1 result data
|
1113
|
-
// yield(id2, name2) ... row 2 result data
|
1114
|
-
return yieldResultRows(context, connection, statement.getResultSet(), block);
|
1115
|
-
}
|
1116
|
-
return context.nil;
|
1117
|
-
}
|
1005
|
+
if (block.isGiven()) {
|
1118
1006
|
if (hasResult) {
|
1119
|
-
|
1007
|
+
// yield(id1, name1) ... row 1 result data
|
1008
|
+
// yield(id2, name2) ... row 2 result data
|
1009
|
+
return yieldResultRows(context, connection, statement.getResultSet(), block);
|
1120
1010
|
}
|
1121
|
-
return context.
|
1011
|
+
return context.nil;
|
1122
1012
|
}
|
1123
|
-
|
1124
|
-
|
1125
|
-
throw e;
|
1126
|
-
}
|
1127
|
-
finally {
|
1128
|
-
close(statement);
|
1013
|
+
if (hasResult) {
|
1014
|
+
return mapToRawResult(context, connection, statement.getResultSet(), false);
|
1129
1015
|
}
|
1016
|
+
return context.runtime.newEmptyArray();
|
1017
|
+
}
|
1018
|
+
catch (final SQLException e) {
|
1019
|
+
debugErrorSQL(context, query);
|
1020
|
+
throw e;
|
1021
|
+
}
|
1022
|
+
finally {
|
1023
|
+
close(statement);
|
1130
1024
|
}
|
1131
1025
|
});
|
1132
1026
|
}
|
1133
1027
|
|
1134
1028
|
protected static String sqlString(final IRubyObject sql) {
|
1135
|
-
return sql
|
1029
|
+
return sql.convertToString().decodeString();
|
1136
1030
|
}
|
1137
1031
|
|
1138
1032
|
/**
|
@@ -1145,26 +1039,24 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1145
1039
|
*/
|
1146
1040
|
@JRubyMethod(required = 1)
|
1147
1041
|
public IRubyObject execute_query(final ThreadContext context, final IRubyObject sql) {
|
1148
|
-
return withConnection(context,
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
statement = createStatement(context, connection);
|
1042
|
+
return withConnection(context, connection -> {
|
1043
|
+
Statement statement = null;
|
1044
|
+
final String query = sqlString(sql);
|
1045
|
+
try {
|
1046
|
+
statement = createStatement(context, connection);
|
1154
1047
|
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1048
|
+
// At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
|
1049
|
+
if (statement.execute(query)) {
|
1050
|
+
return mapQueryResult(context, connection, statement.getResultSet());
|
1051
|
+
}
|
1159
1052
|
|
1160
|
-
|
1053
|
+
return newEmptyResult(context);
|
1161
1054
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
}
|
1055
|
+
} catch (final SQLException e) {
|
1056
|
+
debugErrorSQL(context, query);
|
1057
|
+
throw e;
|
1058
|
+
} finally {
|
1059
|
+
close(statement);
|
1168
1060
|
}
|
1169
1061
|
});
|
1170
1062
|
}
|
@@ -1177,13 +1069,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1177
1069
|
*/
|
1178
1070
|
@JRubyMethod(required = 1)
|
1179
1071
|
public IRubyObject prepare_statement(final ThreadContext context, final IRubyObject sql) {
|
1180
|
-
return withConnection(context,
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
return JavaUtil.convertJavaToRuby(context.runtime, statement);
|
1186
|
-
}
|
1072
|
+
return withConnection(context, connection -> {
|
1073
|
+
final String query = sql.convertToString().getUnicodeValue();
|
1074
|
+
PreparedStatement statement = connection.prepareStatement(query);
|
1075
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1076
|
+
return JavaUtil.convertJavaToRuby(context.runtime, statement);
|
1187
1077
|
});
|
1188
1078
|
}
|
1189
1079
|
|
@@ -1206,40 +1096,40 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1206
1096
|
@JRubyMethod(required = 3)
|
1207
1097
|
public IRubyObject execute_prepared_query(final ThreadContext context, final IRubyObject sql,
|
1208
1098
|
final IRubyObject binds, final IRubyObject cachedStatement) {
|
1209
|
-
return withConnection(context,
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
PreparedStatement statement = null;
|
1099
|
+
return withConnection(context, connection -> {
|
1100
|
+
final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
|
1101
|
+
String query = null;
|
1102
|
+
PreparedStatement statement = null;
|
1214
1103
|
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1104
|
+
try {
|
1105
|
+
if (cached) {
|
1106
|
+
statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
|
1107
|
+
} else {
|
1108
|
+
query = sql.convertToString().getUnicodeValue();
|
1109
|
+
statement = connection.prepareStatement(query);
|
1110
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1111
|
+
}
|
1222
1112
|
|
1223
|
-
|
1113
|
+
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
1224
1114
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1115
|
+
if (statement.execute()) {
|
1116
|
+
ResultSet resultSet = statement.getResultSet();
|
1117
|
+
IRubyObject results = mapQueryResult(context, connection, resultSet);
|
1118
|
+
resultSet.close();
|
1229
1119
|
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1120
|
+
return results;
|
1121
|
+
} else {
|
1122
|
+
return newEmptyResult(context);
|
1123
|
+
}
|
1124
|
+
} catch (final SQLException e) {
|
1125
|
+
if (query == null) query = sql.convertToString().getUnicodeValue();
|
1126
|
+
debugErrorSQL(context, query);
|
1127
|
+
throw e;
|
1128
|
+
} finally {
|
1129
|
+
if ( cached ) {
|
1130
|
+
statement.clearParameters();
|
1131
|
+
} else {
|
1132
|
+
close(statement);
|
1243
1133
|
}
|
1244
1134
|
}
|
1245
1135
|
});
|
@@ -1251,35 +1141,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1251
1141
|
return mapToResult(context, connection, resultSet, columns);
|
1252
1142
|
}
|
1253
1143
|
|
1254
|
-
/**
|
1255
|
-
* @deprecated please do not use this method
|
1256
|
-
*/
|
1257
|
-
@Deprecated // only used by Oracle adapter - also it's really a bad idea
|
1258
|
-
@JRubyMethod(name = "execute_id_insert", required = 2)
|
1259
|
-
public IRubyObject execute_id_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject id) {
|
1260
|
-
final Ruby runtime = context.runtime;
|
1261
|
-
|
1262
|
-
callMethod("warn", RubyString.newUnicodeString(runtime, "DEPRECATED: execute_id_insert(sql, id) will be removed"));
|
1263
|
-
|
1264
|
-
return withConnection(context, new Callable<IRubyObject>() {
|
1265
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
1266
|
-
PreparedStatement statement = null;
|
1267
|
-
final String insertSQL = sql.convertToString().getUnicodeValue();
|
1268
|
-
try {
|
1269
|
-
statement = connection.prepareStatement(insertSQL);
|
1270
|
-
statement.setLong(1, RubyNumeric.fix2long(id));
|
1271
|
-
statement.executeUpdate();
|
1272
|
-
}
|
1273
|
-
catch (final SQLException e) {
|
1274
|
-
debugErrorSQL(context, insertSQL);
|
1275
|
-
throw e;
|
1276
|
-
}
|
1277
|
-
finally { close(statement); }
|
1278
|
-
return id;
|
1279
|
-
}
|
1280
|
-
});
|
1281
|
-
}
|
1282
|
-
|
1283
1144
|
@JRubyMethod(name = "supported_data_types")
|
1284
1145
|
public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
|
1285
1146
|
final Connection connection = getConnection(true);
|
@@ -1303,12 +1164,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1303
1164
|
protected static final int PRIMARY_KEYS_COLUMN_NAME = 4;
|
1304
1165
|
|
1305
1166
|
private List<RubyString> primaryKeys(final ThreadContext context, final String tableName) {
|
1306
|
-
return withConnection(context,
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
return primaryKeys(context, connection, table);
|
1311
|
-
}
|
1167
|
+
return withConnection(context, connection -> {
|
1168
|
+
final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1169
|
+
final TableName table = extractTableName(connection, null, null, _tableName);
|
1170
|
+
return primaryKeys(context, connection, table);
|
1312
1171
|
});
|
1313
1172
|
}
|
1314
1173
|
|
@@ -1316,7 +1175,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1316
1175
|
final Connection connection, final TableName table) throws SQLException {
|
1317
1176
|
final DatabaseMetaData metaData = connection.getMetaData();
|
1318
1177
|
ResultSet resultSet = null;
|
1319
|
-
final List<RubyString> keyNames = new ArrayList
|
1178
|
+
final List<RubyString> keyNames = new ArrayList<>();
|
1320
1179
|
try {
|
1321
1180
|
resultSet = metaData.getPrimaryKeys(table.catalog, table.schema, table.name);
|
1322
1181
|
final Ruby runtime = context.runtime;
|
@@ -1330,26 +1189,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1330
1189
|
return keyNames;
|
1331
1190
|
}
|
1332
1191
|
|
1333
|
-
@Deprecated //@JRubyMethod(name = "tables")
|
1334
|
-
public IRubyObject tables(ThreadContext context) {
|
1335
|
-
return tables(context, null, null, null, TABLE_TYPE);
|
1336
|
-
}
|
1337
|
-
|
1338
|
-
@Deprecated //@JRubyMethod(name = "tables")
|
1339
|
-
public IRubyObject tables(ThreadContext context, IRubyObject catalog) {
|
1340
|
-
return tables(context, toStringOrNull(catalog), null, null, TABLE_TYPE);
|
1341
|
-
}
|
1342
|
-
|
1343
|
-
@Deprecated //@JRubyMethod(name = "tables")
|
1344
|
-
public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern) {
|
1345
|
-
return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), null, TABLE_TYPE);
|
1346
|
-
}
|
1347
|
-
|
1348
|
-
@Deprecated //@JRubyMethod(name = "tables")
|
1349
|
-
public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern, IRubyObject tablePattern) {
|
1350
|
-
return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), toStringOrNull(tablePattern), TABLE_TYPE);
|
1351
|
-
}
|
1352
|
-
|
1353
1192
|
@JRubyMethod(name = "tables", required = 0, optional = 4)
|
1354
1193
|
public IRubyObject tables(final ThreadContext context, final IRubyObject[] args) {
|
1355
1194
|
switch ( args.length ) {
|
@@ -1367,11 +1206,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1367
1206
|
|
1368
1207
|
protected IRubyObject tables(final ThreadContext context,
|
1369
1208
|
final String catalog, final String schemaPattern, final String tablePattern, final String[] types) {
|
1370
|
-
return withConnection(context,
|
1371
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
1372
|
-
return matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false);
|
1373
|
-
}
|
1374
|
-
});
|
1209
|
+
return withConnection(context, connection -> matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false));
|
1375
1210
|
}
|
1376
1211
|
|
1377
1212
|
protected String[] getTableTypes() {
|
@@ -1401,40 +1236,36 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1401
1236
|
|
1402
1237
|
protected IRubyObject tableExists(final ThreadContext context,
|
1403
1238
|
final String defaultSchema, final String tableName) {
|
1404
|
-
return withConnection(context,
|
1405
|
-
|
1406
|
-
|
1407
|
-
return context.runtime.newBoolean( tableExists(context, connection, components) );
|
1408
|
-
}
|
1239
|
+
return withConnection(context, connection -> {
|
1240
|
+
final TableName components = extractTableName(connection, defaultSchema, tableName);
|
1241
|
+
return context.runtime.newBoolean( tableExists(context, connection, components) );
|
1409
1242
|
});
|
1410
1243
|
}
|
1411
1244
|
|
1412
1245
|
@JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
|
1413
1246
|
public RubyArray columns_internal(final ThreadContext context, final IRubyObject[] args)
|
1414
1247
|
throws SQLException {
|
1415
|
-
return withConnection(context,
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
|
1423
|
-
|
1424
|
-
final TableName components;
|
1425
|
-
components = extractTableName(connection, catalog, defaultSchema, tableName);
|
1248
|
+
return withConnection(context, connection -> {
|
1249
|
+
ResultSet columns = null;
|
1250
|
+
try {
|
1251
|
+
final String tableName = args[0].toString();
|
1252
|
+
// optionals (NOTE: catalog argumnet was never used before 1.3.0) :
|
1253
|
+
final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
|
1254
|
+
final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
|
1426
1255
|
|
1427
|
-
|
1428
|
-
|
1429
|
-
}
|
1256
|
+
final TableName components;
|
1257
|
+
components = extractTableName(connection, catalog, defaultSchema, tableName);
|
1430
1258
|
|
1431
|
-
|
1432
|
-
|
1433
|
-
return mapColumnsResult(context, metaData, components, columns);
|
1434
|
-
}
|
1435
|
-
finally {
|
1436
|
-
close(columns);
|
1259
|
+
if ( ! tableExists(context, connection, components) ) {
|
1260
|
+
throw new SQLException("table: " + tableName + " does not exist");
|
1437
1261
|
}
|
1262
|
+
|
1263
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1264
|
+
columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
|
1265
|
+
return mapColumnsResult(context, metaData, components, columns);
|
1266
|
+
}
|
1267
|
+
finally {
|
1268
|
+
close(columns);
|
1438
1269
|
}
|
1439
1270
|
});
|
1440
1271
|
}
|
@@ -1464,70 +1295,68 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1464
1295
|
* should filter the return from this method instead.
|
1465
1296
|
*/
|
1466
1297
|
protected IRubyObject indexes(final ThreadContext context, final String tableName, final String name, final String schemaName) {
|
1467
|
-
return withConnection(context,
|
1468
|
-
|
1469
|
-
|
1470
|
-
final RubyClass IndexDefinition = getIndexDefinition(context);
|
1298
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1299
|
+
final Ruby runtime = context.runtime;
|
1300
|
+
final RubyClass IndexDefinition = getIndexDefinition(context);
|
1471
1301
|
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1302
|
+
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1303
|
+
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1304
|
+
final TableName table = extractTableName(connection, null, _schemaName, _tableName);
|
1475
1305
|
|
1476
|
-
|
1306
|
+
final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
|
1477
1307
|
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
while ( indexInfoSet.next() ) {
|
1486
|
-
String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
|
1487
|
-
if ( indexName == null ) continue;
|
1488
|
-
RubyArray currentColumns = null;
|
1308
|
+
ResultSet indexInfoSet = null;
|
1309
|
+
final RubyArray indexes = RubyArray.newArray(runtime, 8);
|
1310
|
+
try {
|
1311
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1312
|
+
indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
|
1313
|
+
String currentIndex = null;
|
1489
1314
|
|
1490
|
-
|
1315
|
+
while ( indexInfoSet.next() ) {
|
1316
|
+
String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
|
1317
|
+
if ( indexName == null ) continue;
|
1318
|
+
RubyArray currentColumns = null;
|
1491
1319
|
|
1492
|
-
|
1493
|
-
final RubyString rubyColumnName = cachedString(
|
1494
|
-
context, caseConvertIdentifierForRails(metaData, columnName)
|
1495
|
-
);
|
1496
|
-
if ( primaryKeys.contains(rubyColumnName) ) continue;
|
1320
|
+
indexName = caseConvertIdentifierForRails(metaData, indexName);
|
1497
1321
|
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1322
|
+
final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
|
1323
|
+
final RubyString rubyColumnName = cachedString(
|
1324
|
+
context, caseConvertIdentifierForRails(metaData, columnName)
|
1325
|
+
);
|
1326
|
+
if ( primaryKeys.contains(rubyColumnName) ) continue;
|
1501
1327
|
|
1502
|
-
|
1503
|
-
|
1328
|
+
// We are working on a new index
|
1329
|
+
if ( ! indexName.equals(currentIndex) ) {
|
1330
|
+
currentIndex = indexName;
|
1504
1331
|
|
1505
|
-
|
1332
|
+
String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
|
1333
|
+
indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
|
1506
1334
|
|
1507
|
-
|
1508
|
-
cachedString(context, indexTableName), // table_name
|
1509
|
-
cachedString(context, indexName), // index_name
|
1510
|
-
nonUnique ? runtime.getFalse() : runtime.getTrue(), // unique
|
1511
|
-
currentColumns = RubyArray.newArray(runtime, 4) // [] column names
|
1512
|
-
// orders, (since AR 3.2) where, type, using (AR 4.0)
|
1513
|
-
};
|
1335
|
+
final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
|
1514
1336
|
|
1515
|
-
|
1516
|
-
|
1337
|
+
IRubyObject[] args = new IRubyObject[] {
|
1338
|
+
cachedString(context, indexTableName), // table_name
|
1339
|
+
cachedString(context, indexName), // index_name
|
1340
|
+
nonUnique ? context.fals : context.tru, // unique
|
1341
|
+
currentColumns = RubyArray.newArray(runtime, 4) // [] column names
|
1342
|
+
// orders, (since AR 3.2) where, type, using (AR 4.0)
|
1343
|
+
};
|
1517
1344
|
|
1518
|
-
|
1519
|
-
if ( currentColumns != null ) currentColumns.append(rubyColumnName);
|
1345
|
+
indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
|
1520
1346
|
}
|
1521
1347
|
|
1522
|
-
|
1348
|
+
// one or more columns can be associated with an index
|
1349
|
+
if ( currentColumns != null ) currentColumns.append(rubyColumnName);
|
1350
|
+
}
|
1351
|
+
|
1352
|
+
return indexes;
|
1523
1353
|
|
1524
|
-
|
1525
|
-
}
|
1354
|
+
} finally { close(indexInfoSet); }
|
1526
1355
|
});
|
1527
1356
|
}
|
1528
1357
|
|
1529
1358
|
protected RubyClass getIndexDefinition(final ThreadContext context) {
|
1530
|
-
final RubyClass adapterClass =
|
1359
|
+
final RubyClass adapterClass = adapter.getMetaClass();
|
1531
1360
|
IRubyObject IDef = adapterClass.getConstantAt("IndexDefinition");
|
1532
1361
|
return IDef != null ? (RubyClass) IDef : getIndexDefinition(context.runtime);
|
1533
1362
|
}
|
@@ -1538,57 +1367,55 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1538
1367
|
}
|
1539
1368
|
|
1540
1369
|
protected IRubyObject foreignKeys(final ThreadContext context, final String tableName, final String schemaName, final String catalog) {
|
1541
|
-
return withConnection(context,
|
1542
|
-
|
1543
|
-
|
1544
|
-
final RubyClass FKDefinition = getForeignKeyDefinition(context);
|
1370
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1371
|
+
final Ruby runtime = context.runtime;
|
1372
|
+
final RubyClass FKDefinition = getForeignKeyDefinition(context);
|
1545
1373
|
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1374
|
+
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1375
|
+
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1376
|
+
final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
|
1549
1377
|
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1378
|
+
ResultSet fkInfoSet = null;
|
1379
|
+
final List<IRubyObject> fKeys = new ArrayList<>(8);
|
1380
|
+
try {
|
1381
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1382
|
+
fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
|
1555
1383
|
|
1556
|
-
|
1557
|
-
|
1384
|
+
while ( fkInfoSet.next() ) {
|
1385
|
+
final RubyHash options = RubyHash.newHash(runtime);
|
1558
1386
|
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1387
|
+
String fkName = fkInfoSet.getString("FK_NAME");
|
1388
|
+
if (fkName != null) {
|
1389
|
+
fkName = caseConvertIdentifierForRails(metaData, fkName);
|
1390
|
+
options.put(runtime.newSymbol("name"), fkName);
|
1391
|
+
}
|
1564
1392
|
|
1565
|
-
|
1566
|
-
|
1393
|
+
String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
|
1394
|
+
options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
|
1567
1395
|
|
1568
|
-
|
1569
|
-
|
1396
|
+
columnName = fkInfoSet.getString("PKCOLUMN_NAME");
|
1397
|
+
options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
|
1570
1398
|
|
1571
|
-
|
1572
|
-
|
1399
|
+
String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
|
1400
|
+
fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
|
1573
1401
|
|
1574
|
-
|
1575
|
-
|
1402
|
+
String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
|
1403
|
+
pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
|
1576
1404
|
|
1577
|
-
|
1578
|
-
|
1405
|
+
final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
|
1406
|
+
if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
|
1579
1407
|
|
1580
|
-
|
1581
|
-
|
1408
|
+
final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
|
1409
|
+
if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
|
1582
1410
|
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1411
|
+
IRubyObject from_table = cachedString(context, fkTableName);
|
1412
|
+
IRubyObject to_table = cachedString(context, pkTableName);
|
1413
|
+
fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
|
1414
|
+
}
|
1587
1415
|
|
1588
|
-
|
1416
|
+
return runtime.newArray(fKeys);
|
1589
1417
|
|
1590
|
-
|
1591
|
-
}
|
1418
|
+
} finally { close(fkInfoSet); }
|
1592
1419
|
});
|
1593
1420
|
}
|
1594
1421
|
|
@@ -1603,7 +1430,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1603
1430
|
}
|
1604
1431
|
|
1605
1432
|
protected RubyClass getForeignKeyDefinition(final ThreadContext context) {
|
1606
|
-
final RubyClass adapterClass =
|
1433
|
+
final RubyClass adapterClass = adapter.getMetaClass();
|
1607
1434
|
IRubyObject FKDef = adapterClass.getConstantAt("ForeignKeyDefinition");
|
1608
1435
|
return FKDef != null ? (RubyClass) FKDef : getForeignKeyDefinition(context.runtime);
|
1609
1436
|
}
|
@@ -1611,42 +1438,34 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1611
1438
|
|
1612
1439
|
@JRubyMethod(name = "supports_foreign_keys?")
|
1613
1440
|
public IRubyObject supports_foreign_keys_p(final ThreadContext context) throws SQLException {
|
1614
|
-
return withConnection(context,
|
1615
|
-
|
1616
|
-
|
1617
|
-
return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
|
1618
|
-
}
|
1441
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1442
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1443
|
+
return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
|
1619
1444
|
});
|
1620
1445
|
}
|
1621
1446
|
|
1622
1447
|
@JRubyMethod(name = "supports_views?")
|
1623
1448
|
public IRubyObject supports_views_p(final ThreadContext context) throws SQLException {
|
1624
|
-
return withConnection(context,
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
return context.runtime.newBoolean( true );
|
1632
|
-
}
|
1449
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1450
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1451
|
+
final ResultSet tableTypes = metaData.getTableTypes();
|
1452
|
+
try {
|
1453
|
+
while ( tableTypes.next() ) {
|
1454
|
+
if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
|
1455
|
+
return context.runtime.newBoolean( true );
|
1633
1456
|
}
|
1634
1457
|
}
|
1635
|
-
finally {
|
1636
|
-
close(tableTypes);
|
1637
|
-
}
|
1638
|
-
return context.runtime.newBoolean( false );
|
1639
1458
|
}
|
1459
|
+
finally {
|
1460
|
+
close(tableTypes);
|
1461
|
+
}
|
1462
|
+
return context.runtime.newBoolean( false );
|
1640
1463
|
});
|
1641
1464
|
}
|
1642
1465
|
|
1643
1466
|
@JRubyMethod(name = "with_jdbc_connection", alias = "with_connection_retry_guard", frame = true)
|
1644
1467
|
public IRubyObject with_jdbc_connection(final ThreadContext context, final Block block) {
|
1645
|
-
return withConnection(context,
|
1646
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
1647
|
-
return block.call(context, convertJavaToRuby(connection));
|
1648
|
-
}
|
1649
|
-
});
|
1468
|
+
return withConnection(context, connection -> block.call(context, convertJavaToRuby(connection)));
|
1650
1469
|
}
|
1651
1470
|
|
1652
1471
|
/*
|
@@ -1707,24 +1526,22 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1707
1526
|
// TODO: Fix this, the columns don't have the info needed to handle this anymore
|
1708
1527
|
// currently commented out so that it will compile
|
1709
1528
|
|
1710
|
-
return withConnection(context,
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
|
1718
|
-
}
|
1719
|
-
else { // clob
|
1720
|
-
setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
|
1721
|
-
}
|
1722
|
-
setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
|
1723
|
-
*/
|
1724
|
-
return statement.executeUpdate();
|
1529
|
+
return withConnection(context, connection -> {
|
1530
|
+
PreparedStatement statement = null;
|
1531
|
+
try {
|
1532
|
+
statement = connection.prepareStatement(sql);
|
1533
|
+
/*
|
1534
|
+
if ( binary ) { // blob
|
1535
|
+
setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
|
1725
1536
|
}
|
1726
|
-
|
1537
|
+
else { // clob
|
1538
|
+
setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
|
1539
|
+
}
|
1540
|
+
setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
|
1541
|
+
*/
|
1542
|
+
return statement.executeUpdate();
|
1727
1543
|
}
|
1544
|
+
finally { close(statement); }
|
1728
1545
|
});
|
1729
1546
|
}
|
1730
1547
|
|
@@ -1780,7 +1597,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1780
1597
|
final IRubyObject self, final IRubyObject config, final Block block) {
|
1781
1598
|
final IRubyObject ds_or_name = rawDataSourceOrName(context, config);
|
1782
1599
|
|
1783
|
-
if ( ds_or_name == null ) return context.
|
1600
|
+
if ( ds_or_name == null ) return context.fals;
|
1784
1601
|
|
1785
1602
|
final javax.sql.DataSource dataSource;
|
1786
1603
|
final Object dsOrName = ds_or_name.toJava(Object.class);
|
@@ -1836,7 +1653,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1836
1653
|
}
|
1837
1654
|
}
|
1838
1655
|
|
1839
|
-
if ( configValue == null || configValue == context.nil || configValue ==
|
1656
|
+
if ( configValue == null || configValue == context.nil || configValue == context.fals ) {
|
1840
1657
|
return null;
|
1841
1658
|
}
|
1842
1659
|
return configValue;
|
@@ -1859,13 +1676,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1859
1676
|
}
|
1860
1677
|
}
|
1861
1678
|
|
1862
|
-
@Deprecated
|
1863
|
-
@JRubyMethod(name = "setup_jdbc_factory", visibility = Visibility.PROTECTED)
|
1864
|
-
public IRubyObject set_driver_factory(final ThreadContext context) {
|
1865
|
-
setDriverFactory(context);
|
1866
|
-
return get_connection_factory(context.runtime);
|
1867
|
-
}
|
1868
|
-
|
1869
1679
|
private ConnectionFactory setDriverFactory(final ThreadContext context) {
|
1870
1680
|
|
1871
1681
|
final IRubyObject url = getConfigValue(context, "url");
|
@@ -1965,12 +1775,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1965
1775
|
return props;
|
1966
1776
|
}
|
1967
1777
|
|
1968
|
-
@JRubyMethod(name = "setup_jndi_factory", visibility = Visibility.PROTECTED)
|
1969
|
-
public IRubyObject set_data_source_factory(final ThreadContext context) {
|
1970
|
-
setDataSourceFactory(context);
|
1971
|
-
return get_connection_factory(context.runtime);
|
1972
|
-
}
|
1973
|
-
|
1974
1778
|
private ConnectionFactory setDataSourceFactory(final ThreadContext context) {
|
1975
1779
|
final javax.sql.DataSource dataSource; final String lookupName;
|
1976
1780
|
IRubyObject value = getConfigValue(context, "data_source");
|
@@ -1992,28 +1796,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1992
1796
|
private static volatile boolean defaultConfigJndi;
|
1993
1797
|
private static transient ConnectionFactory defaultConnectionFactory;
|
1994
1798
|
|
1995
|
-
/**
|
1996
|
-
* Sets the connection factory from the available configuration.
|
1997
|
-
* @param context
|
1998
|
-
* @see #initialize
|
1999
|
-
*/
|
2000
|
-
@Deprecated
|
2001
|
-
@JRubyMethod(name = "setup_connection_factory", visibility = Visibility.PROTECTED)
|
2002
|
-
public IRubyObject setup_connection_factory(final ThreadContext context) {
|
2003
|
-
setupConnectionFactory(context);
|
2004
|
-
return get_connection_factory(context.runtime);
|
2005
|
-
}
|
2006
|
-
|
2007
|
-
private IRubyObject get_connection_factory(final Ruby runtime) {
|
2008
|
-
return JavaUtil.convertJavaToRuby(runtime, connectionFactory);
|
2009
|
-
}
|
2010
|
-
|
2011
1799
|
/**
|
2012
1800
|
* @return whether the connection factory is JNDI based
|
2013
1801
|
*/
|
2014
1802
|
private boolean setupConnectionFactory(final ThreadContext context) {
|
2015
|
-
final IRubyObject config = getConfig();
|
2016
|
-
|
2017
1803
|
if ( defaultConfig == null ) {
|
2018
1804
|
synchronized(RubyJdbcConnection.class) {
|
2019
1805
|
if ( defaultConfig == null ) {
|
@@ -2045,18 +1831,17 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2045
1831
|
|
2046
1832
|
@JRubyMethod(name = "jndi?", alias = "jndi_connection?")
|
2047
1833
|
public RubyBoolean jndi_p(final ThreadContext context) {
|
2048
|
-
return context.runtime.newBoolean(
|
1834
|
+
return context.runtime.newBoolean(jndi);
|
2049
1835
|
}
|
2050
1836
|
|
2051
1837
|
protected boolean isJndi() { return this.jndi; }
|
2052
1838
|
|
2053
1839
|
@JRubyMethod(name = "config")
|
2054
|
-
public IRubyObject config() { return
|
1840
|
+
public IRubyObject config() { return config; }
|
2055
1841
|
|
2056
1842
|
public IRubyObject getConfig() { return this.config; }
|
2057
1843
|
|
2058
1844
|
protected final IRubyObject getConfigValue(final ThreadContext context, final String key) {
|
2059
|
-
final IRubyObject config = getConfig();
|
2060
1845
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2061
1846
|
if ( config instanceof RubyHash ) {
|
2062
1847
|
final IRubyObject value = ((RubyHash) config).fastARef(keySym);
|
@@ -2067,7 +1852,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2067
1852
|
|
2068
1853
|
protected final IRubyObject setConfigValue(final ThreadContext context,
|
2069
1854
|
final String key, final IRubyObject value) {
|
2070
|
-
final IRubyObject config = getConfig();
|
2071
1855
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2072
1856
|
if ( config instanceof RubyHash ) {
|
2073
1857
|
return ((RubyHash) config).op_aset(context, keySym, value);
|
@@ -2077,7 +1861,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2077
1861
|
|
2078
1862
|
protected final IRubyObject setConfigValueIfNotSet(final ThreadContext context,
|
2079
1863
|
final String key, final IRubyObject value) {
|
2080
|
-
final IRubyObject config = getConfig();
|
2081
1864
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2082
1865
|
if ( config instanceof RubyHash ) {
|
2083
1866
|
final IRubyObject setValue = ((RubyHash) config).fastARef(keySym);
|
@@ -2097,7 +1880,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2097
1880
|
protected final IRubyObject getAdapter() { return this.adapter; }
|
2098
1881
|
|
2099
1882
|
protected RubyClass getJdbcColumnClass(final ThreadContext context) {
|
2100
|
-
return (RubyClass)
|
1883
|
+
return (RubyClass) adapter.callMethod(context, "jdbc_column_class");
|
2101
1884
|
}
|
2102
1885
|
|
2103
1886
|
protected ConnectionFactory getConnectionFactory() throws RaiseException {
|
@@ -2309,7 +2092,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2309
2092
|
@JRubyMethod(name = "raw_date_time?", meta = true)
|
2310
2093
|
public static IRubyObject useRawDateTime(final ThreadContext context, final IRubyObject self) {
|
2311
2094
|
if ( rawDateTime == null ) return context.nil;
|
2312
|
-
return context.runtime.newBoolean(
|
2095
|
+
return context.runtime.newBoolean(rawDateTime);
|
2313
2096
|
}
|
2314
2097
|
|
2315
2098
|
@JRubyMethod(name = "raw_date_time=", meta = true)
|
@@ -2323,17 +2106,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2323
2106
|
return value;
|
2324
2107
|
}
|
2325
2108
|
|
2326
|
-
/**
|
2327
|
-
* @return AR::Type-casted value
|
2328
|
-
* @since 1.3.18
|
2329
|
-
*/
|
2330
|
-
@Deprecated
|
2331
|
-
protected static IRubyObject typeCastFromDatabase(final ThreadContext context,
|
2332
|
-
final IRubyObject adapter, final RubySymbol typeName, final RubyString value) {
|
2333
|
-
final IRubyObject type = adapter.callMethod(context, "lookup_cast_type", typeName);
|
2334
|
-
return type.callMethod(context, "deserialize", value);
|
2335
|
-
}
|
2336
|
-
|
2337
2109
|
protected IRubyObject dateToRuby(final ThreadContext context,
|
2338
2110
|
final Ruby runtime, final ResultSet resultSet, final int column)
|
2339
2111
|
throws SQLException {
|
@@ -2344,11 +2116,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2344
2116
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2345
2117
|
}
|
2346
2118
|
|
2347
|
-
if ( rawDateTime != null && rawDateTime
|
2119
|
+
if ( rawDateTime != null && rawDateTime) {
|
2348
2120
|
return RubyString.newString(runtime, DateTimeUtils.dateToString(value));
|
2349
2121
|
}
|
2350
2122
|
|
2351
|
-
return DateTimeUtils.newDateAsTime(context, value,
|
2123
|
+
return DateTimeUtils.newDateAsTime(context, value, null).callMethod(context, "to_date");
|
2352
2124
|
}
|
2353
2125
|
|
2354
2126
|
protected IRubyObject timeToRuby(final ThreadContext context,
|
@@ -2360,7 +2132,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2360
2132
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2361
2133
|
}
|
2362
2134
|
|
2363
|
-
if ( rawDateTime != null && rawDateTime
|
2135
|
+
if ( rawDateTime != null && rawDateTime) {
|
2364
2136
|
return RubyString.newString(runtime, DateTimeUtils.timeToString(value));
|
2365
2137
|
}
|
2366
2138
|
|
@@ -2376,7 +2148,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2376
2148
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2377
2149
|
}
|
2378
2150
|
|
2379
|
-
if ( rawDateTime != null && rawDateTime
|
2151
|
+
if ( rawDateTime != null && rawDateTime) {
|
2380
2152
|
return RubyString.newString(runtime, DateTimeUtils.timestampToString(value));
|
2381
2153
|
}
|
2382
2154
|
|
@@ -2388,19 +2160,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2388
2160
|
return DateTimeUtils.newTime(context, value, getDefaultTimeZone(context));
|
2389
2161
|
}
|
2390
2162
|
|
2391
|
-
@Deprecated
|
2392
|
-
protected static RubyString timestampToRubyString(final Ruby runtime, String value) {
|
2393
|
-
// Timestamp's format: yyyy-mm-dd hh:mm:ss.fffffffff
|
2394
|
-
String suffix; // assumes java.sql.Timestamp internals :
|
2395
|
-
if ( value.endsWith( suffix = " 00:00:00.0" ) ) {
|
2396
|
-
value = value.substring( 0, value.length() - suffix.length() );
|
2397
|
-
}
|
2398
|
-
else if ( value.endsWith( suffix = ".0" ) ) {
|
2399
|
-
value = value.substring( 0, value.length() - suffix.length() );
|
2400
|
-
}
|
2401
|
-
return RubyString.newUnicodeString(runtime, value);
|
2402
|
-
}
|
2403
|
-
|
2404
2163
|
protected static Boolean rawBoolean;
|
2405
2164
|
static {
|
2406
2165
|
final String booleanRaw = SafePropertyAccessor.getProperty("arjdbc.boolean.raw");
|
@@ -2412,7 +2171,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2412
2171
|
@JRubyMethod(name = "raw_boolean?", meta = true)
|
2413
2172
|
public static IRubyObject useRawBoolean(final ThreadContext context, final IRubyObject self) {
|
2414
2173
|
if ( rawBoolean == null ) return context.nil;
|
2415
|
-
return context.runtime.newBoolean(
|
2174
|
+
return context.runtime.newBoolean(rawBoolean);
|
2416
2175
|
}
|
2417
2176
|
|
2418
2177
|
@JRubyMethod(name = "raw_boolean=", meta = true)
|
@@ -2444,13 +2203,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2444
2203
|
protected IRubyObject booleanToRuby(final ThreadContext context,
|
2445
2204
|
final Ruby runtime, final ResultSet resultSet, final int column)
|
2446
2205
|
throws SQLException {
|
2447
|
-
if ( rawBoolean != null && rawBoolean
|
2206
|
+
if ( rawBoolean != null && rawBoolean) {
|
2448
2207
|
final String value = resultSet.getString(column);
|
2449
2208
|
if ( value == null /* && resultSet.wasNull() */ ) return context.nil;
|
2450
2209
|
return RubyString.newUnicodeString(runtime, value);
|
2451
2210
|
}
|
2452
2211
|
final boolean value = resultSet.getBoolean(column);
|
2453
|
-
if (
|
2212
|
+
if (!value && resultSet.wasNull()) return context.nil;
|
2454
2213
|
return runtime.newBoolean(value);
|
2455
2214
|
}
|
2456
2215
|
|
@@ -2668,7 +2427,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2668
2427
|
}
|
2669
2428
|
}
|
2670
2429
|
|
2671
|
-
protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap
|
2430
|
+
protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<>(32, 1);
|
2672
2431
|
static {
|
2673
2432
|
JDBC_TYPE_FOR.put("string", Types.VARCHAR);
|
2674
2433
|
JDBC_TYPE_FOR.put("text", Types.CLOB);
|
@@ -2710,7 +2469,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2710
2469
|
final String internedType = internedTypeFor(context, attribute);
|
2711
2470
|
final Integer sqlType = jdbcTypeFor(internedType);
|
2712
2471
|
if ( sqlType != null ) {
|
2713
|
-
return sqlType
|
2472
|
+
return sqlType;
|
2714
2473
|
}
|
2715
2474
|
|
2716
2475
|
return Types.OTHER; // -1 as well as 0 are used in Types
|
@@ -2888,11 +2647,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2888
2647
|
statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
|
2889
2648
|
}
|
2890
2649
|
|
2891
|
-
@Deprecated
|
2892
|
-
protected static Timestamp convertToTimestamp(final RubyFloat value) {
|
2893
|
-
return DateTimeUtils.convertToTimestamp(value);
|
2894
|
-
}
|
2895
|
-
|
2896
2650
|
protected static Calendar getCalendar(final DateTimeZone zone) { // final java.util.Date hint
|
2897
2651
|
if (DateTimeZone.UTC == zone) return getCalendarUTC();
|
2898
2652
|
if (DateTimeZone.getDefault() == zone) return new GregorianCalendar();
|
@@ -2938,6 +2692,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2938
2692
|
value = value.callMethod(context, "to_date");
|
2939
2693
|
}
|
2940
2694
|
|
2695
|
+
if (value instanceof RubyDate) {
|
2696
|
+
RubyDate rubyDate = (RubyDate) value;
|
2697
|
+
statement.setDate(index, rubyDate.toJava(Date.class));
|
2698
|
+
return;
|
2699
|
+
}
|
2700
|
+
|
2941
2701
|
// NOTE: assuming Date#to_s does right ...
|
2942
2702
|
statement.setDate(index, Date.valueOf(value.toString()));
|
2943
2703
|
}
|
@@ -2976,7 +2736,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2976
2736
|
// For some reason the driver doesn't like "character varying" as a type
|
2977
2737
|
if ( type.eql(context.runtime.newSymbol("string")) ) return "varchar";
|
2978
2738
|
|
2979
|
-
final RubyHash nativeTypes = (RubyHash)
|
2739
|
+
final RubyHash nativeTypes = (RubyHash) adapter.callMethod(context, "native_database_types");
|
2980
2740
|
// e.g. `integer: { name: 'integer' }`
|
2981
2741
|
final RubyHash typeInfo = (RubyHash) nativeTypes.op_aref(context, type);
|
2982
2742
|
|
@@ -3037,16 +2797,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3037
2797
|
}
|
3038
2798
|
|
3039
2799
|
/**
|
3040
|
-
*
|
3041
|
-
* @return connection
|
3042
|
-
* @throws <code>ActiveRecord::ConnectionNotEstablished</code>, <code>ActiveRecord::JDBCError</code>
|
3043
|
-
*/
|
3044
|
-
protected Connection getConnection() throws RaiseException {
|
3045
|
-
return getConnection(false);
|
3046
|
-
}
|
3047
|
-
|
3048
|
-
/**
|
3049
|
-
* @see #getConnection()
|
2800
|
+
* Returns a connection (might cause a reconnect if there's none).
|
3050
2801
|
* @param required set to true if a connection is required to exists (e.g. on commit)
|
3051
2802
|
* @return connection
|
3052
2803
|
* @throws <code>ActiveRecord::ConnectionNotEstablished</code> if disconnected
|
@@ -3061,17 +2812,15 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3061
2812
|
}
|
3062
2813
|
}
|
3063
2814
|
|
3064
|
-
|
2815
|
+
protected Connection getConnectionInternal(final boolean required) throws SQLException {
|
3065
2816
|
Connection connection = getConnectionImpl();
|
3066
|
-
if (
|
3067
|
-
if (
|
3068
|
-
|
3069
|
-
|
2817
|
+
if (connection == null && required) {
|
2818
|
+
if (!connected) handleNotConnected(); // raise ConnectionNotEstablished
|
2819
|
+
synchronized (this) {
|
2820
|
+
connection = getConnectionImpl();
|
2821
|
+
if ( connection == null ) {
|
2822
|
+
connectImpl(true); // throws SQLException
|
3070
2823
|
connection = getConnectionImpl();
|
3071
|
-
if ( connection == null ) {
|
3072
|
-
connectImpl( true ); // throws SQLException
|
3073
|
-
connection = getConnectionImpl();
|
3074
|
-
}
|
3075
2824
|
}
|
3076
2825
|
}
|
3077
2826
|
}
|
@@ -3202,7 +2951,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3202
2951
|
try {
|
3203
2952
|
tablesSet = metaData.getTables(catalog, _schemaPattern, _tablePattern, types);
|
3204
2953
|
if ( checkExistsOnly ) { // only check if given table exists
|
3205
|
-
return tablesSet.next() ? context.
|
2954
|
+
return tablesSet.next() ? context.tru : null;
|
3206
2955
|
}
|
3207
2956
|
else {
|
3208
2957
|
return mapTables(context, connection, catalog, _schemaPattern, _tablePattern, tablesSet);
|
@@ -3211,15 +2960,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3211
2960
|
finally { close(tablesSet); }
|
3212
2961
|
}
|
3213
2962
|
|
3214
|
-
@Deprecated
|
3215
|
-
protected IRubyObject matchTables(final Ruby runtime,
|
3216
|
-
final Connection connection,
|
3217
|
-
final String catalog, final String schemaPattern,
|
3218
|
-
final String tablePattern, final String[] types,
|
3219
|
-
final boolean checkExistsOnly) throws SQLException {
|
3220
|
-
return matchTables(runtime.getCurrentContext(), connection, catalog, schemaPattern, tablePattern, types, checkExistsOnly);
|
3221
|
-
}
|
3222
|
-
|
3223
2963
|
// NOTE java.sql.DatabaseMetaData.getTables :
|
3224
2964
|
protected final static int TABLES_TABLE_CAT = 1;
|
3225
2965
|
protected final static int TABLES_TABLE_SCHEM = 2;
|
@@ -3307,7 +3047,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3307
3047
|
final String tabName = results.getString(TABLE_NAME);
|
3308
3048
|
final RubyString tableName = cachedString(context, caseConvertIdentifierForRails(metaData, tabName));
|
3309
3049
|
|
3310
|
-
final IRubyObject type_metadata =
|
3050
|
+
final IRubyObject type_metadata = adapter.callMethod(context, "fetch_type_metadata", sqlType);
|
3311
3051
|
|
3312
3052
|
// (name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
|
3313
3053
|
final IRubyObject[] args = new IRubyObject[] {
|
@@ -3323,7 +3063,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3323
3063
|
ResultSet primaryKeys = null;
|
3324
3064
|
try {
|
3325
3065
|
primaryKeys = metaData.getPrimaryKeys(components.catalog, components.schema, components.name);
|
3326
|
-
final List<String> primaryKeyNames = new ArrayList
|
3066
|
+
final List<String> primaryKeyNames = new ArrayList<>(4);
|
3327
3067
|
while ( primaryKeys.next() ) {
|
3328
3068
|
primaryKeyNames.add( primaryKeys.getString(COLUMN_NAME) );
|
3329
3069
|
}
|
@@ -3372,7 +3112,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3372
3112
|
// not have and auto-generated ID column :
|
3373
3113
|
boolean next = genKeys.next() && genKeys.getMetaData().getColumnCount() > 0;
|
3374
3114
|
// singleResult == null - guess if only single key returned
|
3375
|
-
if ( singleResult == null || singleResult
|
3115
|
+
if ( singleResult == null || singleResult) {
|
3376
3116
|
if ( next ) {
|
3377
3117
|
firstKey = mapGeneratedKey(runtime, genKeys);
|
3378
3118
|
if ( singleResult != null || ! genKeys.next() ) {
|
@@ -3405,7 +3145,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3405
3145
|
if (supportsGeneratedKeys == null) {
|
3406
3146
|
supportsGeneratedKeys = this.supportsGeneratedKeys = connection.getMetaData().supportsGetGeneratedKeys();
|
3407
3147
|
}
|
3408
|
-
return supportsGeneratedKeys
|
3148
|
+
return supportsGeneratedKeys;
|
3409
3149
|
}
|
3410
3150
|
|
3411
3151
|
/**
|
@@ -3437,8 +3177,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3437
3177
|
final ColumnData[] columns = extractColumns(context, connection, resultSet, false);
|
3438
3178
|
|
3439
3179
|
final Ruby runtime = context.runtime;
|
3440
|
-
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
3441
3180
|
while ( resultSet.next() ) {
|
3181
|
+
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
3442
3182
|
for ( int i = 0; i < columns.length; i++ ) {
|
3443
3183
|
final ColumnData column = columns[i];
|
3444
3184
|
blockArgs[i] = jdbcToRuby(context, runtime, column.index, column.type, resultSet);
|
@@ -3464,16 +3204,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3464
3204
|
return setupColumns(context, connection, resultSet.getMetaData(), downCase);
|
3465
3205
|
}
|
3466
3206
|
|
3467
|
-
/**
|
3468
|
-
* @deprecated use {@link #extractColumns(ThreadContext, Connection, ResultSet, boolean)}
|
3469
|
-
*/
|
3470
|
-
@Deprecated
|
3471
|
-
protected ColumnData[] extractColumns(final Ruby runtime,
|
3472
|
-
final Connection connection, final ResultSet resultSet,
|
3473
|
-
final boolean downCase) throws SQLException {
|
3474
|
-
return extractColumns(runtime.getCurrentContext(), connection, resultSet, downCase);
|
3475
|
-
}
|
3476
|
-
|
3477
3207
|
protected <T> T withConnection(final ThreadContext context, final Callable<T> block)
|
3478
3208
|
throws RaiseException {
|
3479
3209
|
try {
|
@@ -3579,13 +3309,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3579
3309
|
}
|
3580
3310
|
|
3581
3311
|
protected boolean isTransient(final Exception exception) {
|
3582
|
-
|
3583
|
-
return false;
|
3312
|
+
return exception instanceof SQLTransientException;
|
3584
3313
|
}
|
3585
3314
|
|
3586
3315
|
protected boolean isRecoverable(final Exception exception) {
|
3587
|
-
|
3588
|
-
|
3316
|
+
return exception instanceof SQLRecoverableException;
|
3317
|
+
// exception instanceof SQLException; // pre JDBC 4.0 drivers?
|
3589
3318
|
}
|
3590
3319
|
|
3591
3320
|
private static Throwable getCause(Throwable exception) {
|
@@ -3743,6 +3472,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3743
3472
|
return Result.newInstance(context, columnsToArray(context, columns), rows, Block.NULL_BLOCK); // Result.new
|
3744
3473
|
}
|
3745
3474
|
|
3475
|
+
protected static IRubyObject newEmptyResult(final ThreadContext context) {
|
3476
|
+
final RubyClass Result = getResult(context.runtime);
|
3477
|
+
return Result.newInstance(context, RubyArray.newEmptyArray(context.runtime), RubyArray.newEmptyArray(context.runtime), Block.NULL_BLOCK); // Result.new
|
3478
|
+
}
|
3479
|
+
|
3746
3480
|
private static RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
|
3747
3481
|
final IRubyObject[] cols = new IRubyObject[columns.length];
|
3748
3482
|
|
@@ -3995,7 +3729,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3995
3729
|
public static void debugStackTrace(final ThreadContext context, final Throwable e) {
|
3996
3730
|
if ( debug || ( context != null && context.runtime.isDebug() ) ) {
|
3997
3731
|
final PrintStream out = context != null ? context.runtime.getOut() : System.out;
|
3998
|
-
if ( debugStackTrace == null || debugStackTrace
|
3732
|
+
if ( debugStackTrace == null || debugStackTrace) {
|
3999
3733
|
e.printStackTrace(out);
|
4000
3734
|
}
|
4001
3735
|
else {
|
@@ -4011,8 +3745,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
4011
3745
|
private static boolean driverUsedLogged;
|
4012
3746
|
|
4013
3747
|
private void logDriverUsed(final Connection connection) {
|
4014
|
-
if (
|
4015
|
-
if ( driverUsedLogged ) return;
|
3748
|
+
if (debug && !driverUsedLogged) {
|
4016
3749
|
driverUsedLogged = true;
|
4017
3750
|
try {
|
4018
3751
|
final DatabaseMetaData meta = connection.getMetaData();
|