sequel 5.20.0 → 5.49.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 (511) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +398 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +80 -16
  7. data/doc/cheat_sheet.rdoc +6 -5
  8. data/doc/code_order.rdoc +10 -12
  9. data/doc/dataset_filtering.rdoc +17 -2
  10. data/doc/fork_safety.rdoc +84 -0
  11. data/doc/migration.rdoc +11 -5
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +10 -2
  15. data/doc/postgresql.rdoc +82 -3
  16. data/doc/querying.rdoc +4 -4
  17. data/doc/release_notes/5.21.0.txt +87 -0
  18. data/doc/release_notes/5.22.0.txt +48 -0
  19. data/doc/release_notes/5.23.0.txt +56 -0
  20. data/doc/release_notes/5.24.0.txt +56 -0
  21. data/doc/release_notes/5.25.0.txt +32 -0
  22. data/doc/release_notes/5.26.0.txt +35 -0
  23. data/doc/release_notes/5.27.0.txt +21 -0
  24. data/doc/release_notes/5.28.0.txt +16 -0
  25. data/doc/release_notes/5.29.0.txt +22 -0
  26. data/doc/release_notes/5.30.0.txt +20 -0
  27. data/doc/release_notes/5.31.0.txt +148 -0
  28. data/doc/release_notes/5.32.0.txt +46 -0
  29. data/doc/release_notes/5.33.0.txt +24 -0
  30. data/doc/release_notes/5.34.0.txt +40 -0
  31. data/doc/release_notes/5.35.0.txt +56 -0
  32. data/doc/release_notes/5.36.0.txt +60 -0
  33. data/doc/release_notes/5.37.0.txt +30 -0
  34. data/doc/release_notes/5.38.0.txt +28 -0
  35. data/doc/release_notes/5.39.0.txt +19 -0
  36. data/doc/release_notes/5.40.0.txt +40 -0
  37. data/doc/release_notes/5.41.0.txt +25 -0
  38. data/doc/release_notes/5.42.0.txt +136 -0
  39. data/doc/release_notes/5.43.0.txt +98 -0
  40. data/doc/release_notes/5.44.0.txt +32 -0
  41. data/doc/release_notes/5.45.0.txt +34 -0
  42. data/doc/release_notes/5.46.0.txt +87 -0
  43. data/doc/release_notes/5.47.0.txt +59 -0
  44. data/doc/release_notes/5.48.0.txt +14 -0
  45. data/doc/release_notes/5.49.0.txt +59 -0
  46. data/doc/sharding.rdoc +2 -0
  47. data/doc/sql.rdoc +13 -1
  48. data/doc/testing.rdoc +20 -7
  49. data/doc/transactions.rdoc +0 -8
  50. data/doc/validations.rdoc +1 -1
  51. data/doc/virtual_rows.rdoc +1 -1
  52. data/lib/sequel/adapters/ado/access.rb +1 -1
  53. data/lib/sequel/adapters/ado.rb +43 -35
  54. data/lib/sequel/adapters/ibmdb.rb +2 -2
  55. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  56. data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
  57. data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
  58. data/lib/sequel/adapters/jdbc.rb +24 -6
  59. data/lib/sequel/adapters/mysql.rb +1 -1
  60. data/lib/sequel/adapters/mysql2.rb +2 -3
  61. data/lib/sequel/adapters/odbc.rb +8 -6
  62. data/lib/sequel/adapters/oracle.rb +5 -4
  63. data/lib/sequel/adapters/postgres.rb +15 -9
  64. data/lib/sequel/adapters/shared/access.rb +6 -6
  65. data/lib/sequel/adapters/shared/mssql.rb +66 -21
  66. data/lib/sequel/adapters/shared/mysql.rb +27 -10
  67. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  68. data/lib/sequel/adapters/shared/postgres.rb +271 -32
  69. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  70. data/lib/sequel/adapters/shared/sqlite.rb +161 -19
  71. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  72. data/lib/sequel/adapters/sqlite.rb +1 -1
  73. data/lib/sequel/adapters/tinytds.rb +15 -2
  74. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
  75. data/lib/sequel/ast_transformer.rb +6 -0
  76. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  77. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  78. data/lib/sequel/connection_pool/single.rb +1 -1
  79. data/lib/sequel/connection_pool/threaded.rb +2 -2
  80. data/lib/sequel/core.rb +333 -319
  81. data/lib/sequel/database/connecting.rb +3 -4
  82. data/lib/sequel/database/logging.rb +7 -1
  83. data/lib/sequel/database/misc.rb +31 -12
  84. data/lib/sequel/database/query.rb +3 -1
  85. data/lib/sequel/database/schema_generator.rb +53 -51
  86. data/lib/sequel/database/schema_methods.rb +38 -23
  87. data/lib/sequel/database/transactions.rb +17 -18
  88. data/lib/sequel/dataset/actions.rb +14 -9
  89. data/lib/sequel/dataset/features.rb +16 -0
  90. data/lib/sequel/dataset/misc.rb +2 -2
  91. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  92. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  93. data/lib/sequel/dataset/query.rb +26 -9
  94. data/lib/sequel/dataset/sql.rb +76 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/deprecated.rb +3 -1
  97. data/lib/sequel/exceptions.rb +2 -0
  98. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  99. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  100. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  101. data/lib/sequel/extensions/blank.rb +8 -0
  102. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  103. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  104. data/lib/sequel/extensions/connection_validator.rb +2 -2
  105. data/lib/sequel/extensions/core_refinements.rb +2 -0
  106. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  107. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  108. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  109. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  110. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  111. data/lib/sequel/extensions/index_caching.rb +9 -7
  112. data/lib/sequel/extensions/inflector.rb +9 -1
  113. data/lib/sequel/extensions/integer64.rb +2 -0
  114. data/lib/sequel/extensions/migration.rb +11 -3
  115. data/lib/sequel/extensions/named_timezones.rb +56 -8
  116. data/lib/sequel/extensions/pagination.rb +1 -1
  117. data/lib/sequel/extensions/pg_array.rb +5 -0
  118. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  119. data/lib/sequel/extensions/pg_enum.rb +11 -3
  120. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  121. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  122. data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
  123. data/lib/sequel/extensions/pg_inet.rb +15 -5
  124. data/lib/sequel/extensions/pg_interval.rb +36 -8
  125. data/lib/sequel/extensions/pg_json.rb +387 -123
  126. data/lib/sequel/extensions/pg_json_ops.rb +238 -0
  127. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  128. data/lib/sequel/extensions/pg_range.rb +17 -9
  129. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  130. data/lib/sequel/extensions/pg_row.rb +4 -2
  131. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  132. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  133. data/lib/sequel/extensions/query.rb +3 -0
  134. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  135. data/lib/sequel/extensions/s.rb +2 -0
  136. data/lib/sequel/extensions/schema_dumper.rb +24 -7
  137. data/lib/sequel/extensions/server_block.rb +18 -7
  138. data/lib/sequel/extensions/sql_comments.rb +2 -2
  139. data/lib/sequel/extensions/string_agg.rb +1 -1
  140. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  141. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  142. data/lib/sequel/extensions/to_dot.rb +9 -3
  143. data/lib/sequel/model/associations.rb +356 -117
  144. data/lib/sequel/model/base.rb +107 -68
  145. data/lib/sequel/model/errors.rb +10 -1
  146. data/lib/sequel/model/inflections.rb +1 -1
  147. data/lib/sequel/model/plugins.rb +9 -3
  148. data/lib/sequel/model.rb +3 -1
  149. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  150. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  151. data/lib/sequel/plugins/association_pks.rb +60 -18
  152. data/lib/sequel/plugins/association_proxies.rb +8 -2
  153. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  154. data/lib/sequel/plugins/auto_validations.rb +39 -5
  155. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  156. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  157. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  158. data/lib/sequel/plugins/caching.rb +3 -0
  159. data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
  160. data/lib/sequel/plugins/column_encryption.rb +728 -0
  161. data/lib/sequel/plugins/composition.rb +7 -2
  162. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  163. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  164. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  165. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  166. data/lib/sequel/plugins/dirty.rb +60 -22
  167. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  168. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  169. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  170. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  171. data/lib/sequel/plugins/json_serializer.rb +57 -35
  172. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  173. data/lib/sequel/plugins/many_through_many.rb +108 -9
  174. data/lib/sequel/plugins/nested_attributes.rb +15 -3
  175. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  176. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
  177. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  178. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  179. data/lib/sequel/plugins/rcte_tree.rb +43 -35
  180. data/lib/sequel/plugins/serialization.rb +8 -3
  181. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  182. data/lib/sequel/plugins/sharding.rb +11 -5
  183. data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
  184. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  185. data/lib/sequel/plugins/static_cache.rb +9 -4
  186. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  187. data/lib/sequel/plugins/string_stripper.rb +1 -1
  188. data/lib/sequel/plugins/subclasses.rb +2 -0
  189. data/lib/sequel/plugins/throw_failures.rb +1 -1
  190. data/lib/sequel/plugins/timestamps.rb +1 -1
  191. data/lib/sequel/plugins/tree.rb +9 -4
  192. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  193. data/lib/sequel/plugins/unused_associations.rb +521 -0
  194. data/lib/sequel/plugins/update_or_create.rb +1 -1
  195. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  196. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  197. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  198. data/lib/sequel/sql.rb +20 -5
  199. data/lib/sequel/timezones.rb +63 -17
  200. data/lib/sequel/version.rb +1 -1
  201. metadata +113 -381
  202. data/Rakefile +0 -151
  203. data/doc/release_notes/4.0.0.txt +0 -262
  204. data/doc/release_notes/4.1.0.txt +0 -85
  205. data/doc/release_notes/4.10.0.txt +0 -226
  206. data/doc/release_notes/4.11.0.txt +0 -147
  207. data/doc/release_notes/4.12.0.txt +0 -105
  208. data/doc/release_notes/4.13.0.txt +0 -169
  209. data/doc/release_notes/4.14.0.txt +0 -68
  210. data/doc/release_notes/4.15.0.txt +0 -56
  211. data/doc/release_notes/4.16.0.txt +0 -36
  212. data/doc/release_notes/4.17.0.txt +0 -38
  213. data/doc/release_notes/4.18.0.txt +0 -36
  214. data/doc/release_notes/4.19.0.txt +0 -45
  215. data/doc/release_notes/4.2.0.txt +0 -129
  216. data/doc/release_notes/4.20.0.txt +0 -79
  217. data/doc/release_notes/4.21.0.txt +0 -94
  218. data/doc/release_notes/4.22.0.txt +0 -72
  219. data/doc/release_notes/4.23.0.txt +0 -65
  220. data/doc/release_notes/4.24.0.txt +0 -99
  221. data/doc/release_notes/4.25.0.txt +0 -181
  222. data/doc/release_notes/4.26.0.txt +0 -44
  223. data/doc/release_notes/4.27.0.txt +0 -78
  224. data/doc/release_notes/4.28.0.txt +0 -57
  225. data/doc/release_notes/4.29.0.txt +0 -41
  226. data/doc/release_notes/4.3.0.txt +0 -40
  227. data/doc/release_notes/4.30.0.txt +0 -37
  228. data/doc/release_notes/4.31.0.txt +0 -57
  229. data/doc/release_notes/4.32.0.txt +0 -132
  230. data/doc/release_notes/4.33.0.txt +0 -88
  231. data/doc/release_notes/4.34.0.txt +0 -86
  232. data/doc/release_notes/4.35.0.txt +0 -130
  233. data/doc/release_notes/4.36.0.txt +0 -116
  234. data/doc/release_notes/4.37.0.txt +0 -50
  235. data/doc/release_notes/4.38.0.txt +0 -67
  236. data/doc/release_notes/4.39.0.txt +0 -127
  237. data/doc/release_notes/4.4.0.txt +0 -92
  238. data/doc/release_notes/4.40.0.txt +0 -179
  239. data/doc/release_notes/4.41.0.txt +0 -77
  240. data/doc/release_notes/4.42.0.txt +0 -221
  241. data/doc/release_notes/4.43.0.txt +0 -87
  242. data/doc/release_notes/4.44.0.txt +0 -125
  243. data/doc/release_notes/4.45.0.txt +0 -370
  244. data/doc/release_notes/4.46.0.txt +0 -404
  245. data/doc/release_notes/4.47.0.txt +0 -56
  246. data/doc/release_notes/4.48.0.txt +0 -293
  247. data/doc/release_notes/4.49.0.txt +0 -222
  248. data/doc/release_notes/4.5.0.txt +0 -34
  249. data/doc/release_notes/4.6.0.txt +0 -30
  250. data/doc/release_notes/4.7.0.txt +0 -103
  251. data/doc/release_notes/4.8.0.txt +0 -175
  252. data/doc/release_notes/4.9.0.txt +0 -190
  253. data/spec/adapter_spec.rb +0 -4
  254. data/spec/adapters/db2_spec.rb +0 -170
  255. data/spec/adapters/mssql_spec.rb +0 -804
  256. data/spec/adapters/mysql_spec.rb +0 -1065
  257. data/spec/adapters/oracle_spec.rb +0 -371
  258. data/spec/adapters/postgres_spec.rb +0 -4125
  259. data/spec/adapters/spec_helper.rb +0 -44
  260. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  261. data/spec/adapters/sqlite_spec.rb +0 -652
  262. data/spec/bin_spec.rb +0 -278
  263. data/spec/core/connection_pool_spec.rb +0 -1250
  264. data/spec/core/database_spec.rb +0 -2865
  265. data/spec/core/dataset_spec.rb +0 -5515
  266. data/spec/core/deprecated_spec.rb +0 -70
  267. data/spec/core/expression_filters_spec.rb +0 -1455
  268. data/spec/core/mock_adapter_spec.rb +0 -722
  269. data/spec/core/object_graph_spec.rb +0 -336
  270. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  271. data/spec/core/schema_generator_spec.rb +0 -214
  272. data/spec/core/schema_spec.rb +0 -1826
  273. data/spec/core/spec_helper.rb +0 -24
  274. data/spec/core/version_spec.rb +0 -14
  275. data/spec/core_extensions_spec.rb +0 -763
  276. data/spec/core_model_spec.rb +0 -2
  277. data/spec/core_spec.rb +0 -1
  278. data/spec/deprecation_helper.rb +0 -30
  279. data/spec/extensions/accessed_columns_spec.rb +0 -51
  280. data/spec/extensions/active_model_spec.rb +0 -99
  281. data/spec/extensions/after_initialize_spec.rb +0 -28
  282. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  283. data/spec/extensions/association_dependencies_spec.rb +0 -125
  284. data/spec/extensions/association_pks_spec.rb +0 -423
  285. data/spec/extensions/association_proxies_spec.rb +0 -100
  286. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  287. data/spec/extensions/auto_validations_spec.rb +0 -229
  288. data/spec/extensions/blacklist_security_spec.rb +0 -95
  289. data/spec/extensions/blank_spec.rb +0 -69
  290. data/spec/extensions/boolean_readers_spec.rb +0 -93
  291. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  292. data/spec/extensions/caching_spec.rb +0 -273
  293. data/spec/extensions/caller_logging_spec.rb +0 -52
  294. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  295. data/spec/extensions/column_conflicts_spec.rb +0 -75
  296. data/spec/extensions/column_select_spec.rb +0 -129
  297. data/spec/extensions/columns_introspection_spec.rb +0 -90
  298. data/spec/extensions/columns_updated_spec.rb +0 -35
  299. data/spec/extensions/composition_spec.rb +0 -248
  300. data/spec/extensions/connection_expiration_spec.rb +0 -151
  301. data/spec/extensions/connection_validator_spec.rb +0 -144
  302. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  303. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  304. data/spec/extensions/constraint_validations_spec.rb +0 -439
  305. data/spec/extensions/core_refinements_spec.rb +0 -528
  306. data/spec/extensions/csv_serializer_spec.rb +0 -183
  307. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  308. data/spec/extensions/dataset_associations_spec.rb +0 -365
  309. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  310. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  311. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  312. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  313. data/spec/extensions/defaults_setter_spec.rb +0 -150
  314. data/spec/extensions/delay_add_association_spec.rb +0 -73
  315. data/spec/extensions/dirty_spec.rb +0 -189
  316. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  317. data/spec/extensions/eager_each_spec.rb +0 -62
  318. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  319. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  320. data/spec/extensions/error_splitter_spec.rb +0 -18
  321. data/spec/extensions/error_sql_spec.rb +0 -20
  322. data/spec/extensions/escaped_like_spec.rb +0 -40
  323. data/spec/extensions/eval_inspect_spec.rb +0 -81
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -291
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -864
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -111
  348. data/spec/extensions/nested_attributes_spec.rb +0 -767
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
  356. data/spec/extensions/pg_enum_spec.rb +0 -118
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -519
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -177
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -870
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -63
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -471
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/throw_failures_spec.rb +0 -74
  411. data/spec/extensions/timestamps_spec.rb +0 -209
  412. data/spec/extensions/to_dot_spec.rb +0 -153
  413. data/spec/extensions/touch_spec.rb +0 -226
  414. data/spec/extensions/tree_spec.rb +0 -334
  415. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  416. data/spec/extensions/unlimited_update_spec.rb +0 -21
  417. data/spec/extensions/update_or_create_spec.rb +0 -83
  418. data/spec/extensions/update_primary_key_spec.rb +0 -105
  419. data/spec/extensions/update_refresh_spec.rb +0 -59
  420. data/spec/extensions/uuid_spec.rb +0 -101
  421. data/spec/extensions/validate_associated_spec.rb +0 -52
  422. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  423. data/spec/extensions/validation_contexts_spec.rb +0 -31
  424. data/spec/extensions/validation_helpers_spec.rb +0 -525
  425. data/spec/extensions/whitelist_security_spec.rb +0 -157
  426. data/spec/extensions/xml_serializer_spec.rb +0 -213
  427. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  428. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  429. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  431. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  432. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  433. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  434. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  436. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  437. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  438. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  439. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  440. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  441. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  443. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  444. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  446. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  447. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  448. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  449. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  450. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  451. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  452. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  453. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  457. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  458. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  459. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  460. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  461. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  462. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  466. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  468. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  469. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  471. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  473. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  474. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  475. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  476. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  478. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  479. data/spec/guards_helper.rb +0 -59
  480. data/spec/integration/associations_test.rb +0 -2597
  481. data/spec/integration/database_test.rb +0 -113
  482. data/spec/integration/dataset_test.rb +0 -1981
  483. data/spec/integration/eager_loader_test.rb +0 -687
  484. data/spec/integration/migrator_test.rb +0 -262
  485. data/spec/integration/model_test.rb +0 -203
  486. data/spec/integration/plugin_test.rb +0 -2396
  487. data/spec/integration/prepared_statement_test.rb +0 -405
  488. data/spec/integration/schema_test.rb +0 -889
  489. data/spec/integration/spec_helper.rb +0 -65
  490. data/spec/integration/timezone_test.rb +0 -86
  491. data/spec/integration/transaction_test.rb +0 -603
  492. data/spec/integration/type_test.rb +0 -127
  493. data/spec/model/association_reflection_spec.rb +0 -803
  494. data/spec/model/associations_spec.rb +0 -4738
  495. data/spec/model/base_spec.rb +0 -875
  496. data/spec/model/class_dataset_methods_spec.rb +0 -146
  497. data/spec/model/dataset_methods_spec.rb +0 -198
  498. data/spec/model/eager_loading_spec.rb +0 -2377
  499. data/spec/model/hooks_spec.rb +0 -370
  500. data/spec/model/inflector_spec.rb +0 -26
  501. data/spec/model/model_spec.rb +0 -956
  502. data/spec/model/plugins_spec.rb +0 -429
  503. data/spec/model/record_spec.rb +0 -2118
  504. data/spec/model/spec_helper.rb +0 -46
  505. data/spec/model/validations_spec.rb +0 -220
  506. data/spec/model_no_assoc_spec.rb +0 -1
  507. data/spec/model_spec.rb +0 -1
  508. data/spec/plugin_spec.rb +0 -1
  509. data/spec/sequel_coverage.rb +0 -15
  510. data/spec/sequel_warning.rb +0 -4
  511. data/spec/spec_config.rb +0 -12
