sequel 3.21.0 → 3.41.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 (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -0,0 +1,189 @@
1
+ Sequel.require 'adapters/jdbc/transactions'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset support for HSQLDB databases accessed via JDBC.
6
+ module HSQLDB
7
+ # Instance methods for HSQLDB Database objects accessed via JDBC.
8
+ module DatabaseMethods
9
+ PRIMARY_KEY_INDEX_RE = /\Asys_idx_sys_pk_/i.freeze
10
+
11
+ include ::Sequel::JDBC::Transactions
12
+
13
+ # HSQLDB uses the :hsqldb database type.
14
+ def database_type
15
+ :hsqldb
16
+ end
17
+
18
+ # HSQLDB uses an IDENTITY sequence as the default value for primary
19
+ # key columns.
20
+ def serial_primary_key_options
21
+ {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
22
+ end
23
+
24
+ # The version of the database, as an integer (e.g 2.2.5 -> 20205)
25
+ def db_version
26
+ @db_version ||= begin
27
+ v = get{DATABASE_VERSION(){}}
28
+ if v =~ /(\d+)\.(\d+)\.(\d+)/
29
+ $1.to_i * 10000 + $2.to_i * 100 + $3.to_i
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # HSQLDB specific SQL for renaming columns, and changing column types and/or nullity.
37
+ def alter_table_sql(table, op)
38
+ case op[:op]
39
+ when :rename_column
40
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} RENAME TO #{quote_identifier(op[:new_name])}"
41
+ when :set_column_type
42
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET DATA TYPE #{type_literal(op)}"
43
+ when :set_column_null
44
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET #{op[:null] ? 'NULL' : 'NOT NULL'}"
45
+ else
46
+ super
47
+ end
48
+ end
49
+
50
+ # HSQLDB requires parens around the SELECT, and the WITH DATA syntax.
51
+ def create_table_as_sql(name, sql, options)
52
+ "#{create_table_prefix_sql(name, options)} AS (#{sql}) WITH DATA"
53
+ end
54
+
55
+ # Use IDENTITY() to get the last inserted id.
56
+ def last_insert_id(conn, opts={})
57
+ statement(conn) do |stmt|
58
+ sql = 'CALL IDENTITY()'
59
+ rs = log_yield(sql){stmt.executeQuery(sql)}
60
+ rs.next
61
+ rs.getInt(1)
62
+ end
63
+ end
64
+
65
+ # Primary key indexes appear to start with sys_idx_sys_pk_ on HSQLDB
66
+ def primary_key_index_re
67
+ PRIMARY_KEY_INDEX_RE
68
+ end
69
+
70
+ # If an :identity option is present in the column, add the necessary IDENTITY SQL.
71
+ # It's possible to use an IDENTITY type, but that defaults the sequence to start
72
+ # at 0 instead of 1, and we don't want that.
73
+ def type_literal(column)
74
+ if column[:identity]
75
+ sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
76
+ if sw = column[:start_with]
77
+ sql << " (START WITH #{sw.to_i}"
78
+ sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
79
+ sql << ")"
80
+ end
81
+ sql
82
+ else
83
+ super
84
+ end
85
+ end
86
+
87
+ # HSQLDB uses clob for text types.
88
+ def uses_clob_for_text?
89
+ true
90
+ end
91
+ end
92
+
93
+ # Dataset class for HSQLDB datasets accessed via JDBC.
94
+ class Dataset < JDBC::Dataset
95
+ BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
96
+ BOOL_TRUE = 'TRUE'.freeze
97
+ BOOL_FALSE = 'FALSE'.freeze
98
+ # HSQLDB does support common table expressions, but the support is broken.
99
+ # CTEs operate more like temprorary tables or views, lasting longer than the duration of the expression.
100
+ # CTEs in earlier queries might take precedence over CTEs with the same name in later queries.
101
+ # Also, if any CTE is recursive, all CTEs must be recursive.
102
+ # If you want to use CTEs with HSQLDB, you'll have to manually modify the dataset to allow it.
103
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
104
+ SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
105
+ APOS = Dataset::APOS
106
+ HSTAR = "H*".freeze
107
+ BLOB_OPEN = "X'".freeze
108
+ BITCOMP_OPEN = "((0 - ".freeze
109
+ BITCOMP_CLOSE = ") - 1)".freeze
110
+ DEFAULT_FROM = " FROM (VALUES (0))".freeze
111
+ TIME_FORMAT = "'%H:%M:%S'".freeze
112
+
113
+ # Handle HSQLDB specific case insensitive LIKE and bitwise operator support.
114
+ def complex_expression_sql_append(sql, op, args)
115
+ case op
116
+ when :ILIKE, :"NOT ILIKE"
117
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
118
+ when :&, :|, :^
119
+ op = BITWISE_METHOD_MAP[op]
120
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
121
+ when :<<
122
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
123
+ when :>>
124
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
125
+ when :%
126
+ sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
127
+ when :'B~'
128
+ sql << BITCOMP_OPEN
129
+ literal_append(sql, args.at(0))
130
+ sql << BITCOMP_CLOSE
131
+ else
132
+ super
133
+ end
134
+ end
135
+
136
+ # HSQLDB requires recursive CTEs to have column aliases.
137
+ def recursive_cte_requires_column_aliases?
138
+ true
139
+ end
140
+
141
+ # HSQLDB does not support IS TRUE.
142
+ def supports_is_true?
143
+ false
144
+ end
145
+
146
+ private
147
+
148
+ # Use string in hex format for blob data.
149
+ def literal_blob_append(sql, v)
150
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << APOS
151
+ end
152
+
153
+ # HSQLDB uses FALSE for false values.
154
+ def literal_false
155
+ BOOL_FALSE
156
+ end
157
+
158
+ # HSQLDB handles fractional seconds in timestamps, but not in times
159
+ def literal_sqltime(v)
160
+ v.strftime(TIME_FORMAT)
161
+ end
162
+
163
+ # HSQLDB uses TRUE for true values.
164
+ def literal_true
165
+ BOOL_TRUE
166
+ end
167
+
168
+ # HSQLDB does not support CTEs well enough for Sequel to enable support for them.
169
+ def select_clause_methods
170
+ SELECT_CLAUSE_METHODS
171
+ end
172
+
173
+ # Use a default FROM table if the dataset does not contain a FROM table.
174
+ def select_from_sql(sql)
175
+ if @opts[:from]
176
+ super
177
+ else
178
+ sql << DEFAULT_FROM
179
+ end
180
+ end
181
+
182
+ # Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
183
+ def select_with_sql_base
184
+ opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,21 @@
1
+ Sequel.require 'adapters/shared/informix'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for Informix specific
6
+ # support via JDBC.
7
+ module Informix
8
+ # Database instance methods for Informix databases accessed via JDBC.
9
+ module DatabaseMethods
10
+ include Sequel::Informix::DatabaseMethods
11
+
12
+ private
13
+
14
+ # TODO: implement
15
+ def last_insert_id(conn, opts={})
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
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
+ module DatabaseMethods
9
+ include Sequel::JDBC::MSSQL::DatabaseMethods
10
+
11
+ private
12
+
13
+ # Handle nil values by using setNull with the correct parameter type.
14
+ def set_ps_arg_nil(cps, i)
15
+ cps.setNull(i, cps.getParameterMetaData.getParameterType(i))
16
+ end
17
+ end
18
+
19
+ # Dataset class for JTDS datasets accessed via JDBC.
20
+ class Dataset < JDBC::Dataset
21
+ include Sequel::MSSQL::DatasetMethods
22
+
23
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
24
+ def jtds_clob(v) v.getSubString(1, v.length) end
25
+ end
26
+
27
+ JTDS_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:jtds_clob)
28
+
29
+ # Handle CLOB types retrieved via JTDS.
30
+ def convert_type_proc(v)
31
+ if v.is_a?(Java::NetSourceforgeJtdsJdbc::ClobImpl)
32
+ JTDS_CLOB_METHOD
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ 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,42 +35,34 @@ 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
46
42
  end
