sequel 3.21.0 → 3.32.0

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 (234) hide show
  1. data/CHANGELOG +539 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -6
  4. data/Rakefile +37 -19
  5. data/bin/sequel +1 -5
  6. data/doc/advanced_associations.rdoc +17 -0
  7. data/doc/association_basics.rdoc +293 -43
  8. data/doc/dataset_basics.rdoc +4 -4
  9. data/doc/dataset_filtering.rdoc +8 -0
  10. data/doc/mass_assignment.rdoc +54 -0
  11. data/doc/migration.rdoc +15 -538
  12. data/doc/model_hooks.rdoc +72 -27
  13. data/doc/opening_databases.rdoc +89 -50
  14. data/doc/prepared_statements.rdoc +40 -13
  15. data/doc/reflection.rdoc +8 -2
  16. data/doc/release_notes/3.22.0.txt +39 -0
  17. data/doc/release_notes/3.23.0.txt +172 -0
  18. data/doc/release_notes/3.24.0.txt +420 -0
  19. data/doc/release_notes/3.25.0.txt +88 -0
  20. data/doc/release_notes/3.26.0.txt +88 -0
  21. data/doc/release_notes/3.27.0.txt +82 -0
  22. data/doc/release_notes/3.28.0.txt +304 -0
  23. data/doc/release_notes/3.29.0.txt +459 -0
  24. data/doc/release_notes/3.30.0.txt +135 -0
  25. data/doc/release_notes/3.31.0.txt +146 -0
  26. data/doc/release_notes/3.32.0.txt +202 -0
  27. data/doc/schema_modification.rdoc +547 -0
  28. data/doc/sharding.rdoc +7 -1
  29. data/doc/testing.rdoc +129 -0
  30. data/doc/transactions.rdoc +137 -0
  31. data/doc/virtual_rows.rdoc +2 -2
  32. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  33. data/lib/sequel/adapters/ado.rb +40 -18
  34. data/lib/sequel/adapters/amalgalite.rb +17 -9
  35. data/lib/sequel/adapters/db2.rb +175 -86
  36. data/lib/sequel/adapters/dbi.rb +15 -15
  37. data/lib/sequel/adapters/do/mysql.rb +5 -7
  38. data/lib/sequel/adapters/do/postgres.rb +0 -5
  39. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  40. data/lib/sequel/adapters/do.rb +17 -36
  41. data/lib/sequel/adapters/firebird.rb +27 -208
  42. data/lib/sequel/adapters/ibmdb.rb +448 -0
  43. data/lib/sequel/adapters/informix.rb +6 -23
  44. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  45. data/lib/sequel/adapters/jdbc/db2.rb +52 -0
  46. data/lib/sequel/adapters/jdbc/derby.rb +260 -0
  47. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  48. data/lib/sequel/adapters/jdbc/h2.rb +66 -30
  49. data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
  50. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  51. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  52. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  53. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  54. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  55. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  58. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  59. data/lib/sequel/adapters/jdbc.rb +231 -78
  60. data/lib/sequel/adapters/mock.rb +339 -0
  61. data/lib/sequel/adapters/mysql.rb +85 -184
  62. data/lib/sequel/adapters/mysql2.rb +26 -25
  63. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  64. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  65. data/lib/sequel/adapters/odbc.rb +28 -9
  66. data/lib/sequel/adapters/openbase.rb +3 -5
  67. data/lib/sequel/adapters/oracle.rb +355 -53
  68. data/lib/sequel/adapters/postgres.rb +194 -33
  69. data/lib/sequel/adapters/shared/access.rb +32 -9
  70. data/lib/sequel/adapters/shared/db2.rb +328 -0
  71. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  72. data/lib/sequel/adapters/shared/informix.rb +53 -0
  73. data/lib/sequel/adapters/shared/mssql.rb +278 -107
  74. data/lib/sequel/adapters/shared/mysql.rb +203 -65
  75. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  76. data/lib/sequel/adapters/shared/oracle.rb +237 -46
  77. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  78. data/lib/sequel/adapters/shared/progress.rb +5 -8
  79. data/lib/sequel/adapters/shared/sqlite.rb +200 -50
  80. data/lib/sequel/adapters/sqlite.rb +29 -21
  81. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  82. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  83. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  84. data/lib/sequel/adapters/swift.rb +5 -5
  85. data/lib/sequel/adapters/tinytds.rb +160 -19
  86. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  87. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  88. data/lib/sequel/ast_transformer.rb +190 -0
  89. data/lib/sequel/connection_pool/threaded.rb +3 -2
  90. data/lib/sequel/connection_pool.rb +1 -1
  91. data/lib/sequel/core.rb +68 -5
  92. data/lib/sequel/database/connecting.rb +5 -6
  93. data/lib/sequel/database/dataset.rb +4 -4
  94. data/lib/sequel/database/dataset_defaults.rb +59 -1
  95. data/lib/sequel/database/logging.rb +1 -1
  96. data/lib/sequel/database/misc.rb +104 -19
  97. data/lib/sequel/database/query.rb +163 -59
  98. data/lib/sequel/database/schema_generator.rb +17 -7
  99. data/lib/sequel/database/schema_methods.rb +59 -29
  100. data/lib/sequel/dataset/actions.rb +240 -76
  101. data/lib/sequel/dataset/features.rb +91 -8
  102. data/lib/sequel/dataset/graph.rb +38 -11
  103. data/lib/sequel/dataset/misc.rb +50 -23
  104. data/lib/sequel/dataset/mutation.rb +12 -7
  105. data/lib/sequel/dataset/prepared_statements.rb +59 -27
  106. data/lib/sequel/dataset/query.rb +236 -43
  107. data/lib/sequel/dataset/sql.rb +676 -267
  108. data/lib/sequel/dataset.rb +8 -0
  109. data/lib/sequel/exceptions.rb +4 -0
  110. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  111. data/lib/sequel/extensions/migration.rb +6 -4
  112. data/lib/sequel/extensions/named_timezones.rb +5 -0
  113. data/lib/sequel/extensions/query.rb +1 -1
  114. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  115. data/lib/sequel/extensions/to_dot.rb +95 -83
  116. data/lib/sequel/model/associations.rb +1081 -344
  117. data/lib/sequel/model/base.rb +420 -133
  118. data/lib/sequel/model/errors.rb +1 -1
  119. data/lib/sequel/model/exceptions.rb +5 -1
  120. data/lib/sequel/model.rb +20 -10
  121. data/lib/sequel/plugins/active_model.rb +13 -1
  122. data/lib/sequel/plugins/association_pks.rb +22 -4
  123. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  124. data/lib/sequel/plugins/composition.rb +43 -10
  125. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  126. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  127. data/lib/sequel/plugins/force_encoding.rb +6 -6
  128. data/lib/sequel/plugins/identity_map.rb +114 -7
  129. data/lib/sequel/plugins/many_through_many.rb +68 -7
  130. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  131. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  132. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  133. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  134. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  135. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  136. data/lib/sequel/plugins/serialization.rb +98 -49
  137. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  138. data/lib/sequel/plugins/sharding.rb +21 -54
  139. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  140. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  141. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  142. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  143. data/lib/sequel/sql.rb +109 -52
  144. data/lib/sequel/timezones.rb +57 -38
  145. data/lib/sequel/version.rb +1 -1
  146. data/spec/adapters/db2_spec.rb +146 -0
  147. data/spec/adapters/mssql_spec.rb +135 -30
  148. data/spec/adapters/mysql_spec.rb +244 -212
  149. data/spec/adapters/oracle_spec.rb +67 -77
  150. data/spec/adapters/postgres_spec.rb +267 -78
  151. data/spec/adapters/spec_helper.rb +6 -5
  152. data/spec/adapters/sqlite_spec.rb +35 -21
  153. data/spec/core/connection_pool_spec.rb +71 -92
  154. data/spec/core/core_sql_spec.rb +21 -30
  155. data/spec/core/database_spec.rb +789 -512
  156. data/spec/core/dataset_spec.rb +1176 -1061
  157. data/spec/core/expression_filters_spec.rb +159 -42
  158. data/spec/core/mock_adapter_spec.rb +419 -0
  159. data/spec/core/object_graph_spec.rb +86 -114
  160. data/spec/core/schema_generator_spec.rb +3 -3
  161. data/spec/core/schema_spec.rb +298 -38
  162. data/spec/core/spec_helper.rb +6 -48
  163. data/spec/extensions/active_model_spec.rb +13 -0
  164. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  165. data/spec/extensions/association_dependencies_spec.rb +2 -12
  166. data/spec/extensions/association_pks_spec.rb +66 -32
  167. data/spec/extensions/caching_spec.rb +23 -50
  168. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  169. data/spec/extensions/columns_introspection_spec.rb +91 -0
  170. data/spec/extensions/composition_spec.rb +18 -13
  171. data/spec/extensions/dataset_associations_spec.rb +199 -0
  172. data/spec/extensions/defaults_setter_spec.rb +64 -0
  173. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  174. data/spec/extensions/identity_map_spec.rb +114 -22
  175. data/spec/extensions/instance_filters_spec.rb +11 -21
  176. data/spec/extensions/instance_hooks_spec.rb +53 -0
  177. data/spec/extensions/json_serializer_spec.rb +4 -5
  178. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  179. data/spec/extensions/list_spec.rb +17 -39
  180. data/spec/extensions/many_through_many_spec.rb +283 -250
  181. data/spec/extensions/migration_spec.rb +35 -32
  182. data/spec/extensions/named_timezones_spec.rb +23 -3
  183. data/spec/extensions/nested_attributes_spec.rb +97 -88
  184. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  185. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  186. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  187. data/spec/extensions/prepared_statements_spec.rb +53 -0
  188. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  189. data/spec/extensions/pretty_table_spec.rb +1 -6
  190. data/spec/extensions/query_spec.rb +6 -0
  191. data/spec/extensions/rcte_tree_spec.rb +41 -43
  192. data/spec/extensions/schema_dumper_spec.rb +5 -8
  193. data/spec/extensions/schema_spec.rb +13 -21
  194. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  195. data/spec/extensions/serialization_spec.rb +81 -43
  196. data/spec/extensions/sharding_spec.rb +66 -140
  197. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  198. data/spec/extensions/spec_helper.rb +13 -61
  199. data/spec/extensions/sql_expr_spec.rb +20 -60
  200. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  201. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  202. data/spec/extensions/timestamps_spec.rb +6 -6
  203. data/spec/extensions/to_dot_spec.rb +4 -7
  204. data/spec/extensions/touch_spec.rb +13 -14
  205. data/spec/extensions/tree_spec.rb +11 -26
  206. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  207. data/spec/extensions/update_primary_key_spec.rb +30 -24
  208. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  209. data/spec/extensions/validation_helpers_spec.rb +16 -35
  210. data/spec/extensions/xml_serializer_spec.rb +16 -4
  211. data/spec/integration/associations_test.rb +661 -21
  212. data/spec/integration/database_test.rb +4 -2
  213. data/spec/integration/dataset_test.rb +500 -67
  214. data/spec/integration/eager_loader_test.rb +19 -21
  215. data/spec/integration/model_test.rb +80 -1
  216. data/spec/integration/plugin_test.rb +367 -119
  217. data/spec/integration/prepared_statement_test.rb +222 -125
  218. data/spec/integration/schema_test.rb +217 -39
  219. data/spec/integration/spec_helper.rb +39 -30
  220. data/spec/integration/timezone_test.rb +38 -12
  221. data/spec/integration/transaction_test.rb +182 -5
  222. data/spec/integration/type_test.rb +17 -3
  223. data/spec/model/association_reflection_spec.rb +201 -7
  224. data/spec/model/associations_spec.rb +955 -662
  225. data/spec/model/base_spec.rb +275 -95
  226. data/spec/model/dataset_methods_spec.rb +7 -27
  227. data/spec/model/eager_loading_spec.rb +677 -676
  228. data/spec/model/hooks_spec.rb +349 -67
  229. data/spec/model/model_spec.rb +222 -168
  230. data/spec/model/plugins_spec.rb +24 -13
  231. data/spec/model/record_spec.rb +381 -218
  232. data/spec/model/spec_helper.rb +13 -71
  233. data/spec/model/validations_spec.rb +11 -0
  234. metadata +117 -73
