sequel 4.26.0 → 5.37.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 (692) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +405 -5656
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +232 -157
  5. data/bin/sequel +32 -9
  6. data/doc/advanced_associations.rdoc +252 -188
  7. data/doc/association_basics.rdoc +231 -273
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +75 -48
  10. data/doc/code_order.rdoc +28 -10
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/mass_assignment.rdoc +74 -31
  16. data/doc/migration.rdoc +72 -46
  17. data/doc/model_dataset_method_design.rdoc +129 -0
  18. data/doc/model_hooks.rdoc +15 -25
  19. data/doc/model_plugins.rdoc +12 -12
  20. data/doc/mssql_stored_procedures.rdoc +3 -3
  21. data/doc/object_model.rdoc +59 -69
  22. data/doc/opening_databases.rdoc +84 -94
  23. data/doc/postgresql.rdoc +268 -38
  24. data/doc/prepared_statements.rdoc +29 -24
  25. data/doc/querying.rdoc +184 -164
  26. data/doc/reflection.rdoc +5 -6
  27. data/doc/release_notes/5.0.0.txt +159 -0
  28. data/doc/release_notes/5.1.0.txt +31 -0
  29. data/doc/release_notes/5.10.0.txt +84 -0
  30. data/doc/release_notes/5.11.0.txt +83 -0
  31. data/doc/release_notes/5.12.0.txt +141 -0
  32. data/doc/release_notes/5.13.0.txt +27 -0
  33. data/doc/release_notes/5.14.0.txt +63 -0
  34. data/doc/release_notes/5.15.0.txt +39 -0
  35. data/doc/release_notes/5.16.0.txt +110 -0
  36. data/doc/release_notes/5.17.0.txt +31 -0
  37. data/doc/release_notes/5.18.0.txt +69 -0
  38. data/doc/release_notes/5.19.0.txt +28 -0
  39. data/doc/release_notes/5.2.0.txt +33 -0
  40. data/doc/release_notes/5.20.0.txt +89 -0
  41. data/doc/release_notes/5.21.0.txt +87 -0
  42. data/doc/release_notes/5.22.0.txt +48 -0
  43. data/doc/release_notes/5.23.0.txt +56 -0
  44. data/doc/release_notes/5.24.0.txt +56 -0
  45. data/doc/release_notes/5.25.0.txt +32 -0
  46. data/doc/release_notes/5.26.0.txt +35 -0
  47. data/doc/release_notes/5.27.0.txt +21 -0
  48. data/doc/release_notes/5.28.0.txt +16 -0
  49. data/doc/release_notes/5.29.0.txt +22 -0
  50. data/doc/release_notes/5.3.0.txt +121 -0
  51. data/doc/release_notes/5.30.0.txt +20 -0
  52. data/doc/release_notes/5.31.0.txt +148 -0
  53. data/doc/release_notes/5.32.0.txt +46 -0
  54. data/doc/release_notes/5.33.0.txt +24 -0
  55. data/doc/release_notes/5.34.0.txt +40 -0
  56. data/doc/release_notes/5.35.0.txt +56 -0
  57. data/doc/release_notes/5.36.0.txt +60 -0
  58. data/doc/release_notes/5.37.0.txt +30 -0
  59. data/doc/release_notes/5.4.0.txt +80 -0
  60. data/doc/release_notes/5.5.0.txt +61 -0
  61. data/doc/release_notes/5.6.0.txt +31 -0
  62. data/doc/release_notes/5.7.0.txt +108 -0
  63. data/doc/release_notes/5.8.0.txt +170 -0
  64. data/doc/release_notes/5.9.0.txt +99 -0
  65. data/doc/schema_modification.rdoc +102 -77
  66. data/doc/security.rdoc +160 -87
  67. data/doc/sharding.rdoc +74 -47
  68. data/doc/sql.rdoc +135 -122
  69. data/doc/testing.rdoc +34 -18
  70. data/doc/thread_safety.rdoc +2 -4
  71. data/doc/transactions.rdoc +101 -19
  72. data/doc/validations.rdoc +64 -51
  73. data/doc/virtual_rows.rdoc +90 -109
  74. data/lib/sequel.rb +3 -1
  75. data/lib/sequel/adapters/ado.rb +154 -22
  76. data/lib/sequel/adapters/ado/access.rb +21 -21
  77. data/lib/sequel/adapters/ado/mssql.rb +8 -15
  78. data/lib/sequel/adapters/amalgalite.rb +17 -25
  79. data/lib/sequel/adapters/ibmdb.rb +52 -58
  80. data/lib/sequel/adapters/jdbc.rb +149 -127
  81. data/lib/sequel/adapters/jdbc/db2.rb +32 -40
  82. data/lib/sequel/adapters/jdbc/derby.rb +56 -58
  83. data/lib/sequel/adapters/jdbc/h2.rb +40 -30
  84. data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
  85. data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
  86. data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
  87. data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
  88. data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
  89. data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
  90. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
  91. data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
  92. data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
  93. data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
  94. data/lib/sequel/adapters/mock.rb +104 -113
  95. data/lib/sequel/adapters/mysql.rb +42 -61
  96. data/lib/sequel/adapters/mysql2.rb +126 -35
  97. data/lib/sequel/adapters/odbc.rb +21 -28
  98. data/lib/sequel/adapters/odbc/db2.rb +3 -1
  99. data/lib/sequel/adapters/odbc/mssql.rb +11 -15
  100. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  101. data/lib/sequel/adapters/oracle.rb +62 -68
  102. data/lib/sequel/adapters/postgres.rb +257 -311
  103. data/lib/sequel/adapters/postgresql.rb +3 -1
  104. data/lib/sequel/adapters/shared/access.rb +75 -79
  105. data/lib/sequel/adapters/shared/db2.rb +96 -74
  106. data/lib/sequel/adapters/shared/mssql.rb +258 -213
  107. data/lib/sequel/adapters/shared/mysql.rb +284 -216
  108. data/lib/sequel/adapters/shared/oracle.rb +175 -60
  109. data/lib/sequel/adapters/shared/postgres.rb +829 -383
  110. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
  111. data/lib/sequel/adapters/shared/sqlite.rb +382 -159
  112. data/lib/sequel/adapters/sqlanywhere.rb +53 -38
  113. data/lib/sequel/adapters/sqlite.rb +111 -105
  114. data/lib/sequel/adapters/tinytds.rb +38 -46
  115. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
  116. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
  117. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  118. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  119. data/lib/sequel/adapters/utils/replace.rb +3 -4
  120. data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
  121. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  122. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  123. data/lib/sequel/ast_transformer.rb +13 -89
  124. data/lib/sequel/connection_pool.rb +54 -26
  125. data/lib/sequel/connection_pool/sharded_single.rb +19 -12
  126. data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
  127. data/lib/sequel/connection_pool/single.rb +21 -12
  128. data/lib/sequel/connection_pool/threaded.rb +137 -119
  129. data/lib/sequel/core.rb +352 -320
  130. data/lib/sequel/database.rb +19 -2
  131. data/lib/sequel/database/connecting.rb +70 -55
  132. data/lib/sequel/database/dataset.rb +15 -5
  133. data/lib/sequel/database/dataset_defaults.rb +20 -102
  134. data/lib/sequel/database/features.rb +20 -4
  135. data/lib/sequel/database/logging.rb +25 -7
  136. data/lib/sequel/database/misc.rb +132 -118
  137. data/lib/sequel/database/query.rb +51 -28
  138. data/lib/sequel/database/schema_generator.rb +188 -75
  139. data/lib/sequel/database/schema_methods.rb +161 -92
  140. data/lib/sequel/database/transactions.rb +260 -58
  141. data/lib/sequel/dataset.rb +28 -12
  142. data/lib/sequel/dataset/actions.rb +354 -170
  143. data/lib/sequel/dataset/dataset_module.rb +46 -0
  144. data/lib/sequel/dataset/features.rb +81 -34
  145. data/lib/sequel/dataset/graph.rb +82 -58
  146. data/lib/sequel/dataset/misc.rb +139 -47
  147. data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
  148. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  149. data/lib/sequel/dataset/query.rb +428 -214
  150. data/lib/sequel/dataset/sql.rb +446 -339
  151. data/lib/sequel/deprecated.rb +14 -2
  152. data/lib/sequel/exceptions.rb +48 -16
  153. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  154. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  155. data/lib/sequel/extensions/_pretty_table.rb +10 -9
  156. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  157. data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
  158. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  159. data/lib/sequel/extensions/blank.rb +2 -0
  160. data/lib/sequel/extensions/caller_logging.rb +79 -0
  161. data/lib/sequel/extensions/columns_introspection.rb +9 -4
  162. data/lib/sequel/extensions/connection_expiration.rb +99 -0
  163. data/lib/sequel/extensions/connection_validator.rb +26 -13
  164. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  165. data/lib/sequel/extensions/constraint_validations.rb +93 -38
  166. data/lib/sequel/extensions/core_extensions.rb +45 -53
  167. data/lib/sequel/extensions/core_refinements.rb +44 -46
  168. data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
  169. data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
  170. data/lib/sequel/extensions/date_arithmetic.rb +42 -16
  171. data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
  172. data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
  173. data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
  174. data/lib/sequel/extensions/error_sql.rb +7 -3
  175. data/lib/sequel/extensions/escaped_like.rb +100 -0
  176. data/lib/sequel/extensions/eval_inspect.rb +14 -15
  177. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  178. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  179. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  180. data/lib/sequel/extensions/from_block.rb +2 -31
  181. data/lib/sequel/extensions/graph_each.rb +19 -6
  182. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  183. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  184. data/lib/sequel/extensions/index_caching.rb +109 -0
  185. data/lib/sequel/extensions/inflector.rb +8 -4
  186. data/lib/sequel/extensions/integer64.rb +32 -0
  187. data/lib/sequel/extensions/looser_typecasting.rb +19 -9
  188. data/lib/sequel/extensions/migration.rb +132 -80
  189. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
  190. data/lib/sequel/extensions/named_timezones.rb +88 -23
  191. data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
  192. data/lib/sequel/extensions/null_dataset.rb +12 -8
  193. data/lib/sequel/extensions/pagination.rb +35 -28
  194. data/lib/sequel/extensions/pg_array.rb +227 -316
  195. data/lib/sequel/extensions/pg_array_ops.rb +19 -7
  196. data/lib/sequel/extensions/pg_enum.rb +69 -24
  197. data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
  198. data/lib/sequel/extensions/pg_hstore.rb +50 -59
  199. data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
  200. data/lib/sequel/extensions/pg_inet.rb +34 -15
  201. data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
  202. data/lib/sequel/extensions/pg_interval.rb +26 -26
  203. data/lib/sequel/extensions/pg_json.rb +422 -141
  204. data/lib/sequel/extensions/pg_json_ops.rb +248 -9
  205. data/lib/sequel/extensions/pg_loose_count.rb +5 -1
  206. data/lib/sequel/extensions/pg_range.rb +162 -146
  207. data/lib/sequel/extensions/pg_range_ops.rb +10 -5
  208. data/lib/sequel/extensions/pg_row.rb +53 -87
  209. data/lib/sequel/extensions/pg_row_ops.rb +36 -13
  210. data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
  211. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  212. data/lib/sequel/extensions/pretty_table.rb +4 -0
  213. data/lib/sequel/extensions/query.rb +12 -7
  214. data/lib/sequel/extensions/round_timestamps.rb +6 -9
  215. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  216. data/lib/sequel/extensions/s.rb +59 -0
  217. data/lib/sequel/extensions/schema_caching.rb +14 -1
  218. data/lib/sequel/extensions/schema_dumper.rb +83 -55
  219. data/lib/sequel/extensions/select_remove.rb +8 -4
  220. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  221. data/lib/sequel/extensions/server_block.rb +50 -17
  222. data/lib/sequel/extensions/server_logging.rb +61 -0
  223. data/lib/sequel/extensions/split_array_nil.rb +8 -4
  224. data/lib/sequel/extensions/sql_comments.rb +96 -0
  225. data/lib/sequel/extensions/sql_expr.rb +4 -1
  226. data/lib/sequel/extensions/string_agg.rb +181 -0
  227. data/lib/sequel/extensions/string_date_time.rb +2 -0
  228. data/lib/sequel/extensions/symbol_aref.rb +53 -0
  229. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  230. data/lib/sequel/extensions/symbol_as.rb +23 -0
  231. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  232. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  233. data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
  234. data/lib/sequel/extensions/to_dot.rb +15 -5
  235. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  236. data/lib/sequel/model.rb +36 -126
  237. data/lib/sequel/model/associations.rb +850 -257
  238. data/lib/sequel/model/base.rb +652 -764
  239. data/lib/sequel/model/dataset_module.rb +13 -10
  240. data/lib/sequel/model/default_inflections.rb +3 -1
  241. data/lib/sequel/model/errors.rb +3 -3
  242. data/lib/sequel/model/exceptions.rb +12 -12
  243. data/lib/sequel/model/inflections.rb +8 -19
  244. data/lib/sequel/model/plugins.rb +111 -0
  245. data/lib/sequel/plugins/accessed_columns.rb +2 -0
  246. data/lib/sequel/plugins/active_model.rb +32 -7
  247. data/lib/sequel/plugins/after_initialize.rb +3 -1
  248. data/lib/sequel/plugins/association_dependencies.rb +27 -18
  249. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  250. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  251. data/lib/sequel/plugins/association_pks.rb +181 -83
  252. data/lib/sequel/plugins/association_proxies.rb +33 -9
  253. data/lib/sequel/plugins/auto_validations.rb +58 -23
  254. data/lib/sequel/plugins/before_after_save.rb +8 -0
  255. data/lib/sequel/plugins/blacklist_security.rb +23 -12
  256. data/lib/sequel/plugins/boolean_readers.rb +9 -6
  257. data/lib/sequel/plugins/boolean_subsets.rb +64 -0
  258. data/lib/sequel/plugins/caching.rb +27 -16
  259. data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
  260. data/lib/sequel/plugins/column_conflicts.rb +18 -3
  261. data/lib/sequel/plugins/column_select.rb +9 -5
  262. data/lib/sequel/plugins/columns_updated.rb +42 -0
  263. data/lib/sequel/plugins/composition.rb +36 -24
  264. data/lib/sequel/plugins/constraint_validations.rb +37 -16
  265. data/lib/sequel/plugins/csv_serializer.rb +58 -35
  266. data/lib/sequel/plugins/dataset_associations.rb +60 -18
  267. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  268. data/lib/sequel/plugins/defaults_setter.rb +74 -13
  269. data/lib/sequel/plugins/delay_add_association.rb +4 -1
  270. data/lib/sequel/plugins/dirty.rb +65 -24
  271. data/lib/sequel/plugins/eager_each.rb +27 -3
  272. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  273. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  274. data/lib/sequel/plugins/error_splitter.rb +19 -12
  275. data/lib/sequel/plugins/finder.rb +246 -0
  276. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  277. data/lib/sequel/plugins/force_encoding.rb +9 -12
  278. data/lib/sequel/plugins/hook_class_methods.rb +39 -54
  279. data/lib/sequel/plugins/input_transformer.rb +20 -10
  280. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  281. data/lib/sequel/plugins/insert_returning_select.rb +4 -2
  282. data/lib/sequel/plugins/instance_filters.rb +12 -8
  283. data/lib/sequel/plugins/instance_hooks.rb +36 -17
  284. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  285. data/lib/sequel/plugins/inverted_subsets.rb +24 -13
  286. data/lib/sequel/plugins/json_serializer.rb +123 -47
  287. data/lib/sequel/plugins/lazy_attributes.rb +20 -14
  288. data/lib/sequel/plugins/list.rb +40 -26
  289. data/lib/sequel/plugins/many_through_many.rb +28 -12
  290. data/lib/sequel/plugins/modification_detection.rb +17 -5
  291. data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
  292. data/lib/sequel/plugins/nested_attributes.rb +55 -28
  293. data/lib/sequel/plugins/optimistic_locking.rb +5 -3
  294. data/lib/sequel/plugins/pg_array_associations.rb +52 -18
  295. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
  296. data/lib/sequel/plugins/pg_row.rb +7 -51
  297. data/lib/sequel/plugins/prepared_statements.rb +53 -72
  298. data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
  299. data/lib/sequel/plugins/rcte_tree.rb +43 -63
  300. data/lib/sequel/plugins/serialization.rb +37 -44
  301. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
  302. data/lib/sequel/plugins/sharding.rb +17 -10
  303. data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
  304. data/lib/sequel/plugins/singular_table_names.rb +2 -0
  305. data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
  306. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  307. data/lib/sequel/plugins/split_values.rb +13 -6
  308. data/lib/sequel/plugins/static_cache.rb +79 -53
  309. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  310. data/lib/sequel/plugins/string_stripper.rb +5 -3
  311. data/lib/sequel/plugins/subclasses.rb +20 -2
  312. data/lib/sequel/plugins/subset_conditions.rb +48 -0
  313. data/lib/sequel/plugins/table_select.rb +4 -2
  314. data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
  315. data/lib/sequel/plugins/throw_failures.rb +110 -0
  316. data/lib/sequel/plugins/timestamps.rb +22 -8
  317. data/lib/sequel/plugins/touch.rb +21 -8
  318. data/lib/sequel/plugins/tree.rb +57 -30
  319. data/lib/sequel/plugins/typecast_on_load.rb +14 -4
  320. data/lib/sequel/plugins/unlimited_update.rb +3 -7
  321. data/lib/sequel/plugins/update_or_create.rb +6 -4
  322. data/lib/sequel/plugins/update_primary_key.rb +3 -1
  323. data/lib/sequel/plugins/update_refresh.rb +28 -15
  324. data/lib/sequel/plugins/uuid.rb +70 -0
  325. data/lib/sequel/plugins/validate_associated.rb +20 -0
  326. data/lib/sequel/plugins/validation_class_methods.rb +40 -19
  327. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  328. data/lib/sequel/plugins/validation_helpers.rb +49 -31
  329. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  330. data/lib/sequel/plugins/xml_serializer.rb +31 -30
  331. data/lib/sequel/sql.rb +479 -329
  332. data/lib/sequel/timezones.rb +62 -32
  333. data/lib/sequel/version.rb +10 -3
  334. metadata +177 -477
  335. data/Rakefile +0 -165
  336. data/doc/active_record.rdoc +0 -912
  337. data/doc/release_notes/1.0.txt +0 -38
  338. data/doc/release_notes/1.1.txt +0 -143
  339. data/doc/release_notes/1.3.txt +0 -101
  340. data/doc/release_notes/1.4.0.txt +0 -53
  341. data/doc/release_notes/1.5.0.txt +0 -155
  342. data/doc/release_notes/2.0.0.txt +0 -298
  343. data/doc/release_notes/2.1.0.txt +0 -271
  344. data/doc/release_notes/2.10.0.txt +0 -328
  345. data/doc/release_notes/2.11.0.txt +0 -215
  346. data/doc/release_notes/2.12.0.txt +0 -534
  347. data/doc/release_notes/2.2.0.txt +0 -253
  348. data/doc/release_notes/2.3.0.txt +0 -88
  349. data/doc/release_notes/2.4.0.txt +0 -106
  350. data/doc/release_notes/2.5.0.txt +0 -137
  351. data/doc/release_notes/2.6.0.txt +0 -157
  352. data/doc/release_notes/2.7.0.txt +0 -166
  353. data/doc/release_notes/2.8.0.txt +0 -171
  354. data/doc/release_notes/2.9.0.txt +0 -97
  355. data/doc/release_notes/3.0.0.txt +0 -221
  356. data/doc/release_notes/3.1.0.txt +0 -406
  357. data/doc/release_notes/3.10.0.txt +0 -286
  358. data/doc/release_notes/3.11.0.txt +0 -254
  359. data/doc/release_notes/3.12.0.txt +0 -304
  360. data/doc/release_notes/3.13.0.txt +0 -210
  361. data/doc/release_notes/3.14.0.txt +0 -118
  362. data/doc/release_notes/3.15.0.txt +0 -78
  363. data/doc/release_notes/3.16.0.txt +0 -45
  364. data/doc/release_notes/3.17.0.txt +0 -58
  365. data/doc/release_notes/3.18.0.txt +0 -120
  366. data/doc/release_notes/3.19.0.txt +0 -67
  367. data/doc/release_notes/3.2.0.txt +0 -268
  368. data/doc/release_notes/3.20.0.txt +0 -41
  369. data/doc/release_notes/3.21.0.txt +0 -87
  370. data/doc/release_notes/3.22.0.txt +0 -39
  371. data/doc/release_notes/3.23.0.txt +0 -172
  372. data/doc/release_notes/3.24.0.txt +0 -420
  373. data/doc/release_notes/3.25.0.txt +0 -88
  374. data/doc/release_notes/3.26.0.txt +0 -88
  375. data/doc/release_notes/3.27.0.txt +0 -82
  376. data/doc/release_notes/3.28.0.txt +0 -304
  377. data/doc/release_notes/3.29.0.txt +0 -459
  378. data/doc/release_notes/3.3.0.txt +0 -192
  379. data/doc/release_notes/3.30.0.txt +0 -135
  380. data/doc/release_notes/3.31.0.txt +0 -146
  381. data/doc/release_notes/3.32.0.txt +0 -202
  382. data/doc/release_notes/3.33.0.txt +0 -157
  383. data/doc/release_notes/3.34.0.txt +0 -671
  384. data/doc/release_notes/3.35.0.txt +0 -144
  385. data/doc/release_notes/3.36.0.txt +0 -245
  386. data/doc/release_notes/3.37.0.txt +0 -338
  387. data/doc/release_notes/3.38.0.txt +0 -234
  388. data/doc/release_notes/3.39.0.txt +0 -237
  389. data/doc/release_notes/3.4.0.txt +0 -325
  390. data/doc/release_notes/3.40.0.txt +0 -73
  391. data/doc/release_notes/3.41.0.txt +0 -155
  392. data/doc/release_notes/3.42.0.txt +0 -74
  393. data/doc/release_notes/3.43.0.txt +0 -105
  394. data/doc/release_notes/3.44.0.txt +0 -152
  395. data/doc/release_notes/3.45.0.txt +0 -179
  396. data/doc/release_notes/3.46.0.txt +0 -122
  397. data/doc/release_notes/3.47.0.txt +0 -270
  398. data/doc/release_notes/3.48.0.txt +0 -477
  399. data/doc/release_notes/3.5.0.txt +0 -510
  400. data/doc/release_notes/3.6.0.txt +0 -366
  401. data/doc/release_notes/3.7.0.txt +0 -179
  402. data/doc/release_notes/3.8.0.txt +0 -151
  403. data/doc/release_notes/3.9.0.txt +0 -233
  404. data/doc/release_notes/4.0.0.txt +0 -262
  405. data/doc/release_notes/4.1.0.txt +0 -85
  406. data/doc/release_notes/4.10.0.txt +0 -226
  407. data/doc/release_notes/4.11.0.txt +0 -147
  408. data/doc/release_notes/4.12.0.txt +0 -105
  409. data/doc/release_notes/4.13.0.txt +0 -169
  410. data/doc/release_notes/4.14.0.txt +0 -68
  411. data/doc/release_notes/4.15.0.txt +0 -56
  412. data/doc/release_notes/4.16.0.txt +0 -36
  413. data/doc/release_notes/4.17.0.txt +0 -38
  414. data/doc/release_notes/4.18.0.txt +0 -36
  415. data/doc/release_notes/4.19.0.txt +0 -45
  416. data/doc/release_notes/4.2.0.txt +0 -129
  417. data/doc/release_notes/4.20.0.txt +0 -79
  418. data/doc/release_notes/4.21.0.txt +0 -94
  419. data/doc/release_notes/4.22.0.txt +0 -72
  420. data/doc/release_notes/4.23.0.txt +0 -65
  421. data/doc/release_notes/4.24.0.txt +0 -99
  422. data/doc/release_notes/4.25.0.txt +0 -181
  423. data/doc/release_notes/4.26.0.txt +0 -44
  424. data/doc/release_notes/4.3.0.txt +0 -40
  425. data/doc/release_notes/4.4.0.txt +0 -92
  426. data/doc/release_notes/4.5.0.txt +0 -34
  427. data/doc/release_notes/4.6.0.txt +0 -30
  428. data/doc/release_notes/4.7.0.txt +0 -103
  429. data/doc/release_notes/4.8.0.txt +0 -175
  430. data/doc/release_notes/4.9.0.txt +0 -190
  431. data/lib/sequel/adapters/cubrid.rb +0 -142
  432. data/lib/sequel/adapters/do.rb +0 -156
  433. data/lib/sequel/adapters/do/mysql.rb +0 -64
  434. data/lib/sequel/adapters/do/postgres.rb +0 -42
  435. data/lib/sequel/adapters/do/sqlite3.rb +0 -40
  436. data/lib/sequel/adapters/jdbc/as400.rb +0 -82
  437. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
  438. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
  439. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
  440. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
  441. data/lib/sequel/adapters/odbc/progress.rb +0 -8
  442. data/lib/sequel/adapters/shared/cubrid.rb +0 -243
  443. data/lib/sequel/adapters/shared/firebird.rb +0 -245
  444. data/lib/sequel/adapters/shared/informix.rb +0 -52
  445. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
  446. data/lib/sequel/adapters/shared/progress.rb +0 -38
  447. data/lib/sequel/adapters/swift.rb +0 -158
  448. data/lib/sequel/adapters/swift/mysql.rb +0 -47
  449. data/lib/sequel/adapters/swift/postgres.rb +0 -45
  450. data/lib/sequel/adapters/swift/sqlite.rb +0 -47
  451. data/lib/sequel/adapters/utils/pg_types.rb +0 -68
  452. data/lib/sequel/dataset/mutation.rb +0 -109
  453. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
  454. data/lib/sequel/extensions/filter_having.rb +0 -59
  455. data/lib/sequel/extensions/hash_aliases.rb +0 -45
  456. data/lib/sequel/extensions/meta_def.rb +0 -31
  457. data/lib/sequel/extensions/query_literals.rb +0 -80
  458. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
  459. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
  460. data/lib/sequel/extensions/set_overrides.rb +0 -72
  461. data/lib/sequel/no_core_ext.rb +0 -1
  462. data/lib/sequel/plugins/association_autoreloading.rb +0 -7
  463. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
  464. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
  465. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
  466. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
  467. data/lib/sequel/plugins/schema.rb +0 -80
  468. data/lib/sequel/plugins/scissors.rb +0 -33
  469. data/spec/adapters/db2_spec.rb +0 -160
  470. data/spec/adapters/firebird_spec.rb +0 -411
  471. data/spec/adapters/informix_spec.rb +0 -100
  472. data/spec/adapters/mssql_spec.rb +0 -706
  473. data/spec/adapters/mysql_spec.rb +0 -1287
  474. data/spec/adapters/oracle_spec.rb +0 -313
  475. data/spec/adapters/postgres_spec.rb +0 -3725
  476. data/spec/adapters/spec_helper.rb +0 -43
  477. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  478. data/spec/adapters/sqlite_spec.rb +0 -653
  479. data/spec/bin_spec.rb +0 -254
  480. data/spec/core/connection_pool_spec.rb +0 -1016
  481. data/spec/core/database_spec.rb +0 -2531
  482. data/spec/core/dataset_spec.rb +0 -5098
  483. data/spec/core/deprecated_spec.rb +0 -70
  484. data/spec/core/expression_filters_spec.rb +0 -1243
  485. data/spec/core/mock_adapter_spec.rb +0 -462
  486. data/spec/core/object_graph_spec.rb +0 -303
  487. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  488. data/spec/core/schema_generator_spec.rb +0 -179
  489. data/spec/core/schema_spec.rb +0 -1659
  490. data/spec/core/spec_helper.rb +0 -34
  491. data/spec/core/version_spec.rb +0 -7
  492. data/spec/core_extensions_spec.rb +0 -699
  493. data/spec/extensions/accessed_columns_spec.rb +0 -51
  494. data/spec/extensions/active_model_spec.rb +0 -123
  495. data/spec/extensions/after_initialize_spec.rb +0 -24
  496. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  497. data/spec/extensions/association_dependencies_spec.rb +0 -117
  498. data/spec/extensions/association_pks_spec.rb +0 -365
  499. data/spec/extensions/association_proxies_spec.rb +0 -86
  500. data/spec/extensions/auto_validations_spec.rb +0 -192
  501. data/spec/extensions/blacklist_security_spec.rb +0 -88
  502. data/spec/extensions/blank_spec.rb +0 -69
  503. data/spec/extensions/boolean_readers_spec.rb +0 -93
  504. data/spec/extensions/caching_spec.rb +0 -270
  505. data/spec/extensions/class_table_inheritance_spec.rb +0 -420
  506. data/spec/extensions/column_conflicts_spec.rb +0 -60
  507. data/spec/extensions/column_select_spec.rb +0 -108
  508. data/spec/extensions/columns_introspection_spec.rb +0 -91
  509. data/spec/extensions/composition_spec.rb +0 -242
  510. data/spec/extensions/connection_validator_spec.rb +0 -120
  511. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
  512. data/spec/extensions/constraint_validations_spec.rb +0 -325
  513. data/spec/extensions/core_refinements_spec.rb +0 -519
  514. data/spec/extensions/csv_serializer_spec.rb +0 -173
  515. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  516. data/spec/extensions/dataset_associations_spec.rb +0 -311
  517. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  518. data/spec/extensions/date_arithmetic_spec.rb +0 -150
  519. data/spec/extensions/defaults_setter_spec.rb +0 -101
  520. data/spec/extensions/delay_add_association_spec.rb +0 -52
  521. data/spec/extensions/dirty_spec.rb +0 -180
  522. data/spec/extensions/eager_each_spec.rb +0 -42
  523. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  524. data/spec/extensions/error_splitter_spec.rb +0 -18
  525. data/spec/extensions/error_sql_spec.rb +0 -20
  526. data/spec/extensions/eval_inspect_spec.rb +0 -73
  527. data/spec/extensions/filter_having_spec.rb +0 -40
  528. data/spec/extensions/force_encoding_spec.rb +0 -114
  529. data/spec/extensions/from_block_spec.rb +0 -21
  530. data/spec/extensions/graph_each_spec.rb +0 -109
  531. data/spec/extensions/hash_aliases_spec.rb +0 -24
  532. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  533. data/spec/extensions/inflector_spec.rb +0 -183
  534. data/spec/extensions/input_transformer_spec.rb +0 -54
  535. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  536. data/spec/extensions/instance_filters_spec.rb +0 -79
  537. data/spec/extensions/instance_hooks_spec.rb +0 -276
  538. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  539. data/spec/extensions/json_serializer_spec.rb +0 -291
  540. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  541. data/spec/extensions/list_spec.rb +0 -267
  542. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  543. data/spec/extensions/many_through_many_spec.rb +0 -2172
  544. data/spec/extensions/meta_def_spec.rb +0 -21
  545. data/spec/extensions/migration_spec.rb +0 -712
  546. data/spec/extensions/modification_detection_spec.rb +0 -80
  547. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  548. data/spec/extensions/named_timezones_spec.rb +0 -108
  549. data/spec/extensions/nested_attributes_spec.rb +0 -697
  550. data/spec/extensions/null_dataset_spec.rb +0 -85
  551. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  552. data/spec/extensions/pagination_spec.rb +0 -118
  553. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  554. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  555. data/spec/extensions/pg_array_spec.rb +0 -395
  556. data/spec/extensions/pg_enum_spec.rb +0 -92
  557. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  558. data/spec/extensions/pg_hstore_spec.rb +0 -206
  559. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  560. data/spec/extensions/pg_inet_spec.rb +0 -52
  561. data/spec/extensions/pg_interval_spec.rb +0 -76
  562. data/spec/extensions/pg_json_ops_spec.rb +0 -229
  563. data/spec/extensions/pg_json_spec.rb +0 -218
  564. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  565. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  566. data/spec/extensions/pg_range_spec.rb +0 -404
  567. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  568. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  569. data/spec/extensions/pg_row_spec.rb +0 -360
  570. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  571. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  572. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  573. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  574. data/spec/extensions/prepared_statements_spec.rb +0 -103
  575. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  576. data/spec/extensions/pretty_table_spec.rb +0 -92
  577. data/spec/extensions/query_literals_spec.rb +0 -183
  578. data/spec/extensions/query_spec.rb +0 -102
  579. data/spec/extensions/rcte_tree_spec.rb +0 -392
  580. data/spec/extensions/round_timestamps_spec.rb +0 -43
  581. data/spec/extensions/schema_caching_spec.rb +0 -41
  582. data/spec/extensions/schema_dumper_spec.rb +0 -789
  583. data/spec/extensions/schema_spec.rb +0 -117
  584. data/spec/extensions/scissors_spec.rb +0 -26
  585. data/spec/extensions/select_remove_spec.rb +0 -38
  586. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  587. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  588. data/spec/extensions/serialization_spec.rb +0 -362
  589. data/spec/extensions/server_block_spec.rb +0 -90
  590. data/spec/extensions/set_overrides_spec.rb +0 -61
  591. data/spec/extensions/sharding_spec.rb +0 -198
  592. data/spec/extensions/shared_caching_spec.rb +0 -175
  593. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  594. data/spec/extensions/singular_table_names_spec.rb +0 -22
  595. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  596. data/spec/extensions/spec_helper.rb +0 -71
  597. data/spec/extensions/split_array_nil_spec.rb +0 -24
  598. data/spec/extensions/split_values_spec.rb +0 -22
  599. data/spec/extensions/sql_expr_spec.rb +0 -60
  600. data/spec/extensions/static_cache_spec.rb +0 -361
  601. data/spec/extensions/string_date_time_spec.rb +0 -95
  602. data/spec/extensions/string_stripper_spec.rb +0 -68
  603. data/spec/extensions/subclasses_spec.rb +0 -66
  604. data/spec/extensions/table_select_spec.rb +0 -71
  605. data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
  606. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  607. data/spec/extensions/timestamps_spec.rb +0 -175
  608. data/spec/extensions/to_dot_spec.rb +0 -154
  609. data/spec/extensions/touch_spec.rb +0 -203
  610. data/spec/extensions/tree_spec.rb +0 -274
  611. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  612. data/spec/extensions/unlimited_update_spec.rb +0 -20
  613. data/spec/extensions/update_or_create_spec.rb +0 -87
  614. data/spec/extensions/update_primary_key_spec.rb +0 -100
  615. data/spec/extensions/update_refresh_spec.rb +0 -53
  616. data/spec/extensions/validate_associated_spec.rb +0 -52
  617. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  618. data/spec/extensions/validation_helpers_spec.rb +0 -541
  619. data/spec/extensions/xml_serializer_spec.rb +0 -207
  620. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  621. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  622. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  623. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  624. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  625. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  626. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  627. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  628. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  629. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  630. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  631. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  632. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  633. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  634. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  635. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  636. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  637. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  638. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  639. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  640. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  641. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  642. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  643. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  644. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  645. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  646. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  647. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  648. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  649. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  650. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  651. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  652. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  653. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  654. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  655. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  656. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  657. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  658. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  659. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  660. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  661. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  662. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  663. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  664. data/spec/guards_helper.rb +0 -55
  665. data/spec/integration/associations_test.rb +0 -2454
  666. data/spec/integration/database_test.rb +0 -113
  667. data/spec/integration/dataset_test.rb +0 -1808
  668. data/spec/integration/eager_loader_test.rb +0 -687
  669. data/spec/integration/migrator_test.rb +0 -240
  670. data/spec/integration/model_test.rb +0 -226
  671. data/spec/integration/plugin_test.rb +0 -2240
  672. data/spec/integration/prepared_statement_test.rb +0 -467
  673. data/spec/integration/schema_test.rb +0 -817
  674. data/spec/integration/spec_helper.rb +0 -48
  675. data/spec/integration/timezone_test.rb +0 -86
  676. data/spec/integration/transaction_test.rb +0 -374
  677. data/spec/integration/type_test.rb +0 -133
  678. data/spec/model/association_reflection_spec.rb +0 -525
  679. data/spec/model/associations_spec.rb +0 -4426
  680. data/spec/model/base_spec.rb +0 -759
  681. data/spec/model/class_dataset_methods_spec.rb +0 -146
  682. data/spec/model/dataset_methods_spec.rb +0 -149
  683. data/spec/model/eager_loading_spec.rb +0 -2137
  684. data/spec/model/hooks_spec.rb +0 -604
  685. data/spec/model/inflector_spec.rb +0 -26
  686. data/spec/model/model_spec.rb +0 -982
  687. data/spec/model/plugins_spec.rb +0 -299
  688. data/spec/model/record_spec.rb +0 -2147
  689. data/spec/model/spec_helper.rb +0 -46
  690. data/spec/model/validations_spec.rb +0 -193
  691. data/spec/sequel_coverage.rb +0 -15
  692. data/spec/spec_config.rb +0 -10