@@ -73,6 +73,55 @@
73
73
  # j.pretty # jsonb_pretty(jsonb_column)
74
74
  # j.set(%w'0 a', :h) # jsonb_set(jsonb_column, ARRAY['0','a'], h, true)
75
75
  #
76
+ # j.set_lax(%w'0 a', :h, false, 'raise_exception')
77
+ # # jsonb_set_lax(jsonb_column, ARRAY['0','a'], h, false, 'raise_exception')
78
+ #
79
+ # On PostgreSQL 12+ SQL/JSON path functions and operators are supported:
80
+ #
81
+ # j.path_exists('$.foo') # (jsonb_column @? '$.foo')
82
+ # j.path_match('$.foo') # (jsonb_column @@ '$.foo')
83
+ #
84
+ # j.path_exists!('$.foo') # jsonb_path_exists(jsonb_column, '$.foo')
85
+ # j.path_match!('$.foo') # jsonb_path_match(jsonb_column, '$.foo')
86
+ # j.path_query('$.foo') # jsonb_path_query(jsonb_column, '$.foo')
87
+ # j.path_query_array('$.foo') # jsonb_path_query_array(jsonb_column, '$.foo')
88
+ # j.path_query_first('$.foo') # jsonb_path_query_first(jsonb_column, '$.foo')
89
+ #
90
+ # On PostgreSQL 13+ timezone-aware SQL/JSON path functions and operators are supported:
91
+ #
92
+ # j.path_exists_tz!('$.foo') # jsonb_path_exists_tz(jsonb_column, '$.foo')
93
+ # j.path_match_tz!('$.foo') # jsonb_path_match_tz(jsonb_column, '$.foo')
94
+ # j.path_query_tz('$.foo') # jsonb_path_query_tz(jsonb_column, '$.foo')
95
+ # j.path_query_array_tz('$.foo') # jsonb_path_query_array_tz(jsonb_column, '$.foo')
96
+ # j.path_query_first_tz('$.foo') # jsonb_path_query_first_tz(jsonb_column, '$.foo')
97
+ #
98
+ # For the PostgreSQL 12+ SQL/JSON path functions, one argument is required (+path+) and
99
+ # two more arguments are optional (+vars+ and +silent+). +path+ specifies the JSON path.
100
+ # +vars+ specifies a hash or a string in JSON format of named variables to be
101
+ # substituted in +path+. +silent+ specifies whether errors are suppressed. By default,
102
+ # errors are not suppressed.
103
+ #
104
+ # On PostgreSQL 14+, The JSONB <tt>[]</tt> method will use subscripts instead of being
105
+ # the same as +get+, if the value being wrapped is an identifer:
106
+ #
107
+ # Sequel.pg_jsonb_op(:jsonb_column)[1] # jsonb_column[1]
108
+ # Sequel.pg_jsonb_op(:jsonb_column)[1][2] # jsonb_column[1][2]
109
+ # Sequel.pg_jsonb_op(Sequel[:j][:b])[1] # j.b[1]
110
+ #
111
+ # This support allows you to use JSONB subscripts in UPDATE statements to update only
112
+ # part of a column:
113
+ #
114
+ # c = Sequel.pg_jsonb_op(:c)
115
+ # DB[:t].update(c['key1'] => '1', c['key2'] => '"a"')
116
+ # # UPDATE "t" SET "c"['key1'] = '1', "c"['key2'] = '"a"'
117
+ #
118
+ # Note that you have to provide the value of a JSONB subscript as a JSONB value, so this
119
+ # will update +key1+ to use the number <tt>1</tt>, and +key2+ to use the string <tt>a</tt>.
120
+ # For this reason it may be simpler to use +to_json+:
121
+ #
122
+ # c = Sequel.pg_jsonb_op(:c)
123
+ # DB[:t].update(c['key1'] => 1.to_json, c['key2'] => "a".to_json)
124
+ #
76
125
  # If you are also using the pg_json extension, you should load it before
