activerecord-jdbc-alt-adapter 52.4.0-java → 61.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.nvimlog +0 -0
- data/.travis.yml +63 -39
- data/Gemfile +11 -4
- data/README.md +55 -35
- data/Rakefile +1 -1
- data/Rakefile.jdbc +8 -1
- data/activerecord-jdbc-adapter.gemspec +6 -9
- data/activerecord-jdbc-alt-adapter.gemspec +9 -12
- data/lib/arel/visitors/postgresql_jdbc.rb +1 -1
- data/lib/arel/visitors/sqlserver.rb +49 -23
- data/lib/arjdbc/abstract/connection_management.rb +7 -0
- data/lib/arjdbc/abstract/core.rb +17 -23
- data/lib/arjdbc/abstract/database_statements.rb +30 -2
- data/lib/arjdbc/abstract/statement_cache.rb +2 -5
- data/lib/arjdbc/abstract/transaction_support.rb +22 -7
- 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 +114 -36
- data/lib/arjdbc/mssql/column.rb +19 -1
- data/lib/arjdbc/mssql/connection_methods.rb +10 -2
- data/lib/arjdbc/mssql/database_limits.rb +9 -0
- data/lib/arjdbc/mssql/database_statements.rb +44 -6
- 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 +6 -2
- data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
- data/lib/arjdbc/mssql/quoting.rb +38 -0
- data/lib/arjdbc/mssql/schema_creation.rb +25 -3
- 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 +92 -22
- 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 +59 -21
- data/lib/arjdbc/mysql/connection_methods.rb +6 -1
- data/lib/arjdbc/postgresql/adapter.rb +257 -219
- data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
- data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
- data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
- data/lib/arjdbc/postgresql/column.rb +6 -4
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
- data/lib/arjdbc/postgresql/name.rb +2 -0
- data/lib/arjdbc/postgresql/oid_types.rb +7 -4
- data/lib/arjdbc/sqlite3/adapter.rb +266 -221
- data/lib/arjdbc/sqlite3/connection_methods.rb +26 -4
- data/lib/arjdbc/tasks/databases.rake +21 -13
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +126 -25
- 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 +3 -1
- data/pom.xml +4 -4
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/ArJdbcModule.java +5 -5
- data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +549 -691
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +88 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +125 -53
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +97 -103
- data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
- metadata +10 -18
|
@@ -57,6 +57,7 @@ import org.jruby.RubyString;
|
|
|
57
57
|
import org.jruby.RubySymbol;
|
|
58
58
|
import org.jruby.RubyTime;
|
|
59
59
|
import org.jruby.anno.JRubyMethod;
|
|
60
|
+
import org.jruby.runtime.Block;
|
|
60
61
|
import org.jruby.runtime.ObjectAllocator;
|
|
61
62
|
import org.jruby.runtime.ThreadContext;
|
|
62
63
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
@@ -203,6 +204,57 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
203
204
|
});
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Executes an INSERT SQL statement
|
|
209
|
+
* @param context
|
|
210
|
+
* @param sql
|
|
211
|
+
* @param pk Rails PK
|
|
212
|
+
* @return ActiveRecord::Result
|
|
213
|
+
* @throws SQLException
|
|
214
|
+
*/
|
|
215
|
+
@Override
|
|
216
|
+
@JRubyMethod(name = "execute_insert_pk", required = 2)
|
|
217
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
|
|
218
|
+
|
|
219
|
+
// MSSQL does not like composite primary keys here so chop it if there is more than one column
|
|
220
|
+
IRubyObject modifiedPk = pk;
|
|
221
|
+
|
|
222
|
+
if (pk instanceof RubyArray) {
|
|
223
|
+
RubyArray ary = (RubyArray) pk;
|
|
224
|
+
if (ary.size() > 0) {
|
|
225
|
+
modifiedPk = ary.eltInternal(0);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return super.execute_insert_pk(context, sql, modifiedPk);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Executes an INSERT SQL statement using a prepared statement
|
|
234
|
+
* @param context
|
|
235
|
+
* @param sql
|
|
236
|
+
* @param binds RubyArray of values to be bound to the query
|
|
237
|
+
* @param pk Rails PK
|
|
238
|
+
* @return ActiveRecord::Result
|
|
239
|
+
* @throws SQLException
|
|
240
|
+
*/
|
|
241
|
+
@Override
|
|
242
|
+
@JRubyMethod(name = "execute_insert_pk", required = 3)
|
|
243
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
|
|
244
|
+
final IRubyObject pk) {
|
|
245
|
+
// MSSQL does not like composite primary keys here so chop it if there is more than one column
|
|
246
|
+
IRubyObject modifiedPk = pk;
|
|
247
|
+
|
|
248
|
+
if (pk instanceof RubyArray) {
|
|
249
|
+
RubyArray ary = (RubyArray) pk;
|
|
250
|
+
if (ary.size() > 0) {
|
|
251
|
+
modifiedPk = ary.eltInternal(0);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return super.execute_insert_pk(context, sql, binds, modifiedPk);
|
|
256
|
+
}
|
|
257
|
+
|
|
206
258
|
@Override
|
|
207
259
|
protected Integer jdbcTypeFor(final String type) {
|
|
208
260
|
|
|
@@ -598,6 +650,42 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
598
650
|
});
|
|
599
651
|
}
|
|
600
652
|
|
|
653
|
+
// Get MSSQL minor version eg. 0
|
|
654
|
+
@JRubyMethod
|
|
655
|
+
public IRubyObject database_minor_version(final ThreadContext context) throws SQLException {
|
|
656
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
657
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
658
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
659
|
+
|
|
660
|
+
return context.runtime.newFixnum( metaData.getDatabaseMinorVersion() );
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Get MSSQL product name eg. Microsoft SQL Server
|
|
666
|
+
@JRubyMethod
|
|
667
|
+
public IRubyObject database_product_name(final ThreadContext context) throws SQLException {
|
|
668
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
669
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
670
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
671
|
+
|
|
672
|
+
return context.runtime.newString( metaData.getDatabaseProductName() );
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Get MSSQL product version eg. '14.00.3238'
|
|
678
|
+
@JRubyMethod
|
|
679
|
+
public IRubyObject database_product_version(final ThreadContext context) throws SQLException {
|
|
680
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
681
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
682
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
683
|
+
|
|
684
|
+
return context.runtime.newString( metaData.getDatabaseProductVersion() );
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
|
|
601
689
|
/**
|
|
602
690
|
* Microsoft SQL 2000+ support schemas
|
|
603
691
|
*/
|
|
@@ -40,8 +40,6 @@ import java.sql.Statement;
|
|
|
40
40
|
import java.sql.Timestamp;
|
|
41
41
|
import java.sql.Types;
|
|
42
42
|
|
|
43
|
-
import org.joda.time.DateTime;
|
|
44
|
-
import org.joda.time.DateTimeZone;
|
|
45
43
|
import org.jruby.*;
|
|
46
44
|
import org.jruby.anno.JRubyMethod;
|
|
47
45
|
import org.jruby.exceptions.RaiseException;
|
|
@@ -89,11 +87,9 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
89
87
|
|
|
90
88
|
@JRubyMethod(name = { "full_version" })
|
|
91
89
|
public IRubyObject db_version(final ThreadContext context) {
|
|
92
|
-
return withConnection(context,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return context.runtime.newString(metaData.getDatabaseProductVersion());
|
|
96
|
-
}
|
|
90
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
|
91
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
92
|
+
return context.runtime.newString(metaData.getDatabaseProductVersion());
|
|
97
93
|
});
|
|
98
94
|
}
|
|
99
95
|
|
|
@@ -108,7 +104,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
108
104
|
if ( major < 5 ) {
|
|
109
105
|
final RubyClass errorClass = getConnectionNotEstablished(context.runtime);
|
|
110
106
|
throw context.runtime.newRaiseException(errorClass,
|
|
111
|
-
|
|
107
|
+
"MySQL adapter requires driver >= 5.0 got: " + major + "." + minor);
|
|
112
108
|
}
|
|
113
109
|
if ( major == 5 && minor < 1 ) { // need 5.1 for JDBC 4.0
|
|
114
110
|
// lightweight validation query: "/* ping */ SELECT 1"
|
|
@@ -203,7 +199,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
203
199
|
return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
|
|
204
200
|
}
|
|
205
201
|
|
|
206
|
-
if ( rawDateTime != null && rawDateTime
|
|
202
|
+
if ( rawDateTime != null && rawDateTime) {
|
|
207
203
|
return RubyString.newString(runtime, DateTimeUtils.dummyTimeToString(value));
|
|
208
204
|
}
|
|
209
205
|
|
|
@@ -237,7 +233,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
237
233
|
if (lowerCase == null) {
|
|
238
234
|
lowerCase = lowerCaseIdentifiers = connection.getMetaData().storesLowerCaseIdentifiers();
|
|
239
235
|
}
|
|
240
|
-
return lowerCase
|
|
236
|
+
return lowerCase ? value.toLowerCase() : value;
|
|
241
237
|
}
|
|
242
238
|
|
|
243
239
|
@Override
|
|
@@ -247,7 +243,9 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
247
243
|
connection = super.newConnection();
|
|
248
244
|
}
|
|
249
245
|
catch (SQLException ex) {
|
|
250
|
-
|
|
246
|
+
int errorCode = ex.getErrorCode();
|
|
247
|
+
// access denied, no database
|
|
248
|
+
if (errorCode == 1044 || errorCode == 1049) throw newNoDatabaseError(ex);
|
|
251
249
|
throw ex;
|
|
252
250
|
}
|
|
253
251
|
if ( doStopCleanupThread() ) shutdownCleanupThread();
|
|
@@ -261,7 +259,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
261
259
|
}
|
|
262
260
|
|
|
263
261
|
private static boolean doStopCleanupThread() throws SQLException {
|
|
264
|
-
return stopCleanupThread != null && stopCleanupThread
|
|
262
|
+
return stopCleanupThread != null && stopCleanupThread;
|
|
265
263
|
}
|
|
266
264
|
|
|
267
265
|
private static boolean cleanupThreadShutdown;
|
|
@@ -276,19 +274,11 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
276
274
|
catch (ClassNotFoundException e) {
|
|
277
275
|
debugMessage(null, "missing MySQL JDBC cleanup thread ", e);
|
|
278
276
|
}
|
|
279
|
-
catch (NoSuchMethodException e) {
|
|
280
|
-
debugMessage(null, e);
|
|
281
|
-
}
|
|
282
|
-
catch (IllegalAccessException e) {
|
|
277
|
+
catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
|
|
283
278
|
debugMessage(null, e);
|
|
284
|
-
}
|
|
285
|
-
catch (InvocationTargetException e) {
|
|
279
|
+
} catch (InvocationTargetException e) {
|
|
286
280
|
debugMessage(null, e.getTargetException());
|
|
287
|
-
}
|
|
288
|
-
catch (SecurityException e) {
|
|
289
|
-
debugMessage(null, e);
|
|
290
|
-
}
|
|
291
|
-
finally { cleanupThreadShutdown = true; }
|
|
281
|
+
} finally { cleanupThreadShutdown = true; }
|
|
292
282
|
}
|
|
293
283
|
|
|
294
284
|
}
|
|
@@ -35,27 +35,19 @@ import arjdbc.util.StringHelper;
|
|
|
35
35
|
import java.io.ByteArrayInputStream;
|
|
36
36
|
import java.lang.StringBuilder;
|
|
37
37
|
import java.lang.reflect.InvocationTargetException;
|
|
38
|
-
import java.
|
|
39
|
-
import java.sql
|
|
38
|
+
import java.math.BigDecimal;
|
|
39
|
+
import java.sql.*;
|
|
40
40
|
import java.sql.Date;
|
|
41
|
-
import java.
|
|
42
|
-
import java.sql.ResultSet;
|
|
43
|
-
import java.sql.ResultSetMetaData;
|
|
44
|
-
import java.sql.SQLException;
|
|
45
|
-
import java.sql.Timestamp;
|
|
46
|
-
import java.sql.Types;
|
|
47
|
-
import java.util.ArrayList;
|
|
48
|
-
import java.util.Collections;
|
|
49
|
-
import java.util.HashMap;
|
|
50
|
-
import java.util.Map;
|
|
51
|
-
import java.util.UUID;
|
|
41
|
+
import java.util.*;
|
|
52
42
|
import java.util.regex.Pattern;
|
|
53
43
|
import java.util.regex.Matcher;
|
|
54
44
|
|
|
45
|
+
import org.joda.time.DateTime;
|
|
55
46
|
import org.jruby.*;
|
|
56
47
|
import org.jruby.anno.JRubyMethod;
|
|
57
48
|
import org.jruby.exceptions.RaiseException;
|
|
58
49
|
import org.jruby.ext.bigdecimal.RubyBigDecimal;
|
|
50
|
+
import org.jruby.ext.date.RubyDate;
|
|
59
51
|
import org.jruby.javasupport.JavaUtil;
|
|
60
52
|
import org.jruby.runtime.ObjectAllocator;
|
|
61
53
|
import org.jruby.runtime.ThreadContext;
|
|
@@ -115,6 +107,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
115
107
|
|
|
116
108
|
// Used to wipe trailing 0's from points (3.0, 5.6) -> (3, 5.6)
|
|
117
109
|
private static final Pattern pointCleanerPattern = Pattern.compile("\\.0\\b");
|
|
110
|
+
private static final TimeZone TZ_DEFAULT = TimeZone.getDefault();
|
|
118
111
|
|
|
119
112
|
private RubyClass resultClass;
|
|
120
113
|
private RubyHash typeMap = null;
|
|
@@ -163,15 +156,12 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
163
156
|
try { // public static String getVersion()
|
|
164
157
|
final String version = (String) // "PostgreSQL 9.2 JDBC4 (build 1002)"
|
|
165
158
|
jdbcDriver.getClass().getMethod("getVersion").invoke(null);
|
|
166
|
-
if ( version != null && version.
|
|
159
|
+
if ( version != null && version.contains("JDBC3")) {
|
|
167
160
|
// config[:connection_alive_sql] ||= 'SELECT 1'
|
|
168
161
|
setConfigValueIfNotSet(context, "connection_alive_sql", context.runtime.newString("SELECT 1"));
|
|
169
162
|
}
|
|
170
163
|
}
|
|
171
|
-
catch (NoSuchMethodException
|
|
172
|
-
catch (SecurityException e) { }
|
|
173
|
-
catch (IllegalAccessException e) { }
|
|
174
|
-
catch (InvocationTargetException e) { }
|
|
164
|
+
catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException ignored) { }
|
|
175
165
|
}
|
|
176
166
|
|
|
177
167
|
return driverWrapper;
|
|
@@ -207,9 +197,9 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
207
197
|
RubyClass arrayClass = oidArray(context);
|
|
208
198
|
RubyBasicObject attributeType = (RubyBasicObject) attributeType(context, attribute);
|
|
209
199
|
// The type or its delegate is an OID::Array
|
|
210
|
-
if (arrayClass.isInstance(attributeType) ||
|
|
200
|
+
if (attributeType != null && (arrayClass.isInstance(attributeType) ||
|
|
211
201
|
(attributeType.hasInstanceVariable("@delegate_dc_obj") &&
|
|
212
|
-
arrayClass.isInstance(attributeType.getInstanceVariable("@delegate_dc_obj")))) {
|
|
202
|
+
arrayClass.isInstance(attributeType.getInstanceVariable("@delegate_dc_obj"))))) {
|
|
213
203
|
return "array";
|
|
214
204
|
}
|
|
215
205
|
|
|
@@ -218,11 +208,9 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
218
208
|
|
|
219
209
|
@JRubyMethod(name = "database_product")
|
|
220
210
|
public IRubyObject database_product(final ThreadContext context) {
|
|
221
|
-
return withConnection(context,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return RubyString.newString(context.runtime, metaData.getDatabaseProductName() + ' ' + metaData.getDatabaseProductVersion());
|
|
225
|
-
}
|
|
211
|
+
return withConnection(context, (Callable<IRubyObject>) connection -> {
|
|
212
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
|
213
|
+
return RubyString.newString(context.runtime, metaData.getDatabaseProductName() + ' ' + metaData.getDatabaseProductVersion());
|
|
226
214
|
});
|
|
227
215
|
}
|
|
228
216
|
|
|
@@ -308,6 +296,24 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
308
296
|
statement.setArray(index, connection.createArrayOf(typeName, values));
|
|
309
297
|
}
|
|
310
298
|
|
|
299
|
+
protected void setDecimalParameter(final ThreadContext context,
|
|
300
|
+
final Connection connection, final PreparedStatement statement,
|
|
301
|
+
final int index, final IRubyObject value,
|
|
302
|
+
final IRubyObject attribute, final int type) throws SQLException {
|
|
303
|
+
if (value instanceof RubyBigDecimal) {
|
|
304
|
+
RubyBigDecimal bigDecimal = (RubyBigDecimal) value;
|
|
305
|
+
|
|
306
|
+
// too bad RubyBigDecimal.isNaN() isn't public
|
|
307
|
+
if (bigDecimal.nan_p(context) == context.tru) {
|
|
308
|
+
statement.setDouble(index, Double.NaN);
|
|
309
|
+
} else {
|
|
310
|
+
statement.setBigDecimal(index, bigDecimal.getValue());
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
super.setDecimalParameter(context, connection, statement, index, value, attribute, type);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
311
317
|
@Override
|
|
312
318
|
protected void setBlobParameter(final ThreadContext context,
|
|
313
319
|
final Connection connection, final PreparedStatement statement,
|
|
@@ -377,14 +383,16 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
377
383
|
value = value.callMethod(context, "to_date");
|
|
378
384
|
}
|
|
379
385
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
+
if (value instanceof RubyDate) {
|
|
387
|
+
RubyDate rubyDate = (RubyDate) value;
|
|
388
|
+
DateTime dt = rubyDate.getDateTime();
|
|
389
|
+
// pgjdbc needs adjustment for default JVM timezone
|
|
390
|
+
statement.setDate(index, new Date(dt.getMillis() - TZ_DEFAULT.getOffset(dt.getMillis())));
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
386
393
|
|
|
387
|
-
|
|
394
|
+
// NOTE: assuming Date#to_s does right ...
|
|
395
|
+
statement.setDate(index, Date.valueOf(value.toString()));
|
|
388
396
|
}
|
|
389
397
|
|
|
390
398
|
@Override
|
|
@@ -428,7 +436,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
428
436
|
break;
|
|
429
437
|
|
|
430
438
|
case "interval":
|
|
431
|
-
statement.setObject(index,
|
|
439
|
+
statement.setObject(index, stringToPGInterval(value.toString()));
|
|
432
440
|
break;
|
|
433
441
|
|
|
434
442
|
case "json":
|
|
@@ -485,6 +493,74 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
485
493
|
}
|
|
486
494
|
}
|
|
487
495
|
|
|
496
|
+
private int lookAhead(String value, int position, String find) {
|
|
497
|
+
char [] tokens = find.toCharArray();
|
|
498
|
+
int found = -1;
|
|
499
|
+
|
|
500
|
+
for ( int i = 0; i < tokens.length; i++ ) {
|
|
501
|
+
found = value.indexOf(tokens[i], position);
|
|
502
|
+
if ( found > 0 ) {
|
|
503
|
+
return found;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return found;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
private Object stringToPGInterval(String value) throws SQLException {
|
|
510
|
+
if (!value.startsWith("P")) return new PGInterval(value);
|
|
511
|
+
|
|
512
|
+
PGInterval interval = new PGInterval();
|
|
513
|
+
|
|
514
|
+
/* this is copied from pgjdbc with fixes for Rails */
|
|
515
|
+
int number = 0;
|
|
516
|
+
String dateValue;
|
|
517
|
+
String timeValue = null;
|
|
518
|
+
|
|
519
|
+
int hasTime = value.indexOf('T');
|
|
520
|
+
if ( hasTime > 0 ) {
|
|
521
|
+
/* skip over the P */
|
|
522
|
+
dateValue = value.substring(1,hasTime);
|
|
523
|
+
timeValue = value.substring(hasTime + 1);
|
|
524
|
+
} else {
|
|
525
|
+
/* skip over the P */
|
|
526
|
+
dateValue = value.substring(1);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
for ( int i = 0; i < dateValue.length(); i++ ) {
|
|
530
|
+
int lookAhead = lookAhead(dateValue, i, "YMD");
|
|
531
|
+
if (lookAhead > 0) {
|
|
532
|
+
char type = dateValue.charAt(lookAhead);
|
|
533
|
+
number = Integer.parseInt(dateValue.substring(i, lookAhead));
|
|
534
|
+
if (type == 'Y') {
|
|
535
|
+
interval.setYears(number);
|
|
536
|
+
} else if (type == 'M') {
|
|
537
|
+
interval.setMonths(number);
|
|
538
|
+
} else if (type == 'D') {
|
|
539
|
+
interval.setDays(number);
|
|
540
|
+
}
|
|
541
|
+
i = lookAhead;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if ( timeValue != null ) {
|
|
545
|
+
for (int i = 0; i < timeValue.length(); i++) {
|
|
546
|
+
int lookAhead = lookAhead(timeValue, i, "HMS");
|
|
547
|
+
if (lookAhead > 0) {
|
|
548
|
+
char type = timeValue.charAt(lookAhead);
|
|
549
|
+
String part = timeValue.substring(i, lookAhead);
|
|
550
|
+
if (timeValue.charAt(lookAhead) == 'H') {
|
|
551
|
+
interval.setHours(Integer.parseInt(part));
|
|
552
|
+
} else if (timeValue.charAt(lookAhead) == 'M') {
|
|
553
|
+
interval.setMinutes(Integer.parseInt(part));
|
|
554
|
+
} else if (timeValue.charAt(lookAhead) == 'S') {
|
|
555
|
+
interval.setSeconds(Double.parseDouble(part));
|
|
556
|
+
}
|
|
557
|
+
i = lookAhead;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return interval;
|
|
562
|
+
}
|
|
563
|
+
|
|
488
564
|
protected IRubyObject jdbcToRuby(ThreadContext context, Ruby runtime, int column, int type, ResultSet resultSet) throws SQLException {
|
|
489
565
|
return typeMap != null ?
|
|
490
566
|
convertWithTypeMap(context, runtime, column, type, resultSet) :
|
|
@@ -514,7 +590,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
514
590
|
|
|
515
591
|
private static Double[] parseDoubles(IRubyObject value) {
|
|
516
592
|
Matcher matches = doubleValuePattern.matcher(value.toString());
|
|
517
|
-
ArrayList<Double> doubles = new ArrayList
|
|
593
|
+
ArrayList<Double> doubles = new ArrayList<>(4); // Paths and polygons may be larger but this covers points/circles/boxes/line segments
|
|
518
594
|
|
|
519
595
|
while ( matches.find() ) {
|
|
520
596
|
doubles.add(Double.parseDouble(matches.group()));
|
|
@@ -729,6 +805,11 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
729
805
|
return DateTimeUtils.parseDate(context, value, getDefaultTimeZone(context));
|
|
730
806
|
}
|
|
731
807
|
|
|
808
|
+
protected IRubyObject decimalToRuby(final ThreadContext context,
|
|
809
|
+
final Ruby runtime, final ResultSet resultSet, final int column) throws SQLException {
|
|
810
|
+
if ("NaN".equals(resultSet.getString(column))) return new RubyBigDecimal(runtime, BigDecimal.ZERO, true);
|
|
811
|
+
return super.decimalToRuby(context, runtime, resultSet, column);
|
|
812
|
+
}
|
|
732
813
|
|
|
733
814
|
/**
|
|
734
815
|
* Detects PG specific types and converts them to their Ruby equivalents
|
|
@@ -861,34 +942,25 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
861
942
|
private static String formatInterval(final Object object) {
|
|
862
943
|
final PGInterval interval = (PGInterval) object;
|
|
863
944
|
final StringBuilder str = new StringBuilder(32);
|
|
945
|
+
str.append("P");
|
|
864
946
|
|
|
865
947
|
final int years = interval.getYears();
|
|
866
|
-
if (years != 0) str.append(years).append("
|
|
948
|
+
if (years != 0) str.append(years).append("Y");
|
|
867
949
|
|
|
868
950
|
final int months = interval.getMonths();
|
|
869
|
-
if (months != 0) str.append(months).append("
|
|
951
|
+
if (months != 0) str.append(months).append("M");
|
|
870
952
|
|
|
871
953
|
final int days = interval.getDays();
|
|
872
|
-
if (days != 0) str.append(days).append("
|
|
954
|
+
if (days != 0) str.append(days).append("D");
|
|
873
955
|
|
|
874
956
|
final int hours = interval.getHours();
|
|
875
957
|
final int mins = interval.getMinutes();
|
|
876
|
-
final
|
|
877
|
-
if (hours != 0 || mins != 0 || secs != 0) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
str.append(
|
|
881
|
-
|
|
882
|
-
if (mins < 10) str.append('0');
|
|
883
|
-
|
|
884
|
-
str.append(mins).append(':');
|
|
885
|
-
|
|
886
|
-
if (secs < 10) str.append('0');
|
|
887
|
-
|
|
888
|
-
str.append(secs);
|
|
889
|
-
|
|
890
|
-
} else if (str.length() > 1) {
|
|
891
|
-
str.deleteCharAt(str.length() - 1); // " " at the end
|
|
958
|
+
final double secs = interval.getSeconds();
|
|
959
|
+
if (hours != 0 || mins != 0 || secs != 0) {
|
|
960
|
+
str.append("T");
|
|
961
|
+
if (hours != 0) str.append(hours).append("H");
|
|
962
|
+
if (mins != 0) str.append(mins).append("M");
|
|
963
|
+
if (secs != 0) str.append(secs).append("S");
|
|
892
964
|
}
|
|
893
965
|
|
|
894
966
|
return str.toString();
|