activerecord-jdbc-adapter 1.3.0.beta2 → 1.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (282) hide show
  1. data/.gitignore +14 -8
  2. data/.travis.yml +40 -31
  3. data/.yardopts +4 -0
  4. data/Appraisals +2 -5
  5. data/CONTRIBUTING.md +46 -0
  6. data/Gemfile +21 -4
  7. data/Gemfile.lock +42 -17
  8. data/{History.txt → History.md} +142 -75
  9. data/README.md +102 -104
  10. data/RUNNING_TESTS.md +76 -0
  11. data/Rakefile.jdbc +20 -0
  12. data/activerecord-jdbc-adapter.gemspec +35 -18
  13. data/gemfiles/rails23.gemfile +4 -3
  14. data/gemfiles/rails23.gemfile.lock +9 -6
  15. data/gemfiles/rails30.gemfile +4 -3
  16. data/gemfiles/rails30.gemfile.lock +9 -6
  17. data/gemfiles/rails31.gemfile +4 -3
  18. data/gemfiles/rails31.gemfile.lock +9 -6
  19. data/gemfiles/rails32.gemfile +4 -3
  20. data/gemfiles/rails32.gemfile.lock +17 -14
  21. data/gemfiles/rails40.gemfile +5 -5
  22. data/gemfiles/rails40.gemfile.lock +17 -69
  23. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  25. data/lib/arel/visitors/compat.rb +22 -3
  26. data/lib/arel/visitors/db2.rb +8 -4
  27. data/lib/arel/visitors/derby.rb +14 -13
  28. data/lib/arel/visitors/firebird.rb +5 -4
  29. data/lib/arel/visitors/hsqldb.rb +11 -9
  30. data/lib/arel/visitors/sql_server.rb +89 -61
  31. data/lib/arjdbc.rb +1 -1
  32. data/lib/arjdbc/db2/adapter.rb +181 -212
  33. data/lib/arjdbc/db2/as400.rb +31 -18
  34. data/lib/arjdbc/db2/column.rb +167 -0
  35. data/lib/arjdbc/db2/connection_methods.rb +2 -0
  36. data/lib/arjdbc/derby/adapter.rb +206 -107
  37. data/lib/arjdbc/derby/connection_methods.rb +4 -9
  38. data/lib/arjdbc/firebird.rb +1 -0
  39. data/lib/arjdbc/firebird/adapter.rb +202 -64
  40. data/lib/arjdbc/firebird/connection_methods.rb +20 -0
  41. data/lib/arjdbc/h2/adapter.rb +56 -36
  42. data/lib/arjdbc/hsqldb/adapter.rb +99 -68
  43. data/lib/arjdbc/jdbc/adapter.rb +474 -265
  44. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  45. data/lib/arjdbc/jdbc/adapter_require.rb +8 -7
  46. data/lib/arjdbc/jdbc/arel_support.rb +132 -0
  47. data/lib/arjdbc/jdbc/base_ext.rb +8 -7
  48. data/lib/arjdbc/jdbc/callbacks.rb +16 -10
  49. data/lib/arjdbc/jdbc/column.rb +25 -3
  50. data/lib/arjdbc/jdbc/connection.rb +28 -55
  51. data/lib/arjdbc/jdbc/extension.rb +14 -14
  52. data/lib/arjdbc/jdbc/java.rb +6 -3
  53. data/lib/arjdbc/jdbc/jdbc.rake +1 -1
  54. data/lib/arjdbc/jdbc/quoted_primary_key.rb +2 -2
  55. data/lib/arjdbc/jdbc/rake_tasks.rb +1 -1
  56. data/lib/arjdbc/jdbc/type_converter.rb +5 -2
  57. data/lib/arjdbc/mssql/adapter.rb +160 -280
  58. data/lib/arjdbc/mssql/column.rb +182 -0
  59. data/lib/arjdbc/mssql/connection_methods.rb +37 -4
  60. data/lib/arjdbc/mssql/explain_support.rb +13 -21
  61. data/lib/arjdbc/mssql/limit_helpers.rb +79 -42
  62. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  63. data/lib/arjdbc/mssql/utils.rb +11 -11
  64. data/lib/arjdbc/mysql/adapter.rb +165 -247
  65. data/lib/arjdbc/mysql/column.rb +123 -0
  66. data/lib/arjdbc/mysql/connection_methods.rb +3 -6
  67. data/lib/arjdbc/oracle/adapter.rb +282 -288
  68. data/lib/arjdbc/oracle/column.rb +122 -0
  69. data/lib/arjdbc/oracle/connection_methods.rb +3 -0
  70. data/lib/arjdbc/postgresql/adapter.rb +336 -574
  71. data/lib/arjdbc/postgresql/column.rb +458 -0
  72. data/lib/arjdbc/postgresql/connection_methods.rb +1 -2
  73. data/lib/arjdbc/postgresql/schema_creation.rb +38 -0
  74. data/lib/arjdbc/sqlite3/adapter.rb +189 -145
  75. data/lib/arjdbc/sqlite3/explain_support.rb +1 -1
  76. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +8 -8
  77. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  78. data/lib/arjdbc/util/table_copier.rb +110 -0
  79. data/lib/arjdbc/version.rb +6 -7
  80. data/pom.xml +56 -2
  81. data/rakelib/02-test.rake +72 -83
  82. data/rakelib/db.rake +29 -17
  83. data/src/java/arjdbc/ArJdbcModule.java +21 -18
  84. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +84 -12
  85. data/src/java/arjdbc/derby/DerbyModule.java +140 -143
  86. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +58 -7
  87. data/src/java/arjdbc/h2/H2Module.java +43 -0
  88. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +7 -6
  89. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1223 -648
  90. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +24 -23
  91. data/src/java/arjdbc/mysql/MySQLModule.java +33 -32
  92. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +147 -30
  93. data/src/java/arjdbc/oracle/OracleModule.java +13 -13
  94. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +114 -6
  95. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +166 -36
  96. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +101 -19
  97. data/src/java/arjdbc/util/QuotingUtils.java +19 -19
  98. metadata +240 -394
  99. data/bench/bench_attributes.rb +0 -13
  100. data/bench/bench_attributes_new.rb +0 -14
  101. data/bench/bench_create.rb +0 -12
  102. data/bench/bench_find_all.rb +0 -12
  103. data/bench/bench_find_all_mt.rb +0 -25
  104. data/bench/bench_model.rb +0 -85
  105. data/bench/bench_new.rb +0 -12
  106. data/bench/bench_new_valid.rb +0 -12
  107. data/bench/bench_valid.rb +0 -13
  108. data/lib/arel/engines/sql/compilers/db2_compiler.rb +0 -9
  109. data/lib/arel/engines/sql/compilers/derby_compiler.rb +0 -6
  110. data/lib/arel/engines/sql/compilers/h2_compiler.rb +0 -6
  111. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +0 -15
  112. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +0 -6
  113. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +0 -46
  114. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +0 -98
  115. data/lib/arjdbc/mssql/lock_helpers.rb +0 -76
  116. data/lib/arjdbc/mssql/tsql_methods.rb +0 -58
  117. data/lib/arjdbc/postgresql/column_cast.rb +0 -134
  118. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +0 -25
  119. data/test/activerecord/jall.sh +0 -7
  120. data/test/activerecord/jtest.sh +0 -3
  121. data/test/assets/flowers.jpg +0 -0
  122. data/test/binary.rb +0 -67
  123. data/test/db/db2.rb +0 -43
  124. data/test/db/db2/binary_test.rb +0 -6
  125. data/test/db/db2/has_many_through_test.rb +0 -6
  126. data/test/db/db2/rake_test.rb +0 -82
  127. data/test/db/db2/rake_test_data.sql +0 -35
  128. data/test/db/db2/reset_column_information_test.rb +0 -5
  129. data/test/db/db2/serialize_test.rb +0 -6
  130. data/test/db/db2/simple_test.rb +0 -81
  131. data/test/db/db2/test_helper.rb +0 -6
  132. data/test/db/db2/unit_test.rb +0 -73
  133. data/test/db/derby.rb +0 -12
  134. data/test/db/derby/binary_test.rb +0 -6
  135. data/test/db/derby/migration_test.rb +0 -74
  136. data/test/db/derby/rake_test.rb +0 -96
  137. data/test/db/derby/reset_column_information_test.rb +0 -6
  138. data/test/db/derby/row_locking_test.rb +0 -20
  139. data/test/db/derby/schema_dump_test.rb +0 -5
  140. data/test/db/derby/serialize_test.rb +0 -6
  141. data/test/db/derby/simple_test.rb +0 -173
  142. data/test/db/derby/test_helper.rb +0 -6
  143. data/test/db/derby/unit_test.rb +0 -32
  144. data/test/db/derby/xml_column_test.rb +0 -17
  145. data/test/db/h2.rb +0 -11
  146. data/test/db/h2/binary_test.rb +0 -6
  147. data/test/db/h2/change_column_test.rb +0 -68
  148. data/test/db/h2/identity_column_test.rb +0 -35
  149. data/test/db/h2/offset_test.rb +0 -49
  150. data/test/db/h2/rake_test.rb +0 -98
  151. data/test/db/h2/schema_dump_test.rb +0 -29
  152. data/test/db/h2/serialize_test.rb +0 -6
  153. data/test/db/h2/simple_test.rb +0 -56
  154. data/test/db/hsqldb.rb +0 -11
  155. data/test/db/hsqldb/binary_test.rb +0 -6
  156. data/test/db/hsqldb/rake_test.rb +0 -101
  157. data/test/db/hsqldb/schema_dump_test.rb +0 -19
  158. data/test/db/hsqldb/serialize_test.rb +0 -6
  159. data/test/db/hsqldb/simple_test.rb +0 -17
  160. data/test/db/informix.rb +0 -13
  161. data/test/db/jdbc.rb +0 -16
  162. data/test/db/jdbc_derby.rb +0 -14
  163. data/test/db/jdbc_h2.rb +0 -17
  164. data/test/db/jdbc_mysql.rb +0 -13
  165. data/test/db/jdbc_postgres.rb +0 -23
  166. data/test/db/jndi_config.rb +0 -32
  167. data/test/db/jndi_pooled_config.rb +0 -32
  168. data/test/db/mssql.rb +0 -11
  169. data/test/db/mssql/binary_test.rb +0 -6
  170. data/test/db/mssql/exec_proc_test.rb +0 -46
  171. data/test/db/mssql/identity_insert_test.rb +0 -18
  172. data/test/db/mssql/ignore_system_views_test.rb +0 -40
  173. data/test/db/mssql/limit_offset_test.rb +0 -190
  174. data/test/db/mssql/multibyte_test.rb +0 -16
  175. data/test/db/mssql/multiple_connections_test.rb +0 -71
  176. data/test/db/mssql/rake_test.rb +0 -143
  177. data/test/db/mssql/reset_column_information_test.rb +0 -6
  178. data/test/db/mssql/row_locking_test.rb +0 -7
  179. data/test/db/mssql/serialize_test.rb +0 -6
  180. data/test/db/mssql/simple_test.rb +0 -140
  181. data/test/db/mssql/transaction_test.rb +0 -6
  182. data/test/db/mssql/types_test.rb +0 -205
  183. data/test/db/mssql/unit_test.rb +0 -249
  184. data/test/db/mysql.rb +0 -4
  185. data/test/db/mysql/_rails_test_mysql.32.out +0 -6585
  186. data/test/db/mysql/binary_test.rb +0 -6
  187. data/test/db/mysql/connection_test.rb +0 -51
  188. data/test/db/mysql/index_length_test.rb +0 -58
  189. data/test/db/mysql/multibyte_test.rb +0 -10
  190. data/test/db/mysql/nonstandard_primary_key_test.rb +0 -39
  191. data/test/db/mysql/rake_test.rb +0 -97
  192. data/test/db/mysql/reset_column_information_test.rb +0 -6
  193. data/test/db/mysql/schema_dump_test.rb +0 -228
  194. data/test/db/mysql/serialize_test.rb +0 -6
  195. data/test/db/mysql/simple_test.rb +0 -187
  196. data/test/db/mysql/statement_escaping_test.rb +0 -46
  197. data/test/db/mysql/transaction_test.rb +0 -6
  198. data/test/db/mysql/types_test.rb +0 -30
  199. data/test/db/mysql/unit_test.rb +0 -93
  200. data/test/db/mysql_config.rb +0 -7
  201. data/test/db/oracle.rb +0 -27
  202. data/test/db/oracle/binary_test.rb +0 -6
  203. data/test/db/oracle/limit_test.rb +0 -24
  204. data/test/db/oracle/multibyte_test.rb +0 -22
  205. data/test/db/oracle/rake_test.rb +0 -100
  206. data/test/db/oracle/reset_column_information_test.rb +0 -6
  207. data/test/db/oracle/serialize_test.rb +0 -6
  208. data/test/db/oracle/simple_test.rb +0 -140
  209. data/test/db/oracle/specific_test.rb +0 -180
  210. data/test/db/oracle/transaction_test.rb +0 -31
  211. data/test/db/oracle/unit_test.rb +0 -31
  212. data/test/db/postgres.rb +0 -11
  213. data/test/db/postgres/_rails_test_postgres.32.out +0 -6405
  214. data/test/db/postgres/a_custom_primary_key_test.rb +0 -50
  215. data/test/db/postgres/active_schema_unit_test.rb +0 -68
  216. data/test/db/postgres/array_type_test.rb +0 -101
  217. data/test/db/postgres/binary_test.rb +0 -6
  218. data/test/db/postgres/connection_test.rb +0 -63
  219. data/test/db/postgres/data_types_test.rb +0 -703
  220. data/test/db/postgres/hstore_test.rb +0 -200
  221. data/test/db/postgres/information_schema_leak_test.rb +0 -30
  222. data/test/db/postgres/json_test.rb +0 -86
  223. data/test/db/postgres/ltree_test.rb +0 -51
  224. data/test/db/postgres/mixed_case_test.rb +0 -29
  225. data/test/db/postgres/native_types_test.rb +0 -124
  226. data/test/db/postgres/rake_test.rb +0 -117
  227. data/test/db/postgres/reserved_test.rb +0 -22
  228. data/test/db/postgres/reset_column_information_test.rb +0 -6
  229. data/test/db/postgres/row_locking_test.rb +0 -21
  230. data/test/db/postgres/schema_dump_test.rb +0 -95
  231. data/test/db/postgres/schema_test.rb +0 -115
  232. data/test/db/postgres/simple_test.rb +0 -260
  233. data/test/db/postgres/table_alias_length_test.rb +0 -16
  234. data/test/db/postgres/transaction_test.rb +0 -6
  235. data/test/db/postgres/unit_test.rb +0 -31
  236. data/test/db/postgres_config.rb +0 -10
  237. data/test/db/sqlite3.rb +0 -6
  238. data/test/db/sqlite3/_rails_test_sqlite3.32.out +0 -6274
  239. data/test/db/sqlite3/has_many_though_test.rb +0 -6
  240. data/test/db/sqlite3/rake_test.rb +0 -71
  241. data/test/db/sqlite3/reset_column_information_test.rb +0 -6
  242. data/test/db/sqlite3/schema_dump_test.rb +0 -6
  243. data/test/db/sqlite3/serialize_test.rb +0 -6
  244. data/test/db/sqlite3/simple_test.rb +0 -268
  245. data/test/db/sqlite3/transaction_test.rb +0 -32
  246. data/test/db/sqlite3/type_conversion_test.rb +0 -104
  247. data/test/has_many_through.rb +0 -61
  248. data/test/informix_simple_test.rb +0 -48
  249. data/test/jdbc/db2.rb +0 -36
  250. data/test/jdbc/oracle.rb +0 -34
  251. data/test/jdbc_column_test.rb +0 -23
  252. data/test/jdbc_common.rb +0 -16
  253. data/test/jdbc_connection_test.rb +0 -196
  254. data/test/jndi_callbacks_test.rb +0 -33
  255. data/test/jndi_test.rb +0 -55
  256. data/test/manualTestDatabase.rb +0 -191
  257. data/test/models/add_not_null_column_to_table.rb +0 -9
  258. data/test/models/auto_id.rb +0 -15
  259. data/test/models/binary.rb +0 -18
  260. data/test/models/custom_pk_name.rb +0 -15
  261. data/test/models/data_types.rb +0 -40
  262. data/test/models/entry.rb +0 -41
  263. data/test/models/mixed_case.rb +0 -22
  264. data/test/models/reserved_word.rb +0 -15
  265. data/test/models/rights_and_roles.rb +0 -57
  266. data/test/models/string_id.rb +0 -17
  267. data/test/models/thing.rb +0 -17
  268. data/test/models/topic.rb +0 -32
  269. data/test/models/validates_uniqueness_of_string.rb +0 -19
  270. data/test/rails/mysql.rb +0 -13
  271. data/test/rails/sqlite3/version.rb +0 -6
  272. data/test/rails_stub.rb +0 -31
  273. data/test/rake_test_support.rb +0 -298
  274. data/test/row_locking.rb +0 -102
  275. data/test/schema_dump.rb +0 -182
  276. data/test/serialize.rb +0 -275
  277. data/test/shared_helper.rb +0 -35
  278. data/test/simple.rb +0 -1317
  279. data/test/sybase_jtds_simple_test.rb +0 -28
  280. data/test/sybase_reset_column_information_test.rb +0 -6
  281. data/test/test_helper.rb +0 -304
  282. data/test/transaction.rb +0 -109
