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,44 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
# @deprecated Re-implemented in Java - no longer used, left for compatibility.
|
4
|
+
class JdbcDriver
|
5
|
+
attr_reader :name, :properties
|
6
|
+
|
7
|
+
def initialize(name, properties = {})
|
8
|
+
@name = name
|
9
|
+
@driver = driver_class.new
|
10
|
+
if properties.is_a?(Java::JavaUtil::Properties)
|
11
|
+
@properties = properties # allow programmatically set properties
|
12
|
+
else
|
13
|
+
@properties = Java::JavaUtil::Properties.new
|
14
|
+
properties.each { |key, val| @properties[key.to_s] = val.to_s } if properties
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def driver_class
|
19
|
+
@driver_class ||= begin
|
20
|
+
driver_class_const = (@name[0...1].capitalize + @name[1..@name.length]).gsub(/\./, '_')
|
21
|
+
Jdbc::DriverManager.java_class.synchronized do # avoid 2 threads here
|
22
|
+
unless Jdbc.const_defined?(driver_class_const)
|
23
|
+
driver_class_name = @name
|
24
|
+
Jdbc.module_eval do
|
25
|
+
java_import(driver_class_name) { driver_class_const }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end unless Jdbc.const_defined?(driver_class_const)
|
29
|
+
driver_class = Jdbc.const_get(driver_class_const)
|
30
|
+
raise "You must specify a driver for your JDBC connection" unless driver_class
|
31
|
+
driver_class
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def connection(url, user, pass)
|
36
|
+
# bypass DriverManager to get around problem with dynamically loaded jdbc drivers
|
37
|
+
properties = self.properties.clone
|
38
|
+
properties.setProperty("user", user.to_s) if user
|
39
|
+
properties.setProperty("password", pass.to_s) if pass
|
40
|
+
@driver.connect(url, properties)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
# Represents exceptions that have propagated up through the JDBC API.
|
3
|
+
class JDBCError < const_defined?(:WrappedDatabaseException) ?
|
4
|
+
WrappedDatabaseException : StatementInvalid
|
5
|
+
|
6
|
+
def initialize(message = nil, cause = $!)
|
7
|
+
super( ( message.nil? && cause ) ? cause.message : message, nil )
|
8
|
+
if cause.is_a? Java::JavaSql::SQLException
|
9
|
+
@jdbc_exception, @cause = cause, nil
|
10
|
+
else
|
11
|
+
@cause, @jdbc_exception = cause, nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# The DB (or JDBC driver implementation specific) vendor error code.
|
16
|
+
# @see #jdbc_exception
|
17
|
+
# @return [Integer, NilClass]
|
18
|
+
def error_code
|
19
|
+
if ( @error_code ||= nil ).nil?
|
20
|
+
@error_code = jdbc_exception ? jdbc_exception.getErrorCode : nil
|
21
|
+
else
|
22
|
+
@error_code
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# @deprecated
|
26
|
+
# @see #error_code
|
27
|
+
def errno; error_code end
|
28
|
+
# @deprecated
|
29
|
+
# @private
|
30
|
+
def errno=(code); @error_code = code end
|
31
|
+
|
32
|
+
# SQL code as standardized by ISO/ANSI and Open Group (X/Open), although
|
33
|
+
# some codes have been reserved for DB vendors to define for themselves.
|
34
|
+
# @see #jdbc_exception
|
35
|
+
# @return [String, NilClass]
|
36
|
+
def sql_state; jdbc_exception ? jdbc_exception.getSQLState : nil end
|
37
|
+
|
38
|
+
# The full Java exception (SQLException) object that was raised (if any).
|
39
|
+
# @note Navigate through chained exceptions using `jdbc_exception.next_exception`.
|
40
|
+
def jdbc_exception; @jdbc_exception end
|
41
|
+
alias_method :sql_exception, :jdbc_exception
|
42
|
+
|
43
|
+
def set_jdbc_exception(exception); @jdbc_exception = exception end
|
44
|
+
# @deprecated
|
45
|
+
# @private
|
46
|
+
alias_method :sql_exception=, :set_jdbc_exception
|
47
|
+
|
48
|
+
# true if the current error might be recovered e.g. by re-trying the transaction
|
49
|
+
def recoverable?; jdbc_exception.is_a?(Java::JavaSql::SQLRecoverableException) end
|
50
|
+
# true when a failed operation might be able to succeed when retried (e.g. timeouts)
|
51
|
+
def transient?; jdbc_exception.is_a?(Java::JavaSql::SQLTransientException) end
|
52
|
+
|
53
|
+
# Likely (but not necessarily) the same as {#jdbc_exception}.
|
54
|
+
def cause; ( @cause ||= nil ) || jdbc_exception end
|
55
|
+
# @override
|
56
|
+
# @private for correct super-class (StatementInvalid) compatibility
|
57
|
+
alias_method :original_exception, :cause
|
58
|
+
|
59
|
+
# @override
|
60
|
+
def set_backtrace(backtrace)
|
61
|
+
@raw_backtrace = backtrace
|
62
|
+
if ( nested = cause ) && nested != self
|
63
|
+
backtrace = backtrace - (
|
64
|
+
nested.respond_to?(:raw_backtrace) ? nested.raw_backtrace : nested.backtrace )
|
65
|
+
backtrace << "#{nested.backtrace.first}: #{nested.message} (#{nested.class.name})"
|
66
|
+
backtrace.concat nested.backtrace[1..-1] || []
|
67
|
+
end
|
68
|
+
super(backtrace)
|
69
|
+
end
|
70
|
+
|
71
|
+
# @private
|
72
|
+
def raw_backtrace; @raw_backtrace ||= backtrace end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,69 @@
|
|
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 `ActiveRecord::ConnectionAdapters::AbstractAdapter` methods).
|
6
|
+
#
|
7
|
+
# When you declare your extension, you provide a block that detects when a
|
8
|
+
# database configured to use the extension is present and loads the necessary
|
9
|
+
# code for it. AR-JDBC will patch the code into the base `JdbcAdapter` by
|
10
|
+
# extending an instance of it with your extension module.
|
11
|
+
#
|
12
|
+
# @note This functionality is usually no longer needed and using ActiveRecord
|
13
|
+
# conventions (exporting a `xyz_connection` methods for `adapter: xyz`) should
|
14
|
+
# be preferred instead.
|
15
|
+
#
|
16
|
+
# @param name the name of a module to be defined under {ArJdbc}
|
17
|
+
# @param block should be a one or two-arity initialization code block that
|
18
|
+
# receives the dialect name or driver class name as the first argument, and
|
19
|
+
# optionally the database configuration hash as a second argument
|
20
|
+
# ```ruby
|
21
|
+
# ArJdbc.extension :MegaDB do |name|
|
22
|
+
# if name =~ /mega/i # driver or DB name returned by driver
|
23
|
+
# require 'arjdbc/megadb' # contains ArJdbc::MegaDB
|
24
|
+
# true
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# ```
|
28
|
+
def self.extension(name, &block)
|
29
|
+
if const_defined?(name)
|
30
|
+
mod = const_get(name)
|
31
|
+
else
|
32
|
+
mod = const_set(name, Module.new)
|
33
|
+
end
|
34
|
+
(class << mod; self; end).instance_eval do
|
35
|
+
define_method :adapter_matcher do |_name, config|
|
36
|
+
if block.arity == 1
|
37
|
+
block.call(_name) ? mod : false
|
38
|
+
else
|
39
|
+
block.call(_name, config) ? mod : false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end unless mod.respond_to?(:adapter_matcher)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.discover_extensions
|
46
|
+
if defined?(Gem) && Gem.respond_to?(:find_files)
|
47
|
+
arjdbc_path = Gem.loaded_specs['activerecord-jdbc-adapter-ficoh'].full_gem_path
|
48
|
+
files = Gem.find_files('arjdbc/discover').map do |path|
|
49
|
+
# in case multiple adapter gems installed only "self" discovery :
|
50
|
+
if path =~ /activerecord\-jdbc\-adapter\-.*\/lib\/arjdbc\/discover\.rb/
|
51
|
+
path.start_with?(arjdbc_path) ? path : nil
|
52
|
+
else
|
53
|
+
path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
else
|
57
|
+
files = $LOAD_PATH.map do |path|
|
58
|
+
discover = File.join(path, 'arjdbc', 'discover.rb')
|
59
|
+
File.exist?(discover) ? discover : nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
files.each do |file|
|
63
|
+
next unless file
|
64
|
+
puts "loading AR-JDBC extension #{file}" if $DEBUG
|
65
|
+
require file
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,154 @@
|
|
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
|
+
|
9
|
+
TRUE_VALUES = Column::TRUE_VALUES if Column.const_defined?(:TRUE_VALUES)
|
10
|
+
FALSE_VALUES = Column.const_defined?(:FALSE_VALUES) ? Column::FALSE_VALUES : ActiveModel::Type::Boolean::FALSE_VALUES
|
11
|
+
|
12
|
+
#module Format
|
13
|
+
ISO_DATE = Column::Format::ISO_DATE
|
14
|
+
ISO_DATETIME = Column::Format::ISO_DATETIME
|
15
|
+
#end
|
16
|
+
|
17
|
+
# Used to convert from BLOBs to Strings
|
18
|
+
def binary_to_string(value)
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
def value_to_date(value)
|
23
|
+
if value.is_a?(String)
|
24
|
+
return nil if value.empty?
|
25
|
+
fast_string_to_date(value) || fallback_string_to_date(value)
|
26
|
+
elsif value.respond_to?(:to_date)
|
27
|
+
value.to_date
|
28
|
+
else
|
29
|
+
value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def string_to_time(string)
|
34
|
+
return string unless string.is_a?(String)
|
35
|
+
return nil if string.empty?
|
36
|
+
return string if string =~ /^-?infinity$/.freeze
|
37
|
+
|
38
|
+
fast_string_to_time(string) || fallback_string_to_time(string)
|
39
|
+
end
|
40
|
+
|
41
|
+
def string_to_dummy_time(string)
|
42
|
+
return string unless string.is_a?(String)
|
43
|
+
return nil if string.empty?
|
44
|
+
|
45
|
+
dummy_time_string = "2000-01-01 #{string}"
|
46
|
+
|
47
|
+
fast_string_to_time(dummy_time_string) || begin
|
48
|
+
time_hash = Date._parse(dummy_time_string)
|
49
|
+
return nil if time_hash[:hour].nil?
|
50
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# convert something to a boolean
|
55
|
+
def value_to_boolean(value)
|
56
|
+
if value.is_a?(String) && value.empty?
|
57
|
+
nil
|
58
|
+
else
|
59
|
+
TRUE_VALUES.include?(value)
|
60
|
+
end
|
61
|
+
end if const_defined?(:TRUE_VALUES) # removed on AR 5.0
|
62
|
+
|
63
|
+
# convert something to a boolean
|
64
|
+
def value_to_boolean(value)
|
65
|
+
if value.is_a?(String) && value.empty?
|
66
|
+
nil
|
67
|
+
else
|
68
|
+
! FALSE_VALUES.include?(value)
|
69
|
+
end
|
70
|
+
end unless const_defined?(:TRUE_VALUES)
|
71
|
+
|
72
|
+
# Used to convert values to integer.
|
73
|
+
# handle the case when an integer column is used to store boolean values
|
74
|
+
def value_to_integer(value)
|
75
|
+
case value
|
76
|
+
when TrueClass, FalseClass
|
77
|
+
value ? 1 : 0
|
78
|
+
else
|
79
|
+
value.to_i rescue nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# convert something to a BigDecimal
|
84
|
+
def value_to_decimal(value)
|
85
|
+
# Using .class is faster than .is_a? and
|
86
|
+
# subclasses of BigDecimal will be handled
|
87
|
+
# in the else clause
|
88
|
+
if value.class == BigDecimal
|
89
|
+
value
|
90
|
+
elsif value.respond_to?(:to_d)
|
91
|
+
value.to_d
|
92
|
+
else
|
93
|
+
value.to_s.to_d
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
# '0.123456' -> 123456
|
99
|
+
# '1.123456' -> 123456
|
100
|
+
def microseconds(time)
|
101
|
+
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
|
102
|
+
end
|
103
|
+
|
104
|
+
def new_date(year, mon, mday)
|
105
|
+
if year && year != 0
|
106
|
+
Date.new(year, mon, mday) rescue nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
|
111
|
+
# Treat 0000-00-00 00:00:00 as nil.
|
112
|
+
return nil if year.nil? || (year == 0 && mon == 0 && mday == 0)
|
113
|
+
|
114
|
+
if offset
|
115
|
+
time = Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
|
116
|
+
return nil unless time
|
117
|
+
|
118
|
+
time -= offset
|
119
|
+
ActiveRecord::Base.default_timezone == :utc ? time : time.getlocal
|
120
|
+
else
|
121
|
+
timezone = ActiveRecord::Base.default_timezone
|
122
|
+
Time.public_send(timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def fast_string_to_date(string)
|
127
|
+
if string =~ ISO_DATE
|
128
|
+
new_date $1.to_i, $2.to_i, $3.to_i
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Doesn't handle time zones.
|
133
|
+
def fast_string_to_time(string)
|
134
|
+
if string =~ ISO_DATETIME
|
135
|
+
microsec = ($7.to_r * 1_000_000).to_i
|
136
|
+
new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def fallback_string_to_date(string)
|
141
|
+
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
142
|
+
end
|
143
|
+
|
144
|
+
def fallback_string_to_time(string)
|
145
|
+
time_hash = Date._parse(string)
|
146
|
+
time_hash[:sec_fraction] = microseconds(time_hash)
|
147
|
+
time_hash[:year] *= -1 if time_hash[:zone] == 'BC'
|
148
|
+
|
149
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
# I want to use JDBC's DatabaseMetaData#getTypeInfo to choose the best native types to
|
4
|
+
# use for ActiveRecord's Adapter#native_database_types in a database-independent way,
|
5
|
+
# but apparently a database driver can return multiple types for a given
|
6
|
+
# java.sql.Types constant. So this type converter uses some heuristics to try to pick
|
7
|
+
# the best (most common) type to use. It's not great, it would be better to just
|
8
|
+
# delegate to each database's existing AR adapter's native_database_types method, but I
|
9
|
+
# wanted to try to do this in a way that didn't pull in all the other adapters as
|
10
|
+
# dependencies. Improvements appreciated.
|
11
|
+
class JdbcTypeConverter
|
12
|
+
|
13
|
+
# @private
|
14
|
+
TEXT_TYPES = [ Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB ]
|
15
|
+
private_constant :TEXT_TYPES if respond_to? :private_constant
|
16
|
+
|
17
|
+
# @private
|
18
|
+
FLOAT_TYPES = [ Jdbc::Types::FLOAT, Jdbc::Types::DOUBLE, Jdbc::Types::REAL ]
|
19
|
+
private_constant :FLOAT_TYPES if respond_to? :private_constant
|
20
|
+
|
21
|
+
# @private
|
22
|
+
BINARY_TYPES = [ Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB ]
|
23
|
+
private_constant :BINARY_TYPES if respond_to? :private_constant
|
24
|
+
|
25
|
+
# The basic ActiveRecord types, mapped to an array of procs that are used to #select
|
26
|
+
# the best type. The procs are used as selectors in order until there is only one
|
27
|
+
# type left. If all the selectors are applied and there is still more than one
|
28
|
+
# type, an exception will be raised.
|
29
|
+
AR_TO_JDBC_TYPES = {
|
30
|
+
:string => [ lambda {|r| Jdbc::Types::VARCHAR == r['data_type'].to_i},
|
31
|
+
lambda {|r| r['type_name'] =~ /^varchar/i},
|
32
|
+
lambda {|r| r['type_name'] =~ /^varchar$/i},
|
33
|
+
lambda {|r| r['type_name'] =~ /varying/i}],
|
34
|
+
:text => [ lambda {|r| TEXT_TYPES.include?(r['data_type'].to_i)},
|
35
|
+
lambda {|r| r['type_name'] =~ /^text$/i}, # For Informix
|
36
|
+
lambda {|r| r['type_name'] =~ /sub_type 1$/i}, # For FireBird
|
37
|
+
lambda {|r| r['type_name'] =~ /^(text|clob)$/i},
|
38
|
+
lambda {|r| r['type_name'] =~ /^character large object$/i},
|
39
|
+
lambda {|r| r['sql_data_type'] == 2005}],
|
40
|
+
:integer => [ lambda {|r| Jdbc::Types::INTEGER == r['data_type'].to_i},
|
41
|
+
lambda {|r| r['type_name'] =~ /^integer$/i},
|
42
|
+
lambda {|r| r['type_name'] =~ /^int4$/i},
|
43
|
+
lambda {|r| r['type_name'] =~ /^int$/i}],
|
44
|
+
:decimal => [ lambda {|r| Jdbc::Types::DECIMAL == r['data_type'].to_i},
|
45
|
+
lambda {|r| r['type_name'] =~ /^decimal$/i},
|
46
|
+
lambda {|r| r['type_name'] =~ /^numeric$/i},
|
47
|
+
lambda {|r| r['type_name'] =~ /^number$/i},
|
48
|
+
lambda {|r| r['type_name'] =~ /^real$/i},
|
49
|
+
lambda {|r| r['precision'] == '38'},
|
50
|
+
lambda {|r| r['data_type'].to_i == Jdbc::Types::DECIMAL}],
|
51
|
+
:float => [ lambda {|r| FLOAT_TYPES.include?(r['data_type'].to_i)},
|
52
|
+
lambda {|r| r['data_type'].to_i == Jdbc::Types::REAL}, #Prefer REAL to DOUBLE for Postgresql
|
53
|
+
lambda {|r| r['type_name'] =~ /^float/i},
|
54
|
+
lambda {|r| r['type_name'] =~ /^double$/i},
|
55
|
+
lambda {|r| r['type_name'] =~ /^real$/i},
|
56
|
+
lambda {|r| r['precision'] == '15'}],
|
57
|
+
:datetime => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
|
58
|
+
lambda {|r| r['type_name'] =~ /^datetime$/i},
|
59
|
+
lambda {|r| r['type_name'] =~ /^timestamp$/i},
|
60
|
+
lambda {|r| r['type_name'] =~ /^datetime.+/i},
|
61
|
+
lambda {|r| r['type_name'] =~ /^date/i},
|
62
|
+
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
|
63
|
+
:timestamp => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
|
64
|
+
lambda {|r| r['type_name'] =~ /^timestamp$/i},
|
65
|
+
lambda {|r| r['type_name'] =~ /^datetime$/i},
|
66
|
+
lambda {|r| r['type_name'] =~ /^datetime.+/i},
|
67
|
+
lambda {|r| r['type_name'] =~ /^date/i},
|
68
|
+
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
|
69
|
+
:time => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
|
70
|
+
lambda {|r| r['type_name'] =~ /^time$/i},
|
71
|
+
lambda {|r| r['type_name'] =~ /^datetime$/i},
|
72
|
+
lambda {|r| r['type_name'] =~ /^datetime.+/i}, # For Informix
|
73
|
+
lambda {|r| r['type_name'] =~ /^date/i},
|
74
|
+
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
|
75
|
+
:date => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
|
76
|
+
lambda {|r| r['type_name'] =~ /^date$/i},
|
77
|
+
lambda {|r| r['type_name'] =~ /^date/i},
|
78
|
+
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver3
|
79
|
+
:binary => [ lambda {|r| BINARY_TYPES.include?(r['data_type'].to_i)},
|
80
|
+
lambda {|r| r['type_name'] =~ /^blob/i},
|
81
|
+
lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
|
82
|
+
lambda {|r| r['type_name'] =~ /^varbinary$/i}, # We want this sucker for Mimer
|
83
|
+
lambda {|r| r['type_name'] =~ /^binary$/i}, ],
|
84
|
+
:boolean => [ lambda {|r| Jdbc::Types::BIT == r['data_type'].to_i && r['precision'].to_i == 1},
|
85
|
+
lambda {|r| Jdbc::Types::TINYINT == r['data_type'].to_i},
|
86
|
+
lambda {|r| r['type_name'] =~ /^bool/i},
|
87
|
+
lambda {|r| r['data_type'].to_i == Jdbc::Types::BIT},
|
88
|
+
lambda {|r| r['type_name'] =~ /^tinyint$/i},
|
89
|
+
lambda {|r| r['type_name'] =~ /^decimal$/i},
|
90
|
+
lambda {|r| r['type_name'] =~ /^integer$/i}]
|
91
|
+
}
|
92
|
+
|
93
|
+
def initialize(types)
|
94
|
+
@types = types
|
95
|
+
@types.each {|t| t['type_name'] ||= t['local_type_name']} # Sybase driver seems to want 'local_type_name'
|
96
|
+
end
|
97
|
+
|
98
|
+
def choose_best_types
|
99
|
+
type_map = {}
|
100
|
+
@types.each do |row|
|
101
|
+
name = row['type_name'].downcase
|
102
|
+
k = name.to_sym
|
103
|
+
type_map[k] = { :name => name }
|
104
|
+
set_limit_to_nonzero_precision(type_map[k], row)
|
105
|
+
end
|
106
|
+
|
107
|
+
AR_TO_JDBC_TYPES.keys.each do |ar_type|
|
108
|
+
typerow = choose_type(ar_type)
|
109
|
+
type_map[ar_type] = { :name => typerow['type_name'].downcase }
|
110
|
+
case ar_type
|
111
|
+
when :integer, :string, :decimal
|
112
|
+
set_limit_to_nonzero_precision(type_map[ar_type], typerow)
|
113
|
+
when :boolean
|
114
|
+
type_map[ar_type][:limit] = 1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
type_map
|
118
|
+
end
|
119
|
+
|
120
|
+
def choose_type(ar_type)
|
121
|
+
types = @types
|
122
|
+
AR_TO_JDBC_TYPES[ar_type].each do |proc|
|
123
|
+
new_types = types.reject {|r| r["data_type"].to_i == Jdbc::Types::OTHER}
|
124
|
+
new_types = new_types.select(&proc)
|
125
|
+
new_types = new_types.inject([]) do |typs,t|
|
126
|
+
typs << t unless typs.detect {|el| el['type_name'] == t['type_name']}
|
127
|
+
typs
|
128
|
+
end
|
129
|
+
return new_types.first if new_types.length == 1
|
130
|
+
types = new_types if new_types.length > 0
|
131
|
+
end
|
132
|
+
raise "unable to choose type for #{ar_type} from:\n#{types.collect{|t| t['type_name']}.inspect}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def set_limit_to_nonzero_precision(map, row)
|
136
|
+
if row['precision'] && row['precision'].to_i > 0
|
137
|
+
map[:limit] = row['precision'].to_i
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|