sequel 3.21.0 → 3.36.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 (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -0,0 +1,29 @@
1
+ Sequel.require 'adapters/jdbc/mssql'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for JTDS specific
6
+ # support via JDBC.
7
+ module JTDS
8
+ # Dataset class for JTDS datasets accessed via JDBC.
9
+ class Dataset < JDBC::Dataset
10
+ include Sequel::MSSQL::DatasetMethods
11
+
12
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
13
+ def jtds_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
14
+ end
15
+
16
+ JTDS_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:jtds_clob)
17
+
18
+ # Handle CLOB types retrieved via JTDS.
19
+ def convert_type_proc(v)
20
+ if v.is_a?(Java::NetSourceforgeJtdsJdbc::ClobImpl)
21
+ JTDS_CLOB_METHOD
22
+ else
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -13,20 +13,17 @@ module Sequel
13
13
  # Database instance methods for MSSQL databases accessed via JDBC.
14
14
  module DatabaseMethods
15
15
  PRIMARY_KEY_INDEX_RE = /\Apk__/i.freeze
16
+ ATAT_IDENTITY = 'SELECT @@IDENTITY'.freeze
17
+ SCOPE_IDENTITY = 'SELECT SCOPE_IDENTITY()'.freeze
16
18
 
17
19
  include Sequel::MSSQL::DatabaseMethods
18
20
 
19
- # Return instance of Sequel::JDBC::MSSQL::Dataset with the given opts.
20
- def dataset(opts=nil)
21
- Sequel::JDBC::MSSQL::Dataset.new(self, opts)
22
- end
23
-
24
21
  private
25
22
 
26
23
  # Get the last inserted id using SCOPE_IDENTITY().
27
24
  def last_insert_id(conn, opts={})
28
25
  statement(conn) do |stmt|
29
- sql = opts[:prepared] ? 'SELECT @@IDENTITY' : 'SELECT SCOPE_IDENTITY()'
26
+ sql = opts[:prepared] ? ATAT_IDENTITY : SCOPE_IDENTITY
30
27
  rs = log_yield(sql){stmt.executeQuery(sql)}
31
28
  rs.next
32
29
  rs.getInt(1)
@@ -43,33 +40,6 @@ module Sequel
43
40
  def primary_key_index_re
44
41
  PRIMARY_KEY_INDEX_RE
45
42
  end
46
-
47
- def metadata_dataset
48
- ds = super
49
- # Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
50
- # for the getColumns result set specifies an incorrect type for the
51
- # IS_AUTOINCREMENT column. The column is a string, but the type is
52
- # specified as a short. This causes getObject() to throw a
53
- # com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
54
- # from char to SMALLINT is unsupported." Using getString() rather
55
- # than getObject() for this column avoids the problem.
56
- # Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
57
- def ds.result_set_object_getter
58
- lambda do |result, n, i|
59
- if n == :is_autoincrement
60
- @convert_types ? convert_type(result.getString(i)) : result.getString(i)
61
- else
62
- @convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
63
- end
64
- end
65
- end
66
- ds
67
- end
68
- end
69
-
70
- # Dataset class for MSSQL datasets accessed via JDBC.
71
- class Dataset < JDBC::Dataset
72
- include Sequel::MSSQL::DatasetMethods
73
43
  end
74
44
  end
75
45
  end
@@ -8,11 +8,7 @@ module Sequel
8
8
  # Database instance methods for MySQL databases accessed via JDBC.
9
9
  module DatabaseMethods
10
10
  include Sequel::MySQL::DatabaseMethods
11
-
12
- # Return instance of Sequel::JDBC::MySQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::JDBC::MySQL::Dataset.new(self, opts)
15
- end
11
+ LAST_INSERT_ID = 'SELECT LAST_INSERT_ID()'.freeze
16
12
 
17
13
  private
18
14
 
@@ -39,7 +35,7 @@ module Sequel
39
35
  end
40
36
  else
41
37
  statement(conn) do |stmt|
42
- rs = stmt.executeQuery('SELECT LAST_INSERT_ID()')
38
+ rs = stmt.executeQuery(LAST_INSERT_ID)
43
39
  rs.next
44
40
  rs.getInt(1)
45
41
  end
@@ -56,25 +52,12 @@ module Sequel
56
52
  def schema_column_type(db_type)
57
53
  db_type == 'tinyint(1)' ? :boolean : super
58
54
  end
59
- end
60
55
 