47
43
  end
48
44
 
49
- # MySQL 5.1.12 JDBC adapter requires this to be true,
45
+ # MySQL 5.1.12 JDBC adapter requires generated keys
50
46
  # and previous versions don't mind.
51
- def requires_return_generated_keys?
52
- true
47
+ def execute_statement_insert(stmt, sql)
48
+ stmt.executeUpdate(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS)
53
49
  end
54
-
50
+
51
+ # Return generated keys for insert statements.
52
+ def prepare_jdbc_statement(conn, sql, opts)
53
+ opts[:type] == :insert ? conn.prepareStatement(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS) : super
54
+ end
55
+
55
56
  # Convert tinyint(1) type to boolean
56
57
  def schema_column_type(db_type)
57
58
  db_type == 'tinyint(1)' ? :boolean : super
58
59
  end
59
- end
60
60
 
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
61
+ # Run the default connection setting SQL statements.
62
+ # Apply the connectiong setting SQLs for every new connection.
63
+ def setup_connection(conn)
64
+ mysql_connection_setting_sqls.each{|sql| statement(conn){|s| log_yield(sql){s.execute(sql)}}}
65
+ super
78
66
  end
79
67
  end
80
68
  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
@@ -41,54 +15,105 @@ module Sequel
41
15
  # Add the primary_keys and primary_key_sequences instance variables,