@@ -32,47 +32,89 @@ module Sequel
32
32
  DATABASE_SETUP = {:postgresql=>proc do |db|
33
33
  Sequel.ts_require 'adapters/jdbc/postgresql'
34
34
  db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
35
+ db.dataset_class = Sequel::JDBC::Postgres::Dataset
35
36
  JDBC.load_gem('postgres')
36
37
  org.postgresql.Driver
37
38
  end,
38
39
  :mysql=>proc do |db|
39
40
  Sequel.ts_require 'adapters/jdbc/mysql'
40
41
  db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
42
+ db.dataset_class = Sequel::JDBC::MySQL::Dataset
41
43
  JDBC.load_gem('mysql')
42
44
  com.mysql.jdbc.Driver
43
45
  end,
44
46
  :sqlite=>proc do |db|
45
47
  Sequel.ts_require 'adapters/jdbc/sqlite'
46
48
  db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
49
+ db.dataset_class = Sequel::JDBC::SQLite::Dataset
47
50
  JDBC.load_gem('sqlite3')
48
51
  org.sqlite.JDBC
49
52
  end,
50
53
  :oracle=>proc do |db|
51
54
  Sequel.ts_require 'adapters/jdbc/oracle'
52
55
  db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
56
+ db.dataset_class = Sequel::JDBC::Oracle::Dataset
53
57
  Java::oracle.jdbc.driver.OracleDriver
54
58
  end,
55
59
  :sqlserver=>proc do |db|
56
- Sequel.ts_require 'adapters/jdbc/mssql'
57
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
60
+ Sequel.ts_require 'adapters/jdbc/sqlserver'
61
+ db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
62
+ db.dataset_class = Sequel::JDBC::SQLServer::Dataset
63
+ db.send(:set_mssql_unicode_strings)
58
64
  com.microsoft.sqlserver.jdbc.SQLServerDriver
59
65
  end,
60
66
  :jtds=>proc do |db|
61
- Sequel.ts_require 'adapters/jdbc/mssql'
62
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
67
+ Sequel.ts_require 'adapters/jdbc/jtds'
68
+ db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
69
+ db.dataset_class = Sequel::JDBC::JTDS::Dataset
70
+ db.send(:set_mssql_unicode_strings)
63
71
  JDBC.load_gem('jtds')
64
72
  Java::net.sourceforge.jtds.jdbc.Driver
65
73
  end,
66
74
  :h2=>proc do |db|
67
75
  Sequel.ts_require 'adapters/jdbc/h2'
68
76
  db.extend(Sequel::JDBC::H2::DatabaseMethods)
77
+ db.dataset_class = Sequel::JDBC::H2::Dataset
69
78
  JDBC.load_gem('h2')
70
79
  org.h2.Driver
71
80
  end,
81
+ :hsqldb=>proc do |db|
82
+ Sequel.ts_require 'adapters/jdbc/hsqldb'
83
+ db.extend(Sequel::JDBC::HSQLDB::DatabaseMethods)
84
+ db.dataset_class = Sequel::JDBC::HSQLDB::Dataset
85
+ # Current gem is 1.8.1.3, but Sequel supports 2.2.5
86
+ org.hsqldb.jdbcDriver
87
+ end,
88
+ :derby=>proc do |db|
89
+ Sequel.ts_require 'adapters/jdbc/derby'
90
+ db.extend(Sequel::JDBC::Derby::DatabaseMethods)
91
+ db.dataset_class = Sequel::JDBC::Derby::Dataset
92
+ JDBC.load_gem('derby')
93
+ org.apache.derby.jdbc.EmbeddedDriver
94
+ end,
72
95
  :as400=>proc do |db|
73
96
  Sequel.ts_require 'adapters/jdbc/as400'
74
97
  db.extend(Sequel::JDBC::AS400::DatabaseMethods)
98
+ db.dataset_class = Sequel::JDBC::AS400::Dataset
75
99
  com.ibm.as400.access.AS400JDBCDriver
100
+ end,
101
+ :"informix-sqli"=>proc do |db|
102
+ Sequel.ts_require 'adapters/jdbc/informix'
103
+ db.extend(Sequel::JDBC::Informix::DatabaseMethods)
104
+ db.dataset_class = Sequel::JDBC::Informix::Dataset
105
+ com.informix.jdbc.IfxDriver
106
+ end,
107
+ :db2=>proc do |db|
108
+ Sequel.ts_require 'adapters/jdbc/db2'
109
+ db.extend(Sequel::JDBC::DB2::DatabaseMethods)
110
+ db.dataset_class = Sequel::JDBC::DB2::Dataset
111
+ com.ibm.db2.jcc.DB2Driver
112
+ end,
113
+ :firebirdsql=>proc do |db|
114
+ Sequel.ts_require 'adapters/jdbc/firebird'
115
+ db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
116
+ db.dataset_class = Sequel::JDBC::Firebird::Dataset
117
+ org.firebirdsql.jdbc.FBDriver
76
118
  end
77
119
  }
