activerecord-jdbc-adapter 1.0.3-java → 50.1-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 (268) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.travis.yml +79 -0
  4. data/.yardopts +4 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/Gemfile +91 -0
  7. data/History.md +1191 -0
  8. data/LICENSE.txt +22 -17
  9. data/README.md +169 -0
  10. data/RUNNING_TESTS.md +127 -0
  11. data/Rakefile +294 -5
  12. data/Rakefile.jdbc +20 -0
  13. data/activerecord-jdbc-adapter.gemspec +55 -0
  14. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  15. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  16. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  19. data/lib/activerecord-jdbc-adapter.rb +0 -5
  20. data/lib/arel/visitors/compat.rb +60 -0
  21. data/lib/arel/visitors/db2.rb +128 -6
  22. data/lib/arel/visitors/derby.rb +103 -10
  23. data/lib/arel/visitors/firebird.rb +79 -0
  24. data/lib/arel/visitors/h2.rb +25 -0
  25. data/lib/arel/visitors/hsqldb.rb +18 -10
  26. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  27. data/lib/arel/visitors/sql_server.rb +225 -0
  28. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  29. data/lib/arjdbc.rb +11 -21
  30. data/lib/arjdbc/abstract/connection_management.rb +35 -0
  31. data/lib/arjdbc/abstract/core.rb +64 -0
  32. data/lib/arjdbc/abstract/database_statements.rb +64 -0
  33. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  34. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  35. data/lib/arjdbc/db2.rb +3 -1
  36. data/lib/arjdbc/db2/adapter.rb +630 -250
  37. data/lib/arjdbc/db2/as400.rb +130 -0
  38. data/lib/arjdbc/db2/column.rb +167 -0
  39. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  40. data/lib/arjdbc/derby.rb +1 -5
  41. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  42. data/lib/arjdbc/derby/adapter.rb +409 -217
  43. data/lib/arjdbc/derby/connection_methods.rb +16 -14
  44. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  45. data/lib/arjdbc/discover.rb +62 -50
  46. data/lib/arjdbc/firebird.rb +3 -1
  47. data/lib/arjdbc/firebird/adapter.rb +365 -62
  48. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  49. data/lib/arjdbc/h2.rb +2 -3
  50. data/lib/arjdbc/h2/adapter.rb +273 -6
  51. data/lib/arjdbc/h2/connection_methods.rb +23 -8
  52. data/lib/arjdbc/hsqldb.rb +2 -3
  53. data/lib/arjdbc/hsqldb/adapter.rb +204 -77
  54. data/lib/arjdbc/hsqldb/connection_methods.rb +24 -10
  55. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  56. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  57. data/lib/arjdbc/informix.rb +4 -2
  58. data/lib/arjdbc/informix/adapter.rb +78 -54
  59. data/lib/arjdbc/informix/connection_methods.rb +8 -9
  60. data/lib/arjdbc/jdbc.rb +59 -2
  61. data/lib/arjdbc/jdbc/adapter.rb +356 -166
  62. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  63. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  64. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  65. data/lib/arjdbc/jdbc/callbacks.rb +27 -18
  66. data/lib/arjdbc/jdbc/column.rb +79 -20
  67. data/lib/arjdbc/jdbc/connection.rb +5 -119
  68. data/lib/arjdbc/jdbc/connection_methods.rb +32 -4
  69. data/lib/arjdbc/jdbc/error.rb +65 -0
  70. data/lib/arjdbc/jdbc/extension.rb +41 -29
  71. data/lib/arjdbc/jdbc/java.rb +5 -6
  72. data/lib/arjdbc/jdbc/jdbc.rake +3 -126
  73. data/lib/arjdbc/jdbc/railtie.rb +2 -9
  74. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
  75. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  76. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  77. data/lib/arjdbc/jdbc/type_converter.rb +35 -19
  78. data/lib/arjdbc/mssql.rb +6 -3
  79. data/lib/arjdbc/mssql/adapter.rb +630 -298
  80. data/lib/arjdbc/mssql/column.rb +200 -0
  81. data/lib/arjdbc/mssql/connection_methods.rb +66 -17
  82. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  83. data/lib/arjdbc/mssql/limit_helpers.rb +189 -50
  84. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  85. data/lib/arjdbc/mssql/types.rb +343 -0
  86. data/lib/arjdbc/mssql/utils.rb +82 -0
  87. data/lib/arjdbc/mysql.rb +2 -3
  88. data/lib/arjdbc/mysql/adapter.rb +86 -356
  89. data/lib/arjdbc/mysql/connection_methods.rb +159 -23
  90. data/lib/arjdbc/oracle/adapter.rb +714 -263
  91. data/lib/arjdbc/postgresql.rb +2 -3
  92. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +24 -0
  93. data/lib/arjdbc/postgresql/adapter.rb +570 -400
  94. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  95. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  96. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  97. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  98. data/lib/arjdbc/postgresql/column.rb +51 -0
  99. data/lib/arjdbc/postgresql/connection_methods.rb +57 -18
  100. data/lib/arjdbc/postgresql/name.rb +24 -0
  101. data/lib/arjdbc/postgresql/oid_types.rb +192 -0
  102. data/lib/arjdbc/railtie.rb +11 -0
  103. data/lib/arjdbc/sqlite3.rb +2 -3
  104. data/lib/arjdbc/sqlite3/adapter.rb +518 -198
  105. data/lib/arjdbc/sqlite3/connection_methods.rb +49 -24
  106. data/lib/arjdbc/sybase.rb +2 -2
  107. data/lib/arjdbc/sybase/adapter.rb +7 -6
  108. data/lib/arjdbc/tasks.rb +13 -0
  109. data/lib/arjdbc/tasks/database_tasks.rb +52 -0
  110. data/lib/arjdbc/tasks/databases.rake +91 -0
  111. data/lib/arjdbc/tasks/databases3.rake +215 -0
  112. data/lib/arjdbc/tasks/databases4.rake +39 -0
  113. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  114. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  115. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  116. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  117. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  118. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  119. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  120. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  121. data/lib/arjdbc/util/table_copier.rb +110 -0
  122. data/lib/arjdbc/version.rb +1 -6
  123. data/lib/generators/jdbc/USAGE +9 -0
  124. data/lib/generators/jdbc/jdbc_generator.rb +8 -0
  125. data/lib/jdbc_adapter.rb +1 -1
  126. data/lib/jdbc_adapter/rake_tasks.rb +3 -2
  127. data/lib/jdbc_adapter/version.rb +2 -1
  128. data/pom.xml +114 -0
  129. data/rails_generators/jdbc_generator.rb +1 -1
  130. data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
  131. data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
  132. data/rakelib/01-tomcat.rake +51 -0
  133. data/rakelib/02-test.rake +132 -0
  134. data/rakelib/bundler_ext.rb +11 -0
  135. data/rakelib/compile.rake +67 -22
  136. data/rakelib/db.rake +61 -0
  137. data/rakelib/rails.rake +204 -29
  138. data/src/java/arjdbc/ArJdbcModule.java +286 -0
  139. data/src/java/arjdbc/db2/DB2Module.java +76 -0
  140. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
  141. data/src/java/arjdbc/derby/DerbyModule.java +99 -243
  142. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
  143. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
  144. data/src/java/arjdbc/{jdbc/JdbcConnectionFactory.java → h2/H2Module.java} +20 -6
  145. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +27 -12
  146. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
  147. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +7 -6
  148. data/src/java/arjdbc/jdbc/AdapterJavaService.java +7 -29
  149. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  150. data/src/java/arjdbc/jdbc/ConnectionFactory.java +132 -0
  151. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +157 -0
  152. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  153. data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
  154. data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
  155. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3622 -948
  156. data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
  157. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +181 -0
  158. data/src/java/arjdbc/mysql/MySQLModule.java +99 -81
  159. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
  160. data/src/java/arjdbc/oracle/OracleModule.java +80 -0
  161. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +387 -17
  162. data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
  163. data/src/java/arjdbc/postgresql/PgResultSetMetaDataWrapper.java +23 -0
  164. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
  165. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +184 -0
  166. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +952 -0
  167. data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
  168. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
  169. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  170. data/src/java/arjdbc/util/DateTimeUtils.java +580 -0
  171. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  172. data/src/java/arjdbc/util/QuotingUtils.java +138 -0
  173. data/src/java/arjdbc/util/StringCache.java +63 -0
  174. data/src/java/arjdbc/util/StringHelper.java +159 -0
  175. metadata +245 -268
  176. data/History.txt +0 -369
  177. data/Manifest.txt +0 -180
  178. data/README.txt +0 -181
  179. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  180. data/lib/arel/engines/sql/compilers/db2_compiler.rb +0 -9
  181. data/lib/arel/engines/sql/compilers/derby_compiler.rb +0 -6
  182. data/lib/arel/engines/sql/compilers/h2_compiler.rb +0 -6
  183. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +0 -15
  184. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +0 -6
  185. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +0 -46
  186. data/lib/arel/visitors/mssql.rb +0 -44
  187. data/lib/arjdbc/jdbc/compatibility.rb +0 -51
  188. data/lib/arjdbc/jdbc/core_ext.rb +0 -24
  189. data/lib/arjdbc/jdbc/discover.rb +0 -18
  190. data/lib/arjdbc/jdbc/driver.rb +0 -44
  191. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +0 -87
  192. data/lib/arjdbc/jdbc/quoted_primary_key.rb +0 -28
  193. data/lib/arjdbc/jdbc/require_driver.rb +0 -16
  194. data/lib/arjdbc/mimer.rb +0 -2
  195. data/lib/arjdbc/mimer/adapter.rb +0 -142
  196. data/lib/arjdbc/mssql/tsql_helper.rb +0 -61
  197. data/lib/arjdbc/oracle.rb +0 -3
  198. data/lib/arjdbc/oracle/connection_methods.rb +0 -11
  199. data/lib/pg.rb +0 -4
  200. data/rakelib/package.rake +0 -92
  201. data/rakelib/test.rake +0 -81
  202. data/src/java/arjdbc/jdbc/SQLBlock.java +0 -48
  203. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +0 -127
  204. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +0 -57
  205. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +0 -64
  206. data/test/abstract_db_create.rb +0 -117
  207. data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -31
  208. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +0 -25
  209. data/test/db/db2.rb +0 -11
  210. data/test/db/derby.rb +0 -12
  211. data/test/db/h2.rb +0 -11
  212. data/test/db/hsqldb.rb +0 -13
  213. data/test/db/informix.rb +0 -11
  214. data/test/db/jdbc.rb +0 -11
  215. data/test/db/jndi_config.rb +0 -40
  216. data/test/db/logger.rb +0 -3
  217. data/test/db/mssql.rb +0 -9
  218. data/test/db/mysql.rb +0 -10
  219. data/test/db/oracle.rb +0 -34
  220. data/test/db/postgres.rb +0 -9
  221. data/test/db/sqlite3.rb +0 -11
  222. data/test/db2_simple_test.rb +0 -66
  223. data/test/derby_migration_test.rb +0 -68
  224. data/test/derby_multibyte_test.rb +0 -12
  225. data/test/derby_simple_test.rb +0 -99
  226. data/test/generic_jdbc_connection_test.rb +0 -29
  227. data/test/h2_simple_test.rb +0 -41
  228. data/test/has_many_through.rb +0 -79
  229. data/test/helper.rb +0 -5
  230. data/test/hsqldb_simple_test.rb +0 -6
  231. data/test/informix_simple_test.rb +0 -48
  232. data/test/jdbc_common.rb +0 -25
  233. data/test/jndi_callbacks_test.rb +0 -40
  234. data/test/jndi_test.rb +0 -25
  235. data/test/manualTestDatabase.rb +0 -191
  236. data/test/models/add_not_null_column_to_table.rb +0 -12
  237. data/test/models/auto_id.rb +0 -18
  238. data/test/models/data_types.rb +0 -28
  239. data/test/models/entry.rb +0 -43
  240. data/test/models/mixed_case.rb +0 -25
  241. data/test/models/reserved_word.rb +0 -18
  242. data/test/models/string_id.rb +0 -18
  243. data/test/models/validates_uniqueness_of_string.rb +0 -19
  244. data/test/mssql_db_create_test.rb +0 -26
  245. data/test/mssql_identity_insert_test.rb +0 -19
  246. data/test/mssql_legacy_types_test.rb +0 -58
  247. data/test/mssql_limit_offset_test.rb +0 -136
  248. data/test/mssql_multibyte_test.rb +0 -18
  249. data/test/mssql_simple_test.rb +0 -55
  250. data/test/mysql_db_create_test.rb +0 -27
  251. data/test/mysql_info_test.rb +0 -113
  252. data/test/mysql_multibyte_test.rb +0 -10
  253. data/test/mysql_nonstandard_primary_key_test.rb +0 -42
  254. data/test/mysql_simple_test.rb +0 -49
  255. data/test/oracle_simple_test.rb +0 -18
  256. data/test/oracle_specific_test.rb +0 -83
  257. data/test/pick_rails_version.rb +0 -3
  258. data/test/postgres_db_create_test.rb +0 -32
  259. data/test/postgres_drop_db_test.rb +0 -16
  260. data/test/postgres_mixed_case_test.rb +0 -29
  261. data/test/postgres_nonseq_pkey_test.rb +0 -38
  262. data/test/postgres_reserved_test.rb +0 -22
  263. data/test/postgres_schema_search_path_test.rb +0 -44
  264. data/test/postgres_simple_test.rb +0 -51
  265. data/test/postgres_table_alias_length_test.rb +0 -15
  266. data/test/simple.rb +0 -546
  267. data/test/sqlite3_simple_test.rb +0 -233
  268. data/test/sybase_jtds_simple_test.rb +0 -28