61
- # Dataset class for MySQL datasets accessed via JDBC.
62
- class Dataset < JDBC::Dataset
63
- include Sequel::MySQL::DatasetMethods
64
-
65
- # Use execute_insert to execute the insert_sql.
66
- def insert(*values)
67
- execute_insert(insert_sql(*values))
68
- end
69
-
70
- # Use execute_insert to execute the replace_sql.
71
- def replace(*args)
72
- execute_insert(replace_sql(*args))
73
- end
74
-
75
- # MySQL on JDBC does provides an accurate number of rows matched.
76
- def provides_accurate_rows_matched?
77
- true
56
+ # Run the default connection setting SQL statements.
57
+ # Apply the connectiong setting SQLs for every new connection.
58
+ def setup_connection(conn)
59
+ mysql_connection_setting_sqls.each{|sql| statement(conn){|s| log_yield(sql){s.execute(sql)}}}
60
+ super
78
61
  end
79
62
  end
80
63
  end
@@ -1,4 +1,5 @@
1
1
  Sequel.require 'adapters/shared/oracle'
2
+ Sequel.require 'adapters/jdbc/transactions'
2
3
 
3
4
  module Sequel
4
5
  module JDBC
@@ -6,44 +7,106 @@ module Sequel
6
7
  module Oracle
7
8
  # Instance methods for Oracle Database objects accessed via JDBC.
8
9
  module DatabaseMethods
10
+ PRIMARY_KEY_INDEX_RE = /\Asys_/i.freeze
11
+
9
12
  include Sequel::Oracle::DatabaseMethods
10
- TRANSACTION_BEGIN = 'Transaction.begin'.freeze
11
- TRANSACTION_COMMIT = 'Transaction.commit'.freeze
12
- TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
13
-
14
- # Return Sequel::JDBC::Oracle::Dataset object with the given opts.
15
- def dataset(opts=nil)
16
- Sequel::JDBC::Oracle::Dataset.new(self, opts)
13
+ include Sequel::JDBC::Transactions
14
+
15
+ def self.extended(db)
16
+ db.instance_eval do
17
+ @autosequence = opts[:autosequence]
18
+ @primary_key_sequences = {}
19
+ end
17
20
  end
18
21
 
19
22
  private
20
-
21
- # Use JDBC connection's setAutoCommit to false to start transactions
22
- def begin_transaction(conn, opts={})
23
- log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
24
- conn
23
+
24
+ def last_insert_id(conn, opts)
25
+ unless sequence = opts[:sequence]
26
+ if t = opts[:table]
27
+ sequence = sequence_for_table(t)
28
+ end
29
+ end
30
+ if sequence
31
+ sql = "SELECT #{literal(sequence)}.currval FROM dual"
32
+ statement(conn) do |stmt|
33
+ begin
34
+ rs = log_yield(sql){stmt.executeQuery(sql)}
35
+ rs.next
36
+ rs.getInt(1)
37
+ rescue java.sql.SQLException
38
+ nil
39
+ end
40
+ end
41
+ end
25
42
  end
26
-
27
- # Use JDBC connection's commit method to commit transactions
28
- def commit_transaction(conn, opts={})
29
- log_yield(TRANSACTION_COMMIT){conn.commit}
43
+
44
+ # Primary key indexes appear to start with sys_ on Oracle
45
+ def primary_key_index_re
46
+ PRIMARY_KEY_INDEX_RE
30
47
  end
31
-
32
- # Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
33
- def remove_transaction(conn)
34
- conn.setAutoCommit(true) if conn
35
- @transactions.delete(Thread.current)
48
+
49
+ def schema_parse_table(*)
50
+ sch = super
51
+ sch.each do |c, s|
52
+ if s[:type] == :decimal && s[:scale] == -127
53
+ s[:type] = :integer
54
+ elsif s[:db_type] == 'DATE'
55
+ s[:type] = :datetime
56
+ end
57
+ end
58
+ sch
36
59
  end
37
-
38
- # Use JDBC connection's rollback method to rollback transactions
39
- def rollback_transaction(conn, opts={})
40
- log_yield(TRANSACTION_ROLLBACK){conn.rollback}
60
+
61
+ def schema_parse_table_skip?(h, schema)
62
+ super || (h[:table_schem] != current_user unless schema)
63
+ end
64
+
65
+ # As of Oracle 9.2, releasing savepoints is no longer supported.
66
+ def supports_releasing_savepoints?
67
+ false
41
68
  end
42
69
  end
43
70
 
44
71
  # Dataset class for Oracle datasets accessed via JDBC.
45
72
  class Dataset < JDBC::Dataset
46
73
  include Sequel::Oracle::DatasetMethods