78
120
 
@@ -101,7 +143,7 @@ module Sequel
101
143
  # True by default, can be set to false to roughly double performance when
102
144
  # fetching rows.
103
145
  attr_accessor :convert_types
104
-
146
+
105
147
  # Call the DATABASE_SETUP proc directly after initialization,
106
148
  # so the object always uses sub adapter specific code. Also,
107
149
  # raise an error immediately if the connection doesn't have a
@@ -158,6 +200,7 @@ module Sequel
158
200
  args = [uri(opts)]
159
201
  args.concat([opts[:user], opts[:password]]) if opts[:user] && opts[:password]
160
202
  begin
203
+ JavaSQL::DriverManager.setLoginTimeout(opts[:login_timeout]) if opts[:login_timeout]
161
204
  JavaSQL::DriverManager.getConnection(*args)
162
205
  rescue => e
163
206
  raise e unless driver
@@ -180,11 +223,6 @@ module Sequel
180
223
  setup_connection(conn)
181
224
  end
182
225
 
183
- # Return instances of JDBC::Dataset with the given opts.
184
- def dataset(opts = nil)
185
- JDBC::Dataset.new(self, opts)
186
- end
187
-
188
226
  # Execute the given SQL. If a block is given, if should be a SELECT
189
227
  # statement or something else that returns rows.
