activerecord-jdbc-adapter 1.0.3-java → 50.1-java

Sign up to get free protection for your applications and to get access to all the features.
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