@@ -1,7 +1,9 @@
1
+ # frozen-string-literal: true
2
+ #
1
3
  # The pg_json_ops extension adds support to Sequel's DSL to make
2
4
  # it easier to call PostgreSQL JSON functions and operators (added
3
5
  # first in PostgreSQL 9.3). It also supports the JSONB functions
4
- # and operators added in PostgreSQL 9.4).
6
+ # and operators added in PostgreSQL 9.4.
5
7
  #
6
8
  # To load the extension:
7
9
  #
@@ -20,10 +22,10 @@
20
22
  # jb = Sequel.pg_jsonb(:jsonb_column)
21
23
  #
22
24
  # Also, on most Sequel expression objects, you can call the pg_json
23
- # or pg_jsonb # method:
25
+ # or pg_jsonb method:
24
26
  #
25
- # j = Sequel.expr(:json_column).pg_json
26
- # jb = Sequel.expr(:jsonb_column).pg_jsonb
27
+ # j = Sequel[:json_column].pg_json
28
+ # jb = Sequel[:jsonb_column].pg_jsonb
27
29
  #
28
30
  # If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
29
31
  # or you have loaded the core_refinements extension
@@ -50,6 +52,7 @@
50
52
  # j.each_text # json_each_text(json_column)
51
53
  # j.keys # json_object_keys(json_column)