74
+
75
+ private
76
+
77
+ JAVA_BIG_DECIMAL = ::Sequel::JDBC::Dataset::JAVA_BIG_DECIMAL
78
+
79
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
80
+ def oracle_decimal(v)
81
+ if v.scale == 0
82
+ i = v.long_value
83
+ if v.equals(JAVA_BIG_DECIMAL.new(i))
84
+ i
85
+ else
86
+ decimal(v)
87
+ end
88
+ else
89
+ decimal(v)
90
+ end
91
+ end
92
+ end
93
+
94
+ ORACLE_DECIMAL_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:oracle_decimal)
95
+
96
+ def convert_type_oracle_timestamp(v)
97
+ db.to_application_timestamp(v.to_string)
98
+ end
99
+
100
+ def convert_type_proc(v)
101
+ case v
102
+ when JAVA_BIG_DECIMAL
103
+ ORACLE_DECIMAL_METHOD
104
+ when Java::OracleSql::TIMESTAMP
105
+ method(:convert_type_oracle_timestamp)
106
+ else
107
+ super
108
+ end
109
+ end
47
110
  end
48
111
  end
49
112
  end
@@ -7,32 +7,6 @@ module Sequel
7
7
  # Adapter, Database, and Dataset support for accessing a PostgreSQL
8
8
  # database via JDBC.
9
9
  module Postgres
10
- # Methods to add to the JDBC adapter/connection to allow it to work
11
- # with the shared PostgreSQL code.
12
- module AdapterMethods
13
- include Sequel::Postgres::AdapterMethods
14
-
15
- # Give the JDBC adapter a direct execute method, which creates
16
- # a statement with the given sql and executes it.
17
- def execute(sql, args=nil)
18
- method = block_given? ? :executeQuery : :execute
19
- @db.send(:statement, self) do |stmt|
20
- rows = @db.log_yield(sql){stmt.send(method, sql)}
21
- yield(rows) if block_given?
22
- end
23
- end
24
-
25
- private
26
-
27
- # JDBC specific method of getting specific values from a result set.
28
- def single_value(r)
29
- unless r.nil?
30
- r.next
31
- r.getString(1) unless r.getRow == 0
32
- end
33
- end
34
- end
35
-
36
10
  # Methods to add to Database instances that access PostgreSQL via
37
11
  # JDBC.
38
12
  module DatabaseMethods
@@ -47,48 +21,84 @@ module Sequel
47
21
  end
48
22
  end
49
23
 
50
- # Return instance of Sequel::JDBC::Postgres::Dataset with the given opts.
51
- def dataset(opts=nil)
52
- Sequel::JDBC::Postgres::Dataset.new(self, opts)
53
- end
54
-
55
- # Run the INSERT sql on the database and return the primary key
56
- # for the record.
57
- def execute_insert(sql, opts={})
58
- super(sql, {:type=>:insert}.merge(opts))
59
- end
60
-
61
24
  private
62
25
 
63
- # Extend the adapter with the JDBC PostgreSQL AdapterMethods
26
+ # Use setNull for nil arguments as the default behavior of setString
27
+ # with nil doesn't appear to work correctly on PostgreSQL.
28
+ def set_ps_arg(cps, arg, i)
29
+ arg.nil? ? cps.setNull(i, JavaSQL::Types::NULL) : super
30
+ end
31
+
32
+ # Execute the connection configuration SQL queries on the connection.
64
33
  def setup_connection(conn)
65
34
  conn = super(conn)
66
- conn.extend(Sequel::JDBC::Postgres::AdapterMethods)
67
- conn.db = self
68
- conn.apply_connection_settings
35
+ statement(conn) do |stmt|
36
+ connection_configuration_sqls.each{|sql| log_yield(sql){stmt.execute(sql)}}
37
+ end
69
38
  conn
70
39
  end
71
-
72
- # Call insert_result with the table and values specified in the opts.
73
- def last_insert_id(conn, opts)
74
- insert_result(conn, opts[:table], opts[:values])
75
- end
76
40
  end
77
41
 
78
42
  # Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
79
43
  class Dataset < JDBC::Dataset
80
44
  include Sequel::Postgres::DatasetMethods
45
+ APOS = Dataset::APOS
46
+
47
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
48
+ # Convert Java::OrgPostgresqlJdbc4::Jdbc4Array to ruby arrays
49
+ def pg_array(v)
50
+ _pg_array(v.array)
51
+ end
52
+
53
+ # Convert Java::OrgPostgresqlUtil::PGobject to ruby strings
54
+ def pg_object(v)
55
+ v.to_string
56
+ end
57
+
58
+ private
59
+
60
+ # Handle multi-dimensional Java arrays by recursively mapping them
61
+ # to ruby arrays.
62
+ def _pg_array(v)
63
+ v.to_ary.map do |i|
64
+ if i.respond_to?(:to_ary)
65
+ _pg_array(i)
66
+ else
67
+ i
68
+ end
69
+ end
70
+ end
71
+ end
81
72
 