@@ -1,14 +1,28 @@
1
- module ActiveRecord
2
- class Base
3
- class << self
4
- def hsqldb_connection(config)
5
- require "arjdbc/hsqldb"
6
- config[:url] ||= "jdbc:hsqldb:#{config[:database]}"
7
- config[:driver] ||= "org.hsqldb.jdbcDriver"
8
- embedded_driver(config)
9
- end
1
+ ArJdbc::ConnectionMethods.module_eval do
2
+ def hsqldb_connection(config)
3
+ config[:adapter_spec] ||= ::ArJdbc::HSQLDB
4
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::HsqldbAdapter unless config.key?(:adapter_class)
5
+
6
+ return jndi_connection(config) if jndi_config?(config)
7
+
8
+ begin
9
+ require 'jdbc/hsqldb'
10
+ ::Jdbc::HSQLDB.load_driver(:require) if defined?(::Jdbc::HSQLDB.load_driver)
11
+ rescue LoadError # assuming driver.jar is on the class-path
12
+ end
10
13
 
11
- alias_method :jdbchsqldb_connection, :hsqldb_connection
14
+ config[:url] ||= begin
15
+ db = config[:database]
16
+ if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
17
+ "jdbc:hsqldb:#{db}"
18
+ else
19
+ "jdbc:hsqldb:file:#{db}"
20
+ end
12
21
  end