77
126
  # loading this extension. Doing so will allow you to use the #op method on
78
127
  # JSONHash, JSONHarray, JSONBHash, and JSONBArray, allowing you to perform json/jsonb operations
@@ -292,6 +341,26 @@ module Sequel
292
341
  CONTAINED_BY = ["(".freeze, " <@ ".freeze, ")".freeze].freeze
293
342
  DELETE_PATH = ["(".freeze, " #- ".freeze, ")".freeze].freeze
294
343
  HAS_KEY = ["(".freeze, " ? ".freeze, ")".freeze].freeze
344
+ PATH_EXISTS = ["(".freeze, " @? ".freeze, ")".freeze].freeze
345
+ PATH_MATCH = ["(".freeze, " @@ ".freeze, ")".freeze].freeze
346
+
347
+ # Support subscript syntax for JSONB.
348
+ def [](key)
349
+ if is_array?(key)
350
+ super
351
+ else
352
+ case @value
353
+ when Symbol, SQL::Identifier, SQL::QualifiedIdentifier, JSONBSubscriptOp
354
+ # Only use subscripts for identifiers. In other cases, switching from
355
+ # the -> operator to [] for subscripts causes SQL syntax issues. You
356
+ # only need the [] for subscripting when doing assignment, and
357
+ # assignment is generally done on identifiers.
358
+ self.class.new(JSONBSubscriptOp.new(self, key))
359
+ else
360
+ super
361
+ end
362
+ end
363
+ end
295
364
 
