activerecord-jdbc-adapter 72.0-java → 80.0.pre1-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/.github/workflows/ruby.yml +129 -24
- data/.mise.toml +3 -0
- data/Gemfile +42 -47
- data/README.md +3 -2
- data/Rakefile +62 -14
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/lib/arjdbc/abstract/core.rb +1 -1
- data/lib/arjdbc/abstract/database_statements.rb +11 -7
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/postgresql/adapter.rb +4 -1
- data/lib/arjdbc/sqlite3/adapter.rb +48 -7
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/db.rake +5 -3
- data/rakelib/rails.rake +0 -1
- data/src/java/arjdbc/ArJdbcModule.java +13 -10
- data/src/java/arjdbc/db2/DB2Module.java +4 -4
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +8 -9
- data/src/java/arjdbc/h2/H2Module.java +2 -1
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +8 -7
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +5 -6
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +4 -3
- data/src/java/arjdbc/jdbc/DriverWrapper.java +13 -8
- data/src/java/arjdbc/jdbc/JdbcResult.java +10 -7
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +168 -154
- data/src/java/arjdbc/mssql/MSSQLModule.java +3 -3
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +13 -9
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +30 -24
- data/src/java/arjdbc/oracle/OracleModule.java +2 -3
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +22 -18
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +2 -3
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +24 -12
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +16 -12
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -3
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +78 -29
- data/src/java/arjdbc/util/DateTimeUtils.java +7 -5
- data/src/java/arjdbc/util/ObjectSupport.java +2 -2
- data/src/java/arjdbc/util/StringHelper.java +1 -1
- metadata +6 -6
- data/.travis.yml +0 -128
|
@@ -223,17 +223,29 @@ module ArJdbc
|
|
|
223
223
|
|
|
224
224
|
# REFERENTIAL INTEGRITY ====================================
|
|
225
225
|
|
|
226
|
+
def execute_batch(statements, name = nil, **kwargs)
|
|
227
|
+
if statements.is_a?(Array)
|
|
228
|
+
# SQLite JDBC doesn't support multiple statements in one execute
|
|
229
|
+
# Execute each statement separately
|
|
230
|
+
statements.each do |sql|
|
|
231
|
+
raw_execute(sql, name, **kwargs.merge(batch: true))
|
|
232
|
+
end
|
|
233
|
+
else
|
|
234
|
+
raw_execute(statements, name, batch: true, **kwargs)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
226
238
|
def disable_referential_integrity # :nodoc:
|
|
227
239
|
old_foreign_keys = query_value("PRAGMA foreign_keys")
|
|
228
240
|
old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")
|
|
229
241
|
|
|
230
242
|
begin
|
|
231
|
-
|
|
232
|
-
|
|
243
|
+
raw_execute("PRAGMA defer_foreign_keys = ON", "SCHEMA", allow_retry: false, materialize_transactions: false)
|
|
244
|
+
raw_execute("PRAGMA foreign_keys = OFF", "SCHEMA", allow_retry: false, materialize_transactions: false)
|
|
233
245
|
yield
|
|
234
246
|
ensure
|
|
235
|
-
|
|
236
|
-
|
|
247
|
+
raw_execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}", "SCHEMA", allow_retry: false, materialize_transactions: false)
|
|
248
|
+
raw_execute("PRAGMA foreign_keys = #{old_foreign_keys}", "SCHEMA", allow_retry: false, materialize_transactions: false)
|
|
237
249
|
end
|
|
238
250
|
end
|
|
239
251
|
|
|
@@ -388,6 +400,24 @@ module ArJdbc
|
|
|
388
400
|
end
|
|
389
401
|
end
|
|
390
402
|
|
|
403
|
+
# Returns a list of defined virtual tables (for Rails 8 compatibility)
|
|
404
|
+
VIRTUAL_TABLE_REGEX = /USING\s+(\w+)(?:\s*\((.*)\))?/im
|
|
405
|
+
def virtual_tables
|
|
406
|
+
query = <<~SQL
|
|
407
|
+
SELECT name, sql FROM sqlite_master
|
|
408
|
+
WHERE type = 'table' AND sql LIKE 'CREATE VIRTUAL TABLE%';
|
|
409
|
+
SQL
|
|
410
|
+
|
|
411
|
+
exec_query(query, "SCHEMA").cast_values.each_with_object({}) do |(name, sql), memo|
|
|
412
|
+
match = sql.match(VIRTUAL_TABLE_REGEX)
|
|
413
|
+
next unless match
|
|
414
|
+
|
|
415
|
+
module_name = match[1]
|
|
416
|
+
arguments = match[2] || ""
|
|
417
|
+
memo[name] = [module_name, arguments.strip]
|
|
418
|
+
end.to_a
|
|
419
|
+
end
|
|
420
|
+
|
|
391
421
|
def build_insert_sql(insert) # :nodoc:
|
|
392
422
|
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
|
393
423
|
|
|
@@ -791,7 +821,17 @@ module ArJdbc
|
|
|
791
821
|
DEFAULT_PRAGMAS.merge(pragmas).each do |pragma, value|
|
|
792
822
|
if ::SQLite3::Pragmas.respond_to?(pragma)
|
|
793
823
|
stmt = ::SQLite3::Pragmas.public_send(pragma, value)
|
|
794
|
-
|
|
824
|
+
# Skip pragma execution if we're inside a transaction and it's not allowed
|
|
825
|
+
begin
|
|
826
|
+
raw_execute(stmt, "SCHEMA")
|
|
827
|
+
rescue => e
|
|
828
|
+
if e.message.include?("Safety level may not be changed inside a transaction")
|
|
829
|
+
# Log warning and skip this pragma
|
|
830
|
+
warn "Cannot set pragma '#{pragma}' inside a transaction, skipping"
|
|
831
|
+
else
|
|
832
|
+
raise
|
|
833
|
+
end
|
|
834
|
+
end
|
|
795
835
|
else
|
|
796
836
|
warn "Unknown SQLite pragma: #{pragma}"
|
|
797
837
|
end
|
|
@@ -845,7 +885,7 @@ module ActiveRecord::ConnectionAdapters
|
|
|
845
885
|
include ArJdbc::Abstract::ConnectionManagement
|
|
846
886
|
include ArJdbc::Abstract::DatabaseStatements
|
|
847
887
|
include ArJdbc::Abstract::StatementCache
|
|
848
|
-
include
|
|
888
|
+
# Don't include TransactionSupport - use Rails' SQLite3::DatabaseStatements instead
|
|
849
889
|
|
|
850
890
|
|
|
851
891
|
##
|
|
@@ -954,7 +994,8 @@ module ActiveRecord::ConnectionAdapters
|
|
|
954
994
|
|
|
955
995
|
# because the JDBC driver doesn't like multiple SQL statements in one JDBC statement
|
|
956
996
|
def combine_multi_statements(total_sql)
|
|
957
|
-
|
|
997
|
+
# For Rails 8 compatibility - join multiple statements with semicolon
|
|
998
|
+
total_sql.is_a?(Array) ? total_sql.join(";\n") : total_sql
|
|
958
999
|
end
|
|
959
1000
|
|
|
960
1001
|
def type_map
|
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>
|
|
15
|
+
<jruby.version>10.0.0.1</jruby.version>
|
|
16
16
|
</properties>
|
|
17
17
|
|
|
18
18
|
<issueManagement>
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
<artifactId>maven-compiler-plugin</artifactId>
|
|
104
104
|
<version>2.5.1</version>
|
|
105
105
|
<configuration>
|
|
106
|
-
<source>
|
|
107
|
-
<target>
|
|
106
|
+
<source>21</source>
|
|
107
|
+
<target>21</target>
|
|
108
108
|
</configuration>
|
|
109
109
|
</plugin>
|
|
110
110
|
</plugins>
|
data/rakelib/db.rake
CHANGED
|
@@ -39,7 +39,7 @@ GRANT ALL PRIVILEGES ON `test\_%`.* TO #{MYSQL_CONFIG[:username]}@localhost;
|
|
|
39
39
|
task :postgresql do
|
|
40
40
|
require File.expand_path('../../test/shared_helper', __FILE__)
|
|
41
41
|
fail 'could not create test database: psql executable not found' unless psql = which('psql')
|
|
42
|
-
fail 'could not create test database: missing "
|
|
42
|
+
fail 'could not create test database: missing "arjdbc" role' unless PostgresHelper.postgres_role?
|
|
43
43
|
|
|
44
44
|
load 'test/db/postgres_config.rb' # rescue nil
|
|
45
45
|
puts POSTGRES_CONFIG.inspect if $VERBOSE
|
|
@@ -53,11 +53,13 @@ CREATE DATABASE #{POSTGRES_CONFIG[:database]} OWNER #{POSTGRES_CONFIG[:username]
|
|
|
53
53
|
ENCODING '#{POSTGRES_CONFIG[:encoding]}' LC_COLLATE '#{POSTGRES_CONFIG[:collate]}' LC_CTYPE '#{POSTGRES_CONFIG[:collate]}';
|
|
54
54
|
SQL
|
|
55
55
|
|
|
56
|
-
params = { '-U' => ENV['
|
|
56
|
+
params = { '-U' => ENV['PGUSER'] || 'arjdbc', '-d' => 'postgres' }
|
|
57
|
+
params['-h'] = ENV['PGHOST'] if ENV['PGHOST']
|
|
58
|
+
params['-p'] = ENV['PGPORT'] if ENV['PGPORT']
|
|
57
59
|
params['-q'] = nil unless $VERBOSE
|
|
58
60
|
|
|
59
61
|
puts "Creating PostgreSQL (test) database: #{POSTGRES_CONFIG[:database]}"
|
|
60
|
-
sh "cat #{script.path} | #{psql} #{params.to_a.join(' ')}", verbose: $VERBOSE
|
|
62
|
+
sh "PGPASSWORD=#{ENV['PGPASSWORD'] || 'arjdbc'} cat #{script.path} | #{psql} #{params.to_a.join(' ')}", verbose: $VERBOSE
|
|
61
63
|
end
|
|
62
64
|
task postgres: :postgresql
|
|
63
65
|
|
data/rakelib/rails.rake
CHANGED
|
@@ -52,7 +52,6 @@ namespace :rails do
|
|
|
52
52
|
ruby_opts_string += " -C \"#{ar_path}\""
|
|
53
53
|
ruby_opts_string += " -rbundler/setup"
|
|
54
54
|
ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
|
|
55
|
-
ruby_opts_string += " -rmonkey_patches"
|
|
56
55
|
file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
|
|
57
56
|
file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
|
|
58
57
|
# test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
|
|
@@ -43,6 +43,9 @@ import org.jruby.util.ByteList;
|
|
|
43
43
|
|
|
44
44
|
import arjdbc.jdbc.RubyJdbcConnection;
|
|
45
45
|
import static arjdbc.jdbc.RubyJdbcConnection.getJdbcConnection;
|
|
46
|
+
import static org.jruby.api.Access.getModule;
|
|
47
|
+
import static org.jruby.api.Access.objectClass;
|
|
48
|
+
import static org.jruby.api.Create.allocArray;
|
|
46
49
|
|
|
47
50
|
/**
|
|
48
51
|
* ::ArJdbc
|
|
@@ -52,9 +55,10 @@ import static arjdbc.jdbc.RubyJdbcConnection.getJdbcConnection;
|
|
|
52
55
|
public class ArJdbcModule {
|
|
53
56
|
|
|
54
57
|
public static RubyModule load(final Ruby runtime) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
var context = runtime.getCurrentContext();
|
|
59
|
+
return objectClass(context).
|
|
60
|
+
defineModuleUnder(context, "ArJdbc").
|
|
61
|
+
defineMethods(context, ArJdbcModule.class);
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
public static RubyModule get(final Ruby runtime) {
|
|
@@ -142,7 +146,7 @@ public class ArJdbcModule {
|
|
|
142
146
|
catch (NoSuchMethodException e) {
|
|
143
147
|
// "old" e.g. MySQLRubyJdbcConnection.createMySQLJdbcConnectionClass(runtime, jdbcConnection)
|
|
144
148
|
connection.getMethod("create" + moduleName + "JdbcConnectionClass", Ruby.class, RubyClass.class).
|
|
145
|
-
invoke(null, runtime, getJdbcConnection(
|
|
149
|
+
invoke(null, runtime, getJdbcConnection(context));
|
|
146
150
|
}
|
|
147
151
|
}
|
|
148
152
|
}
|
|
@@ -162,20 +166,19 @@ public class ArJdbcModule {
|
|
|
162
166
|
*/
|
|
163
167
|
@JRubyMethod(name = "modules", meta = true)
|
|
164
168
|
public static IRubyObject modules(final ThreadContext context, final IRubyObject self) {
|
|
165
|
-
final Ruby runtime = context.getRuntime();
|
|
166
169
|
final RubyModule arJdbc = (RubyModule) self;
|
|
167
170
|
|
|
168
171
|
final Collection<String> constants = arJdbc.getConstantNames();
|
|
169
|
-
final RubyArray modules =
|
|
172
|
+
final RubyArray modules = allocArray(context, constants.size());
|
|
170
173
|
|
|
171
174
|
for ( final String name : constants ) {
|
|
172
|
-
final IRubyObject constant = arJdbc.getConstant(name, false);
|
|
175
|
+
final IRubyObject constant = arJdbc.getConstant(context, name, false);
|
|
173
176
|
// isModule: return false for Ruby Classes
|
|
174
177
|
if ( constant != null && constant.isModule() ) {
|
|
175
178
|
if ( "Util".equals(name) ) continue;
|
|
176
179
|
if ( "SerializedAttributesHelper".equals(name) ) continue; // deprecated
|
|
177
180
|
if ( "Version".equals(name) ) continue; // deprecated
|
|
178
|
-
modules.append( constant
|
|
181
|
+
modules.append(context, constant);
|
|
179
182
|
}
|
|
180
183
|
}
|
|
181
184
|
return modules;
|
|
@@ -230,9 +233,9 @@ public class ArJdbcModule {
|
|
|
230
233
|
return null;
|
|
231
234
|
}
|
|
232
235
|
|
|
233
|
-
final RubyModule jdbc =
|
|
236
|
+
final RubyModule jdbc = getModule(context, "Jdbc");
|
|
234
237
|
if ( jdbc != null ) { // Jdbc::MySQL
|
|
235
|
-
final RubyModule constant =
|
|
238
|
+
final RubyModule constant = jdbc.getModule(context, constName);
|
|
236
239
|
if ( constant != null ) { // ::Jdbc::MySQL.load_driver :
|
|
237
240
|
if ( constant.respondsTo("load_driver") ) {
|
|
238
241
|
IRubyObject result = constant.callMethod("load_driver");
|
|
@@ -26,6 +26,7 @@ package arjdbc.db2;
|
|
|
26
26
|
import static arjdbc.util.QuotingUtils.BYTES_0;
|
|
27
27
|
import static arjdbc.util.QuotingUtils.BYTES_1;
|
|
28
28
|
import static arjdbc.util.QuotingUtils.quoteSingleQuotesWithFallback;
|
|
29
|
+
import static org.jruby.api.Create.newString;
|
|
29
30
|
|
|
30
31
|
import org.jruby.Ruby;
|
|
31
32
|
import org.jruby.RubyModule;
|
|
@@ -42,9 +43,8 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
|
42
43
|
public class DB2Module {
|
|
43
44
|
|
|
44
45
|
public static RubyModule load(final RubyModule arJdbc) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return db2;
|
|
46
|
+
var context = arJdbc.getRuntime().getCurrentContext();
|
|
47
|
+
return arJdbc.defineModuleUnder(context, "DB2").defineMethods(context, DB2Module.class);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
public static RubyModule load(final Ruby runtime) {
|
|
@@ -63,7 +63,7 @@ public class DB2Module {
|
|
|
63
63
|
public static IRubyObject quoted_true(
|
|
64
64
|
final ThreadContext context,
|
|
65
65
|
final IRubyObject self) {
|
|
66
|
-
return
|
|
66
|
+
return newString(context, BYTES_1);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
@JRubyMethod(name = "quoted_false", required = 0, frame = false)
|
|
@@ -54,17 +54,16 @@ public class DB2RubyJdbcConnection extends RubyJdbcConnection {
|
|
|
54
54
|
super(runtime, metaClass);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
public static RubyClass createDB2JdbcConnectionClass(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return clazz;
|
|
57
|
+
public static RubyClass createDB2JdbcConnectionClass(ThreadContext context, RubyClass jdbcConnection) {
|
|
58
|
+
return getConnectionAdapters(context).
|
|
59
|
+
defineClassUnder(context, "DB2JdbcConnection", jdbcConnection, ALLOCATOR).
|
|
60
|
+
defineMethods(context, DB2RubyJdbcConnection.class);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
public static RubyClass load(final Ruby runtime) {
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
var context = runtime.getCurrentContext();
|
|
65
|
+
RubyClass jdbcConnection = getJdbcConnection(context);
|
|
66
|
+
return createDB2JdbcConnectionClass(context, jdbcConnection);
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
protected static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
|
@@ -112,7 +111,7 @@ public class DB2RubyJdbcConnection extends RubyJdbcConnection {
|
|
|
112
111
|
try {
|
|
113
112
|
statement = connection.prepareStatement("VALUES IDENTITY_VAL_LOCAL()");
|
|
114
113
|
genKeys = statement.executeQuery();
|
|
115
|
-
return doMapGeneratedKeys(context
|
|
114
|
+
return doMapGeneratedKeys(context, genKeys, true);
|
|
116
115
|
}
|
|
117
116
|
catch (final SQLException e) {
|
|
118
117
|
debugMessage(context.runtime, "failed to get generated keys: ", e);
|
|
@@ -37,7 +37,8 @@ import org.jruby.RubyModule;
|
|
|
37
37
|
public class H2Module {
|
|
38
38
|
|
|
39
39
|
public static RubyModule load(final RubyModule arJdbc) {
|
|
40
|
-
|
|
40
|
+
var context = arJdbc.getRuntime().getCurrentContext();
|
|
41
|
+
RubyModule h2 = arJdbc.defineModuleUnder(context, "H2");
|
|
41
42
|
// NOTE: currently no Java implemented Ruby methods
|
|
42
43
|
// h2.defineAnnotatedMethods( H2Module.class );
|
|
43
44
|
return h2;
|
|
@@ -28,9 +28,11 @@ package arjdbc.h2;
|
|
|
28
28
|
import java.sql.Connection;
|
|
29
29
|
import java.sql.SQLException;
|
|
30
30
|
|
|
31
|
+
import arjdbc.db2.DB2RubyJdbcConnection;
|
|
31
32
|
import org.jruby.Ruby;
|
|
32
33
|
import org.jruby.RubyClass;
|
|
33
34
|
import org.jruby.runtime.ObjectAllocator;
|
|
35
|
+
import org.jruby.runtime.ThreadContext;
|
|
34
36
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -45,16 +47,15 @@ public class H2RubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection {
|
|
|
45
47
|
super(runtime, metaClass);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
public static RubyClass createH2JdbcConnectionClass(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return clazz;
|
|
50
|
+
public static RubyClass createH2JdbcConnectionClass(ThreadContext context, RubyClass jdbcConnection) {
|
|
51
|
+
return getConnectionAdapters(context).
|
|
52
|
+
defineClassUnder(context, "H2JdbcConnection", jdbcConnection, ALLOCATOR).
|
|
53
|
+
defineMethods(context, H2RubyJdbcConnection.class);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
public static RubyClass load(final Ruby runtime) {
|
|
56
|
-
|
|
57
|
-
return createH2JdbcConnectionClass(
|
|
57
|
+
var context = runtime.getCurrentContext();
|
|
58
|
+
return createH2JdbcConnectionClass(context, getJdbcConnection(context));
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
protected static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
|
@@ -28,10 +28,10 @@ package arjdbc.hsqldb;
|
|
|
28
28
|
import static arjdbc.util.QuotingUtils.BYTES_0;
|
|
29
29
|
import static arjdbc.util.QuotingUtils.BYTES_1;
|
|
30
30
|
import static arjdbc.util.QuotingUtils.quoteSingleQuotesWithFallback;
|
|
31
|
+
import static org.jruby.api.Create.newString;
|
|
31
32
|
|
|
32
33
|
import org.jruby.Ruby;
|
|
33
34
|
import org.jruby.RubyModule;
|
|
34
|
-
import org.jruby.RubyString;
|
|
35
35
|
import org.jruby.anno.JRubyMethod;
|
|
36
36
|
import org.jruby.runtime.ThreadContext;
|
|
37
37
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
@@ -39,9 +39,8 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
|
39
39
|
public class HSQLDBModule {
|
|
40
40
|
|
|
41
41
|
public static RubyModule load(final RubyModule arJdbc) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return hsqldb;
|
|
42
|
+
var context = arJdbc.getRuntime().getCurrentContext();
|
|
43
|
+
return arJdbc.defineModuleUnder(context, "HSQLDB").defineMethods(context, HSQLDBModule.class);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
public static RubyModule load(final Ruby runtime) {
|
|
@@ -60,14 +59,14 @@ public class HSQLDBModule {
|
|
|
60
59
|
public static IRubyObject quoted_true(
|
|
61
60
|
final ThreadContext context,
|
|
62
61
|
final IRubyObject self) {
|
|
63
|
-
return
|
|
62
|
+
return newString(context, BYTES_1);
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
@JRubyMethod(name = "quoted_false", required = 0, frame = false)
|
|
67
66
|
public static IRubyObject quoted_false(
|
|
68
67
|
final ThreadContext context,
|
|
69
68
|
final IRubyObject self) {
|
|
70
|
-
return
|
|
69
|
+
return newString(context, BYTES_0);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
}
|
|
@@ -36,6 +36,7 @@ import org.jruby.util.SafePropertyAccessor;
|
|
|
36
36
|
|
|
37
37
|
import static arjdbc.jdbc.RubyJdbcConnection.getConnectionNotEstablished;
|
|
38
38
|
import static arjdbc.jdbc.RubyJdbcConnection.wrapException;
|
|
39
|
+
import static org.jruby.api.Access.runtimeErrorClass;
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
*
|
|
@@ -103,7 +104,7 @@ final class DataSourceConnectionFactory implements ConnectionFactory {
|
|
|
103
104
|
if ( ! ( bound instanceof DataSource ) ) {
|
|
104
105
|
if ( bound == null ) throw new NameNotFoundException(); // unlikely to happen
|
|
105
106
|
final String msg = "bound object at '" + name + "' is not a " + DataSource.class.getName() + " but a " + bound.getClass().getName() + "\n" + bound;
|
|
106
|
-
throw wrapException(context, getConnectionNotEstablished(context
|
|
107
|
+
throw wrapException(context, getConnectionNotEstablished(context), new ClassCastException(msg), msg);
|
|
107
108
|
}
|
|
108
109
|
return (DataSource) bound;
|
|
109
110
|
}
|
|
@@ -124,10 +125,10 @@ final class DataSourceConnectionFactory implements ConnectionFactory {
|
|
|
124
125
|
else {
|
|
125
126
|
message = "unable to lookup data source - name: '" + name + "' not found";
|
|
126
127
|
}
|
|
127
|
-
throw wrapException(context, getConnectionNotEstablished(context
|
|
128
|
+
throw wrapException(context, getConnectionNotEstablished(context), e, message);
|
|
128
129
|
}
|
|
129
130
|
catch (NamingException e) {
|
|
130
|
-
throw wrapException(context, context
|
|
131
|
+
throw wrapException(context, runtimeErrorClass(context), e);
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
package arjdbc.jdbc;
|
|
25
25
|
|
|
26
|
+
import java.lang.reflect.InvocationTargetException;
|
|
26
27
|
import java.sql.Connection;
|
|
27
28
|
import java.sql.Driver;
|
|
28
29
|
import java.sql.SQLException;
|
|
@@ -45,7 +46,7 @@ public class DriverWrapper {
|
|
|
45
46
|
private final Properties properties;
|
|
46
47
|
|
|
47
48
|
DriverWrapper(final Ruby runtime, final String name, final Properties properties)
|
|
48
|
-
|
|
49
|
+
throws ClassCastException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
49
50
|
this.driver = allocateDriver( loadDriver(runtime, name) );
|
|
50
51
|
this.properties = properties == null ? new Properties() : properties;
|
|
51
52
|
}
|
|
@@ -59,18 +60,22 @@ public class DriverWrapper {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
private Driver allocateDriver(final Class<? extends Driver> driverClass)
|
|
62
|
-
|
|
63
|
-
return driverClass.newInstance();
|
|
63
|
+
throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
|
|
64
|
+
return driverClass.getDeclaredConstructor().newInstance();
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
protected static Class<? extends Driver> loadDriver(final Ruby runtime, final String name)
|
|
67
68
|
throws ClassCastException {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
try {
|
|
70
|
+
@SuppressWarnings("unchecked")
|
|
71
|
+
Class<? extends Driver> klass = (Class<? extends Driver>) runtime.getJavaSupport().loadJavaClass(name);
|
|
72
|
+
if ( ! Driver.class.isAssignableFrom(klass) ) {
|
|
73
|
+
throw new ClassCastException(klass + " is not assignable from " + Driver.class);
|
|
74
|
+
}
|
|
75
|
+
return klass;
|
|
76
|
+
} catch (ClassNotFoundException e) {
|
|
77
|
+
throw new RuntimeException("Cannot load driver class: " + name, e);
|
|
72
78
|
}
|
|
73
|
-
return klass;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
public Connection connect(final String url, final String user, final String pass)
|
|
@@ -14,6 +14,10 @@ import org.jruby.runtime.Block;
|
|
|
14
14
|
import org.jruby.runtime.ThreadContext;
|
|
15
15
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
16
16
|
|
|
17
|
+
import static org.jruby.api.Create.newArray;
|
|
18
|
+
import static org.jruby.api.Create.newArrayNoCopy;
|
|
19
|
+
import static org.jruby.api.Create.newHash;
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* This is a base Result class to be returned as the "raw" result.
|
|
19
23
|
* It should be overridden for specific adapters to manage type maps
|
|
@@ -31,7 +35,7 @@ public class JdbcResult extends RubyObject {
|
|
|
31
35
|
protected JdbcResult(ThreadContext context, RubyClass clazz, RubyJdbcConnection connection, ResultSet resultSet) throws SQLException {
|
|
32
36
|
super(context.runtime, clazz);
|
|
33
37
|
|
|
34
|
-
values =
|
|
38
|
+
values = newArray(context);
|
|
35
39
|
this.connection = connection;
|
|
36
40
|
|
|
37
41
|
final ResultSetMetaData resultMetaData = resultSet.getMetaData();
|
|
@@ -86,7 +90,7 @@ public class JdbcResult extends RubyObject {
|
|
|
86
90
|
|
|
87
91
|
for (int i = 0; i < tuples.length; i++) {
|
|
88
92
|
RubyArray currentRow = (RubyArray) values.eltInternal(i);
|
|
89
|
-
RubyHash hash =
|
|
93
|
+
RubyHash hash = newHash(context);
|
|
90
94
|
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
91
95
|
hash.fastASet(columnNames[columnIndex], currentRow.eltInternal(columnIndex));
|
|
92
96
|
}
|
|
@@ -101,17 +105,16 @@ public class JdbcResult extends RubyObject {
|
|
|
101
105
|
* @throws SQLException throws!
|
|
102
106
|
*/
|
|
103
107
|
private void processResultSet(final ThreadContext context, final ResultSet resultSet) throws SQLException {
|
|
104
|
-
Ruby runtime = context.runtime;
|
|
105
108
|
int columnCount = columnNames.length;
|
|
106
109
|
|
|
107
110
|
while (resultSet.next()) {
|
|
108
111
|
final IRubyObject[] row = new IRubyObject[columnCount];
|
|
109
112
|
|
|
110
113
|
for (int i = 0; i < columnCount; i++) {
|
|
111
|
-
row[i] = connection.jdbcToRuby(context, runtime, i + 1, columnTypes[i], resultSet); // Result Set is 1 based
|
|
114
|
+
row[i] = connection.jdbcToRuby(context, context.runtime, i + 1, columnTypes[i], resultSet); // Result Set is 1 based
|
|
112
115
|
}
|
|
113
116
|
|
|
114
|
-
values.append(
|
|
117
|
+
values.append(context, newArrayNoCopy(context, row));
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
|
|
@@ -122,9 +125,9 @@ public class JdbcResult extends RubyObject {
|
|
|
122
125
|
* @throws SQLException can be caused by postgres generating its type map
|
|
123
126
|
*/
|
|
124
127
|
public IRubyObject toARResult(final ThreadContext context) throws SQLException {
|
|
125
|
-
final RubyClass Result = RubyJdbcConnection.getResult(context
|
|
128
|
+
final RubyClass Result = RubyJdbcConnection.getResult(context);
|
|
126
129
|
// FIXME: Is this broken? no copy of an array AR::Result can modify? or should it be frozen?
|
|
127
|
-
final RubyArray rubyColumnNames =
|
|
130
|
+
final RubyArray rubyColumnNames = newArrayNoCopy(context, getColumnNames());
|
|
128
131
|
return Result.newInstance(context, rubyColumnNames, values, columnTypeMap(context), Block.NULL_BLOCK);
|
|
129
132
|
}
|
|
130
133
|
}
|