@@ -3,23 +3,35 @@ require 'arjdbc/db2/adapter'
3
3
  module ArJdbc
4
4
  module AS400
5
5
  include DB2
6
-
7
- def self.extended(base); DB2.extended(base); end
8
-
9
- def self.column_selector
10
- [ /as400/i, lambda { |cfg, column| column.extend(::ArJdbc::AS400::Column) } ]
11
- end
12
6
 
7
+ # @private
8
+ def self.extended(adapter); DB2.extended(adapter); end
9
+
10
+ # @private
11
+ def self.initialize!; DB2.initialize!; end
12
+
13
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
13
14
  def self.jdbc_connection_class; DB2.jdbc_connection_class; end
14
15
 
15
- def self.arel2_visitors(config)
16
- visitors = DB2.arel2_visitors(config).dup
17
- visitors['as400'] = ::Arel::Visitors::DB2
18
- visitors
16
+ # @see ActiveRecord::ConnectionAdapters::Jdbc::ArelSupport
17
+ def self.arel_visitor_type(config = nil); DB2.arel_visitor_type(config); end
18
+
19
+ def self.column_selector
20
+ [ /as400/i, lambda { |config, column| column.extend(Column) } ]
19
21
  end
20
22
 
23
+ # @private
24
+ Column = DB2::Column
25
+
26
+ # Boolean emulation can be disabled using :
27
+ #
28
+ # ArJdbc::AS400.emulate_booleans = false
29
+ #
30
+ def self.emulate_booleans; DB2.emulate_booleans; end
31
+ def self.emulate_booleans=(emulate); DB2.emulate_booleans = emulate; end
32
+
21
33
  ADAPTER_NAME = 'AS400'.freeze