296
365
  # jsonb expression for deletion of the given argument from the
297
366
  # current jsonb.
@@ -362,6 +431,120 @@ module Sequel
362
431
  self.class.new(function(:insert, wrap_input_array(path), wrap_input_jsonb(other), insert_after))
363
432
  end
364
433
 
434
+ # Returns whether the JSON path returns any item for the json object.
435
+ #
436
+ # json_op.path_exists("$.foo") # (json @? '$.foo')
437
+ def path_exists(path)
438
+ bool_op(PATH_EXISTS, path)
439
+ end
440
+
441
+ # Returns whether the JSON path returns any item for the json object.
442
+ #
443
+ # json_op.path_exists!("$.foo")
444
+ # # jsonb_path_exists(json, '$.foo')
445
+ #
446
+ # json_op.path_exists!("$.foo ? ($ > $x)", x: 2)
447
+ # # jsonb_path_exists(json, '$.foo ? ($ > $x)', '{"x":2}')
448
+ #
449
+ # json_op.path_exists!("$.foo ? ($ > $x)", {x: 2}, true)
450
+ # # jsonb_path_exists(json, '$.foo ? ($ > $x)', '{"x":2}', true)
451
+ def path_exists!(path, vars=nil, silent=nil)
452
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists, path, vars, silent))
453
+ end
454
+
455
+ # The same as #path_exists!, except that timezone-aware conversions are used for date/time values.
456
+ def path_exists_tz!(path, vars=nil, silent=nil)
457
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists_tz, path, vars, silent))
458
+ end
459
+
460
+ # Returns the first item of the result of JSON path predicate check for the json object.
461
+ # Returns nil if the first item is not true or false.
462
+ #
463
+ # json_op.path_match("$.foo") # (json @@ '$.foo')
464
+ def path_match(path)
465
+ bool_op(PATH_MATCH, path)
466
+ end
467
+
468
+ # Returns the first item of the result of JSON path predicate check for the json object.
469
+ # Returns nil if the first item is not true or false and silent is true.
470
+ #
471
+ # json_op.path_match!("$.foo")
472
+ # # jsonb_path_match(json, '$.foo')
473
+ #
474
+ # json_op.path_match!("$.foo ? ($ > $x)", x: 2)
475
+ # # jsonb_path_match(json, '$.foo ? ($ > $x)', '{"x":2}')
476
+ #
477
+ # json_op.path_match!("$.foo ? ($ > $x)", {x: 2}, true)
478
+ # # jsonb_path_match(json, '$.foo ? ($ > $x)', '{"x":2}', true)
479
+ def path_match!(path, vars=nil, silent=nil)
480
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match, path, vars, silent))
481
+ end
482
+
483
+ # The same as #path_match!, except that timezone-aware conversions are used for date/time values.
484
+ def path_match_tz!(path, vars=nil, silent=nil)
485
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match_tz, path, vars, silent))
486
+ end
487
+
488
+ # Returns a set of all jsonb values specified by the JSON path
489
+ # for the json object.
490
+ #
491
+ # json_op.path_query("$.foo")
492
+ # # jsonb_path_query(json, '$.foo')
493
+ #
494
+ # json_op.path_query("$.foo ? ($ > $x)", x: 2)
495
+ # # jsonb_path_query(json, '$.foo ? ($ > $x)', '{"x":2}')
496
+ #
497
+ # json_op.path_query("$.foo ? ($ > $x)", {x: 2}, true)
498
+ # # jsonb_path_query(json, '$.foo ? ($ > $x)', '{"x":2}', true)
499
+ def path_query(path, vars=nil, silent=nil)
500
+ _path_function(:jsonb_path_query, path, vars, silent)
501
+ end
502
+
503
+ # The same as #path_query, except that timezone-aware conversions are used for date/time values.
504
+ def path_query_tz(path, vars=nil, silent=nil)
505
+ _path_function(:jsonb_path_query_tz, path, vars, silent)
506
+ end
507
+
508
+ # Returns a jsonb array of all values specified by the JSON path
509
+ # for the json object.
510
+ #
511
+ # json_op.path_query_array("$.foo")
512
+ # # jsonb_path_query_array(json, '$.foo')
513
+ #
514
+ # json_op.path_query_array("$.foo ? ($ > $x)", x: 2)
515
+ # # jsonb_path_query_array(json, '$.foo ? ($ > $x)', '{"x":2}')
516
+ #
517
+ # json_op.path_query_array("$.foo ? ($ > $x)", {x: 2}, true)
518
+ # # jsonb_path_query_array(json, '$.foo ? ($ > $x)', '{"x":2}', true)
519
+ def path_query_array(path, vars=nil, silent=nil)
520
+ JSONBOp.new(_path_function(:jsonb_path_query_array, path, vars, silent))
521
+ end
522
+
523
+ # The same as #path_query_array, except that timezone-aware conversions are used for date/time values.
524
+ def path_query_array_tz(path, vars=nil, silent=nil)
525
+ JSONBOp.new(_path_function(:jsonb_path_query_array_tz, path, vars, silent))
526
+ end
527
+
528
+ # Returns the first item of the result specified by the JSON path
529
+ # for the json object.
530
+ #
531
+ # json_op.path_query_first("$.foo")
532
+ # # jsonb_path_query_first(json, '$.foo')
533
+ #
534
+ # json_op.path_query_first("$.foo ? ($ > $x)", x: 2)
535
+ # # jsonb_path_query_first(json, '$.foo ? ($ > $x)', '{"x":2}')
536
+ #
537
+ # json_op.path_query_first("$.foo ? ($ > $x)", {x: 2}, true)
538
+ # # jsonb_path_query_first(json, '$.foo ? ($ > $x)', '{"x":2}', true)
539
+ def path_query_first(path, vars=nil, silent=nil)
540
+ JSONBOp.new(_path_function(:jsonb_path_query_first, path, vars, silent))
541
+ end
542
+
543
+ # The same as #path_query_first, except that timezone-aware conversions are used for date/time values.
544
+ def path_query_first_tz(path, vars=nil, silent=nil)
545
+ JSONBOp.new(_path_function(:jsonb_path_query_first_tz, path, vars, silent))
546
+ end
547
+
365
548
  # Return the receiver, since it is already a JSONBOp.
