activerecord-jdbc-adapter 5.0.pre1 → 51.0
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 +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -27,6 +27,7 @@ package arjdbc.postgresql;
|
|
27
27
|
|
28
28
|
import java.io.ByteArrayInputStream;
|
29
29
|
import java.io.InputStream;
|
30
|
+
import java.lang.StringBuilder;
|
30
31
|
import java.sql.Array;
|
31
32
|
import java.sql.Connection;
|
32
33
|
import java.sql.PreparedStatement;
|
@@ -35,8 +36,10 @@ import java.sql.SQLException;
|
|
35
36
|
import java.sql.Statement;
|
36
37
|
import java.sql.Timestamp;
|
37
38
|
import java.sql.Types;
|
39
|
+
import java.util.HashMap;
|
38
40
|
import java.util.Map;
|
39
41
|
import java.util.UUID;
|
42
|
+
import java.util.regex.Pattern;
|
40
43
|
|
41
44
|
import org.jruby.Ruby;
|
42
45
|
import org.jruby.RubyArray;
|
@@ -46,6 +49,7 @@ import org.jruby.RubyFixnum;
|
|
46
49
|
import org.jruby.RubyFloat;
|
47
50
|
import org.jruby.RubyHash;
|
48
51
|
import org.jruby.RubyIO;
|
52
|
+
import org.jruby.RubyModule;
|
49
53
|
import org.jruby.RubyString;
|
50
54
|
import org.jruby.anno.JRubyMethod;
|
51
55
|
import org.jruby.javasupport.JavaUtil;
|
@@ -57,7 +61,9 @@ import org.jruby.util.ByteList;
|
|
57
61
|
import org.postgresql.PGConnection;
|
58
62
|
import org.postgresql.PGStatement;
|
59
63
|
import org.postgresql.core.BaseConnection;
|
60
|
-
import org.postgresql.
|
64
|
+
import org.postgresql.geometric.PGline;
|
65
|
+
import org.postgresql.geometric.PGlseg;
|
66
|
+
import org.postgresql.geometric.PGpoint;
|
61
67
|
import org.postgresql.util.PGInterval;
|
62
68
|
import org.postgresql.util.PGobject;
|
63
69
|
|
@@ -67,6 +73,52 @@ import org.postgresql.util.PGobject;
|
|
67
73
|
*/
|
68
74
|
public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection {
|
69
75
|
private static final long serialVersionUID = 7235537759545717760L;
|
76
|
+
private static final int HSTORE_TYPE = 100000 + 1111;
|
77
|
+
private static final Pattern binaryStringPattern = Pattern.compile("^[01]+$");
|
78
|
+
private static final Pattern uuidPattern = Pattern.compile("^\\p{XDigit}{8}-(?:\\p{XDigit}{4}-){3}\\p{XDigit}{12}$");
|
79
|
+
|
80
|
+
private static final String[] binaryStrings = {
|
81
|
+
"0000",
|
82
|
+
"0001",
|
83
|
+
"0010",
|
84
|
+
"0011",
|
85
|
+
"0100",
|
86
|
+
"0101",
|
87
|
+
"0110",
|
88
|
+
"0111",
|
89
|
+
"1000",
|
90
|
+
"1001",
|
91
|
+
"1010",
|
92
|
+
"1011",
|
93
|
+
"1100",
|
94
|
+
"1101",
|
95
|
+
"1110",
|
96
|
+
"1111"
|
97
|
+
};
|
98
|
+
|
99
|
+
private static final Map<String, Integer> POSTGRES_JDBC_TYPE_FOR = new HashMap<String, Integer>(32, 1);
|
100
|
+
static {
|
101
|
+
POSTGRES_JDBC_TYPE_FOR.put("bit", Types.OTHER);
|
102
|
+
POSTGRES_JDBC_TYPE_FOR.put("bit_varying", Types.OTHER);
|
103
|
+
POSTGRES_JDBC_TYPE_FOR.put("citext", Types.OTHER);
|
104
|
+
POSTGRES_JDBC_TYPE_FOR.put("daterange", Types.OTHER);
|
105
|
+
POSTGRES_JDBC_TYPE_FOR.put("hstore", Types.OTHER);
|
106
|
+
POSTGRES_JDBC_TYPE_FOR.put("int4range", Types.OTHER);
|
107
|
+
POSTGRES_JDBC_TYPE_FOR.put("int8range", Types.OTHER);
|
108
|
+
POSTGRES_JDBC_TYPE_FOR.put("interval", Types.OTHER);
|
109
|
+
POSTGRES_JDBC_TYPE_FOR.put("json", Types.OTHER);
|
110
|
+
POSTGRES_JDBC_TYPE_FOR.put("jsonb", Types.OTHER);
|
111
|
+
POSTGRES_JDBC_TYPE_FOR.put("line", Types.OTHER);
|
112
|
+
POSTGRES_JDBC_TYPE_FOR.put("lseg", Types.OTHER);
|
113
|
+
POSTGRES_JDBC_TYPE_FOR.put("ltree", Types.OTHER);
|
114
|
+
POSTGRES_JDBC_TYPE_FOR.put("numrange", Types.OTHER);
|
115
|
+
POSTGRES_JDBC_TYPE_FOR.put("point", Types.OTHER);
|
116
|
+
POSTGRES_JDBC_TYPE_FOR.put("tsrange", Types.OTHER);
|
117
|
+
POSTGRES_JDBC_TYPE_FOR.put("tstzrange", Types.OTHER);
|
118
|
+
POSTGRES_JDBC_TYPE_FOR.put("tsvector", Types.OTHER);
|
119
|
+
POSTGRES_JDBC_TYPE_FOR.put("uuid", Types.OTHER);
|
120
|
+
}
|
121
|
+
|
70
122
|
|
71
123
|
protected PostgreSQLRubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
|
72
124
|
super(runtime, metaClass);
|
@@ -128,6 +180,20 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
128
180
|
return value;
|
129
181
|
}
|
130
182
|
|
183
|
+
@Override
|
184
|
+
protected String internedTypeFor(final ThreadContext context, final IRubyObject attribute) throws SQLException {
|
185
|
+
|
186
|
+
final RubyModule postgreSQL = (RubyModule) getConnectionAdapters(context.runtime).getConstant("PostgreSQL");
|
187
|
+
final RubyModule oid = (RubyModule) postgreSQL.getConstant("OID");
|
188
|
+
final RubyClass arrayClass = oid.getClass("Array");
|
189
|
+
|
190
|
+
if ( arrayClass.isInstance(attributeType(context, attribute)) ) {
|
191
|
+
return "array";
|
192
|
+
}
|
193
|
+
|
194
|
+
return super.internedTypeFor(context, attribute);
|
195
|
+
}
|
196
|
+
|
131
197
|
@Override
|
132
198
|
protected Connection newConnection() throws SQLException {
|
133
199
|
final Connection connection = getConnectionFactory().newConnection();
|
@@ -147,43 +213,27 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
147
213
|
return connection;
|
148
214
|
}
|
149
215
|
|
150
|
-
@Override // due statement.setNull(index, Types.BLOB) not working :
|
151
|
-
// org.postgresql.util.PSQLException: ERROR: column "sample_binary" is of type bytea but expression is of type oid
|
152
|
-
protected void setBlobParameter(final ThreadContext context,
|
153
|
-
final Connection connection, final PreparedStatement statement,
|
154
|
-
final int index, final Object value,
|
155
|
-
final IRubyObject column, final int type) throws SQLException {
|
156
|
-
if ( value instanceof IRubyObject ) {
|
157
|
-
setBlobParameter(context, connection, statement, index, (IRubyObject) value, column, type);
|
158
|
-
}
|
159
|
-
else {
|
160
|
-
if ( value == null ) statement.setNull(index, Types.BINARY);
|
161
|
-
else {
|
162
|
-
statement.setBinaryStream(index, (InputStream) value);
|
163
|
-
}
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
216
|
@Override // due statement.setNull(index, Types.BLOB) not working :
|
168
217
|
// org.postgresql.util.PSQLException: ERROR: column "sample_binary" is of type bytea but expression is of type oid
|
169
218
|
protected void setBlobParameter(final ThreadContext context,
|
170
219
|
final Connection connection, final PreparedStatement statement,
|
171
220
|
final int index, final IRubyObject value,
|
172
|
-
final IRubyObject
|
221
|
+
final IRubyObject attribute, final int type) throws SQLException {
|
222
|
+
|
223
|
+
// TODO: Somewhere in the process of storing binary data, we lose about 50 bytes in one of the tests
|
224
|
+
|
173
225
|
if ( value.isNil() ) {
|
174
226
|
statement.setNull(index, Types.BINARY);
|
175
227
|
}
|
176
|
-
else {
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
);
|
186
|
-
}
|
228
|
+
else if ( value instanceof RubyIO ) { // IO/File
|
229
|
+
statement.setBinaryStream(index, ((RubyIO) value).getInStream());
|
230
|
+
}
|
231
|
+
else { // should be a RubyString
|
232
|
+
final ByteList blob = value.asString().getByteList();
|
233
|
+
statement.setBinaryStream(index,
|
234
|
+
new ByteArrayInputStream(blob.unsafeBytes(), blob.getBegin(), blob.getRealSize()),
|
235
|
+
blob.getRealSize() // length
|
236
|
+
);
|
187
237
|
}
|
188
238
|
}
|
189
239
|
|
@@ -211,250 +261,178 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
211
261
|
super.setTimestampParameter(context, connection, statement, index, value, column, type);
|
212
262
|
}
|
213
263
|
|
214
|
-
private static final ByteList INTERVAL =
|
215
|
-
new ByteList( new byte[] { 'i','n','t','e','r','v','a','l' }, false );
|
216
|
-
|
217
|
-
private static final ByteList ARRAY_END = new ByteList( new byte[] { '[',']' }, false );
|
218
|
-
|
219
264
|
@Override
|
220
|
-
protected void
|
265
|
+
protected void setObjectParameter(final ThreadContext context,
|
221
266
|
final Connection connection, final PreparedStatement statement,
|
222
|
-
final int index,
|
223
|
-
final IRubyObject
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
267
|
+
final int index, IRubyObject value,
|
268
|
+
final IRubyObject attribute, final int type) throws SQLException {
|
269
|
+
|
270
|
+
final String columnType = attributeSQLType(context, attribute).asJavaString();
|
271
|
+
|
272
|
+
switch ( columnType ) {
|
273
|
+
case "bit":
|
274
|
+
case "bit_varying":
|
275
|
+
setBitStringParameter(statement, index, value);
|
276
|
+
break;
|
277
|
+
|
278
|
+
case "cidr":
|
279
|
+
case "citext":
|
280
|
+
case "hstore":
|
281
|
+
case "inet":
|
282
|
+
case "ltree":
|
283
|
+
case "macaddr":
|
284
|
+
case "tsvector":
|
285
|
+
setPGobjectParameter(statement, index, value, columnType);
|
286
|
+
break;
|
287
|
+
|
288
|
+
case "interval":
|
289
|
+
statement.setObject(index, new PGInterval(value.toString()));
|
290
|
+
break;
|
291
|
+
|
292
|
+
case "json":
|
293
|
+
case "jsonb":
|
294
|
+
setJsonParameter(context, statement, index, value, columnType);
|
295
|
+
break;
|
296
|
+
|
297
|
+
case "line":
|
298
|
+
statement.setObject(index, new PGline(value.toString()));
|
299
|
+
break;
|
300
|
+
|
301
|
+
case "lseg":
|
302
|
+
statement.setObject(index, new PGlseg(value.toString()));
|
303
|
+
break;
|
304
|
+
|
305
|
+
case "point":
|
306
|
+
statement.setObject(index, new PGpoint(value.toString()));
|
307
|
+
break;
|
308
|
+
|
309
|
+
case "uuid":
|
310
|
+
setUUIDParameter(statement, index, value);
|
311
|
+
break;
|
312
|
+
|
313
|
+
default:
|
314
|
+
if ( columnType.endsWith("range") ) {
|
315
|
+
setRangeParameter(context, statement, index, value, columnType);
|
248
316
|
}
|
249
|
-
|
250
|
-
|
317
|
+
else {
|
318
|
+
super.setObjectParameter(context, connection, statement, index, value, attribute, type);
|
251
319
|
}
|
252
|
-
}
|
253
|
-
statement.setString( index, valueStr );
|
254
320
|
}
|
255
321
|
}
|
256
322
|
|
257
|
-
|
258
|
-
|
259
|
-
IRubyObject
|
260
|
-
if ( oid == null || oid.isNil() ) { // only for user instantiated Column
|
261
|
-
throw new IllegalStateException("missing @oid for column: " + column.inspect());
|
262
|
-
}
|
263
|
-
return RubyFixnum.fix2int(oid);
|
264
|
-
}
|
265
|
-
|
266
|
-
@Override
|
267
|
-
protected void setObjectParameter(final ThreadContext context,
|
268
|
-
final Connection connection, final PreparedStatement statement,
|
269
|
-
final int index, Object value,
|
270
|
-
final IRubyObject column, final int type) throws SQLException {
|
271
|
-
|
272
|
-
final String columnType = column.callMethod(context, "type").asJavaString();
|
273
|
-
|
274
|
-
if ( columnType == (Object) "uuid" ) {
|
275
|
-
setUUIDParameter(statement, index, value);
|
276
|
-
return;
|
277
|
-
}
|
278
|
-
|
279
|
-
if ( columnType == (Object) "json" ) {
|
280
|
-
setJsonParameter(context, statement, index, value, column);
|
281
|
-
return;
|
282
|
-
}
|
283
|
-
|
284
|
-
if ( columnType == (Object) "tsvector" ) {
|
285
|
-
setTsVectorParameter(statement, index, value);
|
286
|
-
return;
|
287
|
-
}
|
288
|
-
|
289
|
-
if ( columnType == (Object) "cidr" || columnType == (Object) "inet"
|
290
|
-
|| columnType == (Object) "macaddr" ) {
|
291
|
-
setAddressParameter(context, statement, index, value, column, columnType);
|
292
|
-
return;
|
293
|
-
}
|
294
|
-
|
295
|
-
if ( columnType != null && columnType.endsWith("range") ) {
|
296
|
-
setRangeParameter(context, statement, index, value, column, columnType);
|
297
|
-
return;
|
298
|
-
}
|
323
|
+
// value should be a ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bit::Data
|
324
|
+
private void setBitStringParameter(final PreparedStatement statement, final int index,
|
325
|
+
final IRubyObject value) throws SQLException {
|
299
326
|
|
300
|
-
|
301
|
-
|
327
|
+
String valueForDB = value.toString();
|
328
|
+
int length = valueForDB.length();
|
302
329
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
330
|
+
/*
|
331
|
+
This means that if somebody sets their binary string to be "111" it
|
332
|
+
will always be assumed to be in binary. This matches the AR (5.0) functionality.
|
333
|
+
If it is meant to be a hex string they should use "0x111".
|
334
|
+
*/
|
335
|
+
if (length > 0 && !binaryStringPattern.matcher(valueForDB).matches()) {
|
336
|
+
StringBuilder builder = new StringBuilder(length * 4);
|
337
|
+
for (int i = 0; i < length; i++) {
|
338
|
+
builder.append(binaryStrings[Character.digit(valueForDB.charAt(i), 16)]);
|
311
339
|
}
|
312
|
-
|
313
|
-
else if ( value == null ) {
|
314
|
-
statement.setNull(index, Types.OTHER); return;
|
340
|
+
valueForDB = builder.toString();
|
315
341
|
}
|
316
342
|
|
317
|
-
|
318
|
-
statement.setObject(index, uuid);
|
343
|
+
setPGobjectParameter(statement, index, valueForDB, "bit");
|
319
344
|
}
|
320
345
|
|
321
346
|
private void setJsonParameter(final ThreadContext context,
|
322
347
|
final PreparedStatement statement, final int index,
|
323
|
-
|
324
|
-
|
325
|
-
if ( value instanceof IRubyObject ) {
|
326
|
-
final IRubyObject rubyValue = (IRubyObject) value;
|
327
|
-
if ( rubyValue.isNil() ) {
|
328
|
-
statement.setNull(index, Types.OTHER); return;
|
329
|
-
}
|
330
|
-
if (!isAr42(column)) { // Value has already been cast for AR42
|
331
|
-
value = column.getMetaClass().callMethod(context, "json_to_string", rubyValue);
|
332
|
-
}
|
333
|
-
}
|
334
|
-
else if ( value == null ) {
|
335
|
-
statement.setNull(index, Types.OTHER); return;
|
336
|
-
}
|
348
|
+
final IRubyObject value, final String columnType) throws SQLException {
|
337
349
|
|
338
350
|
final PGobject pgJson = new PGobject();
|
339
|
-
pgJson.setType(
|
351
|
+
pgJson.setType(columnType);
|
340
352
|
pgJson.setValue(value.toString());
|
341
353
|
statement.setObject(index, pgJson);
|
342
354
|
}
|
343
355
|
|
344
|
-
private void
|
345
|
-
final
|
346
|
-
Object value) throws SQLException {
|
347
|
-
|
348
|
-
if ( value instanceof IRubyObject ) {
|
349
|
-
final IRubyObject rubyValue = (IRubyObject) value;
|
350
|
-
if ( rubyValue.isNil() ) {
|
351
|
-
statement.setNull(index, Types.OTHER); return;
|
352
|
-
}
|
353
|
-
}
|
354
|
-
else if ( value == null ) {
|
355
|
-
statement.setNull(index, Types.OTHER); return;
|
356
|
-
}
|
357
|
-
|
358
|
-
final PGobject pgTsVector = new PGobject();
|
359
|
-
pgTsVector.setType("tsvector");
|
360
|
-
pgTsVector.setValue(value.toString());
|
361
|
-
statement.setObject(index, pgTsVector);
|
362
|
-
}
|
363
|
-
|
364
|
-
private void setAddressParameter(final ThreadContext context,
|
365
|
-
final PreparedStatement statement, final int index,
|
366
|
-
Object value, final IRubyObject column,
|
367
|
-
final String columnType) throws SQLException {
|
368
|
-
|
369
|
-
if ( value instanceof IRubyObject ) {
|
370
|
-
final IRubyObject rubyValue = (IRubyObject) value;
|
371
|
-
if ( rubyValue.isNil() ) {
|
372
|
-
statement.setNull(index, Types.OTHER); return;
|
373
|
-
}
|
374
|
-
if (!isAr42(column)) { // Value has already been cast for AR42
|
375
|
-
value = column.getMetaClass().callMethod(context, "cidr_to_string", rubyValue);
|
376
|
-
}
|
377
|
-
}
|
378
|
-
else if ( value == null ) {
|
379
|
-
statement.setNull(index, Types.OTHER); return;
|
380
|
-
}
|
356
|
+
private void setPGobjectParameter(final PreparedStatement statement, final int index,
|
357
|
+
final Object value, final String columnType) throws SQLException {
|
381
358
|
|
382
|
-
final PGobject
|
383
|
-
|
384
|
-
|
385
|
-
statement.setObject(index,
|
359
|
+
final PGobject param = new PGobject();
|
360
|
+
param.setType(columnType);
|
361
|
+
param.setValue(value.toString());
|
362
|
+
statement.setObject(index, param);
|
386
363
|
}
|
387
364
|
|
388
365
|
private void setRangeParameter(final ThreadContext context,
|
389
366
|
final PreparedStatement statement, final int index,
|
390
|
-
final
|
391
|
-
final String columnType) throws SQLException {
|
367
|
+
final IRubyObject value, final String columnType) throws SQLException {
|
392
368
|
|
393
|
-
final String rangeValue;
|
369
|
+
final String rangeValue = value.toString();
|
370
|
+
final Object pgRange;
|
394
371
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
372
|
+
switch ( columnType ) {
|
373
|
+
case "daterange":
|
374
|
+
pgRange = new DateRangeType(rangeValue);
|
375
|
+
break;
|
376
|
+
case "tsrange":
|
377
|
+
pgRange = new TsRangeType(rangeValue);
|
378
|
+
break;
|
379
|
+
case "tstzrange":
|
380
|
+
pgRange = new TstzRangeType(rangeValue);
|
381
|
+
break;
|
382
|
+
case "int4range":
|
383
|
+
pgRange = new Int4RangeType(rangeValue);
|
384
|
+
break;
|
385
|
+
case "int8range":
|
386
|
+
pgRange = new Int8RangeType(rangeValue);
|
387
|
+
break;
|
388
|
+
default:
|
389
|
+
pgRange = new NumRangeType(rangeValue);
|
407
390
|
}
|
408
391
|
|
409
|
-
final Object pgRange;
|
410
|
-
if ( columnType == (Object) "daterange" ) {
|
411
|
-
pgRange = new DateRangeType(rangeValue);
|
412
|
-
}
|
413
|
-
else if ( columnType == (Object) "tsrange" ) {
|
414
|
-
pgRange = new TsRangeType(rangeValue);
|
415
|
-
}
|
416
|
-
else if ( columnType == (Object) "tstzrange" ) {
|
417
|
-
pgRange = new TstzRangeType(rangeValue);
|
418
|
-
}
|
419
|
-
else if ( columnType == (Object) "int4range" ) {
|
420
|
-
pgRange = new Int4RangeType(rangeValue);
|
421
|
-
}
|
422
|
-
else if ( columnType == (Object) "int8range" ) {
|
423
|
-
pgRange = new Int8RangeType(rangeValue);
|
424
|
-
}
|
425
|
-
else { // if ( columnType == (Object) "numrange" )
|
426
|
-
pgRange = new NumRangeType(rangeValue);
|
427
|
-
}
|
428
392
|
statement.setObject(index, pgRange);
|
429
393
|
}
|
430
394
|
|
431
395
|
@Override
|
432
|
-
protected
|
433
|
-
final
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
if (
|
438
|
-
|
396
|
+
protected void setStringParameter(final ThreadContext context,
|
397
|
+
final Connection connection, final PreparedStatement statement,
|
398
|
+
final int index, final IRubyObject value,
|
399
|
+
final IRubyObject attribute, final int type) throws SQLException {
|
400
|
+
|
401
|
+
if ( attributeSQLType(context, attribute).isNil() ) {
|
402
|
+
/*
|
403
|
+
We have to check for a uuid here because in some cases
|
404
|
+
(for example, when doing "exists?" checks, or with legacy binds)
|
405
|
+
ActiveRecord doesn't send us the actual type of the attribute
|
406
|
+
and Postgres won't compare a uuid column with a string
|
407
|
+
*/
|
408
|
+
final String uuid = value.toString();
|
409
|
+
|
410
|
+
// Checking the length so we don't have the overhead of the regex unless it "looks" like a UUID
|
411
|
+
if ( uuid.length() == 36 && uuidPattern.matcher(uuid).matches() ) {
|
412
|
+
setUUIDParameter(statement, index, value);
|
413
|
+
return;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
super.setStringParameter(context, connection, statement, index, value, attribute, type);
|
439
418
|
}
|
440
419
|
|
441
|
-
private
|
420
|
+
private void setUUIDParameter(final PreparedStatement statement,
|
421
|
+
final int index, final IRubyObject value) throws SQLException {
|
422
|
+
|
423
|
+
statement.setObject(index, UUID.fromString(value.toString()));
|
424
|
+
}
|
442
425
|
|
443
426
|
@Override
|
444
|
-
protected
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
if (
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
if ( "hstore" == (Object) columnType.asJavaString() ) {
|
454
|
-
return HSTORE_TYPE;
|
455
|
-
}
|
456
|
-
} */
|
457
|
-
return type;
|
427
|
+
protected Integer jdbcTypeFor(final String type) {
|
428
|
+
|
429
|
+
Integer typeValue = POSTGRES_JDBC_TYPE_FOR.get(type);
|
430
|
+
|
431
|
+
if ( typeValue != null ) {
|
432
|
+
return typeValue;
|
433
|
+
}
|
434
|
+
|
435
|
+
return super.jdbcTypeFor(type);
|
458
436
|
}
|
459
437
|
|
460
438
|
/**
|
@@ -498,12 +476,8 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
498
476
|
if ( rawDateTime != null && rawDateTime.booleanValue() ) return strValue;
|
499
477
|
|
500
478
|
final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
|
501
|
-
if ( usesType(runtime) ) {
|
502
|
-
return typeCastFromDatabase(context, adapter, runtime.newSymbol("timestamp"), strValue);
|
503
|
-
}
|
504
479
|
|
505
|
-
|
506
|
-
return adapter.callMethod(context, "_string_to_timestamp", strValue);
|
480
|
+
return typeCastFromDatabase(context, adapter, runtime.newSymbol("timestamp"), strValue);
|
507
481
|
}
|
508
482
|
|
509
483
|
@Override
|
@@ -30,7 +30,6 @@ import org.jruby.RubyString;
|
|
30
30
|
import org.jruby.anno.JRubyMethod;
|
31
31
|
import org.jruby.runtime.ThreadContext;
|
32
32
|
import org.jruby.runtime.builtin.IRubyObject;
|
33
|
-
import org.jruby.util.ByteList;
|
34
33
|
|
35
34
|
/**
|
36
35
|
* ArJdbc::SQLite3
|
@@ -56,23 +55,4 @@ public class SQLite3Module {
|
|
56
55
|
);
|
57
56
|
return quoted;
|
58
57
|
}
|
59
|
-
|
60
|
-
private static final ByteList Q_TRUE = new ByteList(new byte[] { '\'', 't', '\'' }, false);
|
61
|
-
|
62
|
-
@JRubyMethod(name = "quoted_true", required = 0, frame = false)
|
63
|
-
public static IRubyObject quoted_true(
|
64
|
-
final ThreadContext context,
|
65
|
-
final IRubyObject self) {
|
66
|
-
return RubyString.newString(context.getRuntime(), Q_TRUE);
|
67
|
-
}
|
68
|
-
|
69
|
-
private static final ByteList Q_FALSE = new ByteList(new byte[] { '\'', 'f', '\'' }, false);
|
70
|
-
|
71
|
-
@JRubyMethod(name = "quoted_false", required = 0, frame = false)
|
72
|
-
public static IRubyObject quoted_false(
|
73
|
-
final ThreadContext context,
|
74
|
-
final IRubyObject self) {
|
75
|
-
return RubyString.newString(context.getRuntime(), Q_FALSE);
|
76
|
-
}
|
77
|
-
|
78
58
|
}
|