22
+ config[:driver] ||= defined?(::Jdbc::HSQLDB.driver_name) ? ::Jdbc::HSQLDB.driver_name : 'org.hsqldb.jdbcDriver'
23
+ config[:connection_alive_sql] ||= 'CALL PI()' # does not like 'SELECT 1'
24
+
25
+ embedded_driver(config)
13
26
  end
27
+ alias_method :jdbchsqldb_connection, :hsqldb_connection
14
28
  end
@@ -0,0 +1,35 @@
1
+ module ArJdbc
2
+ module HSQLDB
3
+ module ExplainSupport
4
+ def supports_explain?; true; end
5
+
6
+ def explain(arel, binds = [])
7
+ sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
8
+ raw_result = exec_query_raw(sql, "EXPLAIN", binds)
9
+ # HSQLDB's SqlTool just prints it as it comes :
10
+ #
11
+ # sql> EXPLAIN PLAN FOR SELECT * FROM entries JOIN users on ... ;
12
+ #
13
+ # isDistinctSelect=[false]
14
+ # isGrouped=[false]
15
+ # isAggregated=[false]
16
+ # columns=[ COLUMN: PUBLIC.ENTRIES.ID
17
+ # not nullable COLUMN: PUBLIC.ENTRIES.TITLE
18
+ # nullable COLUMN: PUBLIC.ENTRIES.UPDATED_ON
19
+ # nullable COLUMN: PUBLIC.ENTRIES.CONTENT
20
+ # nullable COLUMN: PUBLIC.ENTRIES.RATING
21
+ # nullable COLUMN: PUBLIC.ENTRIES.USER_ID
22
+ # nullable COLUMN: PUBLIC.USERS.ID
23
+ # not nullable COLUMN: PUBLIC.USERS.LOGIN
24
+ # nullable
25
+ # ]
26
+ # ...
27
+ # PARAMETERS=[]
28
+ # SUBQUERIES[]
29
+ #
30
+ raw_result.map!(&:values)
31
+ raw_result.join("\n")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module ArJdbc
2
+ module HSQLDB
3
+ # @private
4
+ SchemaCreation = ::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
5
+
6
+ def schema_creation
7
+ SchemaCreation.new self
8
+ end
9
+
10
+ end
11
+ end if ::ActiveRecord::ConnectionAdapters::AbstractAdapter.const_defined? :SchemaCreation
@@ -1,3 +1,5 @@
1
- require 'arjdbc/jdbc'
2
- require 'arjdbc/informix/connection_methods'
1
+ require 'arjdbc'
2
+ ArJdbc.load_java_part :Informix
3
3
  require 'arjdbc/informix/adapter'
4
+ require 'arjdbc/informix/connection_methods'
5
+ ArJdbc.warn_unsupported_adapter 'informix', [4, 2] # warns on AR >= 4.2
@@ -1,47 +1,53 @@
1
- module ::ActiveRecord
2
- class Base
3
- after_save :write_lobs
4
-
5
- private
6
- def write_lobs
7
- if connection.is_a?(ArJdbc::Informix)
8
- self.class.columns.each do |c|
9
- if [:text, :binary].include? c.type
10
- value = self[c.name]
11
- value = value.to_yaml if unserializable_attribute?(c.name, c)
12
-
13
- unless value.nil? || (value == '')
14
- connection.write_large_object(c.type == :binary,
15
- c.name,
16
- self.class.table_name,
17
- self.class.primary_key,
18
- quote_value(id),
19
- value)
1
+ require 'arjdbc/util/serialized_attributes'
2
+
3
+ module ArJdbc
4
+ module Informix
5
+
6
+ @@_lob_callback_added = nil
7
+
8
+ def self.extended(base)
9
+ unless @@_lob_callback_added
10
+ ActiveRecord::Base.class_eval do
11
+ def after_save_with_informix_lob
12
+ lob_columns = self.class.columns.select { |c| [:text, :binary].include?(c.type) }
13
+ lob_columns.each do |column|
14
+ value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
15
+ next if value.nil? || (value == '')
16
+
17
+ connection.write_large_object(
18
+ column.type == :binary, column.name,
19
+ self.class.table_name, self.class.primary_key,
20
+ quote_value(id), value
21
+ )
20
22
  end
21
23
  end
22
24
  end
23
- end
24
- end
25
- end
26
- end
27
25
 
28
- module ::ArJdbc
29
- module Informix
30
- def self.extended(base)
31
- @@db_major_version = base.select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
26
+ ActiveRecord::Base.after_save :after_save_with_informix_lob
27
+ @@_lob_callback_added = true
28
+ end
32
29
  end