73
+ PG_ARRAY_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_array)
74
+ PG_OBJECT_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_object)
75
+
82
76
  # Add the shared PostgreSQL prepared statement methods
83
77
  def prepare(*args)
84
78
  ps = super
85
79
  ps.extend(::Sequel::Postgres::DatasetMethods::PreparedStatementMethods)
86
80
  ps
87
81
  end
82
+
83
+ private
84
+
85
+ # Handle PostgreSQL array and object types. Object types are just
86
+ # turned into strings, similarly to how the native adapter treats
87
+ # the types.
88
+ def convert_type_proc(v)
89
+ case v
90
+ when Java::OrgPostgresqlJdbc4::Jdbc4Array
91
+ PG_ARRAY_METHOD
92
+ when Java::OrgPostgresqlUtil::PGobject
93
+ PG_OBJECT_METHOD
94
+ else
95
+ super
96
+ end
97
+ end
88
98
 
89
99
  # Literalize strings similar to the native postgres adapter
90
- def literal_string(v)
91
- db.synchronize{|c| "'#{c.escape_string(v)}'"}
100
+ def literal_string_append(sql, v)
101
+ sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
92
102
  end
93
103
  end
94
104
  end
@@ -0,0 +1,21 @@
1
+ Sequel.require 'adapters/shared/progress'
2
+ Sequel.require 'adapters/jdbc/transactions'
3
+
4
+ module Sequel
5
+ module JDBC
6
+ # Database and Dataset instance methods for Progress v9 specific
7
+ # support via JDBC.
8
+ module Progress
9
+ # Database instance methods for Progress databases accessed via JDBC.
10
+ module DatabaseMethods
11
+ include Sequel::Progress::DatabaseMethods
12
+ include Sequel::JDBC::Transactions
13
+
14
+ # Progress DatabaseMetaData doesn't even implement supportsSavepoints()
15
+ def supports_savepoints?
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -7,18 +7,33 @@ module Sequel
7
7
  # Instance methods for SQLite Database objects accessed via JDBC.
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
10
+ LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
11
+ FOREIGN_KEY_ERROR_RE = /query does not return ResultSet/.freeze
10
12
 
11
- # Return Sequel::JDBC::SQLite::Dataset object with the given opts.
12
- def dataset(opts=nil)
13
- Sequel::JDBC::SQLite::Dataset.new(self, opts)
13
+ # Swallow pointless exceptions when the foreign key list pragma
14
+ # doesn't return any rows.
15
+ def foreign_key_list(table, opts={})
16
+ super
17
+ rescue Sequel::DatabaseError => e
18
+ raise unless e.message =~ FOREIGN_KEY_ERROR_RE
19
+ []
14
20
  end
15
-
21
+
22
+ # Swallow pointless exceptions when the index list pragma
23
+ # doesn't return any rows.
24
+ def indexes(table, opts={})
25
+ super
26
+ rescue Sequel::DatabaseError => e
27
+ raise unless e.message =~ FOREIGN_KEY_ERROR_RE
28
+ {}
29
+ end
30
+
16
31
  private
17
32
 
18
33
  # Use last_insert_rowid() to get the last inserted id.
19
34
  def last_insert_id(conn, opts={})
20
35
  statement(conn) do |stmt|
21
- rs = stmt.executeQuery('SELECT last_insert_rowid()')
36
+ rs = stmt.executeQuery(LAST_INSERT_ROWID)
22
37
  rs.next
23
38
  rs.getInt(1)
24
39
  end
@@ -39,11 +54,6 @@ module Sequel
39
54
  conn
40
55
  end
41
56
  end
42
-
43
- # Dataset class for SQLite datasets accessed via JDBC.
44
- class Dataset < JDBC::Dataset
45
- include Sequel::SQLite::DatasetMethods
46
- end
47
57
  end
48
58
  end
49
59
  end