190
228
  def execute(sql, opts={}, &block)
@@ -246,12 +284,14 @@ module Sequel
246
284
  indexes
247
285
  end
248
286
 
287
+ # Whether or not JNDI is being used for this connection.
288
+ def jndi?
289
+ !!(uri =~ JNDI_URI_REGEXP)
290
+ end
291
+
249
292
  # All tables in this database
250
293
  def tables(opts={})
251
- ts = []
252
- m = output_identifier_meth
253
- metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
254
- ts
294
+ get_tables('TABLE', opts)
255
295
  end
256
296
 
257
297
  # The uri for this connection. You can specify the uri
@@ -264,11 +304,11 @@ module Sequel
264
304
  ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
265
305
  end
266
306
 
267
- # Whether or not JNDI is being used for this connection.
268
- def jndi?
269
- !!(uri =~ JNDI_URI_REGEXP)
307
+ # All views in this database
308
+ def views(opts={})
309
+ get_tables('VIEW', opts)
270
310
  end
271
-
311
+
272
312
  private
273
313
 
274
314
  # Close given adapter connections
@@ -276,6 +316,12 @@ module Sequel
276
316
  c.close
277
317
  end
278
318
 
319
+ # Raise a disconnect error if the SQL state of the cause of the exception indicates so.
320
+ def disconnect_error?(exception, opts)
321
+ cause = exception.respond_to?(:cause) ? exception.cause : exception
322
+ super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
323
+ end
324
+
279
325
  # Execute the prepared statement. If the provided name is a