366
549
  def pg_jsonb
367
550
  self
@@ -384,8 +567,30 @@ module Sequel
384
567
  self.class.new(function(:set, wrap_input_array(path), wrap_input_jsonb(other), create_missing))
385
568
  end
386
569
 
570
+ # The same as #set, except if +other+ is +nil+, then behaves according to +null_value_treatment+,
571
+ # which can be one of 'raise_exception', 'use_json_null' (default), 'delete_key', or 'return_target'.
572
+ def set_lax(path, other, create_missing=true, null_value_treatment='use_json_null')
573
+ self.class.new(function(:set_lax, wrap_input_array(path), wrap_input_jsonb(other), create_missing, null_value_treatment))
574
+ end
575
+
387
576
  private
388
577
 
578
+ # Internals of the jsonb SQL/JSON path functions.
579
+ def _path_function(func, path, vars, silent)
580
+ args = []
581
+ if vars
582
+ if vars.is_a?(Hash)
583
+ vars = vars.to_json
584
+ end
585
+ args << vars
586
+
587
+ unless silent.nil?
588
+ args << silent
589
+ end
590
+ end
591
+ SQL::Function.new(func, self, path, *args)
592
+ end
593
+
389
594
  # Return a placeholder literal with the given str and args, wrapped
390
595
  # in a boolean expression, used by operators that return booleans.