22
-
34
+
23
35
  def adapter_name
24
36
  ADAPTER_NAME
25
37
  end
@@ -35,7 +47,7 @@ module ArJdbc
35
47
  end
36
48
 
37
49
  # @override
38
- def rename_column(table_name, column_name, new_column_name) # :nodoc:
50
+ def rename_column(table_name, column_name, new_column_name)
39
51
  raise NotImplementedError, "rename_column is not supported on IBM iSeries"
40
52
  end
41
53
 
@@ -43,7 +55,7 @@ module ArJdbc
43
55
  def execute_table_change(sql, table_name, name = nil)
44
56
  execute_and_auto_confirm(sql, name)
45
57
  end
46
-
58
+
47
59
  # holy moly batman! all this to tell AS400 "yes i am sure"
48
60
  def execute_and_auto_confirm(sql, name = nil)
49
61
 
@@ -83,21 +95,22 @@ module ArJdbc
83
95
  @connection.table_exists?(name, schema) :
84
96
  @connection.table_exists?(name)
85
97
  end
86
-
98
+
87
99
  DRIVER_NAME = 'com.ibm.as400.access.AS400JDBCDriver'.freeze
88
-
100
+
101
+ # @private
89
102
  # @deprecated no longer used
90
103
  def as400?
91
104
  true