280
326
  # dataset, use that as the prepared statement, otherwise use
281
327
  # it as a key to look it up in the prepared_statements hash.
@@ -325,6 +371,12 @@ module Sequel
325
371
  end
326
372
  end
327
373
 
374
+ # Gets the connection from JNDI.
375
+ def get_connection_from_jndi
376
+ jndi_name = JNDI_URI_REGEXP.match(uri)[1]
377
+ JavaxNaming::InitialContext.new.lookup(jndi_name).connection
378
+ end
379
+
328
380
  # Gets the JDBC connection uri from the JNDI resource.
329
381
  def get_uri_from_jndi
330
382
  conn = get_connection_from_jndi
@@ -333,12 +385,14 @@ module Sequel
333
385
  conn.close if conn
334
386
  end
335
387
 
336
- # Gets the connection from JNDI.
337
- def get_connection_from_jndi
338
- jndi_name = JNDI_URI_REGEXP.match(uri)[1]
339
- JavaxNaming::InitialContext.new.lookup(jndi_name).connection
388
+ # Backbone of the tables and views support.
389
+ def get_tables(type, opts)
390
+ ts = []
391
+ m = output_identifier_meth
392
+ metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
393
+ ts
340
394
  end
341
-
395
+
342
396
  # Support Date objects used in bound variables
343
397
  def java_sql_date(date)
344
398
  java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
@@ -383,12 +437,6 @@ module Sequel
383
437
  end
384
438
  end
385
439
 
386
- # Treat SQLExceptions with a "Connection Error" SQLState as disconnects
387
- def raise_error(exception, opts={})
388
- cause = exception.respond_to?(:cause) ? exception.cause : exception
389
- super(exception, {:disconnect => cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/}.merge(opts))
390
- end
391
-
392
440
  # Java being java, you need to specify the type of each argument
393
441
  # for the prepared statement, and bind it individually. This