52
54
  # j.typeof # json_typeof(json_column)
55
+ # j.strip_nulls # json_strip_nulls(json_column)
53
56
  #
54
57
  # j.populate(:a) # json_populate_record(:a, json_column)
55
58
  # j.populate_set(:a) # json_populate_recordset(:a, json_column)
@@ -58,11 +61,45 @@
58
61
  #
59
62
  # There are additional methods are are only supported on JSONBOp instances:
60
63
  #
61
- # j.contain_all(:a) # (jsonb_column ?& a)
62
- # j.contain_any(:a) # (jsonb_column ?| a)
63
- # j.contains(:h) # (jsonb_column @> h)
64
- # j.contained_by(:h) # (jsonb_column <@ h)
65
- # j.has_key?('a') # (jsonb_column ? 'a')
64
+ # j - 1 # (jsonb_column - 1)
65
+ # j.concat(:h) # (jsonb_column || h)
66
+ # j.contain_all(:a) # (jsonb_column ?& a)
67
+ # j.contain_any(:a) # (jsonb_column ?| a)
68
+ # j.contains(:h) # (jsonb_column @> h)
69
+ # j.contained_by(:h) # (jsonb_column <@ h)
70
+ # j.delete_path(%w'0 a') # (jsonb_column #- ARRAY['0','a'])
71
+ # j.has_key?('a') # (jsonb_column ? 'a')
72
+ # j.insert(%w'0 a', 'a'=>1) # jsonb_insert(jsonb_column, ARRAY[0, 'a'], '{"a":1}'::jsonb, false)
73
+ # j.pretty # jsonb_pretty(jsonb_column)
74
+ # j.set(%w'0 a', :h) # jsonb_set(jsonb_column, ARRAY['0','a'], h, true)
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.
66
103
  #
