activerecord-jdbc-adapter 1.3.0.rc1 → 1.3.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.
- data/CONTRIBUTING.md +3 -5
- data/Gemfile +3 -5
- data/Gemfile.lock +1 -1
- data/History.md +30 -3
- data/README.md +14 -9
- data/gemfiles/rails23.gemfile +3 -0
- data/gemfiles/rails23.gemfile.lock +8 -0
- data/gemfiles/rails30.gemfile +3 -0
- data/gemfiles/rails30.gemfile.lock +11 -0
- data/gemfiles/rails31.gemfile +3 -0
- data/gemfiles/rails31.gemfile.lock +8 -0
- data/gemfiles/rails32.gemfile +3 -0
- data/gemfiles/rails32.gemfile.lock +11 -0
- data/gemfiles/rails40.gemfile +3 -0
- data/gemfiles/rails40.gemfile.lock +6 -0
- data/lib/arjdbc/db2/adapter.rb +39 -23
- data/lib/arjdbc/db2/column.rb +3 -3
- data/lib/arjdbc/derby/adapter.rb +45 -0
- data/lib/arjdbc/firebird/adapter.rb +38 -36
- data/lib/arjdbc/h2/adapter.rb +1 -1
- data/lib/arjdbc/hsqldb/adapter.rb +1 -0
- data/lib/arjdbc/hsqldb/explain_support.rb +6 -6
- data/lib/arjdbc/jdbc/adapter.rb +80 -39
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -21
- data/lib/arjdbc/mssql/adapter.rb +41 -18
- data/lib/arjdbc/mssql/column.rb +3 -8
- data/lib/arjdbc/mssql/explain_support.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +19 -9
- data/lib/arjdbc/mysql/column.rb +1 -1
- data/lib/arjdbc/mysql/connection_methods.rb +1 -0
- data/lib/arjdbc/mysql/explain_support.rb +2 -1
- data/lib/arjdbc/oracle/adapter.rb +42 -26
- data/lib/arjdbc/oracle/column.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +13 -4
- data/lib/arjdbc/sqlite3/adapter.rb +2 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +5 -5
- data/lib/arjdbc/util/serialized_attributes.rb +87 -0
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/02-test.rake +1 -1
- data/rakelib/db.rake +1 -1
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +2 -2
- data/src/java/arjdbc/derby/DerbyModule.java +26 -173
- data/src/java/arjdbc/h2/H2Module.java +1 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +1 -2
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +10 -9
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -3
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +4 -3
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +189 -70
- data/src/java/arjdbc/jdbc/SQLBlock.java +4 -4
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +6 -7
- data/src/java/arjdbc/mysql/MySQLModule.java +1 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +14 -9
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +19 -3
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +305 -11
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +3 -3
- metadata +6 -5
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/***** BEGIN LICENSE BLOCK *****
|
2
|
+
* Copyright (c) 2012-2013 Karol Bucek <self@kares.org>
|
3
3
|
* Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
|
4
4
|
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
5
5
|
* Copyright (c) 2008-2009 Thomas E Enebo <enebo@acm.org>
|
@@ -41,5 +41,5 @@ public class AdapterJavaService implements BasicLibraryService {
|
|
41
41
|
ArJdbcModule.load(runtime);
|
42
42
|
return true;
|
43
43
|
}
|
44
|
-
|
44
|
+
|
45
45
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
/***** BEGIN LICENSE BLOCK *****
|
2
|
+
* Copyright (c) 2012-2013 Karol Bucek <self@kares.org>
|
2
3
|
* Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
|
3
4
|
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
4
5
|
*
|
@@ -33,12 +34,12 @@ import java.sql.SQLException;
|
|
33
34
|
* @author nicksieger
|
34
35
|
*/
|
35
36
|
public interface JdbcConnectionFactory {
|
36
|
-
|
37
|
+
|
37
38
|
/**
|
38
39
|
* Retrieve a (new) connection from the factory.
|
39
40
|
* @return a connection
|
40
|
-
* @throws SQLException
|
41
|
+
* @throws SQLException
|
41
42
|
*/
|
42
43
|
Connection newConnection() throws SQLException;
|
43
|
-
|
44
|
+
|
44
45
|
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/***** BEGIN LICENSE BLOCK *****
|
2
|
+
* Copyright (c) 2012-2013 Karol Bucek <self@kares.org>
|
3
3
|
* Copyright (c) 2006-2011 Nick Sieger <nick@nicksieger.com>
|
4
4
|
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
5
5
|
* Copyright (c) 2008-2009 Thomas E Enebo <enebo@acm.org>
|
@@ -453,9 +453,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
453
453
|
}
|
454
454
|
}
|
455
455
|
else {
|
456
|
-
|
457
|
-
|
458
|
-
" make sure you pass it on initialize(config, adapter)"));
|
456
|
+
warn(context, "WARN: adapter not set for: " + inspect() +
|
457
|
+
" make sure you pass it on initialize(config, adapter)");
|
459
458
|
}
|
460
459
|
return jdbcConnection;
|
461
460
|
}
|
@@ -542,7 +541,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
542
541
|
try {
|
543
542
|
statement = createStatement(context, connection);
|
544
543
|
if ( doExecute(statement, query) ) {
|
545
|
-
return mapResults(context, connection
|
544
|
+
return mapResults(context, connection, statement, false);
|
546
545
|
} else {
|
547
546
|
return mapGeneratedKeysOrUpdateCount(context, connection, statement);
|
548
547
|
}
|
@@ -791,7 +790,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
791
790
|
return withConnection(context, new Callable<IRubyObject>() {
|
792
791
|
public IRubyObject call(final Connection connection) throws SQLException {
|
793
792
|
final Ruby runtime = context.getRuntime();
|
794
|
-
final DatabaseMetaData metaData = connection.getMetaData();
|
795
793
|
|
796
794
|
Statement statement = null; ResultSet resultSet = null;
|
797
795
|
try {
|
@@ -811,10 +809,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
811
809
|
if ( block != null && block.isGiven() ) {
|
812
810
|
// yield(id1, name1) ... row 1 result data
|
813
811
|
// yield(id2, name2) ... row 2 result data
|
814
|
-
return yieldResultRows(context, runtime,
|
812
|
+
return yieldResultRows(context, runtime, connection, resultSet, block);
|
815
813
|
}
|
816
814
|
|
817
|
-
return mapToRawResult(context, runtime,
|
815
|
+
return mapToRawResult(context, runtime, connection, resultSet, false);
|
818
816
|
}
|
819
817
|
catch (final SQLException e) {
|
820
818
|
debugErrorSQL(context, query);
|
@@ -938,9 +936,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
938
936
|
private IRubyObject mapQueryResult(final ThreadContext context,
|
939
937
|
final Connection connection, final ResultSet resultSet) throws SQLException {
|
940
938
|
final Ruby runtime = context.getRuntime();
|
941
|
-
final
|
942
|
-
|
943
|
-
return mapToResult(context, runtime, metaData, resultSet, columns);
|
939
|
+
final ColumnData[] columns = extractColumns(runtime, connection, resultSet, false);
|
940
|
+
return mapToResult(context, runtime, connection, resultSet, columns);
|
944
941
|
}
|
945
942
|
|
946
943
|
/**
|
@@ -976,10 +973,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
976
973
|
@JRubyMethod(name = "supported_data_types")
|
977
974
|
public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
|
978
975
|
final Ruby runtime = context.getRuntime();
|
979
|
-
final
|
980
|
-
final
|
976
|
+
final Connection connection = getConnection(true);
|
977
|
+
final ResultSet typeDesc = connection.getMetaData().getTypeInfo();
|
978
|
+
final IRubyObject types;
|
981
979
|
try {
|
982
|
-
types = mapToRawResult(context, runtime,
|
980
|
+
types = mapToRawResult(context, runtime, connection, typeDesc, true);
|
983
981
|
}
|
984
982
|
finally { close(typeDesc); }
|
985
983
|
|
@@ -999,8 +997,8 @@ public class RubyJdbcConnection extends RubyObject {
|
|
999
997
|
return withConnection(context, new Callable<List<RubyString>>() {
|
1000
998
|
public List<RubyString> call(final Connection connection) throws SQLException {
|
1001
999
|
final Ruby runtime = context.getRuntime();
|
1000
|
+
final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1002
1001
|
final DatabaseMetaData metaData = connection.getMetaData();
|
1003
|
-
final String _tableName = caseConvertIdentifierForJdbc(metaData, tableName);
|
1004
1002
|
ResultSet resultSet = null;
|
1005
1003
|
final List<RubyString> keyNames = new ArrayList<RubyString>();
|
1006
1004
|
try {
|
@@ -1009,7 +1007,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1009
1007
|
|
1010
1008
|
while (resultSet.next()) {
|
1011
1009
|
String columnName = resultSet.getString(PRIMARY_KEYS_COLUMN_NAME);
|
1012
|
-
columnName = caseConvertIdentifierForRails(
|
1010
|
+
columnName = caseConvertIdentifierForRails(connection, columnName);
|
1013
1011
|
keyNames.add( RubyString.newUnicodeString(runtime, columnName) );
|
1014
1012
|
}
|
1015
1013
|
}
|
@@ -1156,9 +1154,9 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1156
1154
|
final Ruby runtime = context.getRuntime();
|
1157
1155
|
final RubyClass indexDefinition = getIndexDefinition(runtime);
|
1158
1156
|
|
1157
|
+
String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
|
1158
|
+
String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
1159
1159
|
final DatabaseMetaData metaData = connection.getMetaData();
|
1160
|
-
String _tableName = caseConvertIdentifierForJdbc(metaData, tableName);
|
1161
|
-
String _schemaName = caseConvertIdentifierForJdbc(metaData, schemaName);
|
1162
1160
|
|
1163
1161
|
final List<RubyString> primaryKeys = primaryKeys(context, _tableName);
|
1164
1162
|
ResultSet indexInfoSet = null;
|
@@ -1296,12 +1294,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1296
1294
|
column.callMethod(context, "type").toString() == (Object) "binary";
|
1297
1295
|
|
1298
1296
|
final RubyClass recordClass = record.getMetaClass(); // record.class
|
1299
|
-
final IRubyObject
|
1297
|
+
final IRubyObject adapter = recordClass.callMethod(context, "connection");
|
1300
1298
|
|
1301
1299
|
IRubyObject columnName = column.callMethod(context, "name");
|
1302
|
-
columnName =
|
1300
|
+
columnName = adapter.callMethod(context, "quote_column_name", columnName);
|
1303
1301
|
IRubyObject tableName = recordClass.callMethod(context, "table_name");
|
1304
|
-
tableName =
|
1302
|
+
tableName = adapter.callMethod(context, "quote_table_name", tableName);
|
1305
1303
|
final IRubyObject idKey = recordClass.callMethod(context, "primary_key"); // 'id'
|
1306
1304
|
// callMethod(context, "quote", primaryKey);
|
1307
1305
|
final IRubyObject idColumn = // record.class.columns_hash['id']
|
@@ -1342,6 +1340,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1342
1340
|
});
|
1343
1341
|
}
|
1344
1342
|
|
1343
|
+
protected String caseConvertIdentifierForRails(final Connection connection, final String value)
|
1344
|
+
throws SQLException {
|
1345
|
+
if ( value == null ) return null;
|
1346
|
+
return caseConvertIdentifierForRails(connection.getMetaData(), value);
|
1347
|
+
}
|
1348
|
+
|
1345
1349
|
/**
|
1346
1350
|
* Convert an identifier coming back from the database to a case which Rails is expecting.
|
1347
1351
|
*
|
@@ -1356,16 +1360,21 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1356
1360
|
protected static String caseConvertIdentifierForRails(final DatabaseMetaData metaData, final String value)
|
1357
1361
|
throws SQLException {
|
1358
1362
|
if ( value == null ) return null;
|
1359
|
-
|
1360
1363
|
return metaData.storesUpperCaseIdentifiers() ? value.toLowerCase() : value;
|
1361
1364
|
}
|
1362
1365
|
|
1366
|
+
protected String caseConvertIdentifierForJdbc(final Connection connection, final String value)
|
1367
|
+
throws SQLException {
|
1368
|
+
if ( value == null ) return null;
|
1369
|
+
return caseConvertIdentifierForJdbc(connection.getMetaData(), value);
|
1370
|
+
}
|
1371
|
+
|
1363
1372
|
/**
|
1364
1373
|
* Convert an identifier destined for a method which cares about the databases internal
|
1365
1374
|
* storage case. Methods like DatabaseMetaData.getPrimaryKeys() needs the table name to match
|
1366
|
-
* the internal storage name.
|
1375
|
+
* the internal storage name. Arbitrary queries and the like DO NOT need to do this.
|
1367
1376
|
*/
|
1368
|
-
protected String caseConvertIdentifierForJdbc(final DatabaseMetaData metaData, final String value)
|
1377
|
+
protected static String caseConvertIdentifierForJdbc(final DatabaseMetaData metaData, final String value)
|
1369
1378
|
throws SQLException {
|
1370
1379
|
if ( value == null ) return null;
|
1371
1380
|
|
@@ -1375,7 +1384,6 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1375
1384
|
else if ( metaData.storesLowerCaseIdentifiers() ) {
|
1376
1385
|
return value.toLowerCase();
|
1377
1386
|
}
|
1378
|
-
|
1379
1387
|
return value;
|
1380
1388
|
}
|
1381
1389
|
|
@@ -1465,7 +1473,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1465
1473
|
* @throws SQLException
|
1466
1474
|
*/
|
1467
1475
|
protected IRubyObject mapToResult(final ThreadContext context, final Ruby runtime,
|
1468
|
-
final
|
1476
|
+
final Connection connection, final ResultSet resultSet,
|
1469
1477
|
final ColumnData[] columns) throws SQLException {
|
1470
1478
|
|
1471
1479
|
final ResultHandler resultHandler = ResultHandler.getInstance(runtime);
|
@@ -1635,20 +1643,29 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1635
1643
|
return runtime.getKernel().callMethod("BigDecimal", runtime.newString(value));
|
1636
1644
|
}
|
1637
1645
|
|
1638
|
-
protected static
|
1646
|
+
protected static Boolean rawDateTime;
|
1647
|
+
static {
|
1648
|
+
final String dateTimeRaw = System.getProperty("arjdbc.datetime.raw");
|
1649
|
+
if ( dateTimeRaw != null ) {
|
1650
|
+
rawDateTime = Boolean.parseBoolean(dateTimeRaw);
|
1651
|
+
}
|
1652
|
+
// NOTE: we do this since it will have a different value depending on
|
1653
|
+
// AR version - since 4.0 false by default otherwise will be true ...
|
1654
|
+
}
|
1639
1655
|
|
1640
|
-
@JRubyMethod(name = "raw_date_time?")
|
1656
|
+
@JRubyMethod(name = "raw_date_time?", meta = true)
|
1641
1657
|
public static IRubyObject useRawDateTime(final ThreadContext context, final IRubyObject self) {
|
1642
|
-
return context.getRuntime().
|
1658
|
+
if ( rawDateTime == null ) return context.getRuntime().getNil();
|
1659
|
+
return context.getRuntime().newBoolean( rawDateTime.booleanValue() );
|
1643
1660
|
}
|
1644
1661
|
|
1645
|
-
@JRubyMethod(name = "raw_date_time=")
|
1662
|
+
@JRubyMethod(name = "raw_date_time=", meta = true)
|
1646
1663
|
public static IRubyObject setRawDateTime(final IRubyObject self, final IRubyObject value) {
|
1647
1664
|
if ( value instanceof RubyBoolean ) {
|
1648
1665
|
rawDateTime = ((RubyBoolean) value).isTrue();
|
1649
1666
|
}
|
1650
1667
|
else {
|
1651
|
-
rawDateTime = value.isNil();
|
1668
|
+
rawDateTime = value.isNil() ? null : Boolean.TRUE;
|
1652
1669
|
}
|
1653
1670
|
return value;
|
1654
1671
|
}
|
@@ -1664,7 +1681,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1664
1681
|
}
|
1665
1682
|
|
1666
1683
|
final RubyString strValue = RubyString.newUnicodeString(runtime, value.toString());
|
1667
|
-
if ( rawDateTime ) return strValue;
|
1684
|
+
if ( rawDateTime != null && rawDateTime.booleanValue() ) return strValue;
|
1668
1685
|
|
1669
1686
|
final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
|
1670
1687
|
if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
|
@@ -1682,7 +1699,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1682
1699
|
}
|
1683
1700
|
|
1684
1701
|
final RubyString strValue = RubyString.newUnicodeString(runtime, value.toString());
|
1685
|
-
if ( rawDateTime ) return strValue;
|
1702
|
+
if ( rawDateTime != null && rawDateTime.booleanValue() ) return strValue;
|
1686
1703
|
|
1687
1704
|
final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
|
1688
1705
|
if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
|
@@ -1700,7 +1717,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1700
1717
|
}
|
1701
1718
|
|
1702
1719
|
final RubyString strValue = timestampToRubyString(runtime, value.toString());
|
1703
|
-
if ( rawDateTime ) return strValue;
|
1720
|
+
if ( rawDateTime != null && rawDateTime.booleanValue() ) return strValue;
|
1704
1721
|
|
1705
1722
|
final IRubyObject adapter = callMethod(context, "adapter"); // self.adapter
|
1706
1723
|
if ( adapter.isNil() ) return strValue; // NOTE: we warn on init_connection
|
@@ -1728,9 +1745,39 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1728
1745
|
return timestampToRubyString(runtime, value.toString());
|
1729
1746
|
}
|
1730
1747
|
|
1748
|
+
protected static Boolean rawBoolean;
|
1749
|
+
static {
|
1750
|
+
final String booleanRaw = System.getProperty("arjdbc.boolean.raw");
|
1751
|
+
if ( booleanRaw != null ) {
|
1752
|
+
rawBoolean = Boolean.parseBoolean(booleanRaw);
|
1753
|
+
}
|
1754
|
+
}
|
1755
|
+
|
1756
|
+
@JRubyMethod(name = "raw_boolean?", meta = true)
|
1757
|
+
public static IRubyObject useRawBoolean(final ThreadContext context, final IRubyObject self) {
|
1758
|
+
if ( rawBoolean == null ) return context.getRuntime().getNil();
|
1759
|
+
return context.getRuntime().newBoolean( rawBoolean.booleanValue() );
|
1760
|
+
}
|
1761
|
+
|
1762
|
+
@JRubyMethod(name = "raw_boolean=", meta = true)
|
1763
|
+
public static IRubyObject setRawBoolean(final IRubyObject self, final IRubyObject value) {
|
1764
|
+
if ( value instanceof RubyBoolean ) {
|
1765
|
+
rawBoolean = ((RubyBoolean) value).isTrue();
|
1766
|
+
}
|
1767
|
+
else {
|
1768
|
+
rawBoolean = value.isNil() ? null : Boolean.TRUE;
|
1769
|
+
}
|
1770
|
+
return value;
|
1771
|
+
}
|
1772
|
+
|
1731
1773
|
protected IRubyObject booleanToRuby(final ThreadContext context,
|
1732
1774
|
final Ruby runtime, final ResultSet resultSet, final int column)
|
1733
1775
|
throws SQLException {
|
1776
|
+
if ( rawBoolean != null && rawBoolean.booleanValue() ) {
|
1777
|
+
final String value = resultSet.getString(column);
|
1778
|
+
if ( resultSet.wasNull() ) return runtime.getNil();
|
1779
|
+
return RubyString.newUnicodeString(runtime, value);
|
1780
|
+
}
|
1734
1781
|
final boolean value = resultSet.getBoolean(column);
|
1735
1782
|
if ( resultSet.wasNull() ) return runtime.getNil();
|
1736
1783
|
return booleanToRuby(runtime, resultSet, value);
|
@@ -1863,15 +1910,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1863
1910
|
column = (IRubyObject) _param[0]; param = _param[1];
|
1864
1911
|
}
|
1865
1912
|
|
1866
|
-
|
1867
|
-
if ( column != null && ! column.isNil() ) {
|
1868
|
-
type = column.callMethod(context, "type");
|
1869
|
-
}
|
1870
|
-
else {
|
1871
|
-
type = null;
|
1872
|
-
}
|
1873
|
-
|
1874
|
-
setStatementParameter(context, runtime, connection, statement, i + 1, param, type);
|
1913
|
+
setStatementParameter(context, runtime, connection, statement, i + 1, param, column);
|
1875
1914
|
}
|
1876
1915
|
}
|
1877
1916
|
|
@@ -1987,8 +2026,16 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1987
2026
|
|
1988
2027
|
final String internedType;
|
1989
2028
|
if ( column != null && ! column.isNil() ) {
|
1990
|
-
|
1991
|
-
|
2029
|
+
// NOTE: there's no ActiveRecord "convention" really for this ...
|
2030
|
+
// this is based on Postgre's initial support for arrays :
|
2031
|
+
// `column.type` contains the base type while there's `column.array?`
|
2032
|
+
if ( column.respondsTo("array?") && column.callMethod(context, "array?").isTrue() ) {
|
2033
|
+
internedType = "array";
|
2034
|
+
}
|
2035
|
+
else {
|
2036
|
+
final RubySymbol columnType = resolveColumnType(context, runtime, column);
|
2037
|
+
internedType = columnType.asJavaString();
|
2038
|
+
}
|
1992
2039
|
}
|
1993
2040
|
else {
|
1994
2041
|
if ( value instanceof RubyInteger ) {
|
@@ -2452,7 +2499,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2452
2499
|
}
|
2453
2500
|
}
|
2454
2501
|
|
2455
|
-
|
2502
|
+
protected void setArrayParameter(final ThreadContext context,
|
2456
2503
|
final Connection connection, final PreparedStatement statement,
|
2457
2504
|
final int index, final Object value,
|
2458
2505
|
final IRubyObject column, final int type) throws SQLException {
|
@@ -2462,25 +2509,34 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2462
2509
|
else {
|
2463
2510
|
if ( value == null ) statement.setNull(index, Types.ARRAY);
|
2464
2511
|
else {
|
2465
|
-
|
2466
|
-
Array array = connection.createArrayOf(
|
2512
|
+
String typeName = resolveArrayBaseTypeName(context, value, column, type);
|
2513
|
+
Array array = connection.createArrayOf(typeName, (Object[]) value);
|
2467
2514
|
statement.setArray(index, array);
|
2468
2515
|
}
|
2469
2516
|
}
|
2470
2517
|
}
|
2471
2518
|
|
2472
|
-
|
2519
|
+
protected void setArrayParameter(final ThreadContext context,
|
2473
2520
|
final Connection connection, final PreparedStatement statement,
|
2474
2521
|
final int index, final IRubyObject value,
|
2475
2522
|
final IRubyObject column, final int type) throws SQLException {
|
2476
2523
|
if ( value.isNil() ) statement.setNull(index, Types.ARRAY);
|
2477
2524
|
else {
|
2478
|
-
|
2479
|
-
Array array = connection.createArrayOf(
|
2525
|
+
String typeName = resolveArrayBaseTypeName(context, value, column, type);
|
2526
|
+
Array array = connection.createArrayOf(typeName, ((RubyArray) value).toArray());
|
2480
2527
|
statement.setArray(index, array);
|
2481
2528
|
}
|
2482
2529
|
}
|
2483
2530
|
|
2531
|
+
protected String resolveArrayBaseTypeName(final ThreadContext context,
|
2532
|
+
final Object value, final IRubyObject column, final int type) {
|
2533
|
+
// return column.callMethod(context, "sql_type").toString();
|
2534
|
+
String sqlType = column.callMethod(context, "sql_type").toString();
|
2535
|
+
final int index = sqlType.indexOf('('); // e.g. "character varying(255)"
|
2536
|
+
if ( index > 0 ) sqlType = sqlType.substring(0, index);
|
2537
|
+
return sqlType;
|
2538
|
+
}
|
2539
|
+
|
2484
2540
|
protected void setXmlParameter(final ThreadContext context,
|
2485
2541
|
final Connection connection, final PreparedStatement statement,
|
2486
2542
|
final int index, final Object value,
|
@@ -2637,6 +2693,14 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2637
2693
|
debugMessage(context, "connection considered broken due: " + e.toString());
|
2638
2694
|
return false;
|
2639
2695
|
}
|
2696
|
+
catch (AbstractMethodError e) { // non-JDBC 4.0 driver
|
2697
|
+
warn( context,
|
2698
|
+
"WARN: driver does not support checking if connection isValid()" +
|
2699
|
+
" please make sure you're using a JDBC 4.0 compilant driver or" +
|
2700
|
+
" set `connection_alive_sql: ...` in your database configuration" );
|
2701
|
+
debugStackTrace(context, e);
|
2702
|
+
throw e;
|
2703
|
+
}
|
2640
2704
|
finally { close(statement); }
|
2641
2705
|
}
|
2642
2706
|
|
@@ -2671,11 +2735,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2671
2735
|
final String tablePattern, final String[] types,
|
2672
2736
|
final boolean checkExistsOnly) throws SQLException {
|
2673
2737
|
|
2738
|
+
final String _tablePattern = caseConvertIdentifierForJdbc(connection, tablePattern);
|
2739
|
+
final String _schemaPattern = caseConvertIdentifierForJdbc(connection, schemaPattern);
|
2674
2740
|
final DatabaseMetaData metaData = connection.getMetaData();
|
2675
2741
|
|
2676
|
-
final String _tablePattern = caseConvertIdentifierForJdbc(metaData, tablePattern);
|
2677
|
-
final String _schemaPattern = caseConvertIdentifierForJdbc(metaData, schemaPattern);
|
2678
|
-
|
2679
2742
|
ResultSet tablesSet = null;
|
2680
2743
|
try {
|
2681
2744
|
tablesSet = metaData.getTables(catalog, _schemaPattern, _tablePattern, types);
|
@@ -2705,13 +2768,16 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2705
2768
|
* @return List<RubyString>
|
2706
2769
|
* @throws SQLException
|
2707
2770
|
*/
|
2771
|
+
// NOTE: change to accept a connection instead of meta-data
|
2708
2772
|
protected RubyArray mapTables(final Ruby runtime, final DatabaseMetaData metaData,
|
2709
2773
|
final String catalog, final String schemaPattern, final String tablePattern,
|
2710
2774
|
final ResultSet tablesSet) throws SQLException {
|
2711
2775
|
final RubyArray tables = runtime.newArray();
|
2712
2776
|
while ( tablesSet.next() ) {
|
2713
2777
|
String name = tablesSet.getString(TABLES_TABLE_NAME);
|
2778
|
+
|
2714
2779
|
name = caseConvertIdentifierForRails(metaData, name);
|
2780
|
+
|
2715
2781
|
tables.add(RubyString.newUnicodeString(runtime, name));
|
2716
2782
|
}
|
2717
2783
|
return tables;
|
@@ -2920,14 +2986,14 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2920
2986
|
}
|
2921
2987
|
|
2922
2988
|
protected IRubyObject mapResults(final ThreadContext context,
|
2923
|
-
final
|
2989
|
+
final Connection connection, final Statement statement,
|
2924
2990
|
final boolean downCase) throws SQLException {
|
2925
2991
|
|
2926
2992
|
final Ruby runtime = context.getRuntime();
|
2927
2993
|
IRubyObject result;
|
2928
2994
|
ResultSet resultSet = statement.getResultSet();
|
2929
2995
|
try {
|
2930
|
-
result = mapToRawResult(context, runtime,
|
2996
|
+
result = mapToRawResult(context, runtime, connection, resultSet, downCase);
|
2931
2997
|
}
|
2932
2998
|
finally { close(resultSet); }
|
2933
2999
|
|
@@ -2939,7 +3005,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2939
3005
|
do {
|
2940
3006
|
resultSet = statement.getResultSet();
|
2941
3007
|
try {
|
2942
|
-
result = mapToRawResult(context, runtime,
|
3008
|
+
result = mapToRawResult(context, runtime, connection, resultSet, downCase);
|
2943
3009
|
}
|
2944
3010
|
finally { close(resultSet); }
|
2945
3011
|
|
@@ -2966,6 +3032,20 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2966
3032
|
* @param downCase should column names only be in lower case?
|
2967
3033
|
*/
|
2968
3034
|
@SuppressWarnings("unchecked")
|
3035
|
+
private IRubyObject mapToRawResult(final ThreadContext context, final Ruby runtime,
|
3036
|
+
final Connection connection, final ResultSet resultSet,
|
3037
|
+
final boolean downCase) throws SQLException {
|
3038
|
+
|
3039
|
+
final ColumnData[] columns = extractColumns(runtime, connection, resultSet, downCase);
|
3040
|
+
|
3041
|
+
final RubyArray results = runtime.newArray();
|
3042
|
+
// [ { 'col1': 1, 'col2': 2 }, { 'col1': 3, 'col2': 4 } ]
|
3043
|
+
populateFromResultSet(context, runtime, (List<IRubyObject>) results, resultSet, columns);
|
3044
|
+
return results;
|
3045
|
+
}
|
3046
|
+
|
3047
|
+
@Deprecated
|
3048
|
+
@SuppressWarnings("unchecked")
|
2969
3049
|
private IRubyObject mapToRawResult(final ThreadContext context, final Ruby runtime,
|
2970
3050
|
final DatabaseMetaData metaData, final ResultSet resultSet,
|
2971
3051
|
final boolean downCase) throws SQLException {
|
@@ -2979,10 +3059,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2979
3059
|
}
|
2980
3060
|
|
2981
3061
|
private IRubyObject yieldResultRows(final ThreadContext context, final Ruby runtime,
|
2982
|
-
final
|
3062
|
+
final Connection connection, final ResultSet resultSet,
|
2983
3063
|
final Block block) throws SQLException {
|
2984
3064
|
|
2985
|
-
final ColumnData[] columns = extractColumns(runtime,
|
3065
|
+
final ColumnData[] columns = extractColumns(runtime, connection, resultSet, false);
|
2986
3066
|
|
2987
3067
|
final IRubyObject[] blockArgs = new IRubyObject[columns.length];
|
2988
3068
|
while ( resultSet.next() ) {
|
@@ -3005,6 +3085,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3005
3085
|
* @return columns data
|
3006
3086
|
* @throws SQLException
|
3007
3087
|
*/
|
3088
|
+
protected ColumnData[] extractColumns(final Ruby runtime,
|
3089
|
+
final Connection connection, final ResultSet resultSet,
|
3090
|
+
final boolean downCase) throws SQLException {
|
3091
|
+
return setupColumns(runtime, connection, resultSet.getMetaData(), downCase);
|
3092
|
+
}
|
3093
|
+
|
3094
|
+
@Deprecated
|
3008
3095
|
protected ColumnData[] extractColumns(final Ruby runtime,
|
3009
3096
|
final DatabaseMetaData metaData, final ResultSet resultSet,
|
3010
3097
|
final boolean downCase) throws SQLException {
|
@@ -3358,12 +3445,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3358
3445
|
name = nameParts[2];
|
3359
3446
|
}
|
3360
3447
|
|
3361
|
-
final DatabaseMetaData metaData = connection.getMetaData();
|
3362
|
-
|
3363
3448
|
if (schema != null) {
|
3364
|
-
schema = caseConvertIdentifierForJdbc(
|
3449
|
+
schema = caseConvertIdentifierForJdbc(connection, schema);
|
3365
3450
|
}
|
3366
|
-
name = caseConvertIdentifierForJdbc(
|
3451
|
+
name = caseConvertIdentifierForJdbc(connection, name);
|
3367
3452
|
|
3368
3453
|
if (schema != null && ! databaseSupportsSchemas()) {
|
3369
3454
|
catalog = schema;
|
@@ -3395,11 +3480,16 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3395
3480
|
this.index = idx;
|
3396
3481
|
}
|
3397
3482
|
|
3483
|
+
@Override
|
3484
|
+
public String toString() {
|
3485
|
+
return "'" + name + "'i" + index + "t" + type + "";
|
3486
|
+
}
|
3487
|
+
|
3398
3488
|
}
|
3399
3489
|
|
3400
|
-
private
|
3490
|
+
private ColumnData[] setupColumns(
|
3401
3491
|
final Ruby runtime,
|
3402
|
-
final
|
3492
|
+
final Connection connection,
|
3403
3493
|
final ResultSetMetaData resultMetaData,
|
3404
3494
|
final boolean downCase) throws SQLException {
|
3405
3495
|
|
@@ -3407,14 +3497,39 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3407
3497
|
final ColumnData[] columns = new ColumnData[columnCount];
|
3408
3498
|
|
3409
3499
|
for ( int i = 1; i <= columnCount; i++ ) { // metadata is one-based
|
3410
|
-
|
3411
|
-
if (downCase) {
|
3412
|
-
name =
|
3500
|
+
String name = resultMetaData.getColumnLabel(i);
|
3501
|
+
if ( downCase ) {
|
3502
|
+
name = name.toLowerCase();
|
3413
3503
|
} else {
|
3414
|
-
name = caseConvertIdentifierForRails(
|
3504
|
+
name = caseConvertIdentifierForRails(connection, name);
|
3415
3505
|
}
|
3506
|
+
final RubyString columnName = RubyString.newUnicodeString(runtime, name);
|
3416
3507
|
final int columnType = resultMetaData.getColumnType(i);
|
3508
|
+
columns[i - 1] = new ColumnData(columnName, columnType, i);
|
3509
|
+
}
|
3510
|
+
|
3511
|
+
return columns;
|
3512
|
+
}
|
3513
|
+
|
3514
|
+
@Deprecated
|
3515
|
+
private ColumnData[] setupColumns(
|
3516
|
+
final Ruby runtime,
|
3517
|
+
final DatabaseMetaData metaData,
|
3518
|
+
final ResultSetMetaData resultMetaData,
|
3519
|
+
final boolean downCase) throws SQLException {
|
3520
|
+
|
3521
|
+
final int columnCount = resultMetaData.getColumnCount();
|
3522
|
+
final ColumnData[] columns = new ColumnData[columnCount];
|
3523
|
+
|
3524
|
+
for ( int i = 1; i <= columnCount; i++ ) { // metadata is one-based
|
3525
|
+
String name = resultMetaData.getColumnLabel(i);
|
3526
|
+
if ( downCase ) {
|
3527
|
+
name = name.toLowerCase();
|
3528
|
+
} else {
|
3529
|
+
name = caseConvertIdentifierForRails(metaData, name);
|
3530
|
+
}
|
3417
3531
|
final RubyString columnName = RubyString.newUnicodeString(runtime, name);
|
3532
|
+
final int columnType = resultMetaData.getColumnType(i);
|
3418
3533
|
columns[i - 1] = new ColumnData(columnName, columnType, i);
|
3419
3534
|
}
|
3420
3535
|
|
@@ -3491,6 +3606,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
3491
3606
|
}
|
3492
3607
|
}
|
3493
3608
|
|
3609
|
+
protected void warn(final ThreadContext context, final String message) {
|
3610
|
+
callMethod(context, "warn", context.getRuntime().newString(message));
|
3611
|
+
}
|
3612
|
+
|
3494
3613
|
private static RubyArray createCallerBacktrace(final ThreadContext context) {
|
3495
3614
|
final Ruby runtime = context.getRuntime();
|
3496
3615
|
runtime.incrementCallerCount();
|