391
596
  def bool_op(str, other)
@@ -416,6 +621,37 @@ module Sequel
416
621
  end
417
622
  end
418
623
 
624
+ # Represents JSONB subscripts. This is abstracted because the
625
+ # subscript support depends on the database version.
626
+ class JSONBSubscriptOp < SQL::Expression
627
+ SUBSCRIPT = ["".freeze, "[".freeze, "]".freeze].freeze
628
+
629
+ # The expression being subscripted
630
+ attr_reader :expression
631
+
632
+ # The subscript to use
633
+ attr_reader :sub
634
+
635
+ # Set the expression and subscript to the given arguments
636
+ def initialize(expression, sub)
637
+ @expression = expression
638
+ @sub = sub
639
+ freeze
640
+ end
641
+
642
+ # Use subscripts instead of -> operator on PostgreSQL 14+
643
+ def to_s_append(ds, sql)
644
+ server_version = ds.db.server_version
645
+ frag = server_version && server_version >= 140000 ? SUBSCRIPT : JSONOp::GET
646
+ ds.literal_append(sql, Sequel::SQL::PlaceholderLiteralString.new(frag, [@expression, @sub]))
647
+ end
648
+
649
+ # Support transforming of jsonb subscripts
650
+ def sequel_ast_transform(transformer)
651
+ self.class.new(transformer.call(@expression), transformer.call(@sub))
652
+ end
653
+ end
654
+
419
655
  module JSONOpMethods
420
656
  # Wrap the receiver in an JSONOp so you can easily use the PostgreSQL
421
657
  # json functions and operators with it.
@@ -430,7 +666,9 @@ module Sequel
430
666
  end
431
667
  end
432
668
 
669
+ # :nocov:
433
670
  if defined?(JSONArray)
671
+ # :nocov:
434
672
  class JSONArray
435
673
  # Wrap the JSONArray instance in an JSONOp, allowing you to easily use
436
674
  # the PostgreSQL json functions and operators with literal jsons.
@@ -12,7 +12,9 @@
12
12
  #
13
13
  # How accurate this count is depends on the number of rows
14
14
  # added/deleted from the table since the last time it was
15
- # analyzed.
15
+ # analyzed. If the table has not been vacuumed or analyzed
16
+ # yet, this can return 0 or -1 depending on the PostgreSQL
17
+ # version in use.
16
18
  #
17
19
  # To load the extension into the database:
18
20
  #
@@ -158,7 +158,7 @@ module Sequel
158
158
  procs = conversion_procs
159
159
  add_conversion_proc(3908, Parser.new("tsrange", procs[1114]))
160
160
  add_conversion_proc(3910, Parser.new("tstzrange", procs[1184]))
161
- if defined?(PGArray::Creator)
161
+ if respond_to?(:register_array_type) && defined?(PGArray::Creator)
162
162
  add_conversion_proc(3909, PGArray::Creator.new("tsrange", procs[3908]))
163
163
  add_conversion_proc(3911, PGArray::Creator.new("tstzrange", procs[3910]))
164
164
  end
@@ -215,12 +215,6 @@ module Sequel
215
215
 
216
216
  db_type = db_type.to_s.dup.freeze
217
217
 
218
- if converter = opts[:converter]
219
- raise Error, "can't provide both a block and :converter option to register" if block
220
- else
221
- converter = block
222
- end
223
-
224
218
  if soid
225
219
  raise Error, "can't provide both a converter and :subtype_oid option to register" if has_converter
226
220
  raise Error, "no conversion proc for :subtype_oid=>#{soid.inspect} in conversion_procs" unless converter = conversion_procs[soid]
@@ -304,6 +298,8 @@ module Sequel
304
298
  end
305
299
 
306
300
  module DatasetMethods
301
+ private
302
+
307
303
  # Handle literalization of ruby Range objects, treating them as
308
304
  # PostgreSQL ranges.
309
305
  def literal_other_append(sql, v)
@@ -402,6 +398,15 @@ module Sequel
402
398
  end
403
399
  alias == eql?
404
400
 
401
+ # Make sure equal ranges have the same hash.
402
+ def hash
403
+ if @empty
404
+ @db_type.hash
405
+ else
406
+ [@begin, @end, @exclude_begin, @exclude_end, @db_type].hash
407
+ end
408
+ end
409
+
405
410
  # Allow PGRange values in case statements, where they return true if they
406
411
  # are equal to each other using eql?, or if this PGRange can be converted
407
412
  # to a Range, delegating to that range.
@@ -453,14 +458,17 @@ module Sequel
453
458
  end
454
459
 
455
460
  ENDLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.6'
461
+ STARTLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.7'
456
462
 
457
463
  # Return a ruby Range object for this instance, if one can be created.
458
464
  def to_range
459
465
  return @range if @range
460
466
  raise(Error, "cannot create ruby range for an empty PostgreSQL range") if empty?
461
467
  raise(Error, "cannot create ruby range when PostgreSQL range excludes beginning element") if exclude_begin?
462
- raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") unless self.begin
468
+ # :nocov:
469
+ raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") if STARTLESS_RANGE_NOT_SUPPORTED && !self.begin
463
470
  raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") if ENDLESS_RANGE_NOT_SUPPORTED && !self.end
471
+ # :nocov:
464
472
  @range = Range.new(self.begin, self.end, exclude_end?)
465
473
  end
466
474
 
@@ -468,7 +476,7 @@ module Sequel
468
476
  # it must have a beginning and an ending (no unbounded ranges), and it cannot exclude
469
477
  # the beginning element.
470
478
  def valid_ruby_range?