67
104
  # If you are also using the pg_json extension, you should load it before
68
105
  # loading this extension. Doing so will allow you to use the #op method on
@@ -72,6 +109,9 @@
72
109
  # In order to get the automatic conversion from a ruby array to a PostgreSQL array
73
110
  # (as shown in the #[] and #get_text examples above), you need to load the pg_array
74
111
  # extension.
112
+ #
113
+ # Related modules: Sequel::Postgres::JSONBaseOp, Sequel::Postgres::JSONOp,
114
+ # Sequel::Postgres::JSONBOp
75
115
 
76
116
  #
77
117
  module Sequel
@@ -192,6 +232,13 @@ module Sequel
192
232
  SQL::Function.new(function_name(:populate_recordset), arg, self)
193
233
  end
194
234
 
235
+ # Returns a json value stripped of all internal null values.
236
+ #
237
+ # json_op.strip_nulls # json_strip_nulls(json)
238
+ def strip_nulls
239
+ self.class.new(function(:strip_nulls))
240
+ end
241
+
195
242
  # Builds arbitrary record from json object. You need to define the
196
243
  # structure of the record using #as on the resulting object:
197
244
  #
@@ -266,11 +313,31 @@ module Sequel
266
313
  #
267
314
  # jsonb_op = Sequel.pg_jsonb(:jsonb)
