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.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +462 -0
  4. data/.yardopts +4 -0
  5. data/Appraisals +36 -0
  6. data/CONTRIBUTING.md +49 -0
  7. data/Gemfile +68 -0
  8. data/History.md +1191 -0
  9. data/LICENSE.txt +25 -0
  10. data/README.md +277 -0
  11. data/RUNNING_TESTS.md +88 -0
  12. data/Rakefile +298 -0
  13. data/Rakefile.jdbc +20 -0
  14. data/activerecord-jdbc-adapter.gemspec +63 -0
  15. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  16. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  19. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  31. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  32. data/lib/activerecord-jdbc-adapter.rb +1 -0
  33. data/lib/arel/visitors/compat.rb +64 -0
  34. data/lib/arel/visitors/db2.rb +137 -0
  35. data/lib/arel/visitors/derby.rb +112 -0
  36. data/lib/arel/visitors/firebird.rb +79 -0
  37. data/lib/arel/visitors/h2.rb +25 -0
  38. data/lib/arel/visitors/hsqldb.rb +32 -0
  39. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  40. data/lib/arel/visitors/sql_server.rb +225 -0
  41. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  42. data/lib/arjdbc.rb +22 -0
  43. data/lib/arjdbc/db2.rb +4 -0
  44. data/lib/arjdbc/db2/adapter.rb +802 -0
  45. data/lib/arjdbc/db2/as400.rb +137 -0
  46. data/lib/arjdbc/db2/column.rb +177 -0
  47. data/lib/arjdbc/db2/connection_methods.rb +45 -0
  48. data/lib/arjdbc/derby.rb +3 -0
  49. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  50. data/lib/arjdbc/derby/adapter.rb +567 -0
  51. data/lib/arjdbc/derby/connection_methods.rb +16 -0
  52. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  53. data/lib/arjdbc/discover.rb +104 -0
  54. data/lib/arjdbc/firebird.rb +4 -0
  55. data/lib/arjdbc/firebird/adapter.rb +468 -0
  56. data/lib/arjdbc/firebird/connection_methods.rb +20 -0
  57. data/lib/arjdbc/h2.rb +3 -0
  58. data/lib/arjdbc/h2/adapter.rb +335 -0
  59. data/lib/arjdbc/h2/connection_methods.rb +22 -0
  60. data/lib/arjdbc/hsqldb.rb +3 -0
  61. data/lib/arjdbc/hsqldb/adapter.rb +304 -0
  62. data/lib/arjdbc/hsqldb/connection_methods.rb +23 -0
  63. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  64. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  65. data/lib/arjdbc/informix.rb +5 -0
  66. data/lib/arjdbc/informix/adapter.rb +160 -0
  67. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  68. data/lib/arjdbc/jdbc.rb +62 -0
  69. data/lib/arjdbc/jdbc/adapter.rb +997 -0
  70. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  71. data/lib/arjdbc/jdbc/arel_support.rb +149 -0
  72. data/lib/arjdbc/jdbc/base_ext.rb +34 -0
  73. data/lib/arjdbc/jdbc/callbacks.rb +52 -0
  74. data/lib/arjdbc/jdbc/column.rb +83 -0
  75. data/lib/arjdbc/jdbc/connection.rb +26 -0
  76. data/lib/arjdbc/jdbc/connection_methods.rb +59 -0
  77. data/lib/arjdbc/jdbc/driver.rb +44 -0
  78. data/lib/arjdbc/jdbc/error.rb +75 -0
  79. data/lib/arjdbc/jdbc/extension.rb +69 -0
  80. data/lib/arjdbc/jdbc/java.rb +13 -0
  81. data/lib/arjdbc/jdbc/type_cast.rb +154 -0
  82. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  83. data/lib/arjdbc/mssql.rb +7 -0
  84. data/lib/arjdbc/mssql/adapter.rb +822 -0
  85. data/lib/arjdbc/mssql/column.rb +207 -0
  86. data/lib/arjdbc/mssql/connection_methods.rb +72 -0
  87. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  88. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  89. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  90. data/lib/arjdbc/mssql/types.rb +343 -0
  91. data/lib/arjdbc/mssql/utils.rb +82 -0
  92. data/lib/arjdbc/mysql.rb +3 -0
  93. data/lib/arjdbc/mysql/adapter.rb +998 -0
  94. data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
  95. data/lib/arjdbc/mysql/column.rb +167 -0
  96. data/lib/arjdbc/mysql/connection_methods.rb +137 -0
  97. data/lib/arjdbc/mysql/explain_support.rb +82 -0
  98. data/lib/arjdbc/mysql/schema_creation.rb +58 -0
  99. data/lib/arjdbc/oracle.rb +4 -0
  100. data/lib/arjdbc/oracle/adapter.rb +968 -0
  101. data/lib/arjdbc/oracle/column.rb +136 -0
  102. data/lib/arjdbc/oracle/connection_methods.rb +21 -0
  103. data/lib/arjdbc/postgresql.rb +3 -0
  104. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
  105. data/lib/arjdbc/postgresql/adapter.rb +1498 -0
  106. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  107. data/lib/arjdbc/postgresql/base/oid.rb +412 -0
  108. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
  109. data/lib/arjdbc/postgresql/base/schema_definitions.rb +132 -0
  110. data/lib/arjdbc/postgresql/column.rb +640 -0
  111. data/lib/arjdbc/postgresql/connection_methods.rb +44 -0
  112. data/lib/arjdbc/postgresql/explain_support.rb +53 -0
  113. data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
  114. data/lib/arjdbc/postgresql/oid_types.rb +265 -0
  115. data/lib/arjdbc/postgresql/schema_creation.rb +60 -0
  116. data/lib/arjdbc/railtie.rb +11 -0
  117. data/lib/arjdbc/sqlite3.rb +3 -0
  118. data/lib/arjdbc/sqlite3/adapter.rb +654 -0
  119. data/lib/arjdbc/sqlite3/connection_methods.rb +36 -0
  120. data/lib/arjdbc/sqlite3/explain_support.rb +29 -0
  121. data/lib/arjdbc/sybase.rb +2 -0
  122. data/lib/arjdbc/sybase/adapter.rb +47 -0
  123. data/lib/arjdbc/tasks.rb +13 -0
  124. data/lib/arjdbc/tasks/database_tasks.rb +66 -0
  125. data/lib/arjdbc/tasks/databases.rake +91 -0
  126. data/lib/arjdbc/tasks/databases3.rake +239 -0
  127. data/lib/arjdbc/tasks/databases4.rake +39 -0
  128. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  129. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  130. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  131. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  132. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  133. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  134. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
  135. data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
  136. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  137. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  138. data/lib/arjdbc/util/table_copier.rb +108 -0
  139. data/lib/arjdbc/version.rb +8 -0
  140. data/lib/generators/jdbc/USAGE +9 -0
  141. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  142. data/pom.xml +285 -0
  143. data/rails_generators/jdbc_generator.rb +15 -0
  144. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  145. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  146. data/rakelib/01-tomcat.rake +51 -0
  147. data/rakelib/02-test.rake +151 -0
  148. data/rakelib/bundler_ext.rb +11 -0
  149. data/rakelib/db.rake +58 -0
  150. data/rakelib/rails.rake +77 -0
  151. data/src/java/arjdbc/ArJdbcModule.java +288 -0
  152. data/src/java/arjdbc/db2/DB2Module.java +77 -0
  153. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +128 -0
  154. data/src/java/arjdbc/derby/DerbyModule.java +180 -0
  155. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +153 -0
  156. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
  157. data/src/java/arjdbc/h2/H2Module.java +50 -0
  158. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +86 -0
  159. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +74 -0
  160. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +76 -0
  161. data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
  162. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  163. data/src/java/arjdbc/jdbc/ConnectionFactory.java +77 -0
  164. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
  165. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  166. data/src/java/arjdbc/jdbc/DriverWrapper.java +128 -0
  167. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +32 -0
  168. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4541 -0
  169. data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
  170. data/src/java/arjdbc/jdbc/WithResultSet.java +37 -0
  171. data/src/java/arjdbc/mssql/MSSQLModule.java +91 -0
  172. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +193 -0
  173. data/src/java/arjdbc/mysql/MySQLModule.java +140 -0
  174. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +456 -0
  175. data/src/java/arjdbc/oracle/OracleModule.java +81 -0
  176. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +477 -0
  177. data/src/java/arjdbc/postgresql/ByteaUtils.java +171 -0
  178. data/src/java/arjdbc/postgresql/DriverImplementation.java +78 -0
  179. data/src/java/arjdbc/postgresql/PGDriverImplementation.java +535 -0
  180. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +189 -0
  181. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +489 -0
  182. data/src/java/arjdbc/sqlite3/SQLite3Module.java +93 -0
  183. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +405 -0
  184. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  185. data/src/java/arjdbc/util/DateTimeUtils.java +517 -0
  186. data/src/java/arjdbc/util/NumberUtils.java +50 -0
  187. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  188. data/src/java/arjdbc/util/QuotingUtils.java +139 -0
  189. data/src/java/arjdbc/util/StringCache.java +60 -0
  190. data/src/java/arjdbc/util/StringHelper.java +155 -0
  191. 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,13 @@
1
+ require 'java'
2
+ require 'arjdbc/jdbc/adapter_java'
3
+
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module Jdbc
7
+ # @private
8
+ DriverManager = ::Java::JavaSql::DriverManager
9
+ # @private
10
+ Types = ::Java::JavaSql::Types
11
+ end
12
+ end
13
+ 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