394
442
  # guesses which JDBC method to use, and hopefully JRuby will convert
@@ -405,8 +453,8 @@ module Sequel
405
453
  cps.setDouble(i, arg)
406
454
  when TrueClass, FalseClass
407
455
  cps.setBoolean(i, arg)
408
- when nil
409
- cps.setNull(i, JavaSQL::Types::NULL)
456
+ when NilClass
457
+ cps.setString(i, nil)
410
458
  when DateTime
411
459
  cps.setTimestamp(i, java_sql_datetime(arg))
412
460
  when Date
@@ -435,8 +483,8 @@ module Sequel
435
483
 
436
484
  # Parse the table schema for the given table.
437
485
  def schema_parse_table(table, opts={})
438
- m = output_identifier_meth
439
- im = input_identifier_meth
486
+ m = output_identifier_meth(opts[:dataset])
487
+ im = input_identifier_meth(opts[:dataset])
440
488
  ds = dataset
441
489
  schema, table = schema_and_table(table)
442
490
  schema ||= opts[:schema]
@@ -444,9 +492,11 @@ module Sequel
444
492
  table = im.call(table)
445
493
  pks, ts = [], []
446
494
  metadata(:getPrimaryKeys, nil, schema, table) do |h|
495
+ next if schema_parse_table_skip?(h, schema)
447
496
  pks << h[:column_name]
448
497
  end
449
498
  metadata(:getColumns, nil, schema, table, nil) do |h|
499
+ next if schema_parse_table_skip?(h, schema)
450
500
  s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
451
501
  if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
452
502
  s[:type] = :integer
@@ -456,6 +506,12 @@ module Sequel
456
506
  ts
457
507
  end
458
508
 
509
+ # Whether schema_parse_table should skip the given row when
510
+ # parsing the schema.
511
+ def schema_parse_table_skip?(h, schema)
512
+ h[:table_schem] == 'INFORMATION_SCHEMA'
513
+ end
514
+
459
515
  # Yield a new statement object, and ensure that it is closed before returning.
460
516
  def statement(conn)
461
517
  stmt = conn.createStatement
@@ -476,6 +532,8 @@ module Sequel
476
532
 
477
533
  class Dataset < Sequel::Dataset
478
534
  include StoredProcedures
535
+
536
+ Database::DatasetClass = self
479
537
 
480
538
  # Use JDBC PreparedStatements instead of emulated ones. Statements
481
539
  # created using #prepare are cached at the connection level to allow
@@ -489,17 +547,17 @@ module Sequel
489
547
  # Execute the prepared SQL using the stored type and
490
548
  # arguments derived from the hash passed to call.
491
549
  def execute(sql, opts={}, &block)
492
- super(self, {:arguments=>bind_arguments, :type=>sql_query_type}.merge(opts), &block)
550
+ super(self, {:arguments=>bind_arguments}.merge(opts), &block)
493
551
  end
494
552
 
495
553
  # Same as execute, explicit due to intricacies of alias and super.
496
554
  def execute_dui(sql, opts={}, &block)
497
- super(self, {:arguments=>bind_arguments, :type=>sql_query_type}.merge(opts), &block)
555
+ super(self, {:arguments=>bind_arguments}.merge(opts), &block)
498
556
  end
499
557
 
500
558
  # Same as execute, explicit due to intricacies of alias and super.
501
559
  def execute_insert(sql, opts={}, &block)
502
- super(self, {:arguments=>bind_arguments, :type=>sql_query_type}.merge(opts), &block)
560
+ super(self, {:arguments=>bind_arguments, :type=>:insert}.merge(opts), &block)
503
561
  end
504
562
  end
505
563
 
@@ -512,17 +570,17 @@ module Sequel
512
570
 
513
571
  # Execute the database stored procedure with the stored arguments.
514
572
  def execute(sql, opts={}, &block)
515
- super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type=>sql_query_type}.merge(opts), &block)
573
+ super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
516
574
  end
517
575
 
518
576
  # Same as execute, explicit due to intricacies of alias and super.
519
577
  def execute_dui(sql, opts={}, &block)
520
- super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type=>sql_query_type}.merge(opts), &block)
578
+ super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
521
579
  end
522
580
 
523
581
  # Same as execute, explicit due to intricacies of alias and super.
524
582
  def execute_insert(sql, opts={}, &block)
525
- super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type=>sql_query_type}.merge(opts), &block)
583
+ super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type=>:insert}.merge(opts), &block)
526
584
  end