92
105
  end
93
106
 
94
107
  private
95
-
108
+
96
109
  # @override
97
110
  def db2_schema
98
111
  @db2_schema = false unless defined? @db2_schema
99
112
  return @db2_schema if @db2_schema != false
100
- @db2_schema =
113
+ @db2_schema =
101
114
  if config[:schema].present?
102
115
  config[:schema]
103
116
  elsif config[:jndi].present?
@@ -119,6 +132,6 @@ module ArJdbc
119
132
  schema
120
133
  end
121
134
  end
122
-
135
+
123
136
  end
124
137
  end
@@ -0,0 +1,167 @@
1
+ module ArJdbc
2
+ module DB2
3
+
4
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
5
+ def self.column_selector
6
+ [ /(db2|zos)/i, lambda { |config, column| column.extend(Column) } ]
7
+ end
8
+
9
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
10
+ module Column
11
+
12
+ # @private
13
+ def self.included(base)
14
+ # NOTE: assumes a standalone DB2Column class
15
+ class << base; include Cast; end
16
+ end
17
+
18
+ # @deprecated use `self.class.string_to_time`
19
+ def self.cast_to_date_or_time(value)
20
+ return value if value.is_a? Date
21
+ return nil if value.blank?
22
+ # https://github.com/jruby/activerecord-jdbc-adapter/commit/c225126e025df2e98ba3386c67e2a5bc5e5a73e6
23
+ return Time.now if value =~ /^CURRENT/
24
+ guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
25
+ rescue
26
+ value
27
+ end
28
+
29
+ # @deprecated use `self.class.string_to_time` or `self.class.string_to_dummy_time`
30
+ def self.cast_to_time(value)
31
+ return value if value.is_a? Time
32
+ # AS400 returns a 2 digit year, LUW returns a 4 digit year
33
+ time = DateTime.parse(value).to_time rescue nil
34
+ return nil unless time
35
+ time_array = [time.year, time.month, time.day, time.hour, time.min, time.sec]
36
+ time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
37
+ Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
38
+ end
39
+
40
+ # @deprecated
41
+ # @private
42
+ def self.guess_date_or_time(value)
43
+ return value if value.is_a? Date
44
+ ( value && value.hour == 0 && value.min == 0 && value.sec == 0 ) ?
45
+ Date.new(value.year, value.month, value.day) : value
46
+ end
47
+
48
+ # @override
49
+ def type_cast(value)
50
+ return nil if value.nil? || value == 'NULL' || value =~ /^\s*NULL\s*$/i
51
+ case type
52
+ when :string then value
53
+ when :integer then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
54
+ when :primary_key then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
55
+ when :float then value.to_f
56
+ when :date then self.class.string_to_date(value)
57
+ when :datetime then self.class.string_to_time(value)
58
+ when :timestamp then self.class.string_to_time(value)
59
+ when :time then self.class.string_to_dummy_time(value)
60
+ # TODO AS400 stores binary strings in EBCDIC (CCSID 65535), need to convert back to ASCII
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ # @override
67
+ def type_cast_code(var_name)
68
+ case type
69
+ when :date then "#{self.class.name}.string_to_date(#{var_name})"
70
+ when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
71
+ when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
72
+ when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})"
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def simplified_type(field_type)
81
+ case field_type
82
+ when /^decimal\(1\)$/i then DB2.emulate_booleans ? :boolean : :integer
83
+ when /smallint/i then DB2.emulate_booleans ? :boolean : :integer
84
+ when /boolean/i then :boolean
85
+ when /^real|double/i then :float
86
+ when /int|serial/i then :integer
87
+ # if a numeric column has no scale, lets treat it as an integer.
88
+ # The AS400 rpg guys do this ALOT since they have no integer datatype ...
89
+ when /decimal|numeric|decfloat/i
90
+ extract_scale(field_type) == 0 ? :integer : :decimal
91
+ when /timestamp/i then :timestamp
92
+ when /datetime/i then :datetime
93
+ when /time/i then :time
94
+ when /date/i then :date
95
+ # DB2 provides three data types to store these data objects as strings of up to 2 GB in size:
96
+ # Character large objects (CLOBs)
97
+ # Use the CLOB data type to store SBCS or mixed data, such as documents that contain
98
+ # single character set. Use this data type if your data is larger (or might grow larger)
99
+ # than the VARCHAR data type permits.
100
+ # Double-byte character large objects (DBCLOBs)
101
+ # Use the DBCLOB data type to store large amounts of DBCS data, such as documents that
102
+ # use a DBCS character set.
103
+ # Binary large objects (BLOBs)
104
+ # Use the BLOB data type to store large amounts of noncharacter data, such as pictures,
105
+ # voice, and mixed media.
106
+ when /clob|text/i then :text # handles DBCLOB
107
+ when /^long varchar/i then :text # :limit => 32700
108
+ when /blob|binary/i then :binary
109
+ # varchar () for bit data, char () for bit data, long varchar for bit data
110
+ when /for bit data/i then :binary
111
+ when /xml/i then :xml
112
+ when /graphic/i then :graphic # vargraphic, long vargraphic
113
+ when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
120
+ def default_value(value)
121
+ # IBM i (AS400) will return an empty string instead of null for no default
122
+ return nil if value.blank?
123
+
124
+ # string defaults are surrounded by single quotes
125
+ return $1 if value =~ /^'(.*)'$/
126
+
127
+ value
128
+ end
129
+
130
+ module Cast
131
+
132
+ # @override
133
+ def string_to_date(value)
134
+ return nil unless value = current_date_time_parse(value)
135
+
136
+ super
137
+ end
138
+
139
+ # @override
140
+ def string_to_time(value)
141
+ return nil unless value = current_date_time_parse(value)
142
+
143
+ super
144
+ end
145
+
146
+ # @override
147
+ def string_to_dummy_time(value)
148
+ return nil unless value = current_date_time_parse(value)
149
+
150
+ super
151
+ end
152
+
153
+ private
154
+
155
+ def current_date_time_parse(value)
156
+ return value unless value.is_a?(String)
157
+ return nil if value.empty?
158
+ return Time.now if value.index('CURRENT') == 0
159
+
160
+ return value
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -1,4 +1,5 @@
1
1
  ArJdbc::ConnectionMethods.module_eval do
