activerecord-jdbc-adapter 5.0.pre1 → 51.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|