471
- !(empty? || exclude_begin? || !self.begin || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end))
479
+ !(empty? || exclude_begin? || (STARTLESS_RANGE_NOT_SUPPORTED && !self.begin) || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end))
472
480
  end
473
481
 
474
482
  # Whether the beginning of the range is unbounded.
@@ -116,7 +116,9 @@ module Sequel
116
116
  end
117
117
  end
118
118
 
119
+ # :nocov:
119
120
  if defined?(PGRange)
121
+ # :nocov:
120
122
  class PGRange
121
123
  # Wrap the PGRange instance in an RangeOp, allowing you to easily use
122
124
  # the PostgreSQL range functions and operators with literal ranges.
@@ -7,7 +7,7 @@
7
7
  # that when composite fields are retrieved, they are parsed and returned
8
8
  # as instances of Sequel::Postgres::PGRow::(HashRow|ArrayRow), or
9
9
  # optionally a custom type. HashRow and ArrayRow are DelegateClasses of
10
- # of Hash and Array, so they mostly act like a hash or array, but not
10
+ # Hash and Array, so they mostly act like a hash or array, but not
11
11
  # completely (is_a?(Hash) and is_a?(Array) are false). If you want the
12
12
  # actual hash for a HashRow, call HashRow#to_hash, and if you want the
13
13
  # actual array for an ArrayRow, call ArrayRow#to_a. This is done so
@@ -222,13 +222,14 @@ module Sequel
222
222
  # Split the stored string into an array of strings, handling
223
223
  # the different types of quoting.
224
224
  def parse
225
- return @result if @result
226
225
  values = []
227
226
  skip(/\(/)
228
227
  if skip(/\)/)
229
228
  values << nil
230
229
  else
230
+ # :nocov:
231
231
  until eos?