2
+ # @note Assumes DB2 driver (*db2jcc.jar*) is on class-path.
2
3
  def db2_connection(config)
3
4
  config[:url] ||= begin
4
5
  if config[:host] # Type 4 URL: jdbc:db2://server:port/database
@@ -15,6 +16,7 @@ ArJdbc::ConnectionMethods.module_eval do
15
16
  end
16
17
  alias_method :jdbcdb2_connection, :db2_connection
17
18
 
19
+ # @note Assumes AS400 driver (*jt400.jar*) is on class-path.
18
20
  def as400_connection(config)
19
21
  config[:url] ||= begin
20
22
  # jdbc:as400://[host]
@@ -1,8 +1,10 @@
1
1
  ArJdbc.load_java_part :Derby
2
- require 'arjdbc/jdbc/missing_functionality_helper'
2
+
3
+ require 'arjdbc/util/table_copier'
3
4
 
4
5
  module ArJdbc
5
6
  module Derby
7
+ include Util::TableCopier
6
8
 
7
9
  def self.extended(adapter)
8
10
  require 'arjdbc/derby/active_record_patch'
@@ -12,21 +14,20 @@ module ArJdbc
12
14
  require 'arjdbc/derby/active_record_patch'
13
15
  end
14
16
 
15
- def self.column_selector
16
- [ /derby/i, lambda { |cfg, column| column.extend(::ArJdbc::Derby::Column) } ]
17
- end
18
-
17
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
19
18
  def self.jdbc_connection_class
20
19
  ::ActiveRecord::ConnectionAdapters::DerbyJdbcConnection
21
20
  end
22
-
23
- def configure_connection
24
- execute("SET ISOLATION = SERIALIZABLE")
25
- # must be done or SELECT...FOR UPDATE won't work how we expect
21
+
22
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
23
+ def self.column_selector
24
+ [ /derby/i, lambda { |config, column| column.extend(Column) } ]
26
25
  end
27
26
 
27
+ # @note Part of this module is implemented in "native" Java.
28
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
28
29
  module Column
29
-
30
+
30
31
  private
31
32
 
32
33
  def extract_limit(sql_type)
@@ -48,7 +49,7 @@ module ArJdbc
48
49
  end
49
50
  limit
50
51
  end
51
-
52
+
52
53
  def simplified_type(field_type)
53
54
  case field_type
54
55
  when /^smallint/i then :boolean
@@ -58,6 +59,11 @@ module ArJdbc
58
59
  extract_scale(field_type) == 0 ? :integer : :decimal
59
60
  when /^timestamp/i then :datetime
60
61
  when /^xml/i then :xml
62
+ when 'long varchar' then :text
63
+ when /for bit data/i then :binary
64
+ # :name=>"long varchar for bit data", :limit=>32700
65
+ # :name=>"varchar() for bit data", :limit=>32672
66
+ # :name=>"char() for bit data", :limit=>254}
61
67
  else
62
68
  super
63
69
  end
@@ -70,24 +76,43 @@ module ArJdbc
70
76
  return nil if value == "GENERATED_BY_DEFAULT"
71
77
  value
72
78
  end
73
-
79
+
80
+ end
81
+
82
+ # @see ActiveRecord::ConnectionAdapters::Jdbc::ArelSupport
83
+ def self.arel_visitor_type(config = nil)
84
+ require 'arel/visitors/derby'; ::Arel::Visitors::Derby
74
85
  end