42
16
  # so we can get the correct return values for inserted rows.
43
17
  def self.extended(db)
44
- db.instance_eval do
45
- @primary_keys = {}
46
- @primary_key_sequences = {}
47
- end
48
- end
49
-
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))
18
+ db.send(:initialize_postgres_adapter)
59
19
  end
60
20
 
61
21
  private
62
22
 
63
- # Extend the adapter with the JDBC PostgreSQL AdapterMethods
23
+ # Use setNull for nil arguments as the default behavior of setString
24
+ # with nil doesn't appear to work correctly on PostgreSQL.
25
+ def set_ps_arg_nil(cps, i)
26
+ cps.setNull(i, JavaSQL::Types::NULL)
27
+ end
28
+
29
+ # Execute the connection configuration SQL queries on the connection.
64
30
  def setup_connection(conn)
65
31
  conn = super(conn)
66
- conn.extend(Sequel::JDBC::Postgres::AdapterMethods)
67
- conn.db = self
68
- conn.apply_connection_settings
32
+ statement(conn) do |stmt|
33
+ connection_configuration_sqls.each{|sql| log_yield(sql){stmt.execute(sql)}}
34
+ end
69
35
  conn
70
36
  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
37
  end
77
38
 
78
39
  # Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
79
40
  class Dataset < JDBC::Dataset
80
41
  include Sequel::Postgres::DatasetMethods
42
+ APOS = Dataset::APOS
43
+
44
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
45
+ # Convert Java::OrgPostgresqlUtil::PGobject to ruby strings
46
+ def pg_object(v)
47
+ v.to_string
48
+ end
49
+ end
81
50
 
51
+ # Handle conversions of PostgreSQL array instances
52
+ class PGArrayConverter
53
+ # Set the method that will return the correct conversion
54
+ # proc for elements of this array.
55
+ def initialize(meth)
56
+ @conversion_proc_method = meth
57
+ @conversion_proc = nil
58
+ end
59
+
60
+ # Convert Java::OrgPostgresqlJdbc4::Jdbc4Array to ruby arrays
61
+ def call(v)
62
+ _pg_array(v.array)
63
+ end
64
+
65
+ private
66
+
67
+ # Handle multi-dimensional Java arrays by recursively mapping them
68
+ # to ruby arrays of ruby values.
69
+ def _pg_array(v)
70
+ v.to_ary.map do |i|
71
+ if i.respond_to?(:to_ary)
72
+ _pg_array(i)
73
+ elsif i
74
+ if @conversion_proc.nil?
75
+ @conversion_proc = @conversion_proc_method.call(i)
76
+ end
77
+ if @conversion_proc
78
+ @conversion_proc.call(i)
79
+ else
80
+ i
81
+ end
82
+ else
83
+ i
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ PG_OBJECT_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_object)
90
+
82
91
  # Add the shared PostgreSQL prepared statement methods
83
92
  def prepare(*args)
84
93
  ps = super
85
94
  ps.extend(::Sequel::Postgres::DatasetMethods::PreparedStatementMethods)
86
95
  ps
87
96
  end
97
+
98
+ private
99
+
100
+ # Handle PostgreSQL array and object types. Object types are just
101
+ # turned into strings, similarly to how the native adapter treats
102
+ # the types.
103
+ def convert_type_proc(v)
104
+ case v
105
+ when Java::OrgPostgresqlJdbc4::Jdbc4Array
106
+ PGArrayConverter.new(method(:convert_type_proc))
107
+ when Java::OrgPostgresqlUtil::PGobject
108
+ PG_OBJECT_METHOD
109
+ else
110
+ super
111
+ end
112
+ end
88
113
 
89
114
  # Literalize strings similar to the native postgres adapter
90
- def literal_string(v)
91
- db.synchronize{|c| "'#{c.escape_string(v)}'"}
115
+ def literal_string_append(sql, v)
116
+ sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
92
117
  end
93
118
  end
94
119
  end