527
585
  end
528
586
 
@@ -530,13 +588,7 @@ module Sequel
530
588
  # Uses the database's setting by default, can be set to false to roughly
531
589
  # double performance when fetching rows.
532
590
  attr_accessor :convert_types
533
-
534
- # Use the convert_types default setting from the database
535
- def initialize(db, opts={})
536
- @convert_types = db.convert_types
537
- super
538
- end
539
-
591
+
540
592
  # Correctly return rows from the database and return them as hashes.
541
593
  def fetch_rows(sql, &block)
542
594
  execute(sql){|result| process_result_set(result, &block)}
@@ -556,26 +608,77 @@ module Sequel
556
608
  end
557
609
 
558
610
  private
559
-
560
- # Convert the type. Used for converting Java types to ruby types.
561
- def convert_type(v)
611
+
612
+ # Cache Java class constants to speed up lookups
613
+ JAVA_SQL_TIMESTAMP = Java::JavaSQL::Timestamp
614
+ JAVA_SQL_TIME = Java::JavaSQL::Time
615
+ JAVA_SQL_DATE = Java::JavaSQL::Date
616
+ JAVA_SQL_BLOB = Java::JavaSQL::Blob
617
+ JAVA_SQL_CLOB = Java::JavaSQL::Clob
618
+ JAVA_BUFFERED_READER = Java::JavaIo::BufferedReader
619
+ JAVA_BIG_DECIMAL = Java::JavaMath::BigDecimal
620
+ JAVA_BYTE_ARRAY = Java::byte[]
621
+
622
+ # Handle type conversions for common Java types.
623
+ class TYPE_TRANSLATOR
624
+ LF = "\n".freeze
625
+ def time(v) Sequel.string_to_time(v.to_string) end
626
+ def date(v) Date.civil(v.getYear + 1900, v.getMonth + 1, v.getDate) end
627
+ def decimal(v) BigDecimal.new(v.to_string) end
628
+ def byte_array(v) Sequel::SQL::Blob.new(String.from_java_bytes(v)) end
629
+ def blob(v) Sequel::SQL::Blob.new(String.from_java_bytes(v.getBytes(1, v.length))) end
630
+ def clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
631
+ def buffered_reader(v)
632
+ lines = ""
633
+ c = false
634
+ while(line = v.read_line) do
635
+ lines << LF if c
636
+ lines << line
637
+ c ||= true
638
+ end
639
+ lines
640
+ end
641
+ end
642
+ TYPE_TRANSLATOR_INSTANCE = tt = TYPE_TRANSLATOR.new
643
+
644
+ # Cache type translator methods so that duplicate Method
645
+ # objects are not created.
646
+ DECIMAL_METHOD = tt.method(:decimal)
647
+ TIME_METHOD = tt.method(:time)
648
+ DATE_METHOD = tt.method(:date)
649
+ BUFFERED_READER_METHOD = tt.method(:buffered_reader)
650
+ BYTE_ARRAY_METHOD = tt.method(:byte_array)
651
+ BLOB_METHOD = tt.method(:blob)
652
+ CLOB_METHOD = tt.method(:clob)
653
+
654
+ # Convert the given Java timestamp to an instance of Sequel.datetime_class.
655
+ def convert_type_timestamp(v)
656
+ db.to_application_timestamp([v.getYear + 1900, v.getMonth + 1, v.getDate, v.getHours, v.getMinutes, v.getSeconds, v.getNanos])
657
+ end
658
+
659
+ # Return a callable object that will convert any value of <tt>v</tt>'s
660
+ # class to a ruby object. If no callable object can handle <tt>v</tt>'s
661
+ # class, return false so that the negative lookup is cached.
662
+ def convert_type_proc(v)
562
663
  case v