75
86
 
76
- ADAPTER_NAME = 'Derby'
77
-
78
- def adapter_name # :nodoc:
87
+ ADAPTER_NAME = 'Derby'.freeze
88
+
89
+ def adapter_name
79
90
  ADAPTER_NAME
80
91
  end
81
92
 
82
- def self.arel2_visitors(config)
83
- require 'arel/visitors/derby'
84
- {
85
- 'derby' => ::Arel::Visitors::Derby,
86
- 'jdbcderby' => ::Arel::Visitors::Derby,
87
- }
93
+ # @private
94
+ def init_connection(jdbc_connection)
95
+ md = jdbc_connection.meta_data
96
+ major_version = md.database_major_version; minor_version = md.database_minor_version
97
+ if major_version < 10 || (major_version == 10 && minor_version < 5)
98
+ raise ::ActiveRecord::ConnectionFailed, "Derby adapter requires Derby >= 10.5"
99
+ end
100
+ if major_version == 10 && minor_version < 8 # 10.8 ~ supports JDBC 4.1
101
+ config[:connection_alive_sql] ||=
102
+ 'SELECT 1 FROM SYS.SYSSCHEMAS FETCH FIRST 1 ROWS ONLY' # FROM clause mandatory
103
+ else
104
+ # NOTE: since the loaded Java driver class can't change :
105
+ Derby.send(:remove_method, :init_connection) rescue nil
106
+ end
88
107
  end
89
108
 
90
- include ArJdbc::MissingFunctionalityHelper
109
+ def configure_connection
110
+ # must be done or SELECT...FOR UPDATE won't work how we expect :
111
+ execute("SET ISOLATION = SERIALIZABLE")
112
+ # if a user name was specified upon connection, the user's name is the
113
+ # default schema for the connection, if a schema with that name exists
114
+ set_schema(config[:schema]) if config.key?(:schema)
115
+ end
91
116
 
92
117
  def index_name_length
93
118
  128
@@ -95,76 +120,83 @@ module ArJdbc
95
120
 
96
121
  NATIVE_DATABASE_TYPES = {
97
122
  :primary_key => "int GENERATED BY DEFAULT AS identity NOT NULL PRIMARY KEY",
98
- :string => { :name => "varchar", :limit => 255 },
123
+ :string => { :name => "varchar", :limit => 255 }, # 32672
99
124
  :text => { :name => "clob" }, # 2,147,483,647
125
+ :char => { :name => "char", :limit => 254 }, # JDBC limit: 254
100
126
  :binary => { :name => "blob" }, # 2,147,483,647
101
127
  :float => { :name => "float", :limit => 8 }, # DOUBLE PRECISION
102
- :decimal => { :name => "decimal", :precision => 5, :scale => 0 }, # defaults
103
- :numeric => { :name => "decimal", :precision => 5, :scale => 0 }, # defaults
104
- :integer => { :name => "integer", :limit => 4 },
105
- :smallint => { :name => "smallint", :limit => 2 },
106
- :bigint => { :name => "bigint", :limit => 8 },
107
- :real => { :name => "real", :limit => 4 },
108
- :double => { :name => "double", :limit => 8 },
128
+ :real => { :name => "real", :limit => 4 }, # JDBC limit: 23
129
+ :double => { :name => "double", :limit => 8 }, # JDBC limit: 52
130
+ :decimal => { :name => "decimal", :precision => 5, :scale => 0 }, # JDBC limit: 31
131
+ :numeric => { :name => "decimal", :precision => 5, :scale => 0 }, # JDBC limit: 31
132
+ :integer => { :name => "integer", :limit => 4 }, # JDBC limit: 10
133
+ :smallint => { :name => "smallint", :limit => 2 }, # JDBC limit: 5
134
+ :bigint => { :name => "bigint", :limit => 8 }, # JDBC limit: 19
109
135
  :date => { :name => "date" },
110
136
  :time => { :name => "time" },
111
137
  :datetime => { :name => "timestamp" },
112
138
  :timestamp => { :name => "timestamp" },
113
139
  :xml => { :name => "xml" },
114
- :boolean => { :name => "smallint" },
140
+ :boolean => { :name => "smallint", :limit => 1 }, # TODO boolean (since 10.7)
141
+ :object => { :name => "object" },
115
142
  }
116
-
143
+
144
+ # @override
117
145
  def native_database_types
118
- super.merge NATIVE_DATABASE_TYPES
119
- end
120
-
121
- def modify_types(types)
122
- super(types)
123
- types[:primary_key] = NATIVE_DATABASE_TYPES[:primary_key]
124
- [ :string, :float, :decimal, :numeric, :integer,
125
- :smallint, :bigint, :real, :double, :xml ].each do |type|
126
- types[type] = NATIVE_DATABASE_TYPES[type].dup
127
- end
128
- types[:boolean] = NATIVE_DATABASE_TYPES[:boolean].dup
129
- types
146
+ NATIVE_DATABASE_TYPES
130
147
  end
131
-
132
- # in Derby, the following cannot specify a limit :
133
- NO_LIMIT_TYPES = [ :integer, :boolean, :timestamp, :datetime, :date, :time ] # :nodoc:
134
-
148
+
149
+ # @override
150
+ def quoted_date(value)
151
+ if value.acts_like?(:time) && value.respond_to?(:usec)
152
+ usec = sprintf("%06d", value.usec)
153
+ value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
154
+ "#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
155
+ else
156
+ super
157
+ end
158
+ end if ::ActiveRecord::VERSION::MAJOR >= 3
159
+
160
+ # @private In Derby, these cannot specify a limit.
161
+ NO_LIMIT_TYPES = [ :integer, :boolean, :timestamp, :datetime, :date, :time ]
162
+
135
163
  # Convert the specified column type to a SQL string.
136
- def type_to_sql(type, limit = nil, precision = nil, scale = nil) # :nodoc:
164
+ # @override
165
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
137
166
  return super unless NO_LIMIT_TYPES.include?(t = type.to_s.downcase.to_sym)
