activerecord-jdbc-adapter-ficoh 1.3.21-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 +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +462 -0
- data/.yardopts +4 -0
- data/Appraisals +36 -0
- data/CONTRIBUTING.md +49 -0
- data/Gemfile +68 -0
- data/History.md +1191 -0
- data/LICENSE.txt +25 -0
- data/README.md +277 -0
- data/RUNNING_TESTS.md +88 -0
- data/Rakefile +298 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +63 -0
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +1 -0
- data/lib/arel/visitors/compat.rb +64 -0
- data/lib/arel/visitors/db2.rb +137 -0
- data/lib/arel/visitors/derby.rb +112 -0
- data/lib/arel/visitors/firebird.rb +79 -0
- data/lib/arel/visitors/h2.rb +25 -0
- data/lib/arel/visitors/hsqldb.rb +32 -0
- data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
- data/lib/arel/visitors/sql_server.rb +225 -0
- data/lib/arel/visitors/sql_server/ng42.rb +293 -0
- data/lib/arjdbc.rb +22 -0
- data/lib/arjdbc/db2.rb +4 -0
- data/lib/arjdbc/db2/adapter.rb +802 -0
- data/lib/arjdbc/db2/as400.rb +137 -0
- data/lib/arjdbc/db2/column.rb +177 -0
- data/lib/arjdbc/db2/connection_methods.rb +45 -0
- data/lib/arjdbc/derby.rb +3 -0
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +567 -0
- data/lib/arjdbc/derby/connection_methods.rb +16 -0
- data/lib/arjdbc/derby/schema_creation.rb +15 -0
- data/lib/arjdbc/discover.rb +104 -0
- data/lib/arjdbc/firebird.rb +4 -0
- data/lib/arjdbc/firebird/adapter.rb +468 -0
- data/lib/arjdbc/firebird/connection_methods.rb +20 -0
- data/lib/arjdbc/h2.rb +3 -0
- data/lib/arjdbc/h2/adapter.rb +335 -0
- data/lib/arjdbc/h2/connection_methods.rb +22 -0
- data/lib/arjdbc/hsqldb.rb +3 -0
- data/lib/arjdbc/hsqldb/adapter.rb +304 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +23 -0
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
- data/lib/arjdbc/informix.rb +5 -0
- data/lib/arjdbc/informix/adapter.rb +160 -0
- data/lib/arjdbc/informix/connection_methods.rb +9 -0
- data/lib/arjdbc/jdbc.rb +62 -0
- data/lib/arjdbc/jdbc/adapter.rb +997 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/arel_support.rb +149 -0
- data/lib/arjdbc/jdbc/base_ext.rb +34 -0
- data/lib/arjdbc/jdbc/callbacks.rb +52 -0
- data/lib/arjdbc/jdbc/column.rb +83 -0
- data/lib/arjdbc/jdbc/connection.rb +26 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +59 -0
- data/lib/arjdbc/jdbc/driver.rb +44 -0
- data/lib/arjdbc/jdbc/error.rb +75 -0
- data/lib/arjdbc/jdbc/extension.rb +69 -0
- data/lib/arjdbc/jdbc/java.rb +13 -0
- data/lib/arjdbc/jdbc/type_cast.rb +154 -0
- data/lib/arjdbc/jdbc/type_converter.rb +142 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +822 -0
- data/lib/arjdbc/mssql/column.rb +207 -0
- data/lib/arjdbc/mssql/connection_methods.rb +72 -0
- data/lib/arjdbc/mssql/explain_support.rb +99 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/types.rb +343 -0
- data/lib/arjdbc/mssql/utils.rb +82 -0
- data/lib/arjdbc/mysql.rb +3 -0
- data/lib/arjdbc/mysql/adapter.rb +998 -0
- data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
- data/lib/arjdbc/mysql/column.rb +167 -0
- data/lib/arjdbc/mysql/connection_methods.rb +137 -0
- data/lib/arjdbc/mysql/explain_support.rb +82 -0
- data/lib/arjdbc/mysql/schema_creation.rb +58 -0
- data/lib/arjdbc/oracle.rb +4 -0
- data/lib/arjdbc/oracle/adapter.rb +968 -0
- data/lib/arjdbc/oracle/column.rb +136 -0
- data/lib/arjdbc/oracle/connection_methods.rb +21 -0
- data/lib/arjdbc/postgresql.rb +3 -0
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
- data/lib/arjdbc/postgresql/adapter.rb +1498 -0
- data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/oid.rb +412 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +132 -0
- data/lib/arjdbc/postgresql/column.rb +640 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +44 -0
- data/lib/arjdbc/postgresql/explain_support.rb +53 -0
- data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
- data/lib/arjdbc/postgresql/oid_types.rb +265 -0
- data/lib/arjdbc/postgresql/schema_creation.rb +60 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +3 -0
- data/lib/arjdbc/sqlite3/adapter.rb +654 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +36 -0
- data/lib/arjdbc/sqlite3/explain_support.rb +29 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +47 -0
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +66 -0
- data/lib/arjdbc/tasks/databases.rake +91 -0
- data/lib/arjdbc/tasks/databases3.rake +239 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
- data/lib/arjdbc/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/serialized_attributes.rb +98 -0
- data/lib/arjdbc/util/table_copier.rb +108 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +17 -0
- data/pom.xml +285 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
- data/rakelib/01-tomcat.rake +51 -0
- data/rakelib/02-test.rake +151 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/db.rake +58 -0
- data/rakelib/rails.rake +77 -0
- data/src/java/arjdbc/ArJdbcModule.java +288 -0
- data/src/java/arjdbc/db2/DB2Module.java +77 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +128 -0
- data/src/java/arjdbc/derby/DerbyModule.java +180 -0
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +153 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
- data/src/java/arjdbc/h2/H2Module.java +50 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +86 -0
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +74 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +76 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
- data/src/java/arjdbc/jdbc/Callable.java +44 -0
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +77 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
- data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
- data/src/java/arjdbc/jdbc/DriverWrapper.java +128 -0
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +32 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4541 -0
- data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
- data/src/java/arjdbc/jdbc/WithResultSet.java +37 -0
- data/src/java/arjdbc/mssql/MSSQLModule.java +91 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +193 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +140 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +456 -0
- data/src/java/arjdbc/oracle/OracleModule.java +81 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +477 -0
- data/src/java/arjdbc/postgresql/ByteaUtils.java +171 -0
- data/src/java/arjdbc/postgresql/DriverImplementation.java +78 -0
- data/src/java/arjdbc/postgresql/PGDriverImplementation.java +535 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +189 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +489 -0
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +93 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +405 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/DateTimeUtils.java +517 -0
- data/src/java/arjdbc/util/NumberUtils.java +50 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +139 -0
- data/src/java/arjdbc/util/StringCache.java +60 -0
- data/src/java/arjdbc/util/StringHelper.java +155 -0
- metadata +288 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
/*
|
2
|
+
* The MIT License
|
3
|
+
*
|
4
|
+
* Copyright 2013 Karol Bucek.
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
11
|
+
* furnished to do so, subject to the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be included in
|
14
|
+
* all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
* THE SOFTWARE.
|
23
|
+
*/
|
24
|
+
package arjdbc.sqlite3;
|
25
|
+
|
26
|
+
import static arjdbc.util.QuotingUtils.quoteCharAndDecorateWith;
|
27
|
+
import static arjdbc.util.QuotingUtils.quoteCharWith;
|
28
|
+
|
29
|
+
import org.jruby.Ruby;
|
30
|
+
import org.jruby.RubyModule;
|
31
|
+
import org.jruby.RubyString;
|
32
|
+
import org.jruby.anno.JRubyMethod;
|
33
|
+
import org.jruby.runtime.ThreadContext;
|
34
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
35
|
+
import org.jruby.util.ByteList;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* ArJdbc::SQLite3
|
39
|
+
*
|
40
|
+
* @author kares
|
41
|
+
*/
|
42
|
+
@org.jruby.anno.JRubyModule(name = "ArJdbc::SQLite3")
|
43
|
+
public class SQLite3Module {
|
44
|
+
|
45
|
+
public static RubyModule load(final RubyModule arJdbc) {
|
46
|
+
RubyModule sqlite3 = arJdbc.defineModuleUnder("SQLite3");
|
47
|
+
sqlite3.defineAnnotatedMethods( SQLite3Module.class );
|
48
|
+
return sqlite3;
|
49
|
+
}
|
50
|
+
|
51
|
+
public static RubyModule load(final Ruby runtime) {
|
52
|
+
return load( arjdbc.ArJdbcModule.get(runtime) );
|
53
|
+
}
|
54
|
+
|
55
|
+
@JRubyMethod(name = "quote_string", required = 1)
|
56
|
+
public static IRubyObject quote_string(
|
57
|
+
final ThreadContext context,
|
58
|
+
final IRubyObject self,
|
59
|
+
final IRubyObject string) { // string.gsub("'", "''") :
|
60
|
+
final char single = '\'';
|
61
|
+
final RubyString quoted = quoteCharWith(
|
62
|
+
context, (RubyString) string, single, single
|
63
|
+
);
|
64
|
+
return quoted;
|
65
|
+
}
|
66
|
+
|
67
|
+
private static final ByteList Q_TRUE = new ByteList(new byte[] { '\'', 't', '\'' }, false);
|
68
|
+
|
69
|
+
@JRubyMethod(name = "quoted_true", required = 0)
|
70
|
+
public static IRubyObject quoted_true(
|
71
|
+
final ThreadContext context,
|
72
|
+
final IRubyObject self) {
|
73
|
+
return RubyString.newString(context.runtime, Q_TRUE);
|
74
|
+
}
|
75
|
+
|
76
|
+
private static final ByteList Q_FALSE = new ByteList(new byte[] { '\'', 'f', '\'' }, false);
|
77
|
+
|
78
|
+
@JRubyMethod(name = "quoted_false", required = 0)
|
79
|
+
public static IRubyObject quoted_false(
|
80
|
+
final ThreadContext context,
|
81
|
+
final IRubyObject self) {
|
82
|
+
return RubyString.newString(context.runtime, Q_FALSE);
|
83
|
+
}
|
84
|
+
|
85
|
+
@JRubyMethod(name = "quote_column_name", required = 1)
|
86
|
+
public static IRubyObject quote_column_name(
|
87
|
+
final ThreadContext context,
|
88
|
+
final IRubyObject self,
|
89
|
+
final IRubyObject string) { // "#{name.to_s.gsub('"', '""')}"
|
90
|
+
return quoteCharAndDecorateWith(context, string.asString(), '"', '"', (byte) '"', (byte) '"');
|
91
|
+
}
|
92
|
+
|
93
|
+
}
|
@@ -0,0 +1,405 @@
|
|
1
|
+
/***** BEGIN LICENSE BLOCK *****
|
2
|
+
* Copyright (c) 2012-2013 Karol Bucek <self@kares.org>
|
3
|
+
* Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
|
4
|
+
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
|
5
|
+
* Copyright (c) 2008-2009 Thomas E Enebo <enebo@acm.org>
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
* a copy of this software and associated documentation files (the
|
9
|
+
* "Software"), to deal in the Software without restriction, including
|
10
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
* the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be
|
16
|
+
* included in all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
***** END LICENSE BLOCK *****/
|
26
|
+
|
27
|
+
package arjdbc.sqlite3;
|
28
|
+
|
29
|
+
import java.io.IOException;
|
30
|
+
import java.sql.Connection;
|
31
|
+
import java.sql.ResultSet;
|
32
|
+
import java.sql.ResultSetMetaData;
|
33
|
+
import java.sql.SQLException;
|
34
|
+
import java.sql.Statement;
|
35
|
+
import java.sql.DatabaseMetaData;
|
36
|
+
import java.sql.Savepoint;
|
37
|
+
import java.sql.Types;
|
38
|
+
import java.util.List;
|
39
|
+
|
40
|
+
import org.jruby.Ruby;
|
41
|
+
import org.jruby.RubyArray;
|
42
|
+
import org.jruby.RubyClass;
|
43
|
+
import org.jruby.RubyString;
|
44
|
+
import org.jruby.anno.JRubyMethod;
|
45
|
+
import org.jruby.runtime.ObjectAllocator;
|
46
|
+
import org.jruby.runtime.ThreadContext;
|
47
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
48
|
+
|
49
|
+
import arjdbc.jdbc.Callable;
|
50
|
+
import arjdbc.jdbc.RubyJdbcConnection;
|
51
|
+
import arjdbc.util.StringHelper;
|
52
|
+
import org.jruby.util.SafePropertyAccessor;
|
53
|
+
|
54
|
+
/**
|
55
|
+
*
|
56
|
+
* @author enebo
|
57
|
+
*/
|
58
|
+
@org.jruby.anno.JRubyClass(name = "ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection")
|
59
|
+
public class SQLite3RubyJdbcConnection extends RubyJdbcConnection {
|
60
|
+
private static final long serialVersionUID = -5783855018818472773L;
|
61
|
+
|
62
|
+
public SQLite3RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
|
63
|
+
super(runtime, metaClass);
|
64
|
+
}
|
65
|
+
|
66
|
+
public static RubyClass createSQLite3JdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
|
67
|
+
final RubyClass clazz = getConnectionAdapters(runtime). // ActiveRecord::ConnectionAdapters
|
68
|
+
defineClassUnder("SQLite3JdbcConnection", jdbcConnection, ALLOCATOR);
|
69
|
+
clazz.defineAnnotatedMethods( SQLite3RubyJdbcConnection.class );
|
70
|
+
return clazz;
|
71
|
+
}
|
72
|
+
|
73
|
+
public static RubyClass load(final Ruby runtime) {
|
74
|
+
RubyClass jdbcConnection = getJdbcConnection(runtime);
|
75
|
+
return createSQLite3JdbcConnectionClass(runtime, jdbcConnection);
|
76
|
+
}
|
77
|
+
|
78
|
+
protected static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
79
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
80
|
+
return new SQLite3RubyJdbcConnection(runtime, klass);
|
81
|
+
}
|
82
|
+
};
|
83
|
+
|
84
|
+
@JRubyMethod(name = {"last_insert_rowid", "last_insert_id"}, alias = "last_insert_row_id")
|
85
|
+
public IRubyObject last_insert_rowid(final ThreadContext context)
|
86
|
+
throws SQLException {
|
87
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
88
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
89
|
+
Statement statement = null; ResultSet genKeys = null;
|
90
|
+
try {
|
91
|
+
statement = connection.createStatement();
|
92
|
+
// NOTE: strangely this will work and has been used for quite some time :
|
93
|
+
//return mapGeneratedKeys(context.runtime, connection, statement, true);
|
94
|
+
// but we should assume SQLite JDBC will prefer sane API usage eventually :
|
95
|
+
genKeys = statement.executeQuery("SELECT last_insert_rowid()");
|
96
|
+
return doMapGeneratedKeys(context.runtime, genKeys, true);
|
97
|
+
}
|
98
|
+
catch (final SQLException e) {
|
99
|
+
debugMessage(context.runtime, "failed to get generated keys: ", e.getMessage());
|
100
|
+
throw e;
|
101
|
+
}
|
102
|
+
finally { close(genKeys); close(statement); }
|
103
|
+
}
|
104
|
+
});
|
105
|
+
}
|
106
|
+
|
107
|
+
// NOTE: interestingly it supports getGeneratedKeys but not executeUpdate
|
108
|
+
// + the driver does not report it supports it via the meta-data yet does
|
109
|
+
@Override
|
110
|
+
protected boolean supportsGeneratedKeys(final Connection connection) throws SQLException {
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
|
114
|
+
@Override
|
115
|
+
protected Statement createStatement(final ThreadContext context, final Connection connection)
|
116
|
+
throws SQLException {
|
117
|
+
final Statement statement = connection.createStatement();
|
118
|
+
IRubyObject escapeProcessing = getConfigValue(context, "statement_escape_processing");
|
119
|
+
if ( escapeProcessing != null && ! escapeProcessing.isNil() ) {
|
120
|
+
statement.setEscapeProcessing( escapeProcessing.isTrue() );
|
121
|
+
}
|
122
|
+
// else leave as is by default
|
123
|
+
return statement;
|
124
|
+
}
|
125
|
+
|
126
|
+
@Override
|
127
|
+
protected IRubyObject indexes(final ThreadContext context, String table, final String name, String schema) {
|
128
|
+
if ( table != null ) {
|
129
|
+
final int i = table.indexOf('.');
|
130
|
+
if ( i > 0 && schema == null ) {
|
131
|
+
schema = table.substring(0, i);
|
132
|
+
table = table.substring(i + 1);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
final String tableName = table;
|
136
|
+
final String schemaName = schema;
|
137
|
+
// return super.indexes(context, tableName, name, schemaName);
|
138
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
139
|
+
public RubyArray call(final Connection connection) throws SQLException {
|
140
|
+
final Ruby runtime = context.runtime;
|
141
|
+
final RubyClass indexDefinition = getIndexDefinition(runtime);
|
142
|
+
|
143
|
+
final TableName table = extractTableName(connection, schemaName, tableName);
|
144
|
+
|
145
|
+
final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
|
146
|
+
|
147
|
+
final DatabaseMetaData metaData = connection.getMetaData();
|
148
|
+
ResultSet indexInfoSet = null;
|
149
|
+
try {
|
150
|
+
indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
|
151
|
+
}
|
152
|
+
catch (SQLException e) {
|
153
|
+
final String msg = e.getMessage();
|
154
|
+
if ( msg != null && msg.startsWith("[SQLITE_ERROR] SQL error or missing database") ) {
|
155
|
+
return RubyArray.newEmptyArray(runtime); // on 3.8.7 getIndexInfo fails if table has no indexes
|
156
|
+
}
|
157
|
+
throw e;
|
158
|
+
}
|
159
|
+
final RubyArray indexes = RubyArray.newArray(runtime, 8);
|
160
|
+
try {
|
161
|
+
String currentIndex = null;
|
162
|
+
|
163
|
+
while ( indexInfoSet.next() ) {
|
164
|
+
String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
|
165
|
+
if ( indexName == null ) continue;
|
166
|
+
|
167
|
+
final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
|
168
|
+
final RubyString rubyColumnName = RubyString.newUnicodeString(runtime, columnName);
|
169
|
+
if ( primaryKeys.contains(rubyColumnName) ) continue;
|
170
|
+
|
171
|
+
// We are working on a new index
|
172
|
+
if ( ! indexName.equals(currentIndex) ) {
|
173
|
+
currentIndex = indexName;
|
174
|
+
|
175
|
+
String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
|
176
|
+
|
177
|
+
final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
|
178
|
+
|
179
|
+
IRubyObject[] args = new IRubyObject[] {
|
180
|
+
RubyString.newUnicodeString(runtime, indexTableName), // table_name
|
181
|
+
RubyString.newUnicodeString(runtime, indexName), // index_name
|
182
|
+
runtime.newBoolean( ! nonUnique ), // unique
|
183
|
+
runtime.newArray() // [] for column names, we'll add to that in just a bit
|
184
|
+
// orders, (since AR 3.2) where, type, using (AR 4.0)
|
185
|
+
};
|
186
|
+
|
187
|
+
indexes.append( indexDefinition.callMethod(context, "new", args) ); // IndexDefinition.new
|
188
|
+
}
|
189
|
+
|
190
|
+
// One or more columns can be associated with an index
|
191
|
+
IRubyObject lastIndexDef = indexes.isEmpty() ? null : indexes.entry(-1);
|
192
|
+
if ( lastIndexDef != null ) {
|
193
|
+
( (RubyArray) lastIndexDef.callMethod(context, "columns") ).append(rubyColumnName);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
return indexes;
|
198
|
+
|
199
|
+
} finally { close(indexInfoSet); }
|
200
|
+
}
|
201
|
+
});
|
202
|
+
}
|
203
|
+
|
204
|
+
@Override
|
205
|
+
protected TableName extractTableName(
|
206
|
+
final Connection connection, String catalog, String schema,
|
207
|
+
final String tableName) throws IllegalArgumentException, SQLException {
|
208
|
+
|
209
|
+
final List<String> nameParts = split(tableName, '.');
|
210
|
+
final int len = nameParts.size();
|
211
|
+
if ( len > 3 ) {
|
212
|
+
throw new IllegalArgumentException("table name: " + tableName + " should not contain more than 2 '.'");
|
213
|
+
}
|
214
|
+
|
215
|
+
String name = tableName;
|
216
|
+
|
217
|
+
if ( len == 2 ) {
|
218
|
+
schema = nameParts.get(0);
|
219
|
+
name = nameParts.get(1);
|
220
|
+
}
|
221
|
+
else if ( len == 3 ) {
|
222
|
+
catalog = nameParts.get(0);
|
223
|
+
schema = nameParts.get(1);
|
224
|
+
name = nameParts.get(2);
|
225
|
+
}
|
226
|
+
|
227
|
+
if ( schema != null ) {
|
228
|
+
// NOTE: hack to work-around SQLite JDBC ignoring schema :
|
229
|
+
return new TableName(catalog, null, schema + '.' + name);
|
230
|
+
}
|
231
|
+
return new TableName(catalog, schema, name);
|
232
|
+
}
|
233
|
+
|
234
|
+
@Override
|
235
|
+
protected IRubyObject jdbcToRuby(final ThreadContext context,
|
236
|
+
final Ruby runtime, final int column, int type, final ResultSet resultSet)
|
237
|
+
throws SQLException {
|
238
|
+
// This is rather gross, and only needed because the resultset metadata for SQLite tries to be overly
|
239
|
+
// clever, and returns a type for the column of the "current" row, so an integer value stored in a
|
240
|
+
// decimal column is returned as Types.INTEGER. Therefore, if the first row of a resultset was an
|
241
|
+
// integer value, all rows of that result set would get truncated.
|
242
|
+
if ( resultSet instanceof ResultSetMetaData ) {
|
243
|
+
type = ((ResultSetMetaData) resultSet).getColumnType(column);
|
244
|
+
}
|
245
|
+
// since JDBC 3.8 there seems to be more cleverness built-in that
|
246
|
+
// causes (<= 3.8.7) to get things wrong ... reports DATE SQL type
|
247
|
+
// for "datetime" columns :
|
248
|
+
if ( type == Types.DATE ) {
|
249
|
+
// return timestampToRuby(context, runtime, resultSet, column);
|
250
|
+
return stringToRuby(context, runtime, resultSet, column);
|
251
|
+
}
|
252
|
+
return super.jdbcToRuby(context, runtime, column, type, resultSet);
|
253
|
+
}
|
254
|
+
|
255
|
+
@Override
|
256
|
+
protected boolean useByteStrings() { return true; }
|
257
|
+
|
258
|
+
@Override
|
259
|
+
protected IRubyObject streamToRuby(final ThreadContext context,
|
260
|
+
final Ruby runtime, final ResultSet resultSet, final int column)
|
261
|
+
throws SQLException, IOException {
|
262
|
+
final byte[] bytes = resultSet.getBytes(column);
|
263
|
+
// CAST(X'' AS BLOB) since SQLite 3.8 are returned as null
|
264
|
+
// while they were returned as byte[0] previously in 3.7.x
|
265
|
+
if ( resultSet.wasNull() ) return context.nil;
|
266
|
+
if ( bytes == null ) return RubyString.newEmptyString(runtime);
|
267
|
+
return StringHelper.newString( runtime, bytes );
|
268
|
+
}
|
269
|
+
|
270
|
+
@Override
|
271
|
+
protected IRubyObject stringToRuby(final ThreadContext context,
|
272
|
+
final Ruby runtime, final ResultSet resultSet, final int column)
|
273
|
+
throws SQLException {
|
274
|
+
final byte[] value = resultSet.getBytes(column);
|
275
|
+
if ( resultSet.wasNull() ) return context.nil;
|
276
|
+
if ( value == null ) return StringHelper.newEmptyUTF8String(runtime);
|
277
|
+
return StringHelper.newUTF8String(runtime, value);
|
278
|
+
}
|
279
|
+
|
280
|
+
@Override
|
281
|
+
protected RubyArray mapTables(final ThreadContext context, final Connection connection,
|
282
|
+
final String catalog, final String schemaPattern, final String tablePattern,
|
283
|
+
final ResultSet tablesSet) throws SQLException {
|
284
|
+
final RubyArray tables = RubyArray.newArray(context.runtime, 24);
|
285
|
+
while ( tablesSet.next() ) {
|
286
|
+
String name = tablesSet.getString(TABLES_TABLE_NAME);
|
287
|
+
name = name.toLowerCase(); // simply lower-case for SQLite3
|
288
|
+
tables.append( cachedString(context, name) );
|
289
|
+
}
|
290
|
+
return tables;
|
291
|
+
}
|
292
|
+
|
293
|
+
@Override
|
294
|
+
protected String caseConvertIdentifierForRails(final Connection connection, final String value) {
|
295
|
+
return value;
|
296
|
+
}
|
297
|
+
|
298
|
+
@Override
|
299
|
+
protected String caseConvertIdentifierForJdbc(final Connection connection, final String value) {
|
300
|
+
return value;
|
301
|
+
}
|
302
|
+
|
303
|
+
private static class SavepointStub implements Savepoint {
|
304
|
+
|
305
|
+
static final SavepointStub INSTANCE = new SavepointStub();
|
306
|
+
|
307
|
+
@Override
|
308
|
+
public int getSavepointId() throws SQLException {
|
309
|
+
throw new UnsupportedOperationException();
|
310
|
+
}
|
311
|
+
|
312
|
+
@Override
|
313
|
+
public String getSavepointName() throws SQLException {
|
314
|
+
throw new UnsupportedOperationException();
|
315
|
+
}
|
316
|
+
|
317
|
+
}
|
318
|
+
|
319
|
+
private static Boolean useSavepointAPI;
|
320
|
+
static {
|
321
|
+
final String savepoints = SafePropertyAccessor.getProperty("arjdbc.sqlite.savepoints");
|
322
|
+
if ( savepoints != null ) useSavepointAPI = Boolean.parseBoolean(savepoints);
|
323
|
+
}
|
324
|
+
|
325
|
+
private static boolean useSavepointAPI(final ThreadContext context) {
|
326
|
+
final Boolean working = useSavepointAPI;
|
327
|
+
if ( working == null ) {
|
328
|
+
try { // available since JDBC-SQLite 3.8.9
|
329
|
+
context.runtime.getJavaSupport().loadJavaClass("org.sqlite.jdbc3.JDBC3Savepoint");
|
330
|
+
return useSavepointAPI = Boolean.TRUE;
|
331
|
+
}
|
332
|
+
catch (ClassNotFoundException ex) { /* < 3.8.9 */ }
|
333
|
+
// catch (RuntimeException ex) { }
|
334
|
+
return useSavepointAPI = Boolean.FALSE;
|
335
|
+
}
|
336
|
+
return working;
|
337
|
+
}
|
338
|
+
|
339
|
+
@Override
|
340
|
+
@JRubyMethod(name = "create_savepoint", required = 1)
|
341
|
+
public IRubyObject create_savepoint(final ThreadContext context, final IRubyObject name) {
|
342
|
+
if ( useSavepointAPI(context) ) return super.create_savepoint(context, name);
|
343
|
+
|
344
|
+
if ( name == null || name.isNil() ) {
|
345
|
+
throw new IllegalArgumentException("create_savepoint (without name) not implemented!");
|
346
|
+
}
|
347
|
+
final Connection connection = getConnection(); Statement statement = null;
|
348
|
+
try {
|
349
|
+
connection.setAutoCommit(false);
|
350
|
+
// NOTE: JDBC driver does not support setSavepoint(String) :
|
351
|
+
( statement = connection.createStatement() ).execute("SAVEPOINT " + name.toString());
|
352
|
+
|
353
|
+
getSavepoints(context).put(name, SavepointStub.INSTANCE);
|
354
|
+
|
355
|
+
return name;
|
356
|
+
}
|
357
|
+
catch (SQLException e) {
|
358
|
+
return handleException(context, e);
|
359
|
+
}
|
360
|
+
finally { close(statement); }
|
361
|
+
}
|
362
|
+
|
363
|
+
@Override
|
364
|
+
@JRubyMethod(name = "rollback_savepoint", required = 1)
|
365
|
+
public IRubyObject rollback_savepoint(final ThreadContext context, final IRubyObject name) {
|
366
|
+
if ( useSavepointAPI(context) ) return super.rollback_savepoint(context, name);
|
367
|
+
|
368
|
+
final Connection connection = getConnection(true); Statement statement = null;
|
369
|
+
try {
|
370
|
+
if ( getSavepoints(context).get(name) == null ) {
|
371
|
+
throw context.runtime.newRuntimeError("could not rollback savepoint: '" + name + "' (not set)");
|
372
|
+
}
|
373
|
+
// NOTE: JDBC driver does not implement rollback(Savepoint) :
|
374
|
+
( statement = connection.createStatement() ).execute("ROLLBACK TO SAVEPOINT " + name.toString());
|
375
|
+
|
376
|
+
return context.nil;
|
377
|
+
}
|
378
|
+
catch (SQLException e) {
|
379
|
+
return handleException(context, e);
|
380
|
+
}
|
381
|
+
finally { close(statement); }
|
382
|
+
}
|
383
|
+
|
384
|
+
@Override
|
385
|
+
@JRubyMethod(name = "release_savepoint", required = 1)
|
386
|
+
public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
|
387
|
+
if ( useSavepointAPI(context) ) return super.release_savepoint(context, name);
|
388
|
+
|
389
|
+
final Connection connection = getConnection(true); Statement statement = null;
|
390
|
+
try {
|
391
|
+
if ( getSavepoints(context).remove(name) == null ) {
|
392
|
+
throw context.runtime.newRuntimeError("could not release savepoint: '" + name + "' (not set)");
|
393
|
+
}
|
394
|
+
// NOTE: JDBC driver does not implement release(Savepoint) :
|
395
|
+
( statement = connection.createStatement() ).execute("RELEASE SAVEPOINT " + name.toString());
|
396
|
+
|
397
|
+
return context.nil;
|
398
|
+
}
|
399
|
+
catch (SQLException e) {
|
400
|
+
return handleException(context, e);
|
401
|
+
}
|
402
|
+
finally { close(statement); }
|
403
|
+
}
|
404
|
+
|
405
|
+
}
|