@@ -0,0 +1,66 @@
1
+ Sequel.require 'adapters/jdbc/mssql'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for SQLServer specific
6
+ # support via JDBC.
7
+ module SQLServer
8
+ # Database instance methods for SQLServer databases accessed via JDBC.
9
+ module DatabaseMethods
10
+ include Sequel::JDBC::MSSQL::DatabaseMethods
11
+
12
+ # Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
13
+ # for the getColumns result set specifies an incorrect type for the
14
+ # IS_AUTOINCREMENT column. The column is a string, but the type is
15
+ # specified as a short. This causes getObject() to throw a
16
+ # com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
17
+ # from char to SMALLINT is unsupported." Using getString() rather
18
+ # than getObject() for this column avoids the problem.
19
+ # Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
20
+ module MetadataDatasetMethods
21
+ def process_result_set_convert(cols, result, rn)
22
+ while result.next
23
+ row = {}
24
+ cols.each do |n, i, p|
25
+ v = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
26
+ row[n] = if v
27
+ if p
28
+ p.call(v)
29
+ elsif p.nil?
30
+ cols[i-1][2] = p = convert_type_proc(v)
31
+ if p
32
+ p.call(v)
33
+ else
34
+ v
35
+ end
36
+ else
37
+ v
38
+ end
39
+ else
40
+ v
41
+ end
42
+ end
43
+ row.delete(rn) if rn
44
+ yield row
45
+ end
46
+ end
47
+
48
+ def process_result_set_no_convert(cols, result, rn)
49
+ while result.next
50
+ row = {}
51
+ cols.each do |n, i|
52
+ row[n] = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
53
+ end
54
+ row.delete(rn) if rn
55
+ yield row
56
+ end
57
+ end
58
+ end
59
+
60
+ def metadata_dataset
61
+ super.extend(MetadataDatasetMethods)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,83 @@
1
+ module Sequel
2
+ module JDBC
3
+ module Transactions
4
+ TRANSACTION_BEGIN = 'Transaction.begin'.freeze
5
+ TRANSACTION_COMMIT = 'Transaction.commit'.freeze
6
+ TRANSACTION_RELEASE_SP = 'Transaction.release_savepoint'.freeze
7
+ TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
8
+ TRANSACTION_ROLLBACK_SP = 'Transaction.rollback_savepoint'.freeze
9
+ TRANSACTION_SAVEPOINT= 'Transaction.savepoint'.freeze
10
+
11
+ # Check the JDBC DatabaseMetaData for savepoint support
12
+ def supports_savepoints?
13
+ return @supports_savepoints if defined?(@supports_savepoints)
14
+ @supports_savepoints = synchronize{|c| c.get_meta_data.supports_savepoints}
15
+ end
16
+
17
+ private
18
+
19
+ # Most JDBC drivers that support savepoints support releasing them.
20
+ def supports_releasing_savepoints?
21
+ true
22
+ end
23
+
24
+ # Use JDBC connection's setAutoCommit to false to start transactions
25
+ def begin_transaction(conn, opts={})
26
+ if supports_savepoints?
27
+ th = _trans(conn)
28
+ if sps = th[:savepoints]
29
+ sps << log_yield(TRANSACTION_SAVEPOINT){conn.set_savepoint}
30
+ else
31
+ log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
32
+ th[:savepoints] = []
33
+ end
34
+ th[:savepoint_level] += 1
35
+ else
36
+ log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
37
+ end
38
+ end
39
+
40
+ # Use JDBC connection's commit method to commit transactions
41
+ def commit_transaction(conn, opts={})
42
+ if supports_savepoints?
43
+ sps = _trans(conn)[:savepoints]
44
+ if sps.empty?
45
+ log_yield(TRANSACTION_COMMIT){conn.commit}
46
+ elsif supports_releasing_savepoints?
47
+ log_yield(TRANSACTION_RELEASE_SP){supports_releasing_savepoints? ? conn.release_savepoint(sps.last) : sps.last}
48
+ end
49
+ else
50
+ log_yield(TRANSACTION_COMMIT){conn.commit}
51
+ end
52
+ end
53
+
54
+ # Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
55
+ def remove_transaction(conn, committed)
56
+ if supports_savepoints?
57
+ sps = _trans(conn)[:savepoints]
58
+ conn.setAutoCommit(true) if sps.empty?
59
+ sps.pop
60
+ else
61
+ conn.setAutoCommit(true)
62
+ end
63
+ ensure
64
+ super
65
+ end
66
+
67
+ # Use JDBC connection's rollback method to rollback transactions
68
+ def rollback_transaction(conn, opts={})
69
+ if supports_savepoints?
70
+ sps = _trans(conn)[:savepoints]
71
+ if sps.empty?
72
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
73
+ else
74
+ log_yield(TRANSACTION_ROLLBACK_SP){conn.rollback(sps.last)}
75
+ end
76
+ else
77
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+