138
167
 
139
168
  native_type = NATIVE_DATABASE_TYPES[t]
140
169
  native_type.is_a?(Hash) ? native_type[:name] : native_type
141
170
  end
142
171
 
143
- class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition # :nodoc:
144
-
172
+ # @private
173
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
174
+
145
175
  def xml(*args)
146
176
  options = args.extract_options!
147
177
  column(args[0], 'xml', options)
148
178
  end
149
-
179
+
150
180
  end
151
181
 
152
182
  def table_definition(*args)
153
183
  new_table_definition(TableDefinition, *args)
154
184
  end
155
-
156
- # Override default -- fix case where ActiveRecord passes :default => nil, :null => true
185
+
186
+ # @override fix case where AR passes `:default => nil, :null => true`
157
187
  def add_column_options!(sql, options)
158
188
  options.delete(:default) if options.has_key?(:default) && options[:default].nil?
159
189
  sql << " DEFAULT #{quote(options.delete(:default))}" if options.has_key?(:default)
160
190
  super
161
191
  end
162
192
 
193
+ # @override
163
194
  def empty_insert_statement_value
164
195
  'VALUES ( DEFAULT )' # won't work as Derby does need to know the columns count
165
196
  end
166
-
197
+
167
198
  # Set the sequence to the max value of the table's column.
199
+ # @override
168
200
  def reset_sequence!(table, column, sequence = nil)
169
201
  mpk = select_value("SELECT MAX(#{quote_column_name(column)}) FROM #{quote_table_name(table)}")
170
202
  execute("ALTER TABLE #{quote_table_name(table)} ALTER COLUMN #{quote_column_name(column)} RESTART WITH #{mpk.to_i + 1}")
@@ -183,11 +215,13 @@ module ArJdbc
183
215
  ActiveRecord::Base.send(:subclasses).select { |klass| klass.table_name == table }
184
216
  end
185
217
  private :classes_for_table_name
186
-
187
- def remove_index(table_name, options) #:nodoc:
218
+
219
+ # @override
220
+ def remove_index(table_name, options)
188
221
  execute "DROP INDEX #{index_name(table_name, options)}"
189
222
  end
190
223
 
224
+ # @override
191
225
  def rename_table(name, new_name)
192
226
  execute "RENAME TABLE #{quote_table_name(name)} TO #{quote_table_name(new_name)}"
193
227
  end
@@ -198,29 +232,15 @@ module ArJdbc
198
232
  execute(add_column_sql)
199
233
  end
200
234
 
201
- def execute(sql, name = nil, binds = [])
202
- sql = to_sql(sql, binds)
203
- if sql =~ /\A\s*(UPDATE|INSERT)/i
204
- if ( i = sql =~ /\sWHERE\s/im )
205
- where_part = sql[i..-1]; sql = sql.dup
206
- where_part.gsub!(/!=\s*NULL/, 'IS NOT NULL')
207
- where_part.gsub!(/=\sNULL/i, 'IS NULL')
208
- sql[i..-1] = where_part
209
- end
210
- else
211
- sql = sql.gsub(/=\sNULL/i, 'IS NULL')
212
- end
213
- super(sql, name, binds)
214
- end
215
-
216
235
  # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
217
236
  #
218
237
  # Derby requires the ORDER BY columns in the select list for distinct queries, and
219
238
  # requires that the ORDER BY include the distinct column.
220
- #
239
+ # ```
221
240
  # distinct("posts.id", "posts.created_at desc")
222
- #
223
- # Based on distinct method for PostgreSQL Adapter
241
+ # ```
242
+ # @note This is based on distinct method for the PostgreSQL Adapter.
243
+ # @override
224
244
  def distinct(columns, order_by)
225
245
  return "DISTINCT #{columns}" if order_by.blank?
226
246
 
@@ -234,22 +254,27 @@ module ArJdbc
234
254
  sql = "DISTINCT #{columns}, #{order_columns * ', '}"
235
255
  sql
236
256
  end
237
-
238
- def remove_column(table_name, *column_names) # :nodoc:
257
+
258
+ # @override
259
+ def remove_column(table_name, *column_names)
239
260
  for column_name in column_names.flatten
240
261
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} RESTRICT"
241
262
  end
242
263
  end
243
264
 
244
- # Notes about changing in Derby:
245
- # http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
246
- #
247
- # We support changing columns using the strategy outlined in:
248
- # https://issues.apache.org/jira/browse/DERBY-1515
249
- #
250
- # This feature has not made it into a formal release and is not in Java 6.
251
- # We will need to conditionally support this (supposed to arrive for 10.3.0.0).
265
+ # @override
252
266
  def change_column(table_name, column_name, type, options = {})
267
+ # TODO this needs a review since now we're likely to be on >= 10.8
268
+
269
+ # Notes about changing in Derby:
270
+ # http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
271
+ #
272
+ # We support changing columns using the strategy outlined in:
273
+ # https://issues.apache.org/jira/browse/DERBY-1515
274
+ #
275
+ # This feature has not made it into a formal release and is not in Java 6.
276
+ # We will need to conditionally support this (supposed to arrive for 10.3.0.0).
277
+
253
278
  # null/not nulling is easy, handle that separately
254
279
  if options.include?(:null)
255
280
  # This seems to only work with 10.2 of Derby
@@ -263,14 +288,17 @@ module ArJdbc
263
288
  # anything left to do?
264
289
  unless options.empty?
265
290
  begin
266
- execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
291
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN " <<
292
+ " #{quote_column_name(column_name)} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
267
293
  rescue
268
294
  transaction do
269
295
  temp_new_column_name = "#{column_name}_newtype"
270
296
  # 1) ALTER TABLE t ADD COLUMN c1_newtype NEWTYPE;
271
297
  add_column table_name, temp_new_column_name, type, options
272
298
  # 2) UPDATE t SET c1_newtype = c1;