268
315
  class JSONBOp < JSONBaseOp
316
+ CONCAT = ["(".freeze, " || ".freeze, ")".freeze].freeze
269
317
  CONTAIN_ALL = ["(".freeze, " ?& ".freeze, ")".freeze].freeze
270
318
  CONTAIN_ANY = ["(".freeze, " ?| ".freeze, ")".freeze].freeze
271
319
  CONTAINS = ["(".freeze, " @> ".freeze, ")".freeze].freeze
272
320
  CONTAINED_BY = ["(".freeze, " <@ ".freeze, ")".freeze].freeze
321
+ DELETE_PATH = ["(".freeze, " #- ".freeze, ")".freeze].freeze
273
322
  HAS_KEY = ["(".freeze, " ? ".freeze, ")".freeze].freeze
323
+ PATH_EXISTS = ["(".freeze, " @? ".freeze, ")".freeze].freeze
324
+ PATH_MATCH = ["(".freeze, " @@ ".freeze, ")".freeze].freeze
325
+
326
+ # jsonb expression for deletion of the given argument from the
327
+ # current jsonb.
328
+ #
329
+ # jsonb_op - "a" # (jsonb - 'a')
330
+ def -(other)
331
+ self.class.new(super)
332
+ end
333
+
334
+ # jsonb expression for concatenation of the given jsonb into
335
+ # the current jsonb.
336
+ #
337
+ # jsonb_op.concat(:h) # (jsonb || h)
338
+ def concat(other)
339
+ json_op(CONCAT, wrap_input_jsonb(other))
340
+ end
274
341
 
275
342
  # Check if the receiver contains all of the keys in the given array:
276
343
  #
@@ -300,6 +367,13 @@ module Sequel
300
367
  bool_op(CONTAINED_BY, wrap_input_jsonb(other))
301
368
  end
302
369
 
370
+ # Removes the given path from the receiver.
371
+ #
372
+ # jsonb_op.delete_path(:h) # (jsonb #- h)
373
+ def delete_path(other)
374
+ json_op(DELETE_PATH, wrap_input_array(other))
375
+ end
376
+
303
377
  # Check if the receiver contains the given key:
304
378
  #
305
379
  # jsonb_op.has_key?('a') # (jsonb ? 'a')
@@ -308,13 +382,176 @@ module Sequel
308
382
  end
309
383
  alias include? has_key?
310
384
 
385
+ # Inserts the given jsonb value at the given path in the receiver.
386
+ # The default is to insert the value before the given path, but
387
+ # insert_after can be set to true to insert it after the given path.
388
+ #
389
+ # jsonb_op.insert(['a', 'b'], h) # jsonb_insert(jsonb, ARRAY['a', 'b'], h, false)
390
+ # jsonb_op.insert(['a', 'b'], h, true) # jsonb_insert(jsonb, ARRAY['a', 'b'], h, true)
391
+ def insert(path, other, insert_after=false)
392
+ self.class.new(function(:insert, wrap_input_array(path), wrap_input_jsonb(other), insert_after))
393
+ end
394
+
395
+ # Returns whether the JSON path returns any item for the json object.
396
+ #
397
+ # json_op.path_exists("$.foo") # (json @? '$.foo')
398
+ def path_exists(path)
399
+ bool_op(PATH_EXISTS, path)
400
+ end
401
+
402
+ # Returns whether the JSON path returns any item for the json object.
403
+ #
404
+ # json_op.path_exists!("$.foo")
405
+ # # jsonb_path_exists(json, '$.foo')
406
+ #
407
+ # json_op.path_exists!("$.foo ? ($ > $x)", x: 2)
408
+ # # jsonb_path_exists(json, '$.foo ? ($ > $x)', '{"x":2}')
409
+ #
410
+ # json_op.path_exists!("$.foo ? ($ > $x)", {x: 2}, true)
411
+ # # jsonb_path_exists(json, '$.foo ? ($ > $x)', '{"x":2}', true)
412
+ def path_exists!(path, vars=nil, silent=nil)
413
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists, path, vars, silent))
414
+ end
415
+
416
+ # The same as #path_exists!, except that timezone-aware conversions are used for date/time values.
417
+ def path_exists_tz!(path, vars=nil, silent=nil)
418
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists_tz, path, vars, silent))
419
+ end
420
+
421
+ # Returns the first item of the result of JSON path predicate check for the json object.
422
+ # Returns nil if the first item is not true or false.
423
+ #
424
+ # json_op.path_match("$.foo") # (json @@ '$.foo')
425
+ def path_match(path)
426
+ bool_op(PATH_MATCH, path)
427
+ end
428
+
429
+ # Returns the first item of the result of JSON path predicate check for the json object.
430
+ # Returns nil if the first item is not true or false and silent is true.
431
+ #
432
+ # json_op.path_match!("$.foo")
433
+ # # jsonb_path_match(json, '$.foo')
434
+ #
435
+ # json_op.path_match!("$.foo ? ($ > $x)", x: 2)
436
+ # # jsonb_path_match(json, '$.foo ? ($ > $x)', '{"x":2}')
437
+ #
438
+ # json_op.path_match!("$.foo ? ($ > $x)", {x: 2}, true)
439
+ # # jsonb_path_match(json, '$.foo ? ($ > $x)', '{"x":2}', true)
440
+ def path_match!(path, vars=nil, silent=nil)
441
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match, path, vars, silent))
442
+ end
443
+
444
+ # The same as #path_match!, except that timezone-aware conversions are used for date/time values.
445
+ def path_match_tz!(path, vars=nil, silent=nil)
446
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match_tz, path, vars, silent))
447
+ end
448
+
449
+ # Returns a set of all jsonb values specified by the JSON path
450
+ # for the json object.
451
+ #
452
+ # json_op.path_query("$.foo")
453
+ # # jsonb_path_query(json, '$.foo')
454
+ #
455
+ # json_op.path_query("$.foo ? ($ > $x)", x: 2)
456
+ # # jsonb_path_query(json, '$.foo ? ($ > $x)', '{"x":2}')
457
+ #
458
+ # json_op.path_query("$.foo ? ($ > $x)", {x: 2}, true)
459
+ # # jsonb_path_query(json, '$.foo ? ($ > $x)', '{"x":2}', true)
460
+ def path_query(path, vars=nil, silent=nil)
461
+ _path_function(:jsonb_path_query, path, vars, silent)
462
+ end
463
+
464
+ # The same as #path_query, except that timezone-aware conversions are used for date/time values.
465
+ def path_query_tz(path, vars=nil, silent=nil)
466
+ _path_function(:jsonb_path_query_tz, path, vars, silent)
467
+ end
468
+
469
+ # Returns a jsonb array of all values specified by the JSON path
470
+ # for the json object.
471
+ #
472
+ # json_op.path_query_array("$.foo")
473
+ # # jsonb_path_query_array(json, '$.foo')
474
+ #
475
+ # json_op.path_query_array("$.foo ? ($ > $x)", x: 2)
476
+ # # jsonb_path_query_array(json, '$.foo ? ($ > $x)', '{"x":2}')
477
+ #
478
+ # json_op.path_query_array("$.foo ? ($ > $x)", {x: 2}, true)
479
+ # # jsonb_path_query_array(json, '$.foo ? ($ > $x)', '{"x":2}', true)
480
+ def path_query_array(path, vars=nil, silent=nil)
481
+ JSONBOp.new(_path_function(:jsonb_path_query_array, path, vars, silent))
482
+ end
483
+
484
+ # The same as #path_query_array, except that timezone-aware conversions are used for date/time values.
485
+ def path_query_array_tz(path, vars=nil, silent=nil)
486
+ JSONBOp.new(_path_function(:jsonb_path_query_array_tz, path, vars, silent))
487
+ end
488
+
489
+ # Returns the first item of the result specified by the JSON path
490
+ # for the json object.
491
+ #
492
+ # json_op.path_query_first("$.foo")
493
+ # # jsonb_path_query_first(json, '$.foo')
494
+ #
495
+ # json_op.path_query_first("$.foo ? ($ > $x)", x: 2)
496
+ # # jsonb_path_query_first(json, '$.foo ? ($ > $x)', '{"x":2}')
497
+ #
498
+ # json_op.path_query_first("$.foo ? ($ > $x)", {x: 2}, true)
499
+ # # jsonb_path_query_first(json, '$.foo ? ($ > $x)', '{"x":2}', true)
500
+ def path_query_first(path, vars=nil, silent=nil)
501
+ JSONBOp.new(_path_function(:jsonb_path_query_first, path, vars, silent))
502
+ end
503
+
504
+ # The same as #path_query_first, except that timezone-aware conversions are used for date/time values.
505
+ def path_query_first_tz(path, vars=nil, silent=nil)
506
+ JSONBOp.new(_path_function(:jsonb_path_query_first_tz, path, vars, silent))
507
+ end
508
+
311
509
  # Return the receiver, since it is already a JSONBOp.