563
- when Java::JavaSQL::Timestamp, Java::JavaSQL::Time
564
- Sequel.database_to_application_timestamp(v.to_string)
565
- when Java::JavaSQL::Date
566
- Sequel.string_to_date(v.to_string)
567
- when Java::JavaIo::BufferedReader
568
- lines = []
569
- while(line = v.read_line) do lines << line end
570
- lines.join("\n")
571
- when Java::JavaMath::BigDecimal
572
- BigDecimal.new(v.to_string)
573
- when Java::byte[]
574
- Sequel::SQL::Blob.new(String.from_java_bytes(v))
575
- when Java::JavaSQL::Blob
576
- convert_type(v.getBytes(1, v.length))
664
+ when JAVA_BIG_DECIMAL
665
+ DECIMAL_METHOD
666
+ when JAVA_SQL_TIMESTAMP
667
+ method(:convert_type_timestamp)
668
+ when JAVA_SQL_TIME
669
+ TIME_METHOD
670
+ when JAVA_SQL_DATE
671
+ DATE_METHOD
672
+ when JAVA_BUFFERED_READER
673
+ BUFFERED_READER_METHOD
674
+ when JAVA_BYTE_ARRAY
675
+ BYTE_ARRAY_METHOD
676
+ when JAVA_SQL_BLOB
677
+ BLOB_METHOD
678
+ when JAVA_SQL_CLOB
679
+ CLOB_METHOD
577
680
  else
578
- v
681
+ false
579
682
  end
580
683
  end
581
684
 
@@ -586,32 +689,82 @@ module Sequel
586
689
 
587
690
  # Split out from fetch rows to allow processing of JDBC result sets
588
691
  # that don't come from issuing an SQL string.
589
- def process_result_set(result)
692
+ def process_result_set(result, &block)
590
693
  # get column names
591
694
  meta = result.getMetaData
592
695
  cols = []
593
696
  i = 0
594
697
  meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
595
- @columns = cols.map{|c| c.at(0)}
596
- blk = result_set_object_getter
597
- # get rows
698
+ columns = cols.map{|c| c.at(0)}
699
+ if opts[:offset] && offset_returns_row_number_column?
700
+ rn = row_number_column
701
+ columns.delete(rn)
702
+ end
703
+ @columns = columns
704
+ ct = @convert_types
705
+ if (ct.nil? ? db.convert_types : ct)
706
+ cols.each{|c| c << nil}
707
+ process_result_set_convert(cols, result, rn, &block)
708
+ else
709
+ process_result_set_no_convert(cols, result, rn, &block)
710
+ end
711
+ ensure
712
+ result.close
713
+ end
714
+
715
+ # Use conversion procs to convert data retrieved
716
+ # from the database. This has been optimized, the algorithm it uses
717
+ # is roughly, for each column value in each row:
718
+ # * check if the value is truthy (not false/nil)
719
+ # * if not truthy, return object
720
+ # * otherwise, see if a conversion method exists for
721
+ # the column. All columns start with a nil conversion proc,
722
+ # since unlike other adapters, Sequel doesn't get the type of
723
+ # the column when parsing the column metadata.
724
+ # * if a conversion proc is not false/nil, call it with the object
725
+ # and return the result.
726
+ # * if a conversion proc has already been looked up and doesn't
727
+ # exist (false value), return object.
728
+ # * if a conversion proc hasn't been looked up yet (nil value),
729
+ # call convert_type_proc to get the conversion method. Cache
730
+ # the result of as the column's conversion proc to speed up
731
+ # later processing. If the conversion proc exists, call it
732
+ # and return the result, otherwise, return the object.
733
+ def process_result_set_convert(cols, result, rn)
598
734
  while result.next
599
735
  row = {}
600
- cols.each do |n, i|
601
- row[n] = blk.call(result, n, i)
736
+ cols.each do |n, i, p|
737
+ v = result.getObject(i)
738
+ row[n] = if v
739
+ if p
740
+ p.call(v)
741
+ elsif p.nil?
742
+ cols[i-1][2] = p = convert_type_proc(v)
743
+ if p
744
+ p.call(v)
745
+ else
746
+ v
747
+ end
748
+ else
749
+ v
750
+ end
751
+ else
752
+ v
753
+ end
602
754
  end
755
+ row.delete(rn) if rn
603
756
  yield row
604
757
  end
605
758
  end
606
759
 
607
- # Proc that takes the ResultSet and an integer field number and returns
608
- # the object for that field. Respects the @convert_types setting to
609
- # convert Java types to ruby types.
610
- def result_set_object_getter
611
- if @convert_types
612
- lambda {|result, n, i| convert_type(result.getObject(i))}
613
- else
614
- lambda {|result, n, i| result.getObject(i)}
760
+ # Yield rows without calling any conversion procs. This
761
+ # may yield Java values and not ruby values.
762
+ def process_result_set_no_convert(cols, result, rn)
763
+ while result.next
764
+ row = {}
765
+ cols.each{|n, i| row[n] = result.getObject(i)}
766
+ row.delete(rn) if rn
767
+ yield row
615
768
  end
616
769
  end
617
770
  end