33
30
 
31
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
34
32
  def self.column_selector
35
- [ /informix/i,
36
- lambda { |cfg, column| column.extend(::ArJdbc::Informix::Column) } ]
33
+ [ /informix/i, lambda { |cfg, column| column.extend(ColumnMethods) } ]
37
34
  end
38
35
 
36
+ JdbcConnection = ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
37
+
38
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
39
39
  def self.jdbc_connection_class
40
40
  ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
41
41
  end
42
42
 
43
- module Column
44
- private
43
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
44
+ def jdbc_column_class
45
+ ::ActiveRecord::ConnectionAdapters::InformixColumn
46
+ end
47
+
48
+ module ColumnMethods
49
+
50
+ private
45
51
  # TODO: Test all Informix column types.
46
52
  def simplified_type(field_type)
47
53
  if field_type =~ /serial/i
@@ -50,21 +56,23 @@ module ::ArJdbc
50
56
  super
51
57
  end
52
58
  end
59
+
53
60
  end
54
61
 
55
- def modify_types(tp)
56
- tp[:primary_key] = "SERIAL PRIMARY KEY"
57
- tp[:string] = { :name => "VARCHAR", :limit => 255 }
58
- tp[:integer] = { :name => "INTEGER" }
59
- tp[:float] = { :name => "FLOAT" }
60
- tp[:decimal] = { :name => "DECIMAL" }
61
- tp[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
62
- tp[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
63
- tp[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
64
- tp[:date] = { :name => "DATE" }
65
- tp[:binary] = { :name => "BYTE" }
66
- tp[:boolean] = { :name => "BOOLEAN" }
67
- tp
62
+ def modify_types(types)
63
+ super(types)
64
+ types[:primary_key] = "SERIAL PRIMARY KEY"
65
+ types[:string] = { :name => "VARCHAR", :limit => 255 }
66
+ types[:integer] = { :name => "INTEGER" }
67
+ types[:float] = { :name => "FLOAT" }
68
+ types[:decimal] = { :name => "DECIMAL" }
69
+ types[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
70
+ types[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
71
+ types[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
72
+ types[:date] = { :name => "DATE" }
73
+ types[:binary] = { :name => "BYTE" }
74
+ types[:boolean] = { :name => "BOOLEAN" }
75
+ types
68
76
  end
69
77
 
70
78
  def prefetch_primary_key?(table_name = nil)
@@ -81,11 +89,9 @@ module ::ArJdbc
81
89
 
82
90
  def add_limit_offset!(sql, options)
83
91
  if options[:limit]
84
- limit = "FIRST #{options[:limit]}"
85
- # SKIP available only in IDS >= 10
86
- offset = (@@db_major_version >= 10 && options[:offset]?
87
- "SKIP #{options[:offset]}" : "")
88
- sql.sub!(/^select /i, "SELECT #{offset} #{limit} ")
92
+ limit = "FIRST #{options[:limit]}" # SKIP available only in IDS >= 10 :
93
+ offset = (db_major_version >= 10 && options[:offset] ? "SKIP #{options[:offset]}" : "")
94
+ sql.sub!(/^\s*?select /i, "SELECT #{offset} #{limit} ")
89
95
  end
90
96
  sql
91
97
  end
@@ -100,10 +106,11 @@ module ::ArJdbc
100
106
  end
101
107
 
102
108
  def quote(value, column = nil)
103
- if column && [:binary, :text].include?(column.type)
109
+ column_type = column && column.type
110
+ if column_type == :binary || column_type == :text
104
111
  # LOBs are updated separately by an after_save trigger.
105
112
  "NULL"
106
- elsif column && column.type == :date
113
+ elsif column_type == :date
107
114
  "'#{value.mon}/#{value.day}/#{value.year}'"
108
115
  else
109
116
  super
@@ -129,10 +136,27 @@ module ::ArJdbc
129
136
  @connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
130
137
  end
131
138
 
132
- private
133
- def select(sql, name = nil)
139
+ def select(sql, *rest)
134
140
  # Informix does not like "= NULL", "!= NULL", or "<> NULL".
135
- execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), name)
141
+ super(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), *rest)
142
+ end
143
+
144
+ private
145
+
146
+ def db_major_version
147
+ @@db_major_version ||=
148
+ select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
136
149
  end
150
+
137
151
  end # module Informix
138
152
  end # module ::ArJdbc
153
+
154
+ module ActiveRecord::ConnectionAdapters
155
+ class InformixColumn < JdbcColumn
156
+ include ::ArJdbc::Informix::ColumnMethods
157
+ end
158
+
159
+ class InformixAdapter < JdbcAdapter
160
+ include ::ArJdbc::Informix
161
+ end
162
+ end
@@ -1,10 +1,9 @@
1
- class ActiveRecord::Base
2
- class << self
3
- def informix_connection(config)
4
- config[:port] ||= 9088
5
- config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
6
- config[:driver] = 'com.informix.jdbc.IfxDriver'
7
- jdbc_connection(config)
8
- end
1
+ ArJdbc::ConnectionMethods.module_eval do
2
+ def informix_connection(config)
3
+ config[:port] ||= 9088
4
+ config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
5
+ config[:driver] = 'com.informix.jdbc.IfxDriver'
6
+ config[:adapter_spec] = ::ArJdbc::Informix
7
+ jdbc_connection(config)
9
8
  end
10
- end
9
+ end
@@ -1,2 +1,59 @@
1
- require 'arjdbc/jdbc/adapter'
2
- require 'arjdbc/jdbc/discover'
1
+ require 'active_support/deprecation'
2
+
3
+ module ArJdbc
4
+
5
+ # @private
6
+ AR40 = ::ActiveRecord::VERSION::MAJOR > 3
7
+ # @private
8
+ AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
9
+ # @private
10
+ AR50 = ::ActiveRecord::VERSION::MAJOR > 4
11
+
12
+ class << self
13
+
14
+ # @private Internal API
15
+ def warn_unsupported_adapter(adapter, version = nil)
16
+ warn_prefix = 'NOTE:'
17
+ if version # e.g. [4, 2]
18
+ ar_version = [ ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR, ActiveRecord::VERSION::TINY ]
19
+ if ( ar_version <=> version ) >= 0 # e.g. 4.2.0 > 4.2
20
+ warn_prefix = "NOTE: ActiveRecord #{version.join('.')} with"
21
+ else
22
+ warn_prefix = nil
23
+ end
24
+ end
25
+ warn "#{warn_prefix} adapter: #{adapter} is not (yet) fully supported by AR-JDBC," <<
26
+ " please consider helping us out." if warn_prefix
27
+ end
28
+
29
+ def warn(message, once = nil)
30
+ super(message) || true if warn?(message, once)
31
+ end
32
+
33
+ def deprecate(message, once = nil) # adds a "DEPRECATION WARNING: " prefix
34
+ ::ActiveSupport::Deprecation.warn(message, caller_locations) || true if warn?(message, once)
35
+ end
36
+
37
+ private
38
+
39
+ @@warns = nil
40
+ @@warns = false if ENV_JAVA['arjdbc.warn'].eql? 'false'
41
+
42
+ def warn?(message, once)
43
+ return nil if @@warns.equal?(false) || ! message
44
+ warns = @@warns ||= ( require 'set'; Set.new )
45
+ return false if warns.include?(message)
46
+ warns << message.dup if once
47
+ true
48
+ end
49
+
50
+ end
51
+
52
+ require 'arjdbc/jdbc/adapter'
53
+
54
+ if ENV_JAVA['arjdbc.extensions.discover'].eql? 'true'
55
+ self.discover_extensions
56
+ else
57
+ require 'arjdbc/discover'
58
+ end
59
+ end
@@ -1,285 +1,475 @@
1
1
  require 'active_record/version'
2
2
  require 'active_record/connection_adapters/abstract_adapter'
3
+
3
4
  require 'arjdbc/version'
4
- require 'arjdbc/jdbc/require_driver'
5
- require 'arjdbc/jdbc/connection_methods'
6
- require 'arjdbc/jdbc/compatibility'
7
- require 'arjdbc/jdbc/core_ext'
8
5
  require 'arjdbc/jdbc/java'
9
- require 'arjdbc/jdbc/type_converter'
10
- require 'arjdbc/jdbc/driver'
6
+ require 'arjdbc/jdbc/base_ext'
7
+ require 'arjdbc/jdbc/error'
8
+ require 'arjdbc/jdbc/connection_methods'
11
9
  require 'arjdbc/jdbc/column'
12
10
  require 'arjdbc/jdbc/connection'
13
11
  require 'arjdbc/jdbc/callbacks'
14
12
  require 'arjdbc/jdbc/extension'
15
- require 'bigdecimal'
13
+ require 'arjdbc/jdbc/type_converter'
14
+ require 'arjdbc/abstract/core'
15
+ require 'arjdbc/abstract/connection_management'
16
+ require 'arjdbc/abstract/database_statements'
17
+ require 'arjdbc/abstract/transaction_support'
16
18
 
17
19
  module ActiveRecord
18
20
  module ConnectionAdapters
21
+ # Built on top of `ActiveRecord::ConnectionAdapters::AbstractAdapter` which
22
+ # provides the abstract interface for database-specific functionality, this
23
+ # class serves 2 purposes in AR-JDBC :
24
+ # - as a base class for sub-classes
25
+ # - usable standalone (or with a mixed in adapter spec module)
26
+ #
27
+ # Historically this class is mostly been used standalone and that's still a
28
+ # valid use-case esp. since (with it's `arjdbc.jdbc.RubyJdbcConnectionClass`)
29
+ # JDBC provides a unified interface for all databases in Java it tries to do
30
+ # it's best implementing all `ActiveRecord` functionality on top of that.
31
+ # This might no be perfect that's why it checks for a `config[:adapter_spec]`
32
+ # module (or tries to resolve one from the JDBC driver's meta-data) and if
33
+ # the database has "extended" AR-JDBC support mixes in the given module for
34
+ # each adapter instance.
35
+ # This is sufficient for most database specific specs we support, but for
36
+ # compatibility with native (MRI) adapters it's perfectly fine to sub-class
37
+ # the adapter and override some of its API methods.
19
38
  class JdbcAdapter < AbstractAdapter
20
- extend ShadowCoreMethods
21
- include CompatibilityMethods if CompatibilityMethods.needed?(self)
22
- include JdbcConnectionPoolCallbacks if JdbcConnectionPoolCallbacks.needed?
23
-
24
- attr_reader :config
25
-
26
- def initialize(connection, logger, config)
27
- @config = config
28
- spec = adapter_spec config
29
- unless connection
30
- connection_class = jdbc_connection_class spec
31
- connection = connection_class.new config
32
- end
33
- super(connection, logger)
34
- extend spec if spec
35
- configure_arel2_visitors(config)
36
- connection.adapter = self
37
- JndiConnectionPoolCallbacks.prepare(self, connection)
38
- end
39
+ include Jdbc::ConnectionPoolCallbacks
40
+
41
+ include ArJdbc::Abstract::Core
42
+ include ArJdbc::Abstract::ConnectionManagement
43
+ include ArJdbc::Abstract::DatabaseStatements
44
+ include ArJdbc::Abstract::TransactionSupport
45
+
46
+ attr_reader :prepared_statements
39
47
 
48
+ # Returns the (JDBC) connection class to be used for this adapter.
49
+ # This is used by (database specific) spec modules to override the class
50
+ # used assuming some of the available methods have been re-defined.
51
+ # @see ActiveRecord::ConnectionAdapters::JdbcConnection
40
52
  def jdbc_connection_class(spec)
41
53
  connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
42
- connection_class = ::ActiveRecord::ConnectionAdapters::JdbcConnection unless connection_class
43
- connection_class
54
+ connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
44
55
  end
45
56
 
57
+ # Returns the (JDBC) `ActiveRecord` column class for this adapter.
58
+ # This is used by (database specific) spec modules to override the class.
59
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
46
60
  def jdbc_column_class
47
- ActiveRecord::ConnectionAdapters::JdbcColumn
61
+ ::ActiveRecord::ConnectionAdapters::JdbcColumn
48
62
  end
49
63
 
50
- # Retrieve the raw java.sql.Connection object.
51
- def jdbc_connection
52
- raw_connection.connection
53
- end
54
-
55
- # Locate specialized adapter specification if one exists based on config data
64
+ # Locate the specialized (database specific) adapter specification module
65
+ # if one exists based on provided configuration data. This module will than
66
+ # extend an instance of the adapter (unless an `:adapter_class` provided).
67
+ #
68
+ # This method is called during {#initialize} unless an explicit
69
+ # `config[:adapter_spec]` is set.
70
+ # @param config the configuration to check for `:adapter_spec`
71
+ # @return [Module] the database specific module
56
72
  def adapter_spec(config)
57
- 2.times do
58
- dialect = (config[:dialect] || config[:driver]).to_s
59
- ::ArJdbc.constants.map { |name| ::ArJdbc.const_get name }.each do |constant|
60
- if constant.respond_to? :adapter_matcher
61
- spec = constant.adapter_matcher(dialect, config)
62
- return spec if spec
63
- end
73
+ dialect = (config[:dialect] || config[:driver]).to_s
74
+ ::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
75
+ if constant.respond_to?(:adapter_matcher)
76
+ spec = constant.adapter_matcher(dialect, config)
77
+ return spec if spec
64
78
  end
79
+ end
65
80
 
66
- # If nothing matches and we're using jndi, try to automatically detect the database.
67
- break unless config[:jndi] and !config[:dialect]
68
- begin
69
- conn = Java::javax.naming.InitialContext.new.lookup(config[:jndi]).getConnection
70
- config[:dialect] = conn.getMetaData.getClass.getName.downcase
71
-
72
- # Derby-specific hack
73
- if ::ArJdbc::Derby.adapter_matcher(config[:dialect], config)
74
- # Needed to set the correct database schema name
75
- config[:username] ||= conn.getMetaData.getUserName
81
+ unless config.key?(:dialect)
82
+ begin # does nothing unless config[:jndi] || config[:data_source]
83
+ dialect = ::ArJdbc.with_meta_data_from_data_source_if_any(config) do
84
+ |meta_data| config[:dialect] = meta_data.getDatabaseProductName
76
85
  end
77
- rescue
78
- conn.close
86
+ return adapter_spec(config) if dialect # re-try matching with :dialect
87
+ rescue => e
88
+ ::ArJdbc.warn("failed to set :dialect from database meda-data: #{e.inspect}")
89
+ else
90
+ return adapter_spec(config) # re-try matching a spec with set config[:dialect]
79
91
  end
80
92
  end
93
+
81
94
  nil
82
95
  end
83
96
 
84
- def modify_types(tp)
85
- tp
97
+ ADAPTER_NAME = 'JDBC'.freeze
98
+
99
+ # @return [String] the 'JDBC' adapter name.
100
+ def adapter_name
101
+ ADAPTER_NAME
86
102
  end
87
103
 
88
- def adapter_name #:nodoc:
89
- 'JDBC'
104
+ # @override
105
+ # Will return true even when native adapter classes passed in
106
+ # e.g. `jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter`
107
+ #
108
+ # This is only necessary (for built-in adapters) when
109
+ # `config[:adapter_class]` is forced to `nil` and the `:adapter_spec`
110
+ # module is used to extend the `JdbcAdapter`, otherwise we replace the
111
+ # class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
112
+ def is_a?(klass)
113
+ # This is to fake out current_adapter? conditional logic in AR tests
114
+ if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i
115
+ true
116
+ else
117
+ super
118
+ end
90
119
  end
91
120
 
92
- def arel2_visitors
93
- {}
121
+ # @deprecated re-implemented - no longer used
122
+ # @return [Hash] the AREL visitor to use
123
+ # If there's a `self.arel2_visitors(config)` method on the adapter
124
+ # spec than it is preferred and will be used instead of this one.
125
+ def self.arel2_visitors(config)
126
+ { 'jdbc' => ::Arel::Visitors::ToSql }
94
127
  end
95
128
 
96
- def configure_arel2_visitors(config)
97
- if defined?(::Arel::Visitors::VISITORS)
98
- visitors = ::Arel::Visitors::VISITORS
99
- visitor = nil
100
- arel2_visitors.each do |k,v|
101
- visitor = v
102
- visitors[k] = v unless visitors.has_key?(k)
103
- end
104
- if visitor && config[:dialect] && config[:adapter] =~ /^(jdbc|jndi)$/
105
- visitors[config[:adapter]] = visitor
106
- end
129
+ # @deprecated re-implemented - no longer used
130
+ # @see #arel2_visitors
131
+ def self.configure_arel2_visitors(config)
132
+ visitors = ::Arel::Visitors::VISITORS
133
+ klass = config[:adapter_spec]
134
+ klass = self unless klass.respond_to?(:arel2_visitors)
135
+ visitor = nil
136
+ klass.arel2_visitors(config).each do |name, arel|
137
+ visitors[name] = ( visitor = arel )
138
+ end
139
+ if visitor && config[:adapter] =~ /^(jdbc|jndi)$/
140
+ visitors[ config[:adapter] ] = visitor
141
+ end
142
+ visitor
143
+ end
144
+
145
+ # DB specific types are detected but adapter specs (or extenders) are
146
+ # expected to hand tune these types for concrete databases.
147
+ # @return [Hash] the native database types
148
+ # @override
149
+ def native_database_types
150
+ @native_database_types ||= begin
151
+ types = @connection.native_database_types
152
+ modify_types(types)
153
+ types
107
154
  end
108
155
  end
109
156
 
110
- def is_a?(klass) # :nodoc:
111
- # This is to fake out current_adapter? conditional logic in AR tests
112
- if Class === klass && klass.name =~ /#{adapter_name}Adapter$/i
113
- true
114
- else
115
- super
116
- end
157
+ # @override introduced in AR 4.2
158
+ def valid_type?(type)
159
+ ! native_database_types[type].nil?
117
160
  end
118
161
 
119
- def supports_migrations?
120
- true
162
+ # Allows for modification of the detected native types.
163
+ # @param types the resolved native database types
164
+ # @see #native_database_types
165
+ def modify_types(types)
166
+ types
121
167
  end
122
168
 
123
- def native_database_types #:nodoc:
124
- @connection.native_database_types
169
+ # Abstract adapter default implementation does nothing silently.
170
+ # @override
171
+ def structure_dump
172
+ raise NotImplementedError, "structure_dump not supported"
125
173
  end
126
174
 
127
- def database_name #:nodoc:
175
+ # JDBC adapters support migration.
176
+ # @return [true]
177
+ # @override
178
+ def supports_migrations?
179
+ true
180
+ end
181
+
182
+ # Returns the underlying database name.
183
+ # @override
184
+ def database_name
128
185
  @connection.database_name
129
186
  end
130
187
 
131
- def native_sql_to_type(tp)
132
- if /^(.*?)\(([0-9]+)\)/ =~ tp
133
- tname = $1
134
- limit = $2.to_i
135
- ntype = native_database_types
136
- if ntype[:primary_key] == tp
137
- return :primary_key,nil
188
+ # @private
189
+ def native_sql_to_type(type)
190
+ if /^(.*?)\(([0-9]+)\)/ =~ type
191
+ tname, limit = $1, $2.to_i
192
+ ntypes = native_database_types
193
+ if ntypes[:primary_key] == type
194
+ return :primary_key, nil
138
195
  else
139
- ntype.each do |name,val|
196
+ ntypes.each do |name, val|
140
197
  if name == :primary_key
141
198
  next
142
199
  end
143
- if val[:name].downcase == tname.downcase && (val[:limit].nil? || val[:limit].to_i == limit)
144
- return name,limit
200
+ if val[:name].downcase == tname.downcase &&
201
+ ( val[:limit].nil? || val[:limit].to_i == limit )
202
+ return name, limit
145
203
  end
146
204
  end
147
205
  end
148
- elsif /^(.*?)/ =~ tp
206
+ elsif /^(.*?)/ =~ type
149
207
  tname = $1
150
- ntype = native_database_types
151
- if ntype[:primary_key] == tp
152
- return :primary_key,nil
208
+ ntypes = native_database_types
209
+ if ntypes[:primary_key] == type
210
+ return :primary_key, nil
153
211
  else
154
- ntype.each do |name,val|
212
+ ntypes.each do |name, val|
155
213
  if val[:name].downcase == tname.downcase && val[:limit].nil?
156
- return name,nil
214
+ return name, nil
157
215
  end
158
216
  end
159
217
  end
160
218
  else
161
- return :string,255
219
+ return :string, 255
162
220
  end
163
- return nil,nil
221
+ return nil, nil
164
222
  end
165
223
 
166
- def active?
167
- @connection.active?
224
+ def columns(table_name, name = nil)
225
+ @connection.columns(table_name.to_s)
168
226
  end
169
227
 
170
- def reconnect!
171
- @connection.reconnect!
172
- @connection
228
+ # @override
229
+ def supports_views?
230
+ @connection.supports_views?
173
231
  end
174
232
 
175
- def disconnect!
176
- @connection.disconnect!
233
+ # Similar to {#exec_query} except it returns "raw" results in an array
234
+ # where each rows is a hash with keys as columns (just like Rails used to
235
+ # do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
236
+ # @param sql the query string (or AREL object)
237
+ # @param name logging marker for the executed SQL statement log entry
238
+ # @param binds the bind parameters
239
+ # @yield [v1, v2] depending on the row values returned from the query
240
+ # In case a block is given it will yield each row from the result set
241
+ # instead of returning mapped query results in an array.
242
+ # @return [Array] unless a block is given
243
+ def exec_query_raw(sql, name = 'SQL', binds = [], &block)
244
+ sql = to_sql(sql, binds) if sql.respond_to?(:to_sql)
245
+
246
+ if prepared_statements?
247
+ log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
248
+ else
249
+ log(sql, name) { @connection.execute_query_raw(sql, &block) }
250
+ end
177
251
  end
178
252
 
179
- def execute(sql, name = nil)
253
+ # @private
254
+ # @override
255
+ def select_rows(sql, name = nil, binds = [])
256
+ exec_query_raw(sql, name, binds).map!(&:values)
257
+ end
258
+
259
+ # Executes the SQL statement in the context of this connection.
260
+ # The return value from this method depends on the SQL type (whether
261
+ # it's a SELECT, INSERT etc.). For INSERTs a generated id might get
262
+ # returned while for UPDATE statements the affected row count.
263
+ # Please note that this method returns "raw" results (in an array) for
264
+ # statements that return a result set, while {#exec_query} is expected to
265
+ # return a `ActiveRecord::Result` (since AR 3.1).
266
+ # @note This method does not use prepared statements.
267
+ # @note The method does not emulate various "native" `execute` results on MRI.
268
+ # @see #exec_query
269
+ # @see #exec_insert
270
+ # @see #exec_update
271
+ def execute(sql, name = nil, binds = nil)
272
+ sql = to_sql(sql, binds) if binds
180
273
  if name == :skip_logging
181
- _execute(sql)
274
+ _execute(sql, name)
182
275
  else
183
- log(sql, name) { _execute(sql) }
276
+ log(sql, name) { _execute(sql, name) }
184
277
  end
185
278
  end
186
279
 
187
- # we need to do it this way, to allow Rails stupid tests to always work
188
- # even if we define a new execute method. Instead of mixing in a new
189
- # execute, an _execute should be mixed in.
280
+ # We need to do it this way, to allow Rails stupid tests to always work
281
+ # even if we define a new `execute` method. Instead of mixing in a new
282
+ # `execute`, an `_execute` should be mixed in.
283
+ # @deprecated it was only introduced due tests
284
+ # @private
190
285
  def _execute(sql, name = nil)
191
286
  @connection.execute(sql)
192
287
  end
288
+ private :_execute
289
+
290
+ # Kind of `execute(sql) rescue nil` but logging failures at debug level only.
291
+ def execute_quietly(sql, name = 'SQL')
292
+ log(sql, name) do
293
+ begin
294
+ _execute(sql)
295
+ rescue => e
296
+ logger.debug("#{e.class}: #{e.message}: #{sql}")
297
+ end
298
+ end
299
+ end
193
300
 
194
- def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
195
- insert_sql(sql, name, pk, id_value, sequence_name)
301
+ # @override
302
+ def tables(name = nil)
303
+ @connection.tables
196
304
  end
197
305
 
198
- def jdbc_update(sql, name = nil) #:nodoc:
199
- execute(sql, name)
306
+ # @override
307
+ def table_exists?(name)
308
+ return false unless name
309
+ @connection.table_exists?(name) # schema_name = nil
200
310
  end
201
- def jdbc_select_all(sql, name = nil)
202
- select(sql, name)
311
+
312
+ # @override
313
+ def data_sources
314
+ tables
203
315
  end
204
316
 
205
- if ActiveRecord::VERSION::MAJOR < 3
206
- # Allow query caching to work even when we override alias_method_chain'd methods
207
- alias_chained_method :select_all, :query_cache, :jdbc_select_all
208
- alias_chained_method :update, :query_dirty, :jdbc_update
209
- alias_chained_method :insert, :query_dirty, :jdbc_insert
317
+ # @override
318
+ def data_source_exists?(name)
319
+ table_exists?(name)
320
+ end
210
321
 
211
- # Do we need this? Not in AR 3.
212
- def select_one(sql, name = nil)
213
- select(sql, name).first
214
- end
322
+ # @override
323
+ def indexes(table_name, name = nil, schema_name = nil)
324
+ @connection.indexes(table_name, name, schema_name)
215
325
  end
216
326
 
217
- def select_rows(sql, name = nil)
218
- rows = []
219
- select(sql, name).each {|row| rows << row.values }
220
- rows
327
+ # @override
328
+ def pk_and_sequence_for(table)
329
+ ( key = primary_key(table) ) ? [ key, nil ] : nil
221
330
  end
222
331
 
223
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
224
- id = execute(sql, name = nil)
225
- id_value || id
332
+ # @override
333
+ def primary_keys(table)
334
+ @connection.primary_keys(table)
226
335
  end
227
336
 
228
- def jdbc_columns(table_name, name = nil)
229
- @connection.columns(table_name.to_s)
337
+ # @override
338
+ def foreign_keys(table_name)
339
+ @connection.foreign_keys(table_name)
230
340
  end
231
- alias_chained_method :columns, :query_cache, :jdbc_columns
232
341
 
233
- def tables(name = nil)
234
- @connection.tables
342
+ # Does our database (+ its JDBC driver) support foreign-keys?
343
+ # @since 1.3.18
344
+ # @override
345
+ def supports_foreign_keys?
346
+ @connection.supports_foreign_keys?
235
347
  end
236
348
 
237
- def table_exists?(name)
238
- jdbc_columns(name) rescue nil
349
+ # @deprecated Rather use {#update_lob_value} instead.
350
+ def write_large_object(*args)
351
+ @connection.write_large_object(*args)
239
352
  end
240
353
 
241
- def indexes(table_name, name = nil, schema_name = nil)
242
- @connection.indexes(table_name, name, schema_name)
354
+ # @param record the record e.g. `User.find(1)`
355
+ # @param column the model's column e.g. `User.columns_hash['photo']`
356
+ # @param value the lob value - string or (IO or Java) stream
357
+ def update_lob_value(record, column, value)
358
+ @connection.update_lob_value(record, column, value)
359
+ end
360
+
361
+ protected
362
+
363
+ # Take an id from the result of an INSERT query.
364
+ # @return [Integer, NilClass]
365
+ def last_inserted_id(result)
366
+ if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
367
+ result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
368
+ else
369
+ result
370
+ end
243
371
  end
244
372
 
245
- def begin_db_transaction
246
- @connection.begin
373
+ # aliasing #create_table_definition as #table_definition :
374
+ alias table_definition create_table_definition
375
+
376
+ # `TableDefinition.new native_database_types, name, temporary, options`
377
+ # and ActiveRecord 4.1 supports optional `as` argument (which defaults
378
+ # to nil) to provide the SQL to use to generate the table:
379
+ # `TableDefinition.new native_database_types, name, temporary, options, as`
380
+ # @private
381
+ def create_table_definition(*args)
382
+ table_definition(*args)
247
383
  end
248
384
 
249
- def commit_db_transaction
250
- @connection.commit
385
+ # @note AR-4x arguments expected: `(name, temporary, options)`
386
+ # @private documented bellow
387
+ def new_table_definition(table_definition, *args)
388
+ table_definition.new(*args)
251
389
  end
390
+ private :new_table_definition
252
391
 
253
- def rollback_db_transaction
254
- @connection.rollback
392
+ # @private
393
+ def new_index_definition(table, name, unique, columns, lengths,
394
+ orders = nil, where = nil, type = nil, using = nil)
395
+ IndexDefinition.new(table, name, unique, columns, lengths, orders, where, type, using)
255
396
  end
397
+ private :new_index_definition
256
398
 
257
- def write_large_object(*args)
258
- @connection.write_large_object(*args)
399
+ #
400
+
401
+ # Provides backwards-compatibility on ActiveRecord 4.1 for DB adapters
402
+ # that override this and than call super expecting to work.
403
+ # @note This method is available in 4.0 but won't be in 4.1
404
+ # @private
405
+ def add_column_options!(sql, options)
406
+ sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
407
+ # must explicitly check for :null to allow change_column to work on migrations
408
+ sql << " NOT NULL" if options[:null] == false
409
+ sql << " AUTO_INCREMENT" if options[:auto_increment] == true
259
410
  end
411
+ public :add_column_options!
260
412
 
261
- def pk_and_sequence_for(table)
262
- key = primary_key(table)
263
- [key, nil] if key
413
+ # @return whether `:prepared_statements` are to be used
414
+ def prepared_statements?
415
+ return @prepared_statements unless (@prepared_statements ||= nil).nil?
416
+ @prepared_statements = self.class.prepared_statements?(config)
264
417
  end
265
418
 
266
- def primary_key(table)
267
- primary_keys(table).first
419
+ # Allows changing the prepared statements setting for this connection.
420
+ # @see #prepared_statements?
421
+ #def prepared_statements=(statements)
422
+ # @prepared_statements = statements
423
+ #end
424
+
425
+ def self.prepared_statements?(config)
426
+ config.key?(:prepared_statements) ?
427
+ type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
428
+ false # off by default - NOTE: on AR 4.x it's on by default !?
268
429
  end
269
430
 
270
- def primary_keys(table)
271
- @connection.primary_keys(table)
431
+ private
432
+
433
+ # Helper useful during {#quote} since AREL might pass in it's literals
434
+ # to be quoted, fixed since AREL 4.0.0.beta1 : http://git.io/7gyTig
435
+ def sql_literal?(value); ::Arel::Nodes::SqlLiteral === value; end
436
+
437
+ # Helper to get local/UTC time (based on `ActiveRecord::Base.default_timezone`).
438
+ def get_time(value)
439
+ get = ::ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
440
+ value.respond_to?(get) ? value.send(get) : value
441
+ end
442
+
443
+ # @return whether the given SQL string is a 'SELECT' like
444
+ # query (returning a result set)
445
+ def self.select?(sql)
446
+ JdbcConnection::select?(sql)
272
447
  end
273
448
 
274
- def select(*args)
275
- execute(*args)
449
+ # @return whether the given SQL string is an 'INSERT' query
450
+ def self.insert?(sql)
451
+ JdbcConnection::insert?(sql)
276
452
  end
277
453
 
278
- def translate_exception(e, message)
279
- puts e.backtrace if $DEBUG || ENV['DEBUG']
280
- super
454
+ # @return whether the given SQL string is an 'UPDATE' (or 'DELETE') query
455
+ def self.update?(sql)
456
+ ! select?(sql) && ! insert?(sql)
281
457
  end
282
- protected :translate_exception
458
+
459
+ unless defined? AbstractAdapter.type_cast_config_to_integer
460
+
461
+ # @private
462
+ def self.type_cast_config_to_integer(config)
463
+ config =~ /\A\d+\z/ ? config.to_i : config
464
+ end
465
+
466
+ end
467
+
468
+ # @private
469
+ def self.type_cast_config_to_boolean(config)
470
+ config == 'false' ? false : (config == 'true' ? true : config)
471
+ end
472
+
283
473
  end
284
474
  end
285
475
  end