312
510
  def pg_jsonb
313
511
  self
314
512
  end
315
513
 
514
+ # Return a pretty printed version of the receiver as a string expression.
515
+ #
516
+ # jsonb_op.pretty # jsonb_pretty(jsonb)
517
+ def pretty
518
+ Sequel::SQL::StringExpression.new(:NOOP, function(:pretty))
519
+ end
520
+
521
+ # Set the given jsonb value at the given path in the receiver.
522
+ # By default, this will create the value if it does not exist, but
523
+ # create_missing can be set to false to not create a new value.
524
+ #
525
+ # jsonb_op.set(['a', 'b'], h) # jsonb_set(jsonb, ARRAY['a', 'b'], h, true)
526
+ # jsonb_op.set(['a', 'b'], h, false) # jsonb_set(jsonb, ARRAY['a', 'b'], h, false)
527
+ def set(path, other, create_missing=true)
528
+ self.class.new(function(:set, wrap_input_array(path), wrap_input_jsonb(other), create_missing))
529
+ end
530
+
531
+ # The same as #set, except if +other+ is +nil+, then behaves according to +null_value_treatment+,
532
+ # which can be one of 'raise_exception', 'use_json_null' (default), 'delete_key', or 'return_target'.
533
+ def set_lax(path, other, create_missing=true, null_value_treatment='use_json_null')
534
+ self.class.new(function(:set_lax, wrap_input_array(path), wrap_input_jsonb(other), create_missing, null_value_treatment))
535
+ end
536
+
316
537
  private
317
538
 
539
+ # Internals of the jsonb SQL/JSON path functions.
540
+ def _path_function(func, path, vars, silent)
541
+ args = []
542
+ if vars
543
+ if vars.is_a?(Hash)
544
+ vars = vars.to_json
545
+ end
546
+ args << vars
547
+
548
+ unless silent.nil?
549
+ args << silent
550
+ end
551
+ end
552
+ SQL::Function.new(func, self, path, *args)
553
+ end
554
+
318
555
  # Return a placeholder literal with the given str and args, wrapped
319
556
  # in a boolean expression, used by operators that return booleans.
320
557
  def bool_op(str, other)
@@ -359,7 +596,9 @@ module Sequel
359
596
  end
360
597
  end
361
598
 
599
+ # :nocov:
362
600
  if defined?(JSONArray)
601
+ # :nocov:
363
602
  class JSONArray
364
603
  # Wrap the JSONArray instance in an JSONOp, allowing you to easily use
365
604
  # the PostgreSQL json functions and operators with literal jsons.
@@ -1,3 +1,5 @@
1
+ # frozen-string-literal: true
2
+ #
1
3
  # The pg_loose_count extension looks at the table statistics
2
4
  # in the PostgreSQL system tables to get a fast approximate
3
5
  # count of the number of rows in a given table:
@@ -6,7 +8,7 @@
6
8
  #
7
9
  # It can also support schema qualified tables:
8
10
  #
9
- # DB.loose_count(:schema__table) # => 123456
11
+ # DB.loose_count(Sequel[:schema][:table]) # => 123456
10
12
  #
11
13
  # How accurate this count is depends on the number of rows
12
14
  # added/deleted from the table since the last time it was
@@ -15,6 +17,8 @@
15
17
  # To load the extension into the database:
16
18
  #
17
19
  # DB.extension :pg_loose_count
20
+ #
21
+ # Related module: Sequel::Postgres::LooseCount
18
22
 
19
23
  #
20
24
  module Sequel
@@ -1,3 +1,5 @@
1
+ # frozen-string-literal: true
2
+ #
1
3
  # The pg_range extension adds support for the PostgreSQL 9.2+ range
2
4
  # types to Sequel. PostgreSQL range types are similar to ruby's
3
5
  # Range class, representating an array of values. However, they
@@ -38,100 +40,43 @@
38
40
  # If you specify the range database type, Sequel will automatically cast
39
41
  # the value to that type when literalizing.
40
42
  #
41
- # If you would like to use range columns in your model objects, you
42
- # probably want to modify the schema parsing/typecasting so that it
43
- # recognizes and correctly handles the range type columns, which you can
44
- # do by:
43
+ # To use this extension, load it into the Database instance:
45
44
  #
46
45
  # DB.extension :pg_range
47
46
  #
48
- # If you are not using the native postgres or jdbc/postgresql adapters and are using range
49
- # types as model column values you probably should use the
50
- # pg_typecast_on_load plugin if the column values are returned as a string.
51
- #
52
47
  # See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
53
48
  # for details on using range type columns in CREATE/ALTER TABLE statements.
54
49
  #
50
+ # This extension makes it easy to add support for other range types. In
51
+ # general, you just need to make sure that the subtype is handled and has the
52
+ # appropriate converter installed. For user defined
53
+ # types, you can do this via:
54
+ #
55
+ # DB.add_conversion_proc(subtype_oid){|string| }
56
+ #
57
+ # Then you can call
58
+ # Sequel::Postgres::PGRange::DatabaseMethods#register_range_type
59
+ # to automatically set up a handler for the range type. So if you
60
+ # want to support the timerange type (assuming the time type is already
61
+ # supported):
62
+ #
63
+ # DB.register_range_type('timerange')
64
+ #
55
65
  # This extension integrates with the pg_array extension. If you plan
56
66
  # to use arrays of range types, load the pg_array extension before the
57
67
  # pg_range extension:
58
68
  #
59
69
  # DB.extension :pg_array, :pg_range
60
-
61
- Sequel.require 'adapters/utils/pg_types'
70
+ #
71
+ # Related module: Sequel::Postgres::PGRange
62
72
 
63
73
  module Sequel
64
74
  module Postgres
65
75
  class PGRange
66
76
  include Sequel::SQL::AliasMethods
67
77
 