232
+ # :nocov:
232
233
  if skip(/"/)
233
234
  values << scan(/(\\.|""|[^"])*/).gsub(/\\(.)|"(")/, '\1\2')
234
235
  skip(/"[,)]/)
@@ -481,6 +482,7 @@ module Sequel
481
482
  row_type(db_type, v)
482
483
  end
483
484
  private meth
485
+ alias_method(meth, meth)
484
486
  end
485
487
 
486
488
  nil
@@ -158,6 +158,30 @@ module Sequel
158
158
  end
159
159
  end
160
160
  end
161
+
162
+ # :nocov:
163
+ if defined?(PGRow::ArrayRow)
164
+ # :nocov:
165
+ class PGRow::ArrayRow
166
+ # Wrap the PGRow::ArrayRow instance in an PGRowOp, allowing you to easily use
167
+ # the PostgreSQL row functions and operators with literal rows.
168
+ def op
169
+ Sequel.pg_row_op(self)
170
+ end
171
+ end
172
+ end
173
+
174
+ # :nocov:
175
+ if defined?(PGRow::HashRow)
176
+ # :nocov:
177
+ class PGRow::HashRow
178
+ # Wrap the PGRow::ArrayRow instance in an PGRowOp, allowing you to easily use
179
+ # the PostgreSQL row functions and operators with literal rows.
180
+ def op
181
+ Sequel.pg_row_op(self)
182
+ end
183
+ end
184
+ end
161
185
  end
162
186
 
163
187
  module SQL::Builders
@@ -15,6 +15,8 @@
15
15
  module Sequel
16
16
  module Postgres
17
17
  module Timestamptz
18
+ private
19
+
18
20
  # Use timestamptz by default for generic timestamp value.
19
21
  def type_literal_generic_datetime(column)
20
22
  :timestamptz
@@ -74,6 +74,9 @@ module Sequel
74
74
  raise(Sequel::Error, "method #{method.inspect} did not return a dataset") unless @dataset.is_a?(Dataset)
75
75
  self
76
76
  end
77
+ # :nocov:
78
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
79
+ # :nocov:
77
80
  end
78
81
  end
79
82
 
@@ -0,0 +1,72 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The run_transaction_hooks extension allows for running after_commit or
4
+ # after_rollback extensions before commit or rollback. It then removes
5
+ # the hook after running it, so it will not be run twice.
6
+ #
7
+ # This extension should only be used in transactional tests where the
8
+ # transaction always rolls back, to test the behavior of the after_commit
9
+ # and after_rollback hooks. Any other usage is probably a bad idea.
10
+ #
11
+ # Example:
12
+ #
13
+ # DB.extension :run_transaction_hooks
14
+ # x = 1
15
+ # DB.transaction(rollback: :always) do
16
+ # DB.after_rollback{x = 3}
17
+ # DB.after_commit{x = 2}
18
+ #
19
+ # x # => 1
20
+ # DB.run_after_rollback_hooks
21
+ # x # => 3
22
+ # DB.run_after_commit_hooks
23
+ # x # => 2
24
+ # end
25
+ # x # => 2
26
+
27
+ #
28
+ class Sequel::Database
29
+ module RunTransactionHooks
30
+ # Run all savepoint and transaction after_commit hooks for the current transaction,
31
+ # and remove the hooks after running them.
32
+ # Options:
33
+ # :server :: The server/shard to use.
34
+ def run_after_commit_hooks(opts=OPTS)
35
+ _run_transaction_hooks(:after_commit, opts)
36
+ end
37
+
38
+ # Run all savepoint and transaction after_rollback hooks for the current transaction,
39
+ # and remove the hooks after running them.
40
+ # Options:
41
+ # :server :: The server/shard to use.
42
+ def run_after_rollback_hooks(opts=OPTS)
43
+ _run_transaction_hooks(:after_rollback, opts)
44
+ end
45
+
46
+ private
47
+
48
+ def _run_transaction_hooks(type, opts)
49
+ synchronize(opts[:server]) do |conn|
50
+ unless h = _trans(conn)
51
+ raise Sequel::Error, "Cannot call run_#{type}_hooks outside of a transaction"
52
+ end
53
+
54
+ if hooks = h[type]
55
+ hooks.each(&:call)
56
+ hooks.clear
57
+ end
58
+
59
+ if (savepoints = h[:savepoints])
60
+ savepoints.each do |savepoint|
61
+ if hooks = savepoint[type]
62
+ hooks.each(&:call)
63
+ hooks.clear
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ register_extension(:run_transaction_hooks, RunTransactionHooks)
72
+ end
@@ -49,7 +49,9 @@ module Sequel::S
49
49
  Sequel.expr(*a, &block)
50
50
  end
51
51
 
52
+ # :nocov:
52
53
  if RUBY_VERSION >= '2.0.0'
54
+ # :nocov:
53
55
  refine Object do
54
56
  include Sequel::S
55
57
  end
@@ -6,6 +6,17 @@
6
6
  # the current database). The main interface is through
7
7
  # Sequel::Database#dump_schema_migration.
8
8
  #
9
+ # The schema_dumper extension is quite limited in what types of
10
+ # database objects it supports. In general, it only supports
11
+ # dumping tables, columns, primary key and foreign key constraints,
12
+ # and some indexes. It does not support most table options, CHECK
13
+ # constraints, partial indexes, database functions, triggers,
14
+ # security grants/revokes, and a wide variety of other useful
15
+ # database properties. Be aware of the limitations when using the
16
+ # schema_dumper extension. If you are dumping the schema to restore
17
+ # to the same database type, it is recommended to use your database's
18
+ # dump and restore programs instead of the schema_dumper extension.
19
+ #
9
20
  # To load the extension:
10
21
  #
11
22
  # DB.extension :schema_dumper
@@ -37,7 +48,7 @@ module Sequel
37
48
  {:type =>schema[:type] == :boolean ? TrueClass : Integer}
38
49
  when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/
39
50
  {:type=>:Bignum}
40
- when /\A(?:real|float(?: unsigned)?|double(?: precision)?|double\(\d+,\d+\)(?: unsigned)?)\z/
51
+ when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\))(?: unsigned)?\z/
41
52
  {:type=>Float}
42
53
  when 'boolean', 'bit', 'bool'
43
54
  {:type=>TrueClass}
@@ -57,7 +68,7 @@ module Sequel
57
68
  {:type=>String, :size=>($1.to_i if $1)}
58
69
  when /\A(?:small)?money\z/
59
70
  {:type=>BigDecimal, :size=>[19,2]}
60
- when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/
71
+ when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?(?: unsigned)?\z/
61
72
  s = [($1.to_i if $1), ($2.to_i if $2)].compact
62
73
  {:type=>BigDecimal, :size=>(s.empty? ? nil : s)}
63
74
  when /\A(?:bytea|(?:tiny|medium|long)?blob|(?:var)?binary)(?:\((\d+)\))?\z/
@@ -199,12 +210,18 @@ END_MIG
199
210
  end
200
211
  type = col_opts.delete(:type)
201
212
  col_opts.delete(:size) if col_opts[:size].nil?
202
- col_opts[:default] = if schema[:ruby_default].nil?
203
- column_schema_to_ruby_default_fallback(schema[:default], options)
213
+ if schema[:generated]
214
+ if options[:same_db] && database_type == :postgres
215
+ col_opts[:generated_always_as] = column_schema_to_ruby_default_fallback(schema[:default], options)
216
+ end
204
217
  else
205
- schema[:ruby_default]
218
+ col_opts[:default] = if schema[:ruby_default].nil?
219
+ column_schema_to_ruby_default_fallback(schema[:default], options)
220
+ else
221
+ schema[:ruby_default]
222
+ end
223
+ col_opts.delete(:default) if col_opts[:default].nil?
206
224
  end
207
- col_opts.delete(:default) if col_opts[:default].nil?
208
225
  col_opts[:null] = false if schema[:allow_null] == false
209
226
  if table = schema[:table]
210
227
  [:key, :on_delete, :on_update, :deferrable].each{|f| col_opts[f] = schema[f] if schema[f]}
@@ -212,7 +229,7 @@ END_MIG
212
229
  gen.foreign_key(name, table, col_opts)
213
230
  else
214
231
  gen.column(name, type, col_opts)
215
- if [Integer, :Bignum, Float].include?(type) && schema[:db_type] =~ / unsigned\z/io
232
+ if [Integer, :Bignum, Float, BigDecimal].include?(type) && schema[:db_type] =~ / unsigned\z/io
216
233
  gen.check(Sequel::SQL::Identifier.new(name) >= 0)
217
234
  end
218
235
  end
@@ -52,6 +52,12 @@
52
52
  # DB[:a].server(:read_only).delete # Uses shard2
53
53
  # end
54
54
  #
55
+ # If you use an invalid server when calling with_server, it will be
56
+ # treated the same way as if you called Dataset#server with an invalid
57
+ # server. By default, the default server will be used in such cases.
58
+ # If you would like a different server to be used, or an exception to
59
+ # be raised, then use the :servers_hash Database option.
60
+ #
55
61
  # Related modules: Sequel::ServerBlock, Sequel::UnthreadedServerBlock,
56
62
  # Sequel::ThreadedServerBlock
57
63
 
@@ -110,9 +116,9 @@ module Sequel
110
116
  else
111
117
  case server
112
118
  when :default, nil
113
- @default_servers[-1][0]
119
+ @servers[@default_servers[-1][0]]
114
120
  when :read_only
115
- @default_servers[-1][1]
121
+ @servers[@default_servers[-1][1]]
116
122
  else
117
123
  super
118
124
  end
@@ -137,13 +143,13 @@ module Sequel
137
143
 
138
144
  # Make the given server the new default server for the current thread.
139
145
  def set_default_server(default_server, read_only_server=default_server)
140
- sync{(@default_servers[Thread.current] ||= [])} << [default_server, read_only_server]
146
+ sync{(@default_servers[Sequel.current] ||= [])} << [default_server, read_only_server]
141
147
  end
142
148
 
143
149
  # Remove the current default server for the current thread, restoring the
144
150
  # previous default server.
145
151
  def clear_default_server
146
- t = Thread.current
152
+ t = Sequel.current
147
153
  a = sync{@default_servers[t]}
148
154
  a.pop
149
155
  sync{@default_servers.delete(t)} if a.empty?
@@ -151,15 +157,20 @@ module Sequel
151
157
 
152
158
  # Use the server given to with_server for the given thread, if appropriate.
153
159
  def pick_server(server)
154
- a = sync{@default_servers[Thread.current]}
160
+ a = sync{@default_servers[Sequel.current]}
155
161
  if !a || a.empty?
156
162
  super
157
163
  else
164
+ # Hash handling required to work when loaded after arbitrary servers plugin.
158
165
  case server
159
166
  when :default, nil
160
- a[-1][0]
167
+ v = a[-1][0]
168
+ v = @servers[v] unless v.is_a?(Hash)
169
+ v
161
170
  when :read_only
162
- a[-1][1]
171
+ v = a[-1][1]
172
+ v = @servers[v] unless v.is_a?(Hash)
173
+ v
163
174
  else
164
175
  super
165
176
  end