activerecord-jdbc-alt-adapter 52.5.1-java → 60.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- 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/activerecord-jdbc-alt-adapter.gemspec +5 -8
- data/lib/arel/visitors/sqlserver.rb +33 -23
- data/lib/arjdbc/abstract/connection_management.rb +7 -0
- data/lib/arjdbc/abstract/core.rb +16 -23
- data/lib/arjdbc/abstract/database_statements.rb +24 -0
- 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/mssql.rb +3 -1
- data/lib/arjdbc/mssql/adapter.rb +105 -36
- data/lib/arjdbc/mssql/column.rb +5 -1
- data/lib/arjdbc/mssql/connection_methods.rb +8 -2
- data/lib/arjdbc/mssql/database_limits.rb +2 -0
- data/lib/arjdbc/mssql/database_statements.rb +43 -5
- data/lib/arjdbc/mssql/errors.rb +2 -0
- data/lib/arjdbc/mssql/explain_support.rb +3 -1
- data/lib/arjdbc/mssql/extensions/attribute_methods.rb +5 -1
- data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
- data/lib/arjdbc/mssql/quoting.rb +38 -0
- data/lib/arjdbc/mssql/schema_creation.rb +24 -2
- data/lib/arjdbc/mssql/schema_definitions.rb +10 -0
- data/lib/arjdbc/mssql/schema_dumper.rb +2 -0
- data/lib/arjdbc/mssql/schema_statements.rb +63 -21
- data/lib/arjdbc/mssql/transaction.rb +2 -0
- data/lib/arjdbc/mssql/types.rb +2 -0
- data/lib/arjdbc/mssql/types/binary_types.rb +2 -0
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +2 -0
- data/lib/arjdbc/mssql/types/deprecated_types.rb +2 -0
- data/lib/arjdbc/mssql/types/numeric_types.rb +2 -0
- data/lib/arjdbc/mssql/types/string_types.rb +2 -0
- data/lib/arjdbc/mssql/utils.rb +2 -0
- data/lib/arjdbc/mysql/adapter.rb +47 -18
- 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/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 -4
- data/lib/arjdbc/tasks/databases.rake +13 -10
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +49 -5
- 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/src/java/arjdbc/ArJdbcModule.java +5 -5
- data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +405 -628
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +37 -0
- 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
- data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
- metadata +5 -14
@@ -23,17 +23,27 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
23
23
|
raise
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
|
+
config[:properties] ||= {}
|
28
|
+
|
27
29
|
database = config[:database] # NOTE: "jdbc:sqlite::memory:" syntax is supported
|
28
30
|
config[:url] ||= "jdbc:sqlite:#{database == ':memory:' ? '' : database}"
|
29
31
|
config[:connection_alive_sql] ||= 'SELECT 1'
|
30
32
|
|
33
|
+
if config[:readonly]
|
34
|
+
# See
|
35
|
+
# * http://sqlite.org/c3ref/open.html
|
36
|
+
# * http://sqlite.org/c3ref/c_open_autoproxy.html
|
37
|
+
# => 0x01 = readonly, 0x40 = uri (default in JDBC)
|
38
|
+
config[:properties][:open_mode] = 0x01 | 0x40
|
39
|
+
end
|
40
|
+
|
31
41
|
timeout = config[:timeout]
|
32
42
|
if timeout && timeout.to_s !~ /\A\d+\Z/
|
33
43
|
raise TypeError.new "Timeout must be nil or a number (got: #{timeout})."
|
34
44
|
end
|
35
45
|
|
36
|
-
options =
|
46
|
+
options = config[:properties]
|
37
47
|
options['busy_timeout'] ||= timeout unless timeout.nil?
|
38
48
|
|
39
49
|
jdbc_connection(config)
|
@@ -51,8 +61,9 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
51
61
|
def parse_sqlite3_config!(config)
|
52
62
|
database = ( config[:database] ||= config[:dbfile] )
|
53
63
|
if ':memory:' != database
|
54
|
-
|
55
|
-
|
64
|
+
# make sure to have an absolute path. Ruby and Java don't agree on working directory
|
65
|
+
config[:database] = File.expand_path(database, defined?(Rails.root) ? Rails.root : nil)
|
66
|
+
dirname = File.dirname(config[:database])
|
56
67
|
Dir.mkdir(dirname) unless File.directory?(dirname)
|
57
68
|
end
|
58
69
|
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,17 +1,37 @@
|
|
1
|
+
require 'active_record/tasks/database_tasks'
|
2
|
+
|
1
3
|
require 'arjdbc/tasks/jdbc_database_tasks'
|
2
4
|
|
3
5
|
module ArJdbc
|
4
6
|
module Tasks
|
5
7
|
class MSSQLDatabaseTasks < JdbcDatabaseTasks
|
8
|
+
delegate :clear_active_connections!, to: ActiveRecord::Base
|
9
|
+
|
10
|
+
def create
|
11
|
+
establish_master_connection
|
12
|
+
connection.create_database(configuration['database'])
|
13
|
+
establish_connection configuration
|
14
|
+
rescue ActiveRecord::StatementInvalid => error
|
15
|
+
case error.message
|
16
|
+
when /database .* already exists/i
|
17
|
+
raise ActiveRecord::Tasks::DatabaseAlreadyExists
|
18
|
+
else
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def drop
|
24
|
+
establish_master_connection
|
25
|
+
connection.drop_database configuration['database']
|
26
|
+
end
|
6
27
|
|
7
28
|
def purge
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
establish_connection(test)
|
12
|
-
connection.recreate_database(test_database)
|
29
|
+
clear_active_connections!
|
30
|
+
drop
|
31
|
+
create
|
13
32
|
end
|
14
33
|
|
34
|
+
|
15
35
|
def structure_dump(filename)
|
16
36
|
config = config_from_url_if_needed
|
17
37
|
`smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
|
@@ -24,6 +44,10 @@ module ArJdbc
|
|
24
44
|
|
25
45
|
private
|
26
46
|
|
47
|
+
def establish_master_connection
|
48
|
+
establish_connection configuration.merge('database' => 'master')
|
49
|
+
end
|
50
|
+
|
27
51
|
def config_from_url_if_needed
|
28
52
|
config = self.config
|
29
53
|
if config['url'] && ! config.key?('database')
|
@@ -42,5 +66,25 @@ module ArJdbc
|
|
42
66
|
end
|
43
67
|
|
44
68
|
end
|
69
|
+
|
70
|
+
module DatabaseTasksMSSQL
|
71
|
+
extend ActiveSupport::Concern
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
|
75
|
+
def check_protected_environments!
|
76
|
+
super
|
77
|
+
rescue ActiveRecord::JDBCError => error
|
78
|
+
case error.message
|
79
|
+
when /cannot open database .* requested by the login/i
|
80
|
+
else
|
81
|
+
raise
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
ActiveRecord::Tasks::DatabaseTasks.send :include, DatabaseTasksMSSQL
|
45
89
|
end
|
46
90
|
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>
|
@@ -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
|
-
supported = metaData.supportsTransactionIsolationLevel(level);
|
316
|
-
}
|
317
|
-
else {
|
318
|
-
final int level = metaData.getDefaultTransactionIsolation();
|
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);
|
322
306
|
}
|
307
|
+
else {
|
308
|
+
final int level = metaData.getDefaultTransactionIsolation();
|
309
|
+
supported = level > Connection.TRANSACTION_NONE; // > 0
|
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;
|
@@ -735,33 +684,35 @@ public class RubyJdbcConnection extends RubyObject {
|
|
735
684
|
|
736
685
|
@JRubyMethod(name = "read_only?")
|
737
686
|
public IRubyObject is_read_only(final ThreadContext context) {
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
return context.runtime.newBoolean(
|
687
|
+
try {
|
688
|
+
final Connection connection = getConnectionInternal(false);
|
689
|
+
if (connection != null) {
|
690
|
+
return context.runtime.newBoolean(connection.isReadOnly());
|
742
691
|
}
|
743
|
-
|
692
|
+
} catch (SQLException e) {
|
693
|
+
return handleException(context, e);
|
744
694
|
}
|
745
695
|
return context.nil;
|
746
696
|
}
|
747
697
|
|
748
698
|
@JRubyMethod(name = "read_only=")
|
749
699
|
public IRubyObject set_read_only(final ThreadContext context, final IRubyObject flag) {
|
750
|
-
final Connection connection = getConnection(true);
|
751
700
|
try {
|
701
|
+
final Connection connection = getConnectionInternal(true);
|
752
702
|
connection.setReadOnly( flag.isTrue() );
|
753
703
|
return context.runtime.newBoolean( connection.isReadOnly() );
|
704
|
+
} catch (SQLException e) {
|
705
|
+
return handleException(context, e);
|
754
706
|
}
|
755
|
-
catch (SQLException e) { return handleException(context, e); }
|
756
707
|
}
|
757
708
|
|
758
709
|
@JRubyMethod(name = { "open?" /* "conn?" */ })
|
759
710
|
public IRubyObject open_p(final ThreadContext context) {
|
760
|
-
|
711
|
+
try {
|
712
|
+
final Connection connection = getConnectionInternal(false);
|
761
713
|
|
762
|
-
|
714
|
+
if (connection == null) return context.fals;
|
763
715
|
|
764
|
-
try {
|
765
716
|
// NOTE: isClosed method generally cannot be called to determine
|
766
717
|
// whether a connection to a database is valid or invalid ...
|
767
718
|
return context.runtime.newBoolean(!connection.isClosed());
|
@@ -774,10 +725,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
774
725
|
public IRubyObject close(final ThreadContext context) {
|
775
726
|
final Connection connection = getConnection(false);
|
776
727
|
|
777
|
-
if (connection == null) return context.
|
728
|
+
if (connection == null) return context.fals;
|
778
729
|
|
779
730
|
try {
|
780
|
-
if (connection.isClosed()) return context.
|
731
|
+
if (connection.isClosed()) return context.fals;
|
781
732
|
|
782
733
|
setConnection(null); // does connection.close();
|
783
734
|
} catch (Exception e) {
|
@@ -787,69 +738,65 @@ public class RubyJdbcConnection extends RubyObject {
|
|
787
738
|
|
788
739
|
// ActiveRecord expects a closed connection to not try and re-open a connection
|
789
740
|
// whereas JNDI expects that.
|
790
|
-
if (!
|
741
|
+
if (!jndi) disconnect(context);
|
791
742
|
|
792
|
-
return context.
|
743
|
+
return context.tru;
|
793
744
|
}
|
794
745
|
|
795
746
|
@JRubyMethod(name = "database_name")
|
796
747
|
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);
|
748
|
+
return withConnection(context, connection -> {
|
749
|
+
String name = connection.getCatalog();
|
750
|
+
if ( name == null ) {
|
751
|
+
name = connection.getMetaData().getUserName();
|
752
|
+
if ( name == null ) return context.nil;
|
805
753
|
}
|
754
|
+
return context.runtime.newString(name);
|
806
755
|
});
|
807
756
|
}
|
808
757
|
|
809
758
|
@JRubyMethod(name = "execute", required = 1)
|
810
759
|
public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
|
811
760
|
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();
|
761
|
+
return withConnection(context, connection -> {
|
762
|
+
Statement statement = null;
|
763
|
+
try {
|
764
|
+
statement = createStatement(context, connection);
|
822
765
|
|
823
|
-
|
824
|
-
|
766
|
+
// For DBs that do support multiple statements, lets return the last result set
|
767
|
+
// to be consistent with AR
|
768
|
+
boolean hasResultSet = doExecute(statement, query);
|
769
|
+
int updateCount = statement.getUpdateCount();
|
825
770
|
|
826
|
-
|
771
|
+
IRubyObject result = context.nil; // If no results, return nil
|
772
|
+
ResultSet resultSet;
|
827
773
|
|
828
|
-
|
829
|
-
resultSet = statement.getResultSet();
|
774
|
+
while (hasResultSet || updateCount != -1) {
|
830
775
|
|
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
|
-
}
|
776
|
+
if (hasResultSet) {
|
777
|
+
resultSet = statement.getResultSet();
|
839
778
|
|
840
|
-
//
|
841
|
-
|
842
|
-
|
779
|
+
// Unfortunately the result set gets closed when getMoreResults()
|
780
|
+
// is called, so we have to process the result sets as we get them
|
781
|
+
// this shouldn't be an issue in most cases since we're only getting 1 result set anyways
|
782
|
+
result = mapExecuteResult(context, connection, resultSet);
|
783
|
+
resultSet.close();
|
784
|
+
} else {
|
785
|
+
result = context.runtime.newFixnum(updateCount);
|
843
786
|
}
|
844
787
|
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
debugErrorSQL(context, query);
|
849
|
-
throw e;
|
850
|
-
} finally {
|
851
|
-
close(statement);
|
788
|
+
// Check to see if there is another result set
|
789
|
+
hasResultSet = statement.getMoreResults();
|
790
|
+
updateCount = statement.getUpdateCount();
|
852
791
|
}
|
792
|
+
|
793
|
+
return result;
|
794
|
+
|
795
|
+
} catch (final SQLException e) {
|
796
|
+
debugErrorSQL(context, query);
|
797
|
+
throw e;
|
798
|
+
} finally {
|
799
|
+
close(statement);
|
853
800
|
}
|
854
801
|
});
|
855
802
|
}
|
@@ -928,7 +875,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
928
875
|
}
|
929
876
|
|
930
877
|
return mapGeneratedKeys(context, connection, statement);
|
931
|
-
|
932
878
|
} catch (final SQLException e) {
|
933
879
|
debugErrorSQL(context, query);
|
934
880
|
throw e;
|
@@ -971,7 +917,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
971
917
|
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
972
918
|
statement.executeUpdate();
|
973
919
|
return mapGeneratedKeys(context, connection, statement);
|
974
|
-
|
975
920
|
} catch (final SQLException e) {
|
976
921
|
debugErrorSQL(context, query);
|
977
922
|
throw e;
|
@@ -997,22 +942,20 @@ public class RubyJdbcConnection extends RubyObject {
|
|
997
942
|
*/
|
998
943
|
@JRubyMethod(name = {"execute_update", "execute_delete"}, required = 1)
|
999
944
|
public IRubyObject execute_update(final ThreadContext context, final IRubyObject sql) {
|
1000
|
-
return withConnection(context,
|
1001
|
-
|
1002
|
-
|
1003
|
-
final String query = sqlString(sql);
|
945
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
946
|
+
Statement statement = null;
|
947
|
+
final String query = sqlString(sql);
|
1004
948
|
|
1005
|
-
|
1006
|
-
|
949
|
+
try {
|
950
|
+
statement = createStatement(context, connection);
|
1007
951
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
}
|
952
|
+
final int rowCount = statement.executeUpdate(query);
|
953
|
+
return context.runtime.newFixnum(rowCount);
|
954
|
+
} catch (final SQLException e) {
|
955
|
+
debugErrorSQL(context, query);
|
956
|
+
throw e;
|
957
|
+
} finally {
|
958
|
+
close(statement);
|
1016
959
|
}
|
1017
960
|
});
|
1018
961
|
}
|
@@ -1028,21 +971,19 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1028
971
|
*/
|
1029
972
|
@JRubyMethod(name = {"execute_prepared_update", "execute_prepared_delete"}, required = 2)
|
1030
973
|
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
|
-
}
|
974
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
975
|
+
PreparedStatement statement = null;
|
976
|
+
final String query = sqlString(sql);
|
977
|
+
try {
|
978
|
+
statement = connection.prepareStatement(query);
|
979
|
+
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
980
|
+
final int rowCount = statement.executeUpdate();
|
981
|
+
return context.runtime.newFixnum(rowCount);
|
982
|
+
} catch (final SQLException e) {
|
983
|
+
debugErrorSQL(context, query);
|
984
|
+
throw e;
|
985
|
+
} finally {
|
986
|
+
close(statement);
|
1046
987
|
}
|
1047
988
|
});
|
1048
989
|
}
|
@@ -1089,50 +1030,48 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1089
1030
|
|
1090
1031
|
private IRubyObject doExecuteQueryRaw(final ThreadContext context,
|
1091
1032
|
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
|
-
}
|
1033
|
+
return withConnection(context, connection -> {
|
1034
|
+
Statement statement = null; boolean hasResult;
|
1035
|
+
try {
|
1036
|
+
if ( binds == null || binds.isEmpty()) { // plain statement
|
1037
|
+
statement = createStatement(context, connection);
|
1038
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
1039
|
+
hasResult = statement.execute(query);
|
1040
|
+
}
|
1041
|
+
else {
|
1042
|
+
final PreparedStatement prepStatement;
|
1043
|
+
statement = prepStatement = connection.prepareStatement(query);
|
1044
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1045
|
+
statement.setMaxRows(maxRows); // zero means there is no limit
|
1046
|
+
setStatementParameters(context, connection, prepStatement, binds);
|
1047
|
+
hasResult = prepStatement.execute();
|
1048
|
+
}
|
1109
1049
|
|
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
|
-
}
|
1050
|
+
if (block.isGiven()) {
|
1118
1051
|
if (hasResult) {
|
1119
|
-
|
1052
|
+
// yield(id1, name1) ... row 1 result data
|
1053
|
+
// yield(id2, name2) ... row 2 result data
|
1054
|
+
return yieldResultRows(context, connection, statement.getResultSet(), block);
|
1120
1055
|
}
|
1121
|
-
return context.
|
1056
|
+
return context.nil;
|
1122
1057
|
}
|
1123
|
-
|
1124
|
-
|
1125
|
-
throw e;
|
1126
|
-
}
|
1127
|
-
finally {
|
1128
|
-
close(statement);
|
1058
|
+
if (hasResult) {
|
1059
|
+
return mapToRawResult(context, connection, statement.getResultSet(), false);
|
1129
1060
|
}
|
1061
|
+
return context.runtime.newEmptyArray();
|
1062
|
+
}
|
1063
|
+
catch (final SQLException e) {
|
1064
|
+
debugErrorSQL(context, query);
|
1065
|
+
throw e;
|
1066
|
+
}
|
1067
|
+
finally {
|
1068
|
+
close(statement);
|
1130
1069
|
}
|
1131
1070
|
});
|
1132
1071
|
}
|
1133
1072
|
|
1134
1073
|
protected static String sqlString(final IRubyObject sql) {
|
1135
|
-
return sql
|
1074
|
+
return sql.convertToString().decodeString();
|
1136
1075
|
}
|
1137
1076
|
|
1138
1077
|
/**
|
@@ -1145,26 +1084,24 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1145
1084
|
*/
|
1146
1085
|
@JRubyMethod(required = 1)
|
1147
1086
|
public IRubyObject execute_query(final ThreadContext context, final IRubyObject sql) {
|
1148
|
-
return withConnection(context,
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
statement = createStatement(context, connection);
|
1087
|
+
return withConnection(context, connection -> {
|
1088
|
+
Statement statement = null;
|
1089
|
+
final String query = sqlString(sql);
|
1090
|
+
try {
|
1091
|
+
statement = createStatement(context, connection);
|
1154
1092
|
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1093
|
+
// At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
|
1094
|
+
if (statement.execute(query)) {
|
1095
|
+
return mapQueryResult(context, connection, statement.getResultSet());
|
1096
|
+
}
|
1159
1097
|
|
1160
|
-
|
1098
|
+
return newEmptyResult(context);
|
1161
1099
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
}
|
1100
|
+
} catch (final SQLException e) {
|
1101
|
+
debugErrorSQL(context, query);
|
1102
|
+
throw e;
|
1103
|
+
} finally {
|
1104
|
+
close(statement);
|
1168
1105
|
}
|
1169
1106
|
});
|
1170
1107
|
}
|
@@ -1177,13 +1114,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1177
1114
|
*/
|
1178
1115
|
@JRubyMethod(required = 1)
|
1179
1116
|
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
|
-
}
|
1117
|
+
return withConnection(context, connection -> {
|
1118
|
+
final String query = sql.convertToString().getUnicodeValue();
|
1119
|
+
PreparedStatement statement = connection.prepareStatement(query);
|
1120
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1121
|
+
return JavaUtil.convertJavaToRuby(context.runtime, statement);
|
1187
1122
|
});
|
1188
1123
|
}
|
1189
1124
|
|
@@ -1206,40 +1141,40 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1206
1141
|
@JRubyMethod(required = 3)
|
1207
1142
|
public IRubyObject execute_prepared_query(final ThreadContext context, final IRubyObject sql,
|
1208
1143
|
final IRubyObject binds, final IRubyObject cachedStatement) {
|
1209
|
-
return withConnection(context,
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
PreparedStatement statement = null;
|
1144
|
+
return withConnection(context, connection -> {
|
1145
|
+
final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
|
1146
|
+
String query = null;
|
1147
|
+
PreparedStatement statement = null;
|
1214
1148
|
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1149
|
+
try {
|
1150
|
+
if (cached) {
|
1151
|
+
statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
|
1152
|
+
} else {
|
1153
|
+
query = sql.convertToString().getUnicodeValue();
|
1154
|
+
statement = connection.prepareStatement(query);
|
1155
|
+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
|
1156
|
+
}
|
1222
1157
|
|
1223
|
-
|
1158
|
+
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
1224
1159
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1160
|
+
if (statement.execute()) {
|
1161
|
+
ResultSet resultSet = statement.getResultSet();
|
1162
|
+
IRubyObject results = mapQueryResult(context, connection, resultSet);
|
1163
|
+
resultSet.close();
|
1229
1164
|
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1165
|
+
return results;
|
1166
|
+
} else {
|
1167
|
+
return newEmptyResult(context);
|
1168
|
+
}
|
1169
|
+
} catch (final SQLException e) {
|
1170
|
+
if (query == null) query = sql.convertToString().getUnicodeValue();
|
1171
|
+
debugErrorSQL(context, query);
|
1172
|
+
throw e;
|
1173
|
+
} finally {
|
1174
|
+
if ( cached ) {
|
1175
|
+
statement.clearParameters();
|
1176
|
+
} else {
|
1177
|
+
close(statement);
|
1243
1178
|
}
|
1244
1179
|
}
|
1245
1180
|
});
|
@@ -1251,35 +1186,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1251
1186
|
return mapToResult(context, connection, resultSet, columns);
|
1252
1187
|
}
|
1253
1188
|
|
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
1189
|
@JRubyMethod(name = "supported_data_types")
|
1284
1190
|
public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
|
1285
1191
|
final Connection connection = getConnection(true);
|
@@ -1303,12 +1209,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1303
1209
|
protected static final int PRIMARY_KEYS_COLUMN_NAME = 4;
|
1304
1210
|
|
1305
1211
|
private List<RubyString> primaryKeys(final ThreadContext context, final String tableName) {
|
1306
|
-
return withConnection(context,
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
return primaryKeys(context, connection, table);
|
1311
|
-
}
|
1212
|
+
return withConnection(context, connection -> {
|
1213
|
+
final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1214
|
+
final TableName table = extractTableName(connection, null, null, _tableName);
|
1215
|
+
return primaryKeys(context, connection, table);
|
1312
1216
|
});
|
1313
1217
|
}
|
1314
1218
|
|
@@ -1316,7 +1220,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1316
1220
|
final Connection connection, final TableName table) throws SQLException {
|
1317
1221
|
final DatabaseMetaData metaData = connection.getMetaData();
|
1318
1222
|
ResultSet resultSet = null;
|
1319
|
-
final List<RubyString> keyNames = new ArrayList
|
1223
|
+
final List<RubyString> keyNames = new ArrayList<>();
|
1320
1224
|
try {
|
1321
1225
|
resultSet = metaData.getPrimaryKeys(table.catalog, table.schema, table.name);
|
1322
1226
|
final Ruby runtime = context.runtime;
|
@@ -1330,26 +1234,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1330
1234
|
return keyNames;
|
1331
1235
|
}
|
1332
1236
|
|
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
1237
|
@JRubyMethod(name = "tables", required = 0, optional = 4)
|
1354
1238
|
public IRubyObject tables(final ThreadContext context, final IRubyObject[] args) {
|
1355
1239
|
switch ( args.length ) {
|
@@ -1367,11 +1251,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1367
1251
|
|
1368
1252
|
protected IRubyObject tables(final ThreadContext context,
|
1369
1253
|
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
|
-
});
|
1254
|
+
return withConnection(context, connection -> matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false));
|
1375
1255
|
}
|
1376
1256
|
|
1377
1257
|
protected String[] getTableTypes() {
|
@@ -1401,40 +1281,36 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1401
1281
|
|
1402
1282
|
protected IRubyObject tableExists(final ThreadContext context,
|
1403
1283
|
final String defaultSchema, final String tableName) {
|
1404
|
-
return withConnection(context,
|
1405
|
-
|
1406
|
-
|
1407
|
-
return context.runtime.newBoolean( tableExists(context, connection, components) );
|
1408
|
-
}
|
1284
|
+
return withConnection(context, connection -> {
|
1285
|
+
final TableName components = extractTableName(connection, defaultSchema, tableName);
|
1286
|
+
return context.runtime.newBoolean( tableExists(context, connection, components) );
|
1409
1287
|
});
|
1410
1288
|
}
|
1411
1289
|
|
1412
1290
|
@JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
|
1413
1291
|
public RubyArray columns_internal(final ThreadContext context, final IRubyObject[] args)
|
1414
1292
|
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);
|
1293
|
+
return withConnection(context, connection -> {
|
1294
|
+
ResultSet columns = null;
|
1295
|
+
try {
|
1296
|
+
final String tableName = args[0].toString();
|
1297
|
+
// optionals (NOTE: catalog argumnet was never used before 1.3.0) :
|
1298
|
+
final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
|
1299
|
+
final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
|
1426
1300
|
|
1427
|
-
|
1428
|
-
|
1429
|
-
}
|
1301
|
+
final TableName components;
|
1302
|
+
components = extractTableName(connection, catalog, defaultSchema, tableName);
|
1430
1303
|
|
1431
|
-
|
1432
|
-
|
1433
|
-
return mapColumnsResult(context, metaData, components, columns);
|
1434
|
-
}
|
1435
|
-
finally {
|
1436
|
-
close(columns);
|
1304
|
+
if ( ! tableExists(context, connection, components) ) {
|
1305
|
+
throw new SQLException("table: " + tableName + " does not exist");
|
1437
1306
|
}
|
1307
|
+
|
1308
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1309
|
+
columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
|
1310
|
+
return mapColumnsResult(context, metaData, components, columns);
|
1311
|
+
}
|
1312
|
+
finally {
|
1313
|
+
close(columns);
|
1438
1314
|
}
|
1439
1315
|
});
|
1440
1316
|
}
|
@@ -1464,70 +1340,68 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1464
1340
|
* should filter the return from this method instead.
|
1465
1341
|
*/
|
1466
1342
|
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);
|
1471
|
-
|
1472
|
-
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1473
|
-
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1474
|
-
final TableName table = extractTableName(connection, null, _schemaName, _tableName);
|
1343
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1344
|
+
final Ruby runtime = context.runtime;
|
1345
|
+
final RubyClass IndexDefinition = getIndexDefinition(context);
|
1475
1346
|
|
1476
|
-
|
1347
|
+
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1348
|
+
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1349
|
+
final TableName table = extractTableName(connection, null, _schemaName, _tableName);
|
1477
1350
|
|
1478
|
-
|
1479
|
-
final RubyArray indexes = RubyArray.newArray(runtime, 8);
|
1480
|
-
try {
|
1481
|
-
final DatabaseMetaData metaData = connection.getMetaData();
|
1482
|
-
indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
|
1483
|
-
String currentIndex = null;
|
1484
|
-
RubyArray currentColumns = null;
|
1351
|
+
final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
|
1485
1352
|
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1353
|
+
ResultSet indexInfoSet = null;
|
1354
|
+
final RubyArray indexes = RubyArray.newArray(runtime, 8);
|
1355
|
+
try {
|
1356
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1357
|
+
indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
|
1358
|
+
String currentIndex = null;
|
1489
1359
|
|
1490
|
-
|
1360
|
+
while ( indexInfoSet.next() ) {
|
1361
|
+
String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
|
1362
|
+
if ( indexName == null ) continue;
|
1363
|
+
RubyArray currentColumns = null;
|
1491
1364
|
|
1492
|
-
|
1493
|
-
final RubyString rubyColumnName = cachedString(
|
1494
|
-
context, caseConvertIdentifierForRails(metaData, columnName)
|
1495
|
-
);
|
1496
|
-
if ( primaryKeys.contains(rubyColumnName) ) continue;
|
1365
|
+
indexName = caseConvertIdentifierForRails(metaData, indexName);
|
1497
1366
|
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1367
|
+
final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
|
1368
|
+
final RubyString rubyColumnName = cachedString(
|
1369
|
+
context, caseConvertIdentifierForRails(metaData, columnName)
|
1370
|
+
);
|
1371
|
+
if ( primaryKeys.contains(rubyColumnName) ) continue;
|
1501
1372
|
|
1502
|
-
|
1503
|
-
|
1373
|
+
// We are working on a new index
|
1374
|
+
if ( ! indexName.equals(currentIndex) ) {
|
1375
|
+
currentIndex = indexName;
|
1504
1376
|
|
1505
|
-
|
1377
|
+
String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
|
1378
|
+
indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
|
1506
1379
|
|
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
|
-
};
|
1380
|
+
final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
|
1514
1381
|
|
1515
|
-
|
1516
|
-
|
1382
|
+
IRubyObject[] args = new IRubyObject[] {
|
1383
|
+
cachedString(context, indexTableName), // table_name
|
1384
|
+
cachedString(context, indexName), // index_name
|
1385
|
+
nonUnique ? context.fals : context.tru, // unique
|
1386
|
+
currentColumns = RubyArray.newArray(runtime, 4) // [] column names
|
1387
|
+
// orders, (since AR 3.2) where, type, using (AR 4.0)
|
1388
|
+
};
|
1517
1389
|
|
1518
|
-
|
1519
|
-
if ( currentColumns != null ) currentColumns.append(rubyColumnName);
|
1390
|
+
indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
|
1520
1391
|
}
|
1521
1392
|
|
1522
|
-
|
1393
|
+
// one or more columns can be associated with an index
|
1394
|
+
if ( currentColumns != null ) currentColumns.append(rubyColumnName);
|
1395
|
+
}
|
1523
1396
|
|
1524
|
-
|
1525
|
-
|
1397
|
+
return indexes;
|
1398
|
+
|
1399
|
+
} finally { close(indexInfoSet); }
|
1526
1400
|
});
|
1527
1401
|
}
|
1528
1402
|
|
1529
1403
|
protected RubyClass getIndexDefinition(final ThreadContext context) {
|
1530
|
-
final RubyClass adapterClass =
|
1404
|
+
final RubyClass adapterClass = adapter.getMetaClass();
|
1531
1405
|
IRubyObject IDef = adapterClass.getConstantAt("IndexDefinition");
|
1532
1406
|
return IDef != null ? (RubyClass) IDef : getIndexDefinition(context.runtime);
|
1533
1407
|
}
|
@@ -1538,57 +1412,55 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1538
1412
|
}
|
1539
1413
|
|
1540
1414
|
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);
|
1415
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1416
|
+
final Ruby runtime = context.runtime;
|
1417
|
+
final RubyClass FKDefinition = getForeignKeyDefinition(context);
|
1545
1418
|
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1419
|
+
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1420
|
+
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1421
|
+
final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
|
1549
1422
|
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1423
|
+
ResultSet fkInfoSet = null;
|
1424
|
+
final List<IRubyObject> fKeys = new ArrayList<>(8);
|
1425
|
+
try {
|
1426
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1427
|
+
fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
|
1555
1428
|
|
1556
|
-
|
1557
|
-
|
1429
|
+
while ( fkInfoSet.next() ) {
|
1430
|
+
final RubyHash options = RubyHash.newHash(runtime);
|
1558
1431
|
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1432
|
+
String fkName = fkInfoSet.getString("FK_NAME");
|
1433
|
+
if (fkName != null) {
|
1434
|
+
fkName = caseConvertIdentifierForRails(metaData, fkName);
|
1435
|
+
options.put(runtime.newSymbol("name"), fkName);
|
1436
|
+
}
|
1564
1437
|
|
1565
|
-
|
1566
|
-
|
1438
|
+
String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
|
1439
|
+
options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
|
1567
1440
|
|
1568
|
-
|
1569
|
-
|
1441
|
+
columnName = fkInfoSet.getString("PKCOLUMN_NAME");
|
1442
|
+
options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
|
1570
1443
|
|
1571
|
-
|
1572
|
-
|
1444
|
+
String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
|
1445
|
+
fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
|
1573
1446
|
|
1574
|
-
|
1575
|
-
|
1447
|
+
String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
|
1448
|
+
pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
|
1576
1449
|
|
1577
|
-
|
1578
|
-
|
1450
|
+
final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
|
1451
|
+
if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
|
1579
1452
|
|
1580
|
-
|
1581
|
-
|
1453
|
+
final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
|
1454
|
+
if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
|
1582
1455
|
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1456
|
+
IRubyObject from_table = cachedString(context, fkTableName);
|
1457
|
+
IRubyObject to_table = cachedString(context, pkTableName);
|
1458
|
+
fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
|
1459
|
+
}
|
1587
1460
|
|
1588
|
-
|
1461
|
+
return runtime.newArray(fKeys);
|
1589
1462
|
|
1590
|
-
|
1591
|
-
}
|
1463
|
+
} finally { close(fkInfoSet); }
|
1592
1464
|
});
|
1593
1465
|
}
|
1594
1466
|
|
@@ -1603,7 +1475,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1603
1475
|
}
|
1604
1476
|
|
1605
1477
|
protected RubyClass getForeignKeyDefinition(final ThreadContext context) {
|
1606
|
-
final RubyClass adapterClass =
|
1478
|
+
final RubyClass adapterClass = adapter.getMetaClass();
|
1607
1479
|
IRubyObject FKDef = adapterClass.getConstantAt("ForeignKeyDefinition");
|
1608
1480
|
return FKDef != null ? (RubyClass) FKDef : getForeignKeyDefinition(context.runtime);
|
1609
1481
|
}
|
@@ -1611,42 +1483,34 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1611
1483
|
|
1612
1484
|
@JRubyMethod(name = "supports_foreign_keys?")
|
1613
1485
|
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
|
-
}
|
1486
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1487
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1488
|
+
return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
|
1619
1489
|
});
|
1620
1490
|
}
|
1621
1491
|
|
1622
1492
|
@JRubyMethod(name = "supports_views?")
|
1623
1493
|
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
|
-
}
|
1494
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
1495
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
1496
|
+
final ResultSet tableTypes = metaData.getTableTypes();
|
1497
|
+
try {
|
1498
|
+
while ( tableTypes.next() ) {
|
1499
|
+
if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
|
1500
|
+
return context.runtime.newBoolean( true );
|
1633
1501
|
}
|
1634
1502
|
}
|
1635
|
-
finally {
|
1636
|
-
close(tableTypes);
|
1637
|
-
}
|
1638
|
-
return context.runtime.newBoolean( false );
|
1639
1503
|
}
|
1504
|
+
finally {
|
1505
|
+
close(tableTypes);
|
1506
|
+
}
|
1507
|
+
return context.runtime.newBoolean( false );
|
1640
1508
|
});
|
1641
1509
|
}
|
1642
1510
|
|
1643
1511
|
@JRubyMethod(name = "with_jdbc_connection", alias = "with_connection_retry_guard", frame = true)
|
1644
1512
|
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
|
-
});
|
1513
|
+
return withConnection(context, connection -> block.call(context, convertJavaToRuby(connection)));
|
1650
1514
|
}
|
1651
1515
|
|
1652
1516
|
/*
|
@@ -1707,24 +1571,22 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1707
1571
|
// TODO: Fix this, the columns don't have the info needed to handle this anymore
|
1708
1572
|
// currently commented out so that it will compile
|
1709
1573
|
|
1710
|
-
return withConnection(context,
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
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();
|
1574
|
+
return withConnection(context, connection -> {
|
1575
|
+
PreparedStatement statement = null;
|
1576
|
+
try {
|
1577
|
+
statement = connection.prepareStatement(sql);
|
1578
|
+
/*
|
1579
|
+
if ( binary ) { // blob
|
1580
|
+
setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
|
1581
|
+
}
|
1582
|
+
else { // clob
|
1583
|
+
setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
|
1725
1584
|
}
|
1726
|
-
|
1585
|
+
setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
|
1586
|
+
*/
|
1587
|
+
return statement.executeUpdate();
|
1727
1588
|
}
|
1589
|
+
finally { close(statement); }
|
1728
1590
|
});
|
1729
1591
|
}
|
1730
1592
|
|
@@ -1780,7 +1642,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1780
1642
|
final IRubyObject self, final IRubyObject config, final Block block) {
|
1781
1643
|
final IRubyObject ds_or_name = rawDataSourceOrName(context, config);
|
1782
1644
|
|
1783
|
-
if ( ds_or_name == null ) return context.
|
1645
|
+
if ( ds_or_name == null ) return context.fals;
|
1784
1646
|
|
1785
1647
|
final javax.sql.DataSource dataSource;
|
1786
1648
|
final Object dsOrName = ds_or_name.toJava(Object.class);
|
@@ -1836,7 +1698,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1836
1698
|
}
|
1837
1699
|
}
|
1838
1700
|
|
1839
|
-
if ( configValue == null || configValue == context.nil || configValue ==
|
1701
|
+
if ( configValue == null || configValue == context.nil || configValue == context.fals ) {
|
1840
1702
|
return null;
|
1841
1703
|
}
|
1842
1704
|
return configValue;
|
@@ -1859,13 +1721,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1859
1721
|
}
|
1860
1722
|
}
|
1861
1723
|
|
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
1724
|
private ConnectionFactory setDriverFactory(final ThreadContext context) {
|
1870
1725
|
|
1871
1726
|
final IRubyObject url = getConfigValue(context, "url");
|
@@ -1965,12 +1820,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1965
1820
|
return props;
|
1966
1821
|
}
|
1967
1822
|
|
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
1823
|
private ConnectionFactory setDataSourceFactory(final ThreadContext context) {
|
1975
1824
|
final javax.sql.DataSource dataSource; final String lookupName;
|
1976
1825
|
IRubyObject value = getConfigValue(context, "data_source");
|
@@ -1992,28 +1841,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1992
1841
|
private static volatile boolean defaultConfigJndi;
|
1993
1842
|
private static transient ConnectionFactory defaultConnectionFactory;
|
1994
1843
|
|
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
1844
|
/**
|
2012
1845
|
* @return whether the connection factory is JNDI based
|
2013
1846
|
*/
|
2014
1847
|
private boolean setupConnectionFactory(final ThreadContext context) {
|
2015
|
-
final IRubyObject config = getConfig();
|
2016
|
-
|
2017
1848
|
if ( defaultConfig == null ) {
|
2018
1849
|
synchronized(RubyJdbcConnection.class) {
|
2019
1850
|
if ( defaultConfig == null ) {
|
@@ -2045,18 +1876,17 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2045
1876
|
|
2046
1877
|
@JRubyMethod(name = "jndi?", alias = "jndi_connection?")
|
2047
1878
|
public RubyBoolean jndi_p(final ThreadContext context) {
|
2048
|
-
return context.runtime.newBoolean(
|
1879
|
+
return context.runtime.newBoolean(jndi);
|
2049
1880
|
}
|
2050
1881
|
|
2051
1882
|
protected boolean isJndi() { return this.jndi; }
|
2052
1883
|
|
2053
1884
|
@JRubyMethod(name = "config")
|
2054
|
-
public IRubyObject config() { return
|
1885
|
+
public IRubyObject config() { return config; }
|
2055
1886
|
|
2056
1887
|
public IRubyObject getConfig() { return this.config; }
|
2057
1888
|
|
2058
1889
|
protected final IRubyObject getConfigValue(final ThreadContext context, final String key) {
|
2059
|
-
final IRubyObject config = getConfig();
|
2060
1890
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2061
1891
|
if ( config instanceof RubyHash ) {
|
2062
1892
|
final IRubyObject value = ((RubyHash) config).fastARef(keySym);
|
@@ -2067,7 +1897,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2067
1897
|
|
2068
1898
|
protected final IRubyObject setConfigValue(final ThreadContext context,
|
2069
1899
|
final String key, final IRubyObject value) {
|
2070
|
-
final IRubyObject config = getConfig();
|
2071
1900
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2072
1901
|
if ( config instanceof RubyHash ) {
|
2073
1902
|
return ((RubyHash) config).op_aset(context, keySym, value);
|
@@ -2077,7 +1906,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2077
1906
|
|
2078
1907
|
protected final IRubyObject setConfigValueIfNotSet(final ThreadContext context,
|
2079
1908
|
final String key, final IRubyObject value) {
|
2080
|
-
final IRubyObject config = getConfig();
|
2081
1909
|
final RubySymbol keySym = context.runtime.newSymbol(key);
|
2082
1910
|
if ( config instanceof RubyHash ) {
|
2083
1911
|
final IRubyObject setValue = ((RubyHash) config).fastARef(keySym);
|
@@ -2097,7 +1925,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2097
1925
|
protected final IRubyObject getAdapter() { return this.adapter; }
|
2098
1926
|
|
2099
1927
|
protected RubyClass getJdbcColumnClass(final ThreadContext context) {
|
2100
|
-
return (RubyClass)
|
1928
|
+
return (RubyClass) adapter.callMethod(context, "jdbc_column_class");
|
2101
1929
|
}
|
2102
1930
|
|
2103
1931
|
protected ConnectionFactory getConnectionFactory() throws RaiseException {
|
@@ -2309,7 +2137,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2309
2137
|
@JRubyMethod(name = "raw_date_time?", meta = true)
|
2310
2138
|
public static IRubyObject useRawDateTime(final ThreadContext context, final IRubyObject self) {
|
2311
2139
|
if ( rawDateTime == null ) return context.nil;
|
2312
|
-
return context.runtime.newBoolean(
|
2140
|
+
return context.runtime.newBoolean(rawDateTime);
|
2313
2141
|
}
|
2314
2142
|
|
2315
2143
|
@JRubyMethod(name = "raw_date_time=", meta = true)
|
@@ -2323,17 +2151,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2323
2151
|
return value;
|
2324
2152
|
}
|
2325
2153
|
|
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
2154
|
protected IRubyObject dateToRuby(final ThreadContext context,
|
2338
2155
|
final Ruby runtime, final ResultSet resultSet, final int column)
|
2339
2156
|
throws SQLException {
|
@@ -2344,7 +2161,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2344
2161
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2345
2162
|
}
|
2346
2163
|
|
2347
|
-
if ( rawDateTime != null && rawDateTime
|
2164
|
+
if ( rawDateTime != null && rawDateTime) {
|
2348
2165
|
return RubyString.newString(runtime, DateTimeUtils.dateToString(value));
|
2349
2166
|
}
|
2350
2167
|
|
@@ -2360,7 +2177,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2360
2177
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2361
2178
|
}
|
2362
2179
|
|
2363
|
-
if ( rawDateTime != null && rawDateTime
|
2180
|
+
if ( rawDateTime != null && rawDateTime) {
|
2364
2181
|
return RubyString.newString(runtime, DateTimeUtils.timeToString(value));
|
2365
2182
|
}
|
2366
2183
|
|
@@ -2376,7 +2193,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2376
2193
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
2377
2194
|
}
|
2378
2195
|
|
2379
|
-
if ( rawDateTime != null && rawDateTime
|
2196
|
+
if ( rawDateTime != null && rawDateTime) {
|
2380
2197
|
return RubyString.newString(runtime, DateTimeUtils.timestampToString(value));
|
2381
2198
|
}
|
2382
2199
|
|
@@ -2388,19 +2205,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2388
2205
|
return DateTimeUtils.newTime(context, value, getDefaultTimeZone(context));
|
2389
2206
|
}
|
2390
2207
|
|
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
2208
|
protected static Boolean rawBoolean;
|
2405
2209
|
static {
|
2406
2210
|
final String booleanRaw = SafePropertyAccessor.getProperty("arjdbc.boolean.raw");
|
@@ -2412,7 +2216,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2412
2216
|
@JRubyMethod(name = "raw_boolean?", meta = true)
|
2413
2217
|
public static IRubyObject useRawBoolean(final ThreadContext context, final IRubyObject self) {
|
2414
2218
|
if ( rawBoolean == null ) return context.nil;
|
2415
|
-
return context.runtime.newBoolean(
|
2219
|
+
return context.runtime.newBoolean(rawBoolean);
|
2416
2220
|
}
|
2417
2221
|
|
2418
2222
|
@JRubyMethod(name = "raw_boolean=", meta = true)
|
@@ -2444,13 +2248,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2444
2248
|
protected IRubyObject booleanToRuby(final ThreadContext context,
|
2445
2249
|
final Ruby runtime, final ResultSet resultSet, final int column)
|
2446
2250
|
throws SQLException {
|
2447
|
-
if ( rawBoolean != null && rawBoolean
|
2251
|
+
if ( rawBoolean != null && rawBoolean) {
|
2448
2252
|
final String value = resultSet.getString(column);
|
2449
2253
|
if ( value == null /* && resultSet.wasNull() */ ) return context.nil;
|
2450
2254
|
return RubyString.newUnicodeString(runtime, value);
|
2451
2255
|
}
|
2452
2256
|
final boolean value = resultSet.getBoolean(column);
|
2453
|
-
if (
|
2257
|
+
if (!value && resultSet.wasNull()) return context.nil;
|
2454
2258
|
return runtime.newBoolean(value);
|
2455
2259
|
}
|
2456
2260
|
|
@@ -2668,7 +2472,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2668
2472
|
}
|
2669
2473
|
}
|
2670
2474
|
|
2671
|
-
protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap
|
2475
|
+
protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<>(32, 1);
|
2672
2476
|
static {
|
2673
2477
|
JDBC_TYPE_FOR.put("string", Types.VARCHAR);
|
2674
2478
|
JDBC_TYPE_FOR.put("text", Types.CLOB);
|
@@ -2710,7 +2514,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2710
2514
|
final String internedType = internedTypeFor(context, attribute);
|
2711
2515
|
final Integer sqlType = jdbcTypeFor(internedType);
|
2712
2516
|
if ( sqlType != null ) {
|
2713
|
-
return sqlType
|
2517
|
+
return sqlType;
|
2714
2518
|
}
|
2715
2519
|
|
2716
2520
|
return Types.OTHER; // -1 as well as 0 are used in Types
|
@@ -2897,11 +2701,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2897
2701
|
statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
|
2898
2702
|
}
|
2899
2703
|
|
2900
|
-
@Deprecated
|
2901
|
-
protected static Timestamp convertToTimestamp(final RubyFloat value) {
|
2902
|
-
return DateTimeUtils.convertToTimestamp(value);
|
2903
|
-
}
|
2904
|
-
|
2905
2704
|
protected static Calendar getCalendar(final DateTimeZone zone) { // final java.util.Date hint
|
2906
2705
|
if (DateTimeZone.UTC == zone) return getCalendarUTC();
|
2907
2706
|
if (DateTimeZone.getDefault() == zone) return new GregorianCalendar();
|
@@ -2947,9 +2746,14 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2947
2746
|
value = value.callMethod(context, "to_date");
|
2948
2747
|
}
|
2949
2748
|
|
2950
|
-
|
2951
|
-
|
2952
|
-
|
2749
|
+
if (value instanceof RubyDate) {
|
2750
|
+
RubyDate rubyDate = (RubyDate) value;
|
2751
|
+
statement.setDate(index, rubyDate.toJava(Date.class));
|
2752
|
+
return;
|
2753
|
+
}
|
2754
|
+
|
2755
|
+
// NOTE: assuming Date#to_s does right ...
|
2756
|
+
statement.setDate(index, Date.valueOf(value.toString()));
|
2953
2757
|
}
|
2954
2758
|
|
2955
2759
|
protected void setBooleanParameter(final ThreadContext context,
|
@@ -2986,7 +2790,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2986
2790
|
// For some reason the driver doesn't like "character varying" as a type
|
2987
2791
|
if ( type.eql(context.runtime.newSymbol("string")) ) return "varchar";
|
2988
2792
|
|
2989
|
-
final RubyHash nativeTypes = (RubyHash)
|
2793
|
+
final RubyHash nativeTypes = (RubyHash) adapter.callMethod(context, "native_database_types");
|
2990
2794
|
// e.g. `integer: { name: 'integer' }`
|
2991
2795
|
final RubyHash typeInfo = (RubyHash) nativeTypes.op_aref(context, type);
|
2992
2796
|
|
@@ -3047,16 +2851,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3047
2851
|
}
|
3048
2852
|
|
3049
2853
|
/**
|
3050
|
-
*
|
3051
|
-
* @return connection
|
3052
|
-
* @throws <code>ActiveRecord::ConnectionNotEstablished</code>, <code>ActiveRecord::JDBCError</code>
|
3053
|
-
*/
|
3054
|
-
protected Connection getConnection() throws RaiseException {
|
3055
|
-
return getConnection(false);
|
3056
|
-
}
|
3057
|
-
|
3058
|
-
/**
|
3059
|
-
* @see #getConnection()
|
2854
|
+
* Returns a connection (might cause a reconnect if there's none).
|
3060
2855
|
* @param required set to true if a connection is required to exists (e.g. on commit)
|
3061
2856
|
* @return connection
|
3062
2857
|
* @throws <code>ActiveRecord::ConnectionNotEstablished</code> if disconnected
|
@@ -3071,17 +2866,15 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3071
2866
|
}
|
3072
2867
|
}
|
3073
2868
|
|
3074
|
-
|
2869
|
+
protected Connection getConnectionInternal(final boolean required) throws SQLException {
|
3075
2870
|
Connection connection = getConnectionImpl();
|
3076
|
-
if (
|
3077
|
-
if (
|
3078
|
-
|
3079
|
-
|
2871
|
+
if (connection == null && required) {
|
2872
|
+
if (!connected) handleNotConnected(); // raise ConnectionNotEstablished
|
2873
|
+
synchronized (this) {
|
2874
|
+
connection = getConnectionImpl();
|
2875
|
+
if ( connection == null ) {
|
2876
|
+
connectImpl(true); // throws SQLException
|
3080
2877
|
connection = getConnectionImpl();
|
3081
|
-
if ( connection == null ) {
|
3082
|
-
connectImpl( true ); // throws SQLException
|
3083
|
-
connection = getConnectionImpl();
|
3084
|
-
}
|
3085
2878
|
}
|
3086
2879
|
}
|
3087
2880
|
}
|
@@ -3212,7 +3005,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3212
3005
|
try {
|
3213
3006
|
tablesSet = metaData.getTables(catalog, _schemaPattern, _tablePattern, types);
|
3214
3007
|
if ( checkExistsOnly ) { // only check if given table exists
|
3215
|
-
return tablesSet.next() ? context.
|
3008
|
+
return tablesSet.next() ? context.tru : null;
|
3216
3009
|
}
|
3217
3010
|
else {
|
3218
3011
|
return mapTables(context, connection, catalog, _schemaPattern, _tablePattern, tablesSet);
|
@@ -3221,15 +3014,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3221
3014
|
finally { close(tablesSet); }
|
3222
3015
|
}
|
3223
3016
|
|
3224
|
-
@Deprecated
|
3225
|
-
protected IRubyObject matchTables(final Ruby runtime,
|
3226
|
-
final Connection connection,
|
3227
|
-
final String catalog, final String schemaPattern,
|
3228
|
-
final String tablePattern, final String[] types,
|
3229
|
-
final boolean checkExistsOnly) throws SQLException {
|
3230
|
-
return matchTables(runtime.getCurrentContext(), connection, catalog, schemaPattern, tablePattern, types, checkExistsOnly);
|
3231
|
-
}
|
3232
|
-
|
3233
3017
|
// NOTE java.sql.DatabaseMetaData.getTables :
|
3234
3018
|
protected final static int TABLES_TABLE_CAT = 1;
|
3235
3019
|
protected final static int TABLES_TABLE_SCHEM = 2;
|
@@ -3318,7 +3102,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3318
3102
|
final String tabName = results.getString(TABLE_NAME);
|
3319
3103
|
final RubyString tableName = cachedString(context, caseConvertIdentifierForRails(metaData, tabName));
|
3320
3104
|
|
3321
|
-
final IRubyObject type_metadata =
|
3105
|
+
final IRubyObject type_metadata = adapter.callMethod(context, "fetch_type_metadata", sqlType);
|
3322
3106
|
|
3323
3107
|
// (name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
|
3324
3108
|
final IRubyObject[] args = new IRubyObject[] {
|
@@ -3334,7 +3118,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3334
3118
|
ResultSet primaryKeys = null;
|
3335
3119
|
try {
|
3336
3120
|
primaryKeys = metaData.getPrimaryKeys(components.catalog, components.schema, components.name);
|
3337
|
-
final List<String> primaryKeyNames = new ArrayList
|
3121
|
+
final List<String> primaryKeyNames = new ArrayList<>(4);
|
3338
3122
|
while ( primaryKeys.next() ) {
|
3339
3123
|
primaryKeyNames.add( primaryKeys.getString(COLUMN_NAME) );
|
3340
3124
|
}
|
@@ -3383,7 +3167,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3383
3167
|
// not have and auto-generated ID column :
|
3384
3168
|
boolean next = genKeys.next() && genKeys.getMetaData().getColumnCount() > 0;
|
3385
3169
|
// singleResult == null - guess if only single key returned
|
3386
|
-
if ( singleResult == null || singleResult
|
3170
|
+
if ( singleResult == null || singleResult) {
|
3387
3171
|
if ( next ) {
|
3388
3172
|
firstKey = mapGeneratedKey(runtime, genKeys);
|
3389
3173
|
if ( singleResult != null || ! genKeys.next() ) {
|
@@ -3416,7 +3200,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3416
3200
|
if (supportsGeneratedKeys == null) {
|
3417
3201
|
supportsGeneratedKeys = this.supportsGeneratedKeys = connection.getMetaData().supportsGetGeneratedKeys();
|
3418
3202
|
}
|
3419
|
-
return supportsGeneratedKeys
|
3203
|
+
return supportsGeneratedKeys;
|
3420
3204
|
}
|
3421
3205
|
|
3422
3206
|
/**
|
@@ -3448,8 +3232,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3448
3232
|
final ColumnData[] columns = extractColumns(context, connection, resultSet, false);
|
3449
3233
|
|
3450
3234
|
final Ruby runtime = context.runtime;
|
3451
|
-
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
3452
3235
|
while ( resultSet.next() ) {
|
3236
|
+
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
3453
3237
|
for ( int i = 0; i < columns.length; i++ ) {
|
3454
3238
|
final ColumnData column = columns[i];
|
3455
3239
|
blockArgs[i] = jdbcToRuby(context, runtime, column.index, column.type, resultSet);
|
@@ -3475,16 +3259,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3475
3259
|
return setupColumns(context, connection, resultSet.getMetaData(), downCase);
|
3476
3260
|
}
|
3477
3261
|
|
3478
|
-
/**
|
3479
|
-
* @deprecated use {@link #extractColumns(ThreadContext, Connection, ResultSet, boolean)}
|
3480
|
-
*/
|
3481
|
-
@Deprecated
|
3482
|
-
protected ColumnData[] extractColumns(final Ruby runtime,
|
3483
|
-
final Connection connection, final ResultSet resultSet,
|
3484
|
-
final boolean downCase) throws SQLException {
|
3485
|
-
return extractColumns(runtime.getCurrentContext(), connection, resultSet, downCase);
|
3486
|
-
}
|
3487
|
-
|
3488
3262
|
protected <T> T withConnection(final ThreadContext context, final Callable<T> block)
|
3489
3263
|
throws RaiseException {
|
3490
3264
|
try {
|
@@ -3590,13 +3364,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3590
3364
|
}
|
3591
3365
|
|
3592
3366
|
protected boolean isTransient(final Exception exception) {
|
3593
|
-
|
3594
|
-
return false;
|
3367
|
+
return exception instanceof SQLTransientException;
|
3595
3368
|
}
|
3596
3369
|
|
3597
3370
|
protected boolean isRecoverable(final Exception exception) {
|
3598
|
-
|
3599
|
-
|
3371
|
+
return exception instanceof SQLRecoverableException;
|
3372
|
+
// exception instanceof SQLException; // pre JDBC 4.0 drivers?
|
3600
3373
|
}
|
3601
3374
|
|
3602
3375
|
private static Throwable getCause(Throwable exception) {
|
@@ -3754,6 +3527,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3754
3527
|
return Result.newInstance(context, columnsToArray(context, columns), rows, Block.NULL_BLOCK); // Result.new
|
3755
3528
|
}
|
3756
3529
|
|
3530
|
+
protected static IRubyObject newEmptyResult(final ThreadContext context) {
|
3531
|
+
final RubyClass Result = getResult(context.runtime);
|
3532
|
+
return Result.newInstance(context, RubyArray.newEmptyArray(context.runtime), RubyArray.newEmptyArray(context.runtime), Block.NULL_BLOCK); // Result.new
|
3533
|
+
}
|
3534
|
+
|
3757
3535
|
private static RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
|
3758
3536
|
final IRubyObject[] cols = new IRubyObject[columns.length];
|
3759
3537
|
|
@@ -4006,7 +3784,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
4006
3784
|
public static void debugStackTrace(final ThreadContext context, final Throwable e) {
|
4007
3785
|
if ( debug || ( context != null && context.runtime.isDebug() ) ) {
|
4008
3786
|
final PrintStream out = context != null ? context.runtime.getOut() : System.out;
|
4009
|
-
if ( debugStackTrace == null || debugStackTrace
|
3787
|
+
if ( debugStackTrace == null || debugStackTrace) {
|
4010
3788
|
e.printStackTrace(out);
|
4011
3789
|
}
|
4012
3790
|
else {
|
@@ -4022,8 +3800,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
4022
3800
|
private static boolean driverUsedLogged;
|
4023
3801
|
|
4024
3802
|
private void logDriverUsed(final Connection connection) {
|
4025
|
-
if (
|
4026
|
-
if ( driverUsedLogged ) return;
|
3803
|
+
if (debug && !driverUsedLogged) {
|
4027
3804
|
driverUsedLogged = true;
|
4028
3805
|
try {
|
4029
3806
|
final DatabaseMetaData meta = connection.getMetaData();
|