68
- # Map of string database type names to type symbols (e.g. 'int4range' => :int4range),
69
- # used in the schema parsing.
70
- RANGE_TYPES = {}
71
-
72
- EMPTY = 'empty'.freeze
73
- EMPTY_STRING = ''.freeze
74
- COMMA = ','.freeze
75
- QUOTED_EMPTY_STRING = '""'.freeze
76
- OPEN_PAREN = "(".freeze
77
- CLOSE_PAREN = ")".freeze
78
- OPEN_BRACKET = "[".freeze
79
- CLOSE_BRACKET = "]".freeze
80
- ESCAPE_RE = /("|,|\\|\[|\]|\(|\))/.freeze
81
- ESCAPE_REPLACE = '\\\\\1'.freeze
82
- CAST = '::'.freeze
83
-
84
- # Registers a range type that the extension should handle. Makes a Database instance that
85
- # has been extended with DatabaseMethods recognize the range type given and set up the
86
- # appropriate typecasting. Also sets up automatic typecasting for the native postgres
87
- # adapter, so that on retrieval, the values are automatically converted to PGRange instances.
88
- # The db_type argument should be the name of the range type. Accepts the following options:
89
- #
90
- # :converter :: A callable object (e.g. Proc), that is called with the start or end of the range
91
- # (usually a string), and should return the appropriate typecasted object.
92
- # :oid :: The PostgreSQL OID for the range type. This is used by the Sequel postgres adapter
93
- # to set up automatic type conversion on retrieval from the database.
94
- # :subtype_oid :: Should be the PostgreSQL OID for the range's subtype. If given,
95
- # automatically sets the :converter option by looking for scalar conversion
96
- # proc.
97
- #
98
- # If a block is given, it is treated as the :converter option.
99
- def self.register(db_type, opts=OPTS, &block)
100
- db_type = db_type.to_s.dup.freeze
101
-
102
- if converter = opts[:converter]
103
- raise Error, "can't provide both a block and :converter option to register" if block
104
- else
105
- converter = block
106
- end
107
-
108
- if soid = opts[:subtype_oid]
109
- raise Error, "can't provide both a converter and :scalar_oid option to register" if converter
110
- raise Error, "no conversion proc for :scalar_oid=>#{soid.inspect} in PG_TYPES" unless converter = PG_TYPES[soid]
111
- end
112
-
113
- parser = Parser.new(db_type, converter)
114
-
115
- RANGE_TYPES[db_type] = db_type.to_sym
116
-
117
- DatabaseMethods.define_range_typecast_method(db_type, parser)
118
-
119
- if oid = opts[:oid]
120
- Sequel::Postgres::PG_TYPES[oid] = parser
121
- end
122
-
123
- nil
124
- end
125
-
126
78
  # Creates callable objects that convert strings into PGRange instances.
127
79
  class Parser
128
- # Regexp that parses the full range of PostgreSQL range type output,
129
- # except for empty ranges.
130
- PARSER = /\A(\[|\()("((?:\\"|[^"])*)"|[^"]*),("((?:\\"|[^"])*)"|[^"]*)(\]|\))\z/o
131
-
132
- REPLACE_RE = /\\(.)/.freeze
133
- REPLACE_WITH = '\1'.freeze
134
-
135
80
  # The database range type for this parser (e.g. 'int4range'),
136
81
  # automatically setting the db_type for the returned PGRange instances.
137
82
  attr_reader :db_type
@@ -148,11 +93,11 @@ module Sequel
148
93
 
149
94
  # Parse the range type input string into a PGRange value.
150
95
  def call(string)
151
- if string == EMPTY
96
+ if string == 'empty'
152
97
  return PGRange.empty(db_type)
153
98
  end
154
99
 
155
- raise(InvalidValue, "invalid or unhandled range format: #{string.inspect}") unless matches = PARSER.match(string)
100
+ raise(InvalidValue, "invalid or unhandled range format: #{string.inspect}") unless matches = /\A(\[|\()("((?:\\"|[^"])*)"|[^"]*),("((?:\\"|[^"])*)"|[^"]*)(\]|\))\z/.match(string)
156
101
 
157
102
  exclude_begin = matches[1] == '('
158
103
  exclude_end = matches[6] == ')'
@@ -166,12 +111,12 @@ module Sequel
166
111
  # to always use the quoted output form when characters need to be escaped, so
167
112
  # there isn't a need to unescape unquoted output.
168
113
  if beg = matches[3]
169
- beg.gsub!(REPLACE_RE, REPLACE_WITH)
114
+ beg.gsub!(/\\(.)/, '\1')
170
115
  else
171
116
  beg = matches[2] unless matches[2].empty?
172
117
  end
173
118
  if en = matches[5]
174
- en.gsub!(REPLACE_RE, REPLACE_WITH)
119
+ en.gsub!(/\\(.)/, '\1')
175
120
  else
176
121
  en = matches[4] unless matches[4].empty?
177
122
  end
@@ -186,33 +131,38 @@ module Sequel
186
131
  end
187
132
 
188
133
  module DatabaseMethods
189
- # Reset the conversion procs if using the native postgres adapter,
134
+ # Add the conversion procs to the database
190
135
  # and extend the datasets to correctly literalize ruby Range values.
191
136
  def self.extended(db)
192
- db.instance_eval do
137
+ db.instance_exec do
138
+ @pg_range_schema_types ||= {}
193
139
  extend_datasets(DatasetMethods)
194
- copy_conversion_procs([3904, 3906, 3912, 3926, 3905, 3907, 3913, 3927])
140
+ register_range_type('int4range', :oid=>3904, :subtype_oid=>23)
141
+ register_range_type('numrange', :oid=>3906, :subtype_oid=>1700)
142
+ register_range_type('tsrange', :oid=>3908, :subtype_oid=>1114)
143
+ register_range_type('tstzrange', :oid=>3910, :subtype_oid=>1184)
144
+ register_range_type('daterange', :oid=>3912, :subtype_oid=>1082)
145
+ register_range_type('int8range', :oid=>3926, :subtype_oid=>20)
146
+ if respond_to?(:register_array_type)
147
+ register_array_type('int4range', :oid=>3905, :scalar_oid=>3904, :scalar_typecast=>:int4range)
148
+ register_array_type('numrange', :oid=>3907, :scalar_oid=>3906, :scalar_typecast=>:numrange)
149
+ register_array_type('tsrange', :oid=>3909, :scalar_oid=>3908, :scalar_typecast=>:tsrange)
150
+ register_array_type('tstzrange', :oid=>3911, :scalar_oid=>3910, :scalar_typecast=>:tstzrange)
151
+ register_array_type('daterange', :oid=>3913, :scalar_oid=>3912, :scalar_typecast=>:daterange)
152
+ register_array_type('int8range', :oid=>3927, :scalar_oid=>3926, :scalar_typecast=>:int8range)
153
+ end
195
154
  [:int4range, :numrange, :tsrange, :tstzrange, :daterange, :int8range].each do |v|
196
155
  @schema_type_classes[v] = PGRange
197
156
  end
198
- end
199
157
 
200
- procs = db.conversion_procs
201
- procs[3908] = Parser.new("tsrange", procs[1114])
202
- procs[3910] = Parser.new("tstzrange", procs[1184])
203
- if defined?(PGArray::Creator)
204
- procs[3909] = PGArray::Creator.new("tsrange", procs[3908])
205
- procs[3911] = PGArray::Creator.new("tstzrange", procs[3910])
158
+ procs = conversion_procs
159
+ add_conversion_proc(3908, Parser.new("tsrange", procs[1114]))
160
+ add_conversion_proc(3910, Parser.new("tstzrange", procs[1184]))
161
+ if respond_to?(:register_array_type) && defined?(PGArray::Creator)
162
+ add_conversion_proc(3909, PGArray::Creator.new("tsrange", procs[3908]))
163
+ add_conversion_proc(3911, PGArray::Creator.new("tstzrange", procs[3910]))
164
+ end
206
165
  end
207
-
208
- end
209
-
210
- # Define a private range typecasting method for the given type that uses
211
- # the parser argument to do the type conversion.
212
- def self.define_range_typecast_method(type, parser)
213
- meth = :"typecast_value_#{type}"
214
- define_method(meth){|v| typecast_value_pg_range(v, parser)}
215
- private meth
216
166
  end
217
167
 
218
168
  # Handle Range and PGRange values in bound variables
@@ -227,6 +177,64 @@ module Sequel
227
177
  end
228
178
  end
229
179
 
180
+ # Freeze the pg range schema types to prevent adding new ones.
181
+ def freeze
182
+ @pg_range_schema_types.freeze
183
+ super
184
+ end
185
+
186
+ # Register a database specific range type. This can be used to support
187
+ # different range types per Database. Options:
188
+ #
189
+ # :converter :: A callable object (e.g. Proc), that is called with the start or end of the range
190
+ # (usually a string), and should return the appropriate typecasted object.
191
+ # :oid :: The PostgreSQL OID for the range type. This is used by the Sequel postgres adapter
192
+ # to set up automatic type conversion on retrieval from the database.
193
+ # :subtype_oid :: Should be the PostgreSQL OID for the range's subtype. If given,
194
+ # automatically sets the :converter option by looking for scalar conversion
195
+ # proc.
196
+ #
197
+ # If a block is given, it is treated as the :converter option.
198
+ def register_range_type(db_type, opts=OPTS, &block)
199
+ oid = opts[:oid]
200
+ soid = opts[:subtype_oid]
201
+
202
+ if has_converter = opts.has_key?(:converter)
203
+ raise Error, "can't provide both a block and :converter option to register_range_type" if block
204
+ converter = opts[:converter]
205
+ else
206
+ has_converter = true if block
207
+ converter = block
208
+ end
209
+
210
+ unless (soid || has_converter) && oid
211
+ range_oid, subtype_oid = from(:pg_range).join(:pg_type, :oid=>:rngtypid).where(:typname=>db_type.to_s).get([:rngtypid, :rngsubtype])
212
+ soid ||= subtype_oid unless has_converter
213
+ oid ||= range_oid
214
+ end
215
+
216
+ db_type = db_type.to_s.dup.freeze
217
+
218
+ if soid
219
+ raise Error, "can't provide both a converter and :subtype_oid option to register" if has_converter
220
+ raise Error, "no conversion proc for :subtype_oid=>#{soid.inspect} in conversion_procs" unless converter = conversion_procs[soid]
221
+ end
222
+
223
+ parser = Parser.new(db_type, converter)
224
+ add_conversion_proc(oid, parser)
225
+
226
+ @pg_range_schema_types[db_type] = db_type.to_sym
227
+
228
+ singleton_class.class_eval do
229
+ meth = :"typecast_value_#{db_type}"
230
+ define_method(meth){|v| typecast_value_pg_range(v, parser)}
231
+ private meth
232
+ end
233
+
234
+ @schema_type_classes[:"#{opts[:type_symbol] || db_type}"] = PGRange
235
+ nil
236
+ end
237
+
230
238
  private
231
239
 
232
240
  # Handle arrays of range types in bound variables.
@@ -239,31 +247,29 @@ module Sequel
239
247
  end
240
248
  end
241
249
 
242
- # Manually override the typecasting for tsrange and tstzrange types so that
243
- # they use the database's timezone instead of the global Sequel
244
- # timezone.
245
- def get_conversion_procs
246
- procs = super
247
-
248
- procs[3908] = Parser.new("tsrange", procs[1114])
249
- procs[3910] = Parser.new("tstzrange", procs[1184])
250
- if defined?(PGArray::Creator)
251
- procs[3909] = PGArray::Creator.new("tsrange", procs[3908])
252
- procs[3911] = PGArray::Creator.new("tstzrange", procs[3910])
253
- end
254
-
255
- procs
256
- end
257
-
258
250
  # Recognize the registered database range types.
259
251
  def schema_column_type(db_type)
260
- if type = RANGE_TYPES[db_type]
252
+ if type = @pg_range_schema_types[db_type]
261
253
  type
262
254
  else
263
255
  super
264
256
  end
265
257
  end
266
258
 
259
+ # Set the :ruby_default value if the default value is recognized as a range.
260
+ def schema_post_process(_)
261
+ super.each do |a|
262
+ h = a[1]
263
+ db_type = h[:db_type]
264
+ if @pg_range_schema_types[db_type] && h[:default] =~ /\A'([^']+)'::#{db_type}\z/
265
+ default = $1
266
+ if convertor = conversion_procs[h[:oid]]
267
+ h[:ruby_default] = convertor.call(default)
268
+ end
269
+ end
270
+ end
271
+ end
272
+
267
273
  # Typecast value correctly to a PGRange. If already an