273
- execute "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(temp_new_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit])})"
299
+ execute "UPDATE #{quote_table_name(table_name)} SET " <<
300
+ " #{quote_column_name(temp_new_column_name)} = " <<
301
+ " CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit])})"
274
302
  # 3) ALTER TABLE t DROP COLUMN c1;
275
303
  remove_column table_name, column_name
276
304
  # 4) ALTER TABLE t RENAME COLUMN c1_newtype to c1;
@@ -280,53 +308,124 @@ module ArJdbc
280
308
  end
281
309
  end
282
310
 
283
- def rename_column(table_name, column_name, new_column_name) #:nodoc:
284
- execute "RENAME COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
311
+ # @override
312
+ def rename_column(table_name, column_name, new_column_name)
313
+ execute "RENAME COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} " <<
314
+ " TO #{quote_column_name(new_column_name)}"
285
315
  end
286
316
 
317
+ # @override
287
318
  def primary_keys(table_name)
288
319
  @connection.primary_keys table_name.to_s.upcase
289
320
  end
290
321
 
291
- def columns(table_name, name = nil)
292
- @connection.columns_internal(table_name.to_s, nil, derby_schema)
322
+ # @override
323
+ def tables(name = nil)
324
+ @connection.tables(nil, current_schema)
325
+ end
326
+
327
+ # @return [String] the current schema name
328
+ def current_schema
329
+ @current_schema ||=
330
+ select_value "SELECT CURRENT SCHEMA FROM SYS.SYSSCHEMAS FETCH FIRST 1 ROWS ONLY", 'SCHEMA'
331
+ end
332
+
333
+ # Change the current (implicit) Derby schema to be used for this connection.
334
+ def set_schema(schema)
335
+ @current_schema = nil
336
+ execute "SET SCHEMA #{schema}", 'SCHEMA'
293
337
  end
338
+ alias_method :current_schema=, :set_schema
294
339
 
295
- def tables
296
- @connection.tables(nil, derby_schema)
340
+ # Creates a new Derby schema.
341
+ # @see #set_schema
342
+ def create_schema(schema)
343
+ execute "CREATE SCHEMA #{schema}", 'Create Schema'
297
344
  end
298
-
299
- def recreate_database(name = nil, options = {}) # :nodoc:
345
+
346
+ # Drops an existing schema, needs to be empty (no DB objects).
347
+ def drop_schema(schema)
348
+ execute "DROP SCHEMA #{schema} RESTRICT", 'Drop Schema'
349
+ end
350
+
351
+ # @private
352
+ def recreate_database(name = nil, options = {})
300
353
  drop_database(name)
301
354
  create_database(name, options)
302
355
  end
303
-
304
- def create_database(name = nil, options = {}); end # :nodoc:
305
356
 
306
- def drop_database(name = nil) # :nodoc:
357
+ # @private
358
+ def create_database(name = nil, options = {}); end
359
+
360
+ # @private
361
+ def drop_database(name = nil)
307
362
  tables.each { |table| drop_table(table) }
308
363
  end
309
364
 
310
- def quote_column_name(name) # :nodoc:
365
+ # @override
366
+ def quote_column_name(name)
311
367
  %Q{"#{name.to_s.upcase.gsub('"', '""')}"}
312
368
  end
313
369
 
314
- def add_limit_offset!(sql, options) # :nodoc:
370
+ # @note Only used with (non-AREL) ActiveRecord **2.3**.
371
+ # @see Arel::Visitors::Derby
372
+ def add_limit_offset!(sql, options)
315
373
  sql << " OFFSET #{options[:offset]} ROWS" if options[:offset]
316
374
  # ROWS/ROW and FIRST/NEXT mean the same
317
375
  sql << " FETCH FIRST #{options[:limit]} ROWS ONLY" if options[:limit]
376
+ end if ::ActiveRecord::VERSION::MAJOR < 3
377
+
378
+ # @override
379
+ def execute(sql, name = nil, binds = [])
380
+ sql = to_sql(sql, binds)
381
+ insert = self.class.insert?(sql)
382
+ update = ! insert && ! self.class.select?(sql)
383
+ sql = correct_is_null(sql, insert || update)
384
+ super(sql, name, binds)
385
+ end
386
+
387
+ # Returns the value of an identity column of the last *INSERT* statement
388
+ # made over this connection.
389
+ # @note Check the *IDENTITY_VAL_LOCAL* function for documentation.
390
+ # @return [Fixnum]
391
+ def last_insert_id
392
+ @connection.identity_val_local
318
393
  end
319
394
 
320
395
  private
321
-
322
- # Derby appears to define schemas using the username
323
- def derby_schema
324
- if @config.has_key?(:schema)
325
- @config[:schema]
396
+
397
+ def correct_is_null(sql, insert_or_update = false)
398
+ if insert_or_update
399
+ if ( i = sql =~ /\sWHERE\s/im )
400
+ where_part = sql[i..-1]; sql = sql.dup
401
+ where_part.gsub!(/!=\s*NULL/i, 'IS NOT NULL')
402
+ where_part.gsub!(/=\sNULL/i, 'IS NULL')
403
+ sql[i..-1] = where_part
404
+ end
405
+ sql
326
406
  else
327
- (@config[:username] && @config[:username].to_s) || ''
407
+ sql.gsub(/=\sNULL/i, 'IS NULL')
328
408
  end
329
409
  end
330
-
410
+
411
+ # NOTE: only setup query analysis on AR <= 3.0 since on 3.1 {#exec_query},
412
+ # {#exec_insert} will be used for AR generated queries/inserts etc.
413
+ # Also there's prepared statement support and {#execute} is meant to stay
414
+ # as a way of running non-prepared SQL statements (returning raw results).
415
+ if ActiveRecord::VERSION::MAJOR < 3 ||
416
+ ( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 1 )
417
+
418
+ def _execute(sql, name = nil)
419
+ if self.class.insert?(sql)
420
+ @connection.execute_insert(sql)
421
+ elsif self.class.select?(sql)
422
+ @connection.execute_query_raw(sql)
423
+ else
424
+ @connection.execute_update(sql)
425
+ end
426
+ end
427
+
428
+ end
429
+
331
430
  end
332
431
  end