activerecord-jdbc-alt-adapter 50.3.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +100 -0
- data/.yardopts +4 -0
- data/CONTRIBUTING.md +50 -0
- data/Gemfile +92 -0
- data/History.md +1191 -0
- data/LICENSE.txt +26 -0
- data/README.md +240 -0
- data/RUNNING_TESTS.md +127 -0
- data/Rakefile +336 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +55 -0
- data/activerecord-jdbc-alt-adapter.gemspec +56 -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/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 +60 -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 +294 -0
- data/lib/arel/visitors/sqlserver.rb +214 -0
- data/lib/arjdbc.rb +19 -0
- data/lib/arjdbc/abstract/connection_management.rb +35 -0
- data/lib/arjdbc/abstract/core.rb +74 -0
- data/lib/arjdbc/abstract/database_statements.rb +64 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/db2.rb +4 -0
- data/lib/arjdbc/db2/adapter.rb +789 -0
- data/lib/arjdbc/db2/as400.rb +130 -0
- data/lib/arjdbc/db2/column.rb +167 -0
- data/lib/arjdbc/db2/connection_methods.rb +44 -0
- data/lib/arjdbc/derby.rb +3 -0
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +540 -0
- data/lib/arjdbc/derby/connection_methods.rb +20 -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 +434 -0
- data/lib/arjdbc/firebird/connection_methods.rb +23 -0
- data/lib/arjdbc/h2.rb +3 -0
- data/lib/arjdbc/h2/adapter.rb +303 -0
- data/lib/arjdbc/h2/connection_methods.rb +27 -0
- data/lib/arjdbc/hsqldb.rb +3 -0
- data/lib/arjdbc/hsqldb/adapter.rb +297 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +28 -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 +162 -0
- data/lib/arjdbc/informix/connection_methods.rb +9 -0
- data/lib/arjdbc/jdbc.rb +59 -0
- data/lib/arjdbc/jdbc/adapter.rb +475 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/base_ext.rb +15 -0
- data/lib/arjdbc/jdbc/callbacks.rb +53 -0
- data/lib/arjdbc/jdbc/column.rb +97 -0
- data/lib/arjdbc/jdbc/connection.rb +14 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +37 -0
- data/lib/arjdbc/jdbc/error.rb +65 -0
- data/lib/arjdbc/jdbc/extension.rb +59 -0
- data/lib/arjdbc/jdbc/java.rb +13 -0
- data/lib/arjdbc/jdbc/railtie.rb +2 -0
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
- data/lib/arjdbc/jdbc/type_cast.rb +166 -0
- data/lib/arjdbc/jdbc/type_converter.rb +142 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +384 -0
- data/lib/arjdbc/mssql/column.rb +29 -0
- data/lib/arjdbc/mssql/connection_methods.rb +79 -0
- data/lib/arjdbc/mssql/database_statements.rb +134 -0
- data/lib/arjdbc/mssql/errors.rb +6 -0
- data/lib/arjdbc/mssql/explain_support.rb +129 -0
- data/lib/arjdbc/mssql/extensions.rb +36 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/old_adapter.rb +804 -0
- data/lib/arjdbc/mssql/old_column.rb +200 -0
- data/lib/arjdbc/mssql/quoting.rb +101 -0
- data/lib/arjdbc/mssql/schema_creation.rb +31 -0
- data/lib/arjdbc/mssql/schema_definitions.rb +74 -0
- data/lib/arjdbc/mssql/schema_statements.rb +329 -0
- data/lib/arjdbc/mssql/transaction.rb +69 -0
- data/lib/arjdbc/mssql/types.rb +52 -0
- data/lib/arjdbc/mssql/types/binary_types.rb +33 -0
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +134 -0
- data/lib/arjdbc/mssql/types/deprecated_types.rb +40 -0
- data/lib/arjdbc/mssql/types/numeric_types.rb +71 -0
- data/lib/arjdbc/mssql/types/string_types.rb +56 -0
- data/lib/arjdbc/mssql/utils.rb +66 -0
- data/lib/arjdbc/mysql.rb +3 -0
- data/lib/arjdbc/mysql/adapter.rb +140 -0
- data/lib/arjdbc/mysql/connection_methods.rb +166 -0
- data/lib/arjdbc/oracle/adapter.rb +863 -0
- data/lib/arjdbc/postgresql.rb +3 -0
- data/lib/arjdbc/postgresql/adapter.rb +687 -0
- 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/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
- data/lib/arjdbc/postgresql/column.rb +51 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +67 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +266 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +3 -0
- data/lib/arjdbc/sqlite3/adapter.rb +678 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +59 -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 +31 -0
- data/lib/arjdbc/tasks/databases.rake +48 -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/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/serialized_attributes.rb +98 -0
- data/lib/arjdbc/util/table_copier.rb +110 -0
- data/lib/arjdbc/version.rb +3 -0
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +17 -0
- data/lib/jdbc_adapter.rb +2 -0
- data/lib/jdbc_adapter/rake_tasks.rb +4 -0
- data/lib/jdbc_adapter/version.rb +4 -0
- data/pom.xml +114 -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 +132 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/db.rake +75 -0
- data/rakelib/rails.rake +223 -0
- data/src/java/arjdbc/ArJdbcModule.java +276 -0
- data/src/java/arjdbc/db2/DB2Module.java +76 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
- data/src/java/arjdbc/derby/DerbyModule.java +178 -0
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
- data/src/java/arjdbc/h2/H2Module.java +50 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +85 -0
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -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 +45 -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 +119 -0
- data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
- data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +61 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3979 -0
- data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +508 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +152 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
- data/src/java/arjdbc/oracle/OracleModule.java +80 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +455 -0
- data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
- data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +52 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +192 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +948 -0
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/DateTimeUtils.java +699 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +137 -0
- data/src/java/arjdbc/util/StringCache.java +63 -0
- data/src/java/arjdbc/util/StringHelper.java +145 -0
- metadata +269 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
|
|
3
|
+
if defined? ConnectionAdapters::ConnectionSpecification::Resolver # 4.0
|
|
4
|
+
ConnectionAdapters::ConnectionSpecification::Resolver
|
|
5
|
+
elsif defined? Base::ConnectionSpecification::Resolver # 3.2
|
|
6
|
+
Base::ConnectionSpecification::Resolver
|
|
7
|
+
else class << Base; self; end # 2.3, 3.0, 3.1 :
|
|
8
|
+
# def self.establish_connection ... on ActiveRecord::Base
|
|
9
|
+
end.class_eval do
|
|
10
|
+
|
|
11
|
+
# @private
|
|
12
|
+
def require(path)
|
|
13
|
+
# NOTE: we're inspecting resolver.spec connection resolution which does :
|
|
14
|
+
# `require "active_record/connection_adapters/#{spec[:adapter]}_adapter"`
|
|
15
|
+
# ...
|
|
16
|
+
# this {#require} method is only re-defined on a Resolver object and thus
|
|
17
|
+
# will not hurt performance - it will only be called for a few times (most
|
|
18
|
+
# likely once), this should still be fine for AR < 3.2 where this patch
|
|
19
|
+
# ends up on `class << ActiveRecord::Base` since models usually rely on
|
|
20
|
+
# Rails's auto-loading of (missing) constants and rarely use `require`.
|
|
21
|
+
#
|
|
22
|
+
# other alternative (to make sure we do not need to eager load AR built-in
|
|
23
|
+
# adapters) would be to mingle with the $LOAD_PATH which seems worse ...
|
|
24
|
+
case path
|
|
25
|
+
when 'active_record/connection_adapters/mysql_adapter'
|
|
26
|
+
$LOADED_FEATURES << 'active_record/connection_adapters/mysql_adapter.rb'
|
|
27
|
+
super('arjdbc/mysql')
|
|
28
|
+
when 'active_record/connection_adapters/mysql2_adapter'
|
|
29
|
+
$LOADED_FEATURES << 'active_record/connection_adapters/mysql2_adapter.rb'
|
|
30
|
+
super('arjdbc/mysql')
|
|
31
|
+
when 'active_record/connection_adapters/postgresql_adapter'
|
|
32
|
+
$LOADED_FEATURES << 'active_record/connection_adapters/postgresql_adapter.rb'
|
|
33
|
+
super('arjdbc/postgresql')
|
|
34
|
+
when 'active_record/connection_adapters/sqlite_adapter'
|
|
35
|
+
$LOADED_FEATURES << 'active_record/connection_adapters/sqlite_adapter.rb'
|
|
36
|
+
super('arjdbc/sqlite3')
|
|
37
|
+
when 'active_record/connection_adapters/sqlite3_adapter'
|
|
38
|
+
$LOADED_FEATURES << 'active_record/connection_adapters/sqlite3_adapter.rb'
|
|
39
|
+
super('arjdbc/sqlite3')
|
|
40
|
+
else super
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
class << Base
|
|
3
|
+
m = Module.new do
|
|
4
|
+
# Allow adapters to provide their own {#reset_column_information} method.
|
|
5
|
+
# @note This only affects the current thread's connection.
|
|
6
|
+
def reset_column_information # :nodoc:
|
|
7
|
+
# invoke the adapter-specific reset_column_information method
|
|
8
|
+
connection.reset_column_information if connection.respond_to?(:reset_column_information)
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
self.prepend(m)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ActiveRecord::ConnectionAdapters
|
|
2
|
+
module Jdbc
|
|
3
|
+
# ActiveRecord connection pool callbacks for JDBC.
|
|
4
|
+
# @see ActiveRecord::ConnectionAdapters::Jdbc::JndiConnectionPoolCallbacks
|
|
5
|
+
module ConnectionPoolCallbacks
|
|
6
|
+
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.set_callback :checkin, :after, :on_checkin
|
|
9
|
+
base.set_callback :checkout, :before, :on_checkout
|
|
10
|
+
base.class_eval do
|
|
11
|
+
def self.new(*args)
|
|
12
|
+
adapter = super # extend with JndiConnectionPoolCallbacks if a JNDI connection :
|
|
13
|
+
Jdbc::JndiConnectionPoolCallbacks.prepare(adapter, adapter.instance_variable_get(:@connection))
|
|
14
|
+
adapter
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def on_checkin
|
|
20
|
+
# default implementation does nothing
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def on_checkout
|
|
24
|
+
# default implementation does nothing
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
# JNDI specific connection pool callbacks that make sure the JNDI connection
|
|
29
|
+
# is disconnected on check-in and looked up (re-connected) on-checkout.
|
|
30
|
+
module JndiConnectionPoolCallbacks
|
|
31
|
+
|
|
32
|
+
def self.prepare(adapter, connection)
|
|
33
|
+
if adapter.is_a?(ConnectionPoolCallbacks) && connection.jndi?
|
|
34
|
+
adapter.extend self # extend JndiConnectionPoolCallbacks
|
|
35
|
+
connection.disconnect! # if connection.open? - close initial (JNDI) connection
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def on_checkin
|
|
40
|
+
disconnect!
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def on_checkout
|
|
44
|
+
reconnect!
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
# @deprecated use {ActiveRecord::ConnectionAdapters::Jdbc::ConnectionPoolCallbacks}
|
|
50
|
+
JdbcConnectionPoolCallbacks = Jdbc::ConnectionPoolCallbacks
|
|
51
|
+
# @deprecated use {ActiveRecord::ConnectionAdapters::Jdbc::JndiConnectionPoolCallbacks}
|
|
52
|
+
JndiConnectionPoolCallbacks = Jdbc::JndiConnectionPoolCallbacks
|
|
53
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module ConnectionAdapters
|
|
3
|
+
module Jdbc
|
|
4
|
+
autoload :TypeCast, 'arjdbc/jdbc/type_cast'
|
|
5
|
+
end
|
|
6
|
+
# The base class for all of {JdbcAdapter}'s returned columns.
|
|
7
|
+
# Instances of {JdbcColumn} will get extended with "column-spec" modules
|
|
8
|
+
# (similar to how {JdbcAdapter} gets spec modules in) if the adapter spec
|
|
9
|
+
# module provided a `column_selector` (matcher) method for it's database
|
|
10
|
+
# specific type.
|
|
11
|
+
# @see JdbcAdapter#jdbc_column_class
|
|
12
|
+
class JdbcColumn < Column
|
|
13
|
+
# @deprecated attribute writers will be removed in 1.4
|
|
14
|
+
attr_writer :limit, :precision # unless ArJdbc::AR42
|
|
15
|
+
|
|
16
|
+
def initialize(config, name, *args)
|
|
17
|
+
if self.class == JdbcColumn
|
|
18
|
+
# NOTE: extending classes do not want this if they do they shall call
|
|
19
|
+
call_discovered_column_callbacks(config) if config
|
|
20
|
+
default = args.shift
|
|
21
|
+
else # for extending classes allow ignoring first argument :
|
|
22
|
+
if ! config.nil? && ! config.is_a?(Hash)
|
|
23
|
+
default = name; name = config # initialize(name, default, *args)
|
|
24
|
+
else
|
|
25
|
+
default = args.shift
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if ArJdbc::AR50
|
|
30
|
+
default = args[0].cast(default)
|
|
31
|
+
|
|
32
|
+
sql_type = args.delete_at(1)
|
|
33
|
+
type = args.delete_at(0)
|
|
34
|
+
|
|
35
|
+
args.unshift(SqlTypeMetadata.new(:sql_type => sql_type, :type => type))
|
|
36
|
+
elsif ArJdbc::AR42
|
|
37
|
+
default = args[0].type_cast_from_database(default)
|
|
38
|
+
else
|
|
39
|
+
default = default_value(default)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# super <= 4.1: (name, default, sql_type = nil, null = true)
|
|
43
|
+
# super >= 4.2: (name, default, cast_type, sql_type = nil, null = true)
|
|
44
|
+
# super >= 5.0: (name, default, sql_type_metadata = nil, null = true)
|
|
45
|
+
|
|
46
|
+
super(name, default, *args)
|
|
47
|
+
init_column(name, default, *args)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Additional column initialization for sub-classes.
|
|
51
|
+
def init_column(*args); end
|
|
52
|
+
|
|
53
|
+
# Similar to `ActiveRecord`'s `extract_value_from_default(default)`.
|
|
54
|
+
# @return default value for a column (possibly extracted from driver value)
|
|
55
|
+
def default_value(value); value; end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
# @private
|
|
60
|
+
def call_discovered_column_callbacks(config)
|
|
61
|
+
dialect = (config[:dialect] || config[:driver]).to_s
|
|
62
|
+
for matcher, block in self.class.column_types
|
|
63
|
+
block.call(config, self) if matcher === dialect
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
public
|
|
68
|
+
|
|
69
|
+
# Returns the available column types
|
|
70
|
+
# @return [Hash] of (matcher, block) pairs
|
|
71
|
+
def self.column_types
|
|
72
|
+
types = {}
|
|
73
|
+
for mod in ::ArJdbc.modules
|
|
74
|
+
if mod.respond_to?(:column_selector)
|
|
75
|
+
sel = mod.column_selector # [ matcher, block ]
|
|
76
|
+
types[ sel[0] ] = sel[1]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
types
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class << self
|
|
83
|
+
|
|
84
|
+
include Jdbc::TypeCast if ::ActiveRecord::VERSION::STRING >= '4.2'
|
|
85
|
+
|
|
86
|
+
if ActiveRecord::VERSION::MAJOR > 3 && ActiveRecord::VERSION::STRING < '4.2'
|
|
87
|
+
|
|
88
|
+
# @private provides compatibility between AR 3.x/4.0 API
|
|
89
|
+
def string_to_date(value); value_to_date(value) end
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module ConnectionAdapters
|
|
3
|
+
# JDBC (connection) base class, custom adapters we support likely extend
|
|
4
|
+
# this class. For maximum performance most of this class and the sub-classes
|
|
5
|
+
# we ship are implemented in Java, check: *RubyJdbcConnection.java*
|
|
6
|
+
class JdbcConnection
|
|
7
|
+
|
|
8
|
+
def native_database_types
|
|
9
|
+
JdbcTypeConverter.new(supported_data_types).choose_best_types
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
ConnectionMethods = ::ActiveRecord::ConnectionHandling
|
|
3
|
+
|
|
4
|
+
ConnectionMethods.module_eval do
|
|
5
|
+
|
|
6
|
+
def jdbc_connection(config)
|
|
7
|
+
adapter_class = config[:adapter_class] || ::ActiveRecord::ConnectionAdapters::JdbcAdapter
|
|
8
|
+
adapter_class.new(nil, logger, nil, config)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def jndi_connection(config); jdbc_connection(config) end
|
|
12
|
+
|
|
13
|
+
def embedded_driver(config)
|
|
14
|
+
config[:username] ||= "sa"
|
|
15
|
+
config[:password] ||= ""
|
|
16
|
+
jdbc_connection(config)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def jndi_config?(config)
|
|
22
|
+
::ActiveRecord::ConnectionAdapters::JdbcConnection.jndi_config?(config)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @note keeps the same Hash when possible - helps caching on native side
|
|
26
|
+
def symbolize_keys_if_necessary(hash)
|
|
27
|
+
symbolize = false
|
|
28
|
+
hash.each_key do |key|
|
|
29
|
+
if ! key.is_a?(Symbol) && key.respond_to?(:to_sym)
|
|
30
|
+
symbolize = true; break
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
symbolize ? hash.symbolize_keys : hash
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
# Represents exceptions that have propagated up through the JDBC API.
|
|
3
|
+
class JDBCError < WrappedDatabaseException
|
|
4
|
+
|
|
5
|
+
def initialize(message = nil, cause = $!)
|
|
6
|
+
super( ( message.nil? && cause ) ? cause.message : message, nil )
|
|
7
|
+
if cause.is_a? Java::JavaSql::SQLException
|
|
8
|
+
@jdbc_exception, @cause = cause, nil
|
|
9
|
+
else
|
|
10
|
+
@cause, @jdbc_exception = cause, nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# The DB (or JDBC driver implementation specific) vendor error code.
|
|
15
|
+
# @see #jdbc_exception
|
|
16
|
+
# @return [Integer, NilClass]
|
|
17
|
+
def error_code
|
|
18
|
+
if ( @error_code ||= nil ).nil?
|
|
19
|
+
@error_code = jdbc_exception ? jdbc_exception.getErrorCode : nil
|
|
20
|
+
else
|
|
21
|
+
@error_code
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
# @deprecated
|
|
25
|
+
# @see #error_code
|
|
26
|
+
def errno; error_code end
|
|
27
|
+
|
|
28
|
+
# SQL code as standardized by ISO/ANSI and Open Group (X/Open), although
|
|
29
|
+
# some codes have been reserved for DB vendors to define for themselves.
|
|
30
|
+
# @see #jdbc_exception
|
|
31
|
+
# @return [String, NilClass]
|
|
32
|
+
def sql_state; jdbc_exception ? jdbc_exception.getSQLState : nil end
|
|
33
|
+
|
|
34
|
+
# The full Java exception (SQLException) object that was raised (if any).
|
|
35
|
+
# @note Navigate through chained exceptions using `jdbc_exception.next_exception`.
|
|
36
|
+
def jdbc_exception; @jdbc_exception end
|
|
37
|
+
alias_method :sql_exception, :jdbc_exception
|
|
38
|
+
|
|
39
|
+
# true if the current error might be recovered e.g. by re-trying the transaction
|
|
40
|
+
def recoverable?; jdbc_exception.is_a?(Java::JavaSql::SQLRecoverableException) end
|
|
41
|
+
# true when a failed operation might be able to succeed when retried (e.g. timeouts)
|
|
42
|
+
def transient?; jdbc_exception.is_a?(Java::JavaSql::SQLTransientException) end
|
|
43
|
+
|
|
44
|
+
# Likely (but not necessarily) the same as {#jdbc_exception}.
|
|
45
|
+
def cause; ( @cause ||= nil ) || jdbc_exception end
|
|
46
|
+
# @override
|
|
47
|
+
# @private for correct super-class (StatementInvalid) compatibility
|
|
48
|
+
alias_method :original_exception, :cause
|
|
49
|
+
|
|
50
|
+
# @override
|
|
51
|
+
def set_backtrace(backtrace)
|
|
52
|
+
@raw_backtrace = backtrace
|
|
53
|
+
if ( nested = cause ) && ! nested.equal?(self)
|
|
54
|
+
backtrace = backtrace - ( nested.respond_to?(:raw_backtrace) ? nested.raw_backtrace : nested.backtrace )
|
|
55
|
+
backtrace << "#{nested.backtrace.first}: #{nested.message} (#{nested.class.name})"
|
|
56
|
+
backtrace.concat nested.backtrace[1..-1] || []
|
|
57
|
+
end
|
|
58
|
+
super(backtrace)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @private
|
|
62
|
+
def raw_backtrace; @raw_backtrace ||= backtrace end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module ArJdbc
|
|
2
|
+
|
|
3
|
+
# Defines an AR-JDBC extension. An extension consists of a declaration using
|
|
4
|
+
# this method and an ArJdbc::XYZ module that contains implementation and
|
|
5
|
+
# overrides for methods in ActiveRecord::ConnectionAdapters::AbstractAdapter.
|
|
6
|
+
# When you declare your extension, you provide a block that detects when a
|
|
7
|
+
# database configured to use the extension is present and loads the necessary
|
|
8
|
+
# code for it. AR-JDBC will patch the code into the base JdbcAdapter by
|
|
9
|
+
# extending an instance of it with your extension module.
|
|
10
|
+
#
|
|
11
|
+
# +name+ the name of a module to be defined under the +ArJdbc+ module.
|
|
12
|
+
#
|
|
13
|
+
# +block+ should be a one- or two-arity block that receives the dialect name
|
|
14
|
+
# or driver class name as the first argument, and optionally the whole
|
|
15
|
+
# database configuration hash as a second argument
|
|
16
|
+
#
|
|
17
|
+
# Example:
|
|
18
|
+
#
|
|
19
|
+
# ArJdbc.extension :FRoB do |name|
|
|
20
|
+
# if name =~ /frob/i
|
|
21
|
+
# require 'arjdbc/frob' # contains ArJdbc::FRoB
|
|
22
|
+
# true
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
def self.extension(name, &block)
|
|
27
|
+
if const_defined?(name)
|
|
28
|
+
mod = const_get(name)
|
|
29
|
+
else
|
|
30
|
+
mod = const_set(name, Module.new)
|
|
31
|
+
end
|
|
32
|
+
(class << mod; self; end).instance_eval do
|
|
33
|
+
define_method :adapter_matcher do |_name, config|
|
|
34
|
+
if block.arity == 1
|
|
35
|
+
block.call(_name) ? mod : false
|
|
36
|
+
else
|
|
37
|
+
block.call(_name, config) ? mod : false
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end unless mod.respond_to?(:adapter_matcher)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
def self.discover_extensions
|
|
45
|
+
if defined?(Gem) && Gem.respond_to?(:find_files)
|
|
46
|
+
files = Gem.find_files('arjdbc/discover')
|
|
47
|
+
else
|
|
48
|
+
files = $LOAD_PATH.map do |path|
|
|
49
|
+
discover = File.join(path, 'arjdbc', 'discover.rb')
|
|
50
|
+
File.exist?(discover) ? discover : nil
|
|
51
|
+
end.compact
|
|
52
|
+
end
|
|
53
|
+
files.each do |file|
|
|
54
|
+
puts "Loading AR-JDBC extension #{file}" if $DEBUG
|
|
55
|
+
require file
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'active_record/connection_adapters/column'
|
|
2
|
+
|
|
3
|
+
module ActiveRecord::ConnectionAdapters
|
|
4
|
+
module Jdbc
|
|
5
|
+
# Type casting methods taken from AR 4.1's Column class.
|
|
6
|
+
# @private Simply to quickly "hack-in" 4.2 compatibility.
|
|
7
|
+
module TypeCast
|
|
8
|
+
TRUE_VALUES = Column::TRUE_VALUES if Column.const_defined?(:TRUE_VALUES)
|
|
9
|
+
FALSE_VALUES = if defined?(ActiveModel::Type::Boolean::FALSE_VALUES)
|
|
10
|
+
ActiveModel::Type::Boolean::FALSE_VALUES
|
|
11
|
+
else
|
|
12
|
+
Column::FALSE_VALUES
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#module Format
|
|
16
|
+
ISO_DATE = if defined?(ActiveModel::Type::Date::ISO_DATE)
|
|
17
|
+
ActiveModel::Type::Date::ISO_DATE
|
|
18
|
+
else
|
|
19
|
+
Column::Format::ISO_DATE
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
ISO_DATETIME = if defined?(ActiveModel::Type::Helpers::TimeValue::ISO_DATETIME)
|
|
23
|
+
ActiveModel::Type::Helpers::TimeValue::ISO_DATETIME
|
|
24
|
+
else
|
|
25
|
+
Column::Format::ISO_DATETIME
|
|
26
|
+
end
|
|
27
|
+
#end
|
|
28
|
+
|
|
29
|
+
# Used to convert from BLOBs to Strings
|
|
30
|
+
def binary_to_string(value)
|
|
31
|
+
value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def value_to_date(value)
|
|
35
|
+
if value.is_a?(String)
|
|
36
|
+
return nil if value.empty?
|
|
37
|
+
fast_string_to_date(value) || fallback_string_to_date(value)
|
|
38
|
+
elsif value.respond_to?(:to_date)
|
|
39
|
+
value.to_date
|
|
40
|
+
else
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def string_to_time(string)
|
|
46
|
+
return string unless string.is_a?(String)
|
|
47
|
+
return nil if string.empty?
|
|
48
|
+
return string if string =~ /^-?infinity$/.freeze
|
|
49
|
+
|
|
50
|
+
fast_string_to_time(string) || fallback_string_to_time(string)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def string_to_dummy_time(string)
|
|
54
|
+
return string unless string.is_a?(String)
|
|
55
|
+
return nil if string.empty?
|
|
56
|
+
|
|
57
|
+
dummy_time_string = "2000-01-01 #{string}"
|
|
58
|
+
|
|
59
|
+
fast_string_to_time(dummy_time_string) || begin
|
|
60
|
+
time_hash = Date._parse(dummy_time_string)
|
|
61
|
+
return nil if time_hash[:hour].nil?
|
|
62
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# convert something to a boolean
|
|
67
|
+
def value_to_boolean(value)
|
|
68
|
+
if value.is_a?(String) && value.empty?
|
|
69
|
+
nil
|
|
70
|
+
else
|
|
71
|
+
TRUE_VALUES.include?(value)
|
|
72
|
+
end
|
|
73
|
+
end if const_defined?(:TRUE_VALUES) # removed on AR 5.0
|
|
74
|
+
|
|
75
|
+
# convert something to a boolean
|
|
76
|
+
def value_to_boolean(value)
|
|
77
|
+
if value.is_a?(String) && value.empty?
|
|
78
|
+
nil
|
|
79
|
+
else
|
|
80
|
+
! FALSE_VALUES.include?(value)
|
|
81
|
+
end
|
|
82
|
+
end unless const_defined?(:TRUE_VALUES)
|
|
83
|
+
|
|
84
|
+
# Used to convert values to integer.
|
|
85
|
+
# handle the case when an integer column is used to store boolean values
|
|
86
|
+
def value_to_integer(value)
|
|
87
|
+
case value
|
|
88
|
+
when TrueClass, FalseClass
|
|
89
|
+
value ? 1 : 0
|
|
90
|
+
else
|
|
91
|
+
value.to_i rescue nil
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# convert something to a BigDecimal
|
|
96
|
+
def value_to_decimal(value)
|
|
97
|
+
# Using .class is faster than .is_a? and
|
|
98
|
+
# subclasses of BigDecimal will be handled
|
|
99
|
+
# in the else clause
|
|
100
|
+
if value.class == BigDecimal
|
|
101
|
+
value
|
|
102
|
+
elsif value.respond_to?(:to_d)
|
|
103
|
+
value.to_d
|
|
104
|
+
else
|
|
105
|
+
value.to_s.to_d
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
protected
|
|
110
|
+
# '0.123456' -> 123456
|
|
111
|
+
# '1.123456' -> 123456
|
|
112
|
+
def microseconds(time)
|
|
113
|
+
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def new_date(year, mon, mday)
|
|
117
|
+
if year && year != 0
|
|
118
|
+
Date.new(year, mon, mday) rescue nil
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
|
|
123
|
+
# Treat 0000-00-00 00:00:00 as nil.
|
|
124
|
+
return nil if year.nil? || (year == 0 && mon == 0 && mday == 0)
|
|
125
|
+
|
|
126
|
+
if offset
|
|
127
|
+
time = Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
|
|
128
|
+
return nil unless time
|
|
129
|
+
|
|
130
|
+
time -= offset
|
|
131
|
+
ActiveRecord::Base.default_timezone == :utc ? time : time.getlocal
|
|
132
|
+
else
|
|
133
|
+
timezone = ActiveRecord::Base.default_timezone
|
|
134
|
+
Time.public_send(timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def fast_string_to_date(string)
|
|
139
|
+
if string =~ ISO_DATE
|
|
140
|
+
new_date $1.to_i, $2.to_i, $3.to_i
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Doesn't handle time zones.
|
|
145
|
+
def fast_string_to_time(string)
|
|
146
|
+
if string =~ ISO_DATETIME
|
|
147
|
+
microsec = ($7.to_r * 1_000_000).to_i
|
|
148
|
+
new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def fallback_string_to_date(string)
|
|
153
|
+
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def fallback_string_to_time(string)
|
|
157
|
+
time_hash = Date._parse(string)
|
|
158
|
+
time_hash[:sec_fraction] = microseconds(time_hash)
|
|
159
|
+
time_hash[:year] *= -1 if time_hash[:zone] == 'BC'
|
|
160
|
+
|
|
161
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|