268
274
  # PGRange instance with the same db_type, return as is.
269
275
  # If a PGRange with a different subtype, return a new
@@ -292,6 +298,8 @@ module Sequel
292
298
  end
293
299
 
294
300
  module DatasetMethods
301
+ private
302
+
295
303
  # Handle literalization of ruby Range objects, treating them as
296
304
  # PostgreSQL ranges.
297
305
  def literal_other_append(sql, v)
@@ -346,11 +354,20 @@ module Sequel
346
354
 
347
355
  # Delegate to the ruby range object so that the object mostly acts like a range.
348
356
  range_methods = %w'each last first step'
349
- range_methods << 'cover?' if RUBY_VERSION >= '1.9'
350
357
  range_methods.each do |m|
351
358
  class_eval("def #{m}(*a, &block) to_range.#{m}(*a, &block) end", __FILE__, __LINE__)
352
359
  end
353
360
 
361
+ # Return whether the value is inside the range.
362
+ def cover?(value)
363
+ return false if empty?
364
+ b = self.begin
365
+ return false if b && b.public_send(exclude_begin? ? :>= : :>, value)
366
+ e = self.end
367
+ return false if e && e.public_send(exclude_end? ? :<= : :<, value)
368
+ true
369
+ end
370
+
354
371
  # Consider the receiver equal to other PGRange instances with the
355
372
  # same beginning, ending, exclusions, and database type. Also consider
356
373
  # it equal to Range instances if this PGRange can be converted to a
@@ -381,6 +398,15 @@ module Sequel
381
398
  end
382
399
  alias == eql?
383
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
+
384
410
  # Allow PGRange values in case statements, where they return true if they
385
411
  # are equal to each other using eql?, or if this PGRange can be converted
386
412
  # to a Range, delegating to that range.
@@ -416,28 +442,33 @@ module Sequel
416
442
  # Append a literalize version of the receiver to the sql.
417
443
  def sql_literal_append(ds, sql)
418
444
  if (s = @db_type) && !empty?
419
- sql << s.to_s << OPEN_PAREN
445
+ sql << s.to_s << "("
420
446
  ds.literal_append(sql, self.begin)
421
- sql << COMMA
447
+ sql << ','
422
448
  ds.literal_append(sql, self.end)
423
- sql << COMMA
424
- ds.literal_append(sql, "#{exclude_begin? ? OPEN_PAREN : OPEN_BRACKET}#{exclude_end? ? CLOSE_PAREN : CLOSE_BRACKET}")
425
- sql << CLOSE_PAREN
449
+ sql << ','
450
+ ds.literal_append(sql, "#{exclude_begin? ? "(" : "["}#{exclude_end? ? ")" : "]"}")
451
+ sql << ")"
426
452
  else
427
453
  ds.literal_append(sql, unquoted_literal(ds))
428
454
  if s
429
- sql << CAST << s.to_s
455
+ sql << '::' << s.to_s
430
456
  end
431
457
  end
432
458
  end
433
459
 
460
+ ENDLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.6'
461
+ STARTLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.7'
462
+
434
463
  # Return a ruby Range object for this instance, if one can be created.
435
464
  def to_range
436
465
  return @range if @range
437
466
  raise(Error, "cannot create ruby range for an empty PostgreSQL range") if empty?
438
467
  raise(Error, "cannot create ruby range when PostgreSQL range excludes beginning element") if exclude_begin?
439
- raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") unless self.begin
440
- raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") unless self.end
468
+ # :nocov:
469
+ raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") if STARTLESS_RANGE_NOT_SUPPORTED && !self.begin
470
+ raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") if ENDLESS_RANGE_NOT_SUPPORTED && !self.end
471
+ # :nocov:
441
472
  @range = Range.new(self.begin, self.end, exclude_end?)
442
473
  end
443
474
 
@@ -445,7 +476,7 @@ module Sequel
445
476
  # it must have a beginning and an ending (no unbounded ranges), and it cannot exclude
446
477
  # the beginning element.
447
478
  def valid_ruby_range?
448
- !(empty? || exclude_begin? || !self.begin || !self.end)
479
+ !(empty? || exclude_begin? || (STARTLESS_RANGE_NOT_SUPPORTED && !self.begin) || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end))
449
480
  end
450
481
 
451
482
  # Whether the beginning of the range is unbounded.
@@ -462,9 +493,9 @@ module Sequel
462
493
  # Separated out for use by the bound argument code.
463
494
  def unquoted_literal(ds)
464
495
  if empty?
465
- EMPTY
496
+ 'empty'
466
497
  else
467
- "#{exclude_begin? ? OPEN_PAREN : OPEN_BRACKET}#{escape_value(self.begin, ds)},#{escape_value(self.end, ds)}#{exclude_end? ? CLOSE_PAREN : CLOSE_BRACKET}"
498
+ "#{exclude_begin? ? "(" : "["}#{escape_value(self.begin, ds)},#{escape_value(self.end, ds)}#{exclude_end? ? ")" : "]"}"
468
499
  end
469
500
  end
470
501
 
@@ -475,7 +506,7 @@ module Sequel
475
506
  def escape_value(k, ds)
476
507
  case k
477
508
  when nil
478
- EMPTY_STRING
509
+ ''
479
510
  when Date, Time
480
511
  ds.literal(k)[1...-1]
481
512
  when Integer, Float
@@ -486,30 +517,15 @@ module Sequel
486
517
  k
487
518
  when String
488
519
  if k.empty?
489
- QUOTED_EMPTY_STRING
520
+ '""'
490
521
  else
491
- k.gsub(ESCAPE_RE, ESCAPE_REPLACE)
522
+ k.gsub(/("|,|\\|\[|\]|\(|\))/, '\\\\\1')
492
523
  end
493
524
  else
494
- ds.literal(k).gsub(ESCAPE_RE, ESCAPE_REPLACE)
525
+ ds.literal(k).gsub(/("|,|\\|\[|\]|\(|\))/, '\\\\\1')
495
526
  end
496
527
  end
497
528
  end
498
-
499
- PGRange.register('int4range', :oid=>3904, :subtype_oid=>23)
500
- PGRange.register('numrange', :oid=>3906, :subtype_oid=>1700)
501
- PGRange.register('tsrange', :oid=>3908, :subtype_oid=>1114)
502
- PGRange.register('tstzrange', :oid=>3910, :subtype_oid=>1184)
503
- PGRange.register('daterange', :oid=>3912, :subtype_oid=>1082)
504
- PGRange.register('int8range', :oid=>3926, :subtype_oid=>20)
505
- if defined?(PGArray) && PGArray.respond_to?(:register)
506
- PGArray.register('int4range', :oid=>3905, :scalar_oid=>3904, :scalar_typecast=>:int4range)
507
- PGArray.register('numrange', :oid=>3907, :scalar_oid=>3906, :scalar_typecast=>:numrange)
508
- PGArray.register('tsrange', :oid=>3909, :scalar_oid=>3908, :scalar_typecast=>:tsrange)
509
- PGArray.register('tstzrange', :oid=>3911, :scalar_oid=>3910, :scalar_typecast=>:tstzrange)
510
- PGArray.register('daterange', :oid=>3913, :scalar_oid=>3912, :scalar_typecast=>:daterange)
511
- PGArray.register('int8range', :oid=>3927, :scalar_oid=>3926, :scalar_typecast=>:int8range)
512
- end
513
529
  end
514
530
 
515
531
  module SQL::Builders