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
@@ -1,44 +1,99 @@
1
1
  # frozen-string-literal: true
2
2
  #
3
3
  # The pg_json extension adds support for Sequel to handle
4
- # PostgreSQL's json and jsonb types. It is slightly more strict than the
5
- # PostgreSQL json types in that the object returned should be an
6
- # array or object (PostgreSQL's json type considers plain numbers
7
- # strings, true, false, and null as valid). Sequel will work with
8
- # PostgreSQL json values that are not arrays or objects, but support
9
- # is fairly limited and the values do not roundtrip.
4
+ # PostgreSQL's json and jsonb types. By default, it wraps
5
+ # JSON arrays and JSON objects with ruby array-like and
6
+ # hash-like objects. If you would like to wrap JSON primitives
7
+ # (numbers, strings, +null+, +true+, and +false+), you need to
8
+ # use the +wrap_json_primitives+ setter:
10
9
  #
11
- # This extension integrates with Sequel's native postgres and jdbc/postgresql adapters, so
12
- # that when json fields are retrieved, they are parsed and returned
13
- # as instances of Sequel::Postgres::JSONArray or
14
- # Sequel::Postgres::JSONHash (or JSONBArray or JSONBHash for jsonb
15
- # columns). JSONArray and JSONHash are
16
- # DelegateClasses of Array and Hash, so they mostly act the same, but
17
- # not completely (json_array.is_a?(Array) is false). If you want
18
- # the actual array for a JSONArray, call JSONArray#to_a. If you want
19
- # the actual hash for a JSONHash, call JSONHash#to_hash.
20
- # This is done so that Sequel does not treat JSONArray and JSONHash
21
- # like Array and Hash by default, which would cause issues.
10
+ # DB.extension :pg_json
11
+ # DB.wrap_json_primitives = true
12
+ #
13
+ # Note that wrapping JSON primitives changes the behavior for
14
+ # JSON false and null values. Because only +false+ and +nil+
15
+ # in Ruby are considered falsey, wrapping these objects results
16
+ # in unexpected behavior if you use the values directly in
17
+ # conditionals:
18
+ #
19
+ # if DB[:table].get(:json_column)
20
+ # # called if the value of json_column is null/false
21
+ # # if you are wrapping primitives
22
+ # end
23
+ #
24
+ # To extract the Ruby primitive object from the wrapper object,
25
+ # you can use +__getobj__+ (this comes from Ruby's delegate library).
22
26
  #
23
- # To turn an existing Array or Hash into a JSONArray or JSONHash,
24
- # use Sequel.pg_json:
27
+ # To wrap an existing Ruby array, hash, string, integer, float,
28
+ # +nil+, +true+, or +false+, use +Sequel.pg_json_wrap+ or +Sequel.pg_jsonb_wrap+:
29
+ #
30
+ # Sequel.pg_json_wrap(object) # json type
31
+ # Sequel.pg_jsonb_wrap(object) # jsonb type
32
+ #
33
+ # So if you want to insert an array or hash into an json database column:
25
34
  #
26
- # Sequel.pg_json(array) # or Sequel.pg_jsonb(array) for jsonb type
27
- # Sequel.pg_json(hash) # or Sequel.pg_jsonb(hash) for jsonb type
35
+ # DB[:table].insert(column: Sequel.pg_json_wrap([1, 2, 3]))
36
+ # DB[:table].insert(column: Sequel.pg_json_wrap({'a'=>1, 'b'=>2}))
37
+ #
38
+ # Note that the +pg_json_wrap+ and +pg_jsonb_wrap+ methods only handle Ruby primitives,
39
+ # they do not handle already wrapped objects.
28
40
  #
29
41
  # If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
30
42
  # or you have loaded the core_refinements extension
31
- # and have activated refinements for the file, you can also use Array#pg_json and Hash#pg_json:
43
+ # and have activated refinements for the file, you can also use the
44
+ # +pg_json+ and +pg_jsonb+ methods directly on Array or Hash:
32
45
  #
33
- # array.pg_json # or array.pg_jsonb for jsonb type
34
- # hash.pg_json # or hash.pg_jsonb for jsonb type
46
+ # array.pg_json # json type
47
+ # array.pg_jsonb # jsonb type
35
48
  #
36
- # So if you want to insert an array or hash into an json database column:
49
+ # hash.pg_json # json type
50
+ # hash.pg_jsonb # jsonb type
51
+ #
52
+ # Model classes that use json or jsonb columns will have typecasting automatically
53
+ # setup, so you can assign Ruby primitives to model columns and have the wrapped
54
+ # objects automatically created. However, for backwards compatibility, passing
55
+ # a string object will parse the string as JSON, not create a JSON string object.
56
+ #
57
+ # obj = Model.new
58
+ # obj.json_column = {'a'=>'b'}
59
+ # obj.json_column.class
60
+ # # => Sequel::Postgres::JSONHash
61
+ # obj.json_column['a']
62
+ # # => 'b'
63
+ #
64
+ # obj.json_column = '{"a": "b"}'
65
+ # obj.json_column.class
66
+ # # => Sequel::Postgres::JSONHash
67
+ # obj.json_column['a']
68
+ # # => 'b'
69
+ #
70
+ # You can change the handling of string typecasting by using +typecast_json_strings+:
71
+ #
72
+ # DB.typecast_json_strings = true
73
+ # obj.json_column = '{"a": "b"}'
74
+ # obj.json_column.class
75
+ # # => Sequel::Postgres::JSONString
76
+ # obj.json_column
77
+ # # => '{"a": "b"}'
37
78
  #
38
- # DB[:table].insert(column: Sequel.pg_json([1, 2, 3]))
39
- # DB[:table].insert(column: Sequel.pg_json({'a'=>1, 'b'=>2}))
79
+ # Note that +nil+ values are never automatically wrapped:
40
80
  #
41
- # To use this extension, please load it into the Database instance:
81
+ # obj.json_column = nil
82
+ # obj.json_column.class
83
+ # # => NilClass
84
+ # obj.json_column
85
+ # # => nil
86
+ #
87
+ # If you want to set a JSON null value when using a model, you must wrap it
88
+ # explicitly:
89
+ #
90
+ # obj.json_column = Sequel.pg_json_wrap(nil)
91
+ # obj.json_column.class
92
+ # # => Sequel::Postgres::JSONNull
93
+ # obj.json_column
94
+ # # => nil
95
+ #
96
+ # To use this extension, load it into the Database instance:
42
97
  #
43
98
  # DB.extension :pg_json
44
99
  #
@@ -46,7 +101,7 @@
46
101
  # for details on using json columns in CREATE/ALTER TABLE statements.
47
102
  #
48
103
  # This extension integrates with the pg_array extension. If you plan
49
- # to use the json[] type, load the pg_array extension before the
104
+ # to use the json[] or jsonb[] types, load the pg_array extension before the
50
105
  # pg_json extension:
51
106
  #
52
107
  # DB.extension :pg_array, :pg_json
@@ -54,114 +109,219 @@
54
109
  # Note that when accessing json hashes, you should always use strings for keys.
55
110
  # Attempting to use other values (such as symbols) will not work correctly.
56
111
  #
57
- # This extension requires both the json and delegate libraries.
112
+ # This extension requires both the json and delegate libraries. However, you
113
+ # can override +Sequel.parse_json+, +Sequel.object_to_json+, and
114
+ # +Sequel.json_parser_error_class+ to use an alternative JSON implementation.
58
115
  #
59
- # Related modules: Sequel::Postgres::JSONArrayBase, Sequel::Postgres::JSONArray,
60
- # Sequel::Postgres::JSONArray, Sequel::Postgres::JSONBArray, Sequel::Postgres::JSONHashBase,
61
- # Sequel::Postgres::JSONHash, Sequel::Postgres::JSONBHash, Sequel::Postgres::JSONDatabaseMethods
116
+ # Related modules: Sequel::Postgres::JSONDatabaseMethods
62
117
 
63
118
  require 'delegate'
64
119
  require 'json'
65
120
 
66
121
  module Sequel
67
122
  module Postgres
68
- # Class representing PostgreSQL JSON/JSONB column array values.
69
- class JSONArrayBase < DelegateClass(Array)
70
- include Sequel::SQL::AliasMethods
71
- include Sequel::SQL::CastMethods
72
-
73
- # Convert the array to a json string and append a
74
- # literalized version of the string to the sql.
75
- def sql_literal_append(ds, sql)
76
- ds.literal_append(sql, Sequel.object_to_json(self))
77
- end
123
+ # A module included in all of the JSON wrapper classes.
124
+ module JSONObject
78
125
  end
79
126
 
80
- class JSONArray < JSONArrayBase
81
- # Cast as json
82
- def sql_literal_append(ds, sql)
83
- super
84
- sql << '::json'
85
- end
127
+ # A module included in all of the JSONB wrapper classes.
128
+ module JSONBObject
86
129
  end
87
130
 
88
- class JSONBArray < JSONArrayBase
89
- # Cast as jsonb
90
- def sql_literal_append(ds, sql)
91
- super
92
- sql << '::jsonb'
131
+ create_delegate_class = lambda do |name, delegate_class|
132
+ base_class = DelegateClass(delegate_class)
133
+ base_class.class_eval do
134
+ include Sequel::SQL::AliasMethods
135
+ include Sequel::SQL::CastMethods
93
136
  end
94
- end
95
137
 
96
- # Class representing PostgreSQL JSON/JSONB column hash/object values.
97
- class JSONHashBase < DelegateClass(Hash)
98
- include Sequel::SQL::AliasMethods
99
- include Sequel::SQL::CastMethods
138
+ json_class = Class.new(base_class) do
139
+ include JSONObject
100
140
 
101
- # Convert the hash to a json string and append a
102
- # literalized version of the string to the sql.
103
- def sql_literal_append(ds, sql)
104
- ds.literal_append(sql, Sequel.object_to_json(self))
141
+ def sql_literal_append(ds, sql)
142
+ ds.literal_append(sql, Sequel.object_to_json(self))
143
+ sql << '::json'
144
+ end
105
145
  end
106
146
 
107
- # Return the object being delegated to.
108
- alias to_hash __getobj__
109
- end
147
+ jsonb_class = Class.new(base_class) do
148
+ include JSONBObject
110
149
 
111
- class JSONHash < JSONHashBase
112
- # Cast as json
113
- def sql_literal_append(ds, sql)
114
- super
115
- sql << '::json'
150
+ def sql_literal_append(ds, sql)
151
+ ds.literal_append(sql, Sequel.object_to_json(self))
152
+ sql << '::jsonb'
153
+ end
116
154
  end
155
+
156
+ const_set(:"JSON#{name}Base", base_class)
157
+ const_set(:"JSON#{name}", json_class)
158
+ const_set(:"JSONB#{name}", jsonb_class)
117
159
  end
118
160
 
119
- class JSONBHash < JSONHashBase
120
- # Cast as jsonb
121
- def sql_literal_append(ds, sql)
122
- super
123
- sql << '::jsonb'
124
- end
161
+ create_delegate_class.call(:Array, Array)
162
+ create_delegate_class.call(:Hash, Hash)
163
+ create_delegate_class.call(:String, String)
164
+ create_delegate_class.call(:Integer, Integer)
165
+ create_delegate_class.call(:Float, Float)
166
+ create_delegate_class.call(:Null, NilClass)
167
+ create_delegate_class.call(:True, TrueClass)
168
+ create_delegate_class.call(:False, FalseClass)
169
+
170
+ JSON_WRAPPER_MAPPING = {
171
+ ::Array => JSONArray,
172
+ ::Hash => JSONHash,
173
+ }.freeze
174
+
175
+ JSONB_WRAPPER_MAPPING = {
176
+ ::Array => JSONBArray,
177
+ ::Hash => JSONBHash,
178
+ }.freeze
179
+
180
+ JSON_PRIMITIVE_WRAPPER_MAPPING = {
181
+ ::String => JSONString,
182
+ ::Integer => JSONInteger,
183
+ ::Float => JSONFloat,
184
+ ::NilClass => JSONNull,
185
+ ::TrueClass => JSONTrue,
186
+ ::FalseClass => JSONFalse,
187
+ }
188
+
189
+ JSONB_PRIMITIVE_WRAPPER_MAPPING = {
190
+ ::String => JSONBString,
191
+ ::Integer => JSONBInteger,
192
+ ::Float => JSONBFloat,
193
+ ::NilClass => JSONBNull,
194
+ ::TrueClass => JSONBTrue,
195
+ ::FalseClass => JSONBFalse,
196
+ }
197
+
198
+ if RUBY_VERSION < '2.4'
199
+ # :nocov:
200
+ JSON_PRIMITIVE_WRAPPER_MAPPING[Fixnum] = JSONInteger
201
+ JSON_PRIMITIVE_WRAPPER_MAPPING[Bignum] = JSONInteger
202
+ JSONB_PRIMITIVE_WRAPPER_MAPPING[Fixnum] = JSONBInteger
203
+ JSONB_PRIMITIVE_WRAPPER_MAPPING[Bignum] = JSONBInteger
204
+ # :nocov:
125
205
  end
126
206
 
207
+ JSON_PRIMITIVE_WRAPPER_MAPPING.freeze
208
+ JSONB_PRIMITIVE_WRAPPER_MAPPING.freeze
209
+
210
+ JSON_COMBINED_WRAPPER_MAPPING =JSON_WRAPPER_MAPPING.merge(JSON_PRIMITIVE_WRAPPER_MAPPING).freeze
211
+ JSONB_COMBINED_WRAPPER_MAPPING =JSONB_WRAPPER_MAPPING.merge(JSONB_PRIMITIVE_WRAPPER_MAPPING).freeze
212
+ JSONB_WRAP_CLASSES = JSONB_COMBINED_WRAPPER_MAPPING.keys.freeze
213
+
214
+ Sequel::Deprecation.deprecate_constant(self, :JSON_WRAPPER_MAPPING)
215
+ Sequel::Deprecation.deprecate_constant(self, :JSONB_WRAPPER_MAPPING)
216
+ Sequel::Deprecation.deprecate_constant(self, :JSON_PRIMITIVE_WRAPPER_MAPPING)
217
+ Sequel::Deprecation.deprecate_constant(self, :JSONB_PRIMITIVE_WRAPPER_MAPPING)
218
+ Sequel::Deprecation.deprecate_constant(self, :JSON_COMBINED_WRAPPER_MAPPING)
219
+ Sequel::Deprecation.deprecate_constant(self, :JSONB_COMBINED_WRAPPER_MAPPING)
220
+ Sequel::Deprecation.deprecate_constant(self, :JSONB_WRAP_CLASSES)
221
+
222
+ JSON_WRAP_CLASSES = [Hash, Array, String, Integer, Float, NilClass, TrueClass, FalseClass].freeze
223
+
127
224
  # Methods enabling Database object integration with the json type.
128
225
  module JSONDatabaseMethods
129
226
  def self.extended(db)
130
227
  db.instance_exec do
131
- add_conversion_proc(114, JSONDatabaseMethods.method(:db_parse_json))
132
- add_conversion_proc(3802, JSONDatabaseMethods.method(:db_parse_jsonb))
228
+ add_conversion_proc(114, method(:_db_parse_json))
229
+ add_conversion_proc(3802, method(:_db_parse_jsonb))
133
230
  if respond_to?(:register_array_type)
134
231
  register_array_type('json', :oid=>199, :scalar_oid=>114)
135
232
  register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802)
136
233
  end
137
- @schema_type_classes[:json] = [JSONHash, JSONArray]
138
- @schema_type_classes[:jsonb] = [JSONBHash, JSONBArray]
234
+ @schema_type_classes[:json] = [JSONObject]
235
+ @schema_type_classes[:jsonb] = [JSONBObject]
139
236
  end
140
237
  end
141
238
 
142
- # Parse JSON data coming from the database. Since PostgreSQL allows
143
- # non JSON data in JSON fields (such as plain numbers and strings),
144
- # we don't want to raise an exception for that.
239
+ # Return the wrapper class for the json type if value is Hash or Array.
240
+ def self.json_wrapper(value)
241
+ case value
242
+ when ::Hash
243
+ JSONHash
244
+ when ::Array
245
+ JSONArray
246
+ end
247
+ end
248
+
249
+ # Return the wrapper class for the jsonb type if value is Hash or Array.
250
+ def self.jsonb_wrapper(value)
251
+ case value
252
+ when ::Hash
253
+ JSONBHash
254
+ when ::Array
255
+ JSONBArray
256
+ end
257
+ end
258
+
259
+ # Return the wrapper class for the json type if value is a supported type.
260
+ def self.json_primitive_wrapper(value)
261
+ case value
262
+ when ::Hash
263
+ JSONHash
264
+ when ::Array
265
+ JSONArray
266
+ when ::String
267
+ JSONString
268
+ when ::Integer
269
+ JSONInteger
270
+ when ::Float
271
+ JSONFloat
272
+ when ::NilClass
273
+ JSONNull
274
+ when ::TrueClass
275
+ JSONTrue
276
+ when ::FalseClass
277
+ JSONFalse
278
+ end
279
+ end
280
+
281
+ # Return the wrapper class for the jsonb type if value is a supported type.
282
+ def self.jsonb_primitive_wrapper(value)
283
+ case value
284
+ when ::Hash
285
+ JSONBHash
286
+ when ::Array
287
+ JSONBArray
288
+ when ::String
289
+ JSONBString
290
+ when ::Integer
291
+ JSONBInteger
292
+ when ::Float
293
+ JSONBFloat
294
+ when ::NilClass
295
+ JSONBNull
296
+ when ::TrueClass
297
+ JSONBTrue
298
+ when ::FalseClass
299
+ JSONBFalse
300
+ end
301
+ end
302
+
303
+ # Deprecated
145
304
  def self.db_parse_json(s)
305
+ # SEQUEL6: Remove
146
306
  parse_json(s)
147
307
  rescue Sequel::InvalidValue
148
308
  raise unless s.is_a?(String)
149
309
  parse_json("[#{s}]").first
150
310
  end
151
311
 
152
- # Same as db_parse_json, but consider the input as jsonb.
312
+ # Deprecated
153
313
  def self.db_parse_jsonb(s)
314
+ # SEQUEL6: Remove
154
315
  parse_json(s, true)
155
316
  rescue Sequel::InvalidValue
156
317
  raise unless s.is_a?(String)
157
318
  parse_json("[#{s}]").first
158
319
  end
159
320
 
160
- # Parse the given string as json, returning either a JSONArray
161
- # or JSONHash instance (or JSONBArray or JSONBHash instance if jsonb
162
- # argument is true), or a String, Numeric, true, false, or nil
163
- # if the json library used supports that.
321
+ # Deprecated
164
322
  def self.parse_json(s, jsonb=false)
323
+ # SEQUEL6: Remove
324
+ Sequel::Deprecation.deprecate("Sequel::Postgres::JSONDatabaseMethods.{parse_json,db_parse_json,db_parse_jsonb} are deprecated and will be removed in Sequel 6.")
165
325
  begin
166
326
  value = Sequel.parse_json(s)
167
327
  rescue Sequel.json_parser_error_class => e
@@ -180,10 +340,22 @@ module Sequel
180
340
  end
181
341
  end
182
342
 
343
+ # Whether to wrap JSON primitives instead of using Ruby objects.
344
+ # Wrapping the primitives allows the primitive values to roundtrip,
345
+ # but it can cause problems, especially as false/null JSON values
346
+ # will be treated as truthy in Ruby due to the wrapping. False by
347
+ # default.
348
+ attr_accessor :wrap_json_primitives
349
+
350
+ # Whether to typecast strings for json/jsonb types as JSON
351
+ # strings, instead of trying to parse the string as JSON.
352
+ # False by default.
353
+ attr_accessor :typecast_json_strings
354
+
183
355
  # Handle json and jsonb types in bound variables
184
356
  def bound_variable_arg(arg, conn)
185
357
  case arg
186
- when JSONArrayBase, JSONHashBase
358
+ when JSONObject, JSONBObject
187
359
  Sequel.object_to_json(arg)
188
360
  else
189
361
  super
@@ -192,10 +364,72 @@ module Sequel
192
364
 
193
365
  private
194
366
 
367
+ # Parse JSON data coming from the database. Since PostgreSQL allows
368
+ # non JSON data in JSON fields (such as plain numbers and strings),
369
+ # we don't want to raise an exception for that.
370
+ def _db_parse_json(s)
371
+ _wrap_json(_parse_json(s))
372
+ rescue Sequel::InvalidValue
373
+ raise unless s.is_a?(String)
374
+ _wrap_json(_parse_json("[#{s}]").first)
375
+ end
376
+
377
+ # Same as _db_parse_json, but consider the input as jsonb.
378
+ def _db_parse_jsonb(s)
379
+ _wrap_jsonb(_parse_json(s))
380
+ rescue Sequel::InvalidValue
381
+ raise unless s.is_a?(String)
382
+ _wrap_jsonb(_parse_json("[#{s}]").first)
383
+ end
384
+
385
+ # Parse the given string as json, returning either a JSONArray
386
+ # or JSONHash instance (or JSONBArray or JSONBHash instance if jsonb
387
+ # argument is true), or a String, Numeric, true, false, or nil
388
+ # if the json library used supports that.
389
+ def _parse_json(s)
390
+ begin
391
+ Sequel.parse_json(s)
392
+ rescue Sequel.json_parser_error_class => e
393
+ raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
394
+ end
395
+ end
396
+
397
+ # Wrap the parsed JSON value in the appropriate JSON wrapper class.
398
+ # Only wrap primitive values if wrap_json_primitives is set.
399
+ def _wrap_json(value)
400
+ if klass = JSONDatabaseMethods.json_wrapper(value)
401
+ klass.new(value)
402
+ elsif klass = JSONDatabaseMethods.json_primitive_wrapper(value)
403
+ if wrap_json_primitives
404
+ klass.new(value)
405
+ else
406
+ value
407
+ end
408
+ else
409
+ raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}"
410
+ end
411
+ end
412
+
413
+ # Wrap the parsed JSON value in the appropriate JSONB wrapper class.
414
+ # Only wrap primitive values if wrap_json_primitives is set.
415
+ def _wrap_jsonb(value)
416
+ if klass = JSONDatabaseMethods.jsonb_wrapper(value)
417
+ klass.new(value)
418
+ elsif klass = JSONDatabaseMethods.jsonb_primitive_wrapper(value)
419
+ if wrap_json_primitives
420
+ klass.new(value)
421
+ else
422
+ value
423
+ end
424
+ else
425
+ raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}"
426
+ end
427
+ end
428
+
195
429
  # Handle json[] and jsonb[] types in bound variables.
196
430
  def bound_variable_array(a)
197
431
  case a
198
- when JSONHashBase, JSONArrayBase
432
+ when JSONObject, JSONBObject
199
433
  "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\""
200
434
  else
201
435
  super
@@ -238,41 +472,43 @@ module Sequel
238
472
  end
239
473
  end
240
474
 
241
- # Convert the value given to a JSONArray or JSONHash
475
+ # Convert the value given to a JSON wrapper object.
242
476
  def typecast_value_json(value)
243
477
  case value
244
- when JSONArray, JSONHash
478
+ when JSONObject
245
479
  value
246
- when Array
247
- JSONArray.new(value)
248
- when Hash
249
- JSONHash.new(value)
250
- when JSONBArray
251
- JSONArray.new(value.to_a)
252
- when JSONBHash
253
- JSONHash.new(value.to_hash)
254
480
  when String
255
- JSONDatabaseMethods.parse_json(value)
481
+ if typecast_json_strings
482
+ JSONString.new(value)
483
+ else
484
+ _wrap_json(_parse_json(value))
485
+ end
486
+ when *JSON_WRAP_CLASSES
487
+ JSONDatabaseMethods.json_primitive_wrapper(value).new(value)
488
+ when JSONBObject
489
+ value = value.__getobj__
490
+ JSONDatabaseMethods.json_primitive_wrapper(value).new(value)
256
491
  else
257
492
  raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}"
258
493
  end
259
494
  end
260
495
 
261
- # Convert the value given to a JSONBArray or JSONBHash
496
+ # Convert the value given to a JSONB wrapper object.
262
497
  def typecast_value_jsonb(value)
263
498
  case value
264
- when JSONBArray, JSONBHash
499
+ when JSONBObject
265
500
  value
266
- when Array
267
- JSONBArray.new(value)
268
- when Hash
269
- JSONBHash.new(value)
270
- when JSONArray
271
- JSONBArray.new(value.to_a)
272
- when JSONHash
273
- JSONBHash.new(value.to_hash)
274
501
  when String
275
- JSONDatabaseMethods.parse_json(value, true)
502
+ if typecast_json_strings
503
+ JSONBString.new(value)
504
+ else
505
+ _wrap_jsonb(_parse_json(value))
506
+ end
507
+ when *JSON_WRAP_CLASSES
508
+ JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value)
509
+ when JSONObject
510
+ value = value.__getobj__
511
+ JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value)
276
512
  else
277
513
  raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}"
278
514
  end
@@ -282,40 +518,68 @@ module Sequel
282
518
 
283
519
  module SQL::Builders
284
520
  # Wrap the array or hash in a Postgres::JSONArray or Postgres::JSONHash.
521
+ # Also handles Postgres::JSONObject and JSONBObjects.
522
+ # For other objects, calls +Sequel.pg_json_op+ (which is defined
523
+ # by the pg_json_ops extension).
285
524
  def pg_json(v)
286
525
  case v
287
- when Postgres::JSONArray, Postgres::JSONHash
526
+ when Postgres::JSONObject
288
527
  v
289
528
  when Array
290
529
  Postgres::JSONArray.new(v)
291
530
  when Hash
292
531
  Postgres::JSONHash.new(v)
293
- when Postgres::JSONBArray
294
- Postgres::JSONArray.new(v.to_a)
295
- when Postgres::JSONBHash
296
- Postgres::JSONHash.new(v.to_hash)
532
+ when Postgres::JSONBObject
533
+ v = v.__getobj__
534
+ Postgres::JSONDatabaseMethods.json_primitive_wrapper(v).new(v)
297
535
  else
298
536
  Sequel.pg_json_op(v)
299
537
  end
300
538
  end
301
539
 
540
+ # Wraps Ruby array, hash, string, integer, float, true, false, and nil
541
+ # values with the appropriate JSON wrapper. Raises an exception for
542
+ # other types.
543
+ def pg_json_wrap(v)
544
+ case v
545
+ when *Postgres::JSON_WRAP_CLASSES
546
+ Postgres::JSONDatabaseMethods.json_primitive_wrapper(v).new(v)
547
+ else
548
+ raise Error, "invalid value passed to Sequel.pg_json_wrap: #{v.inspect}"
549
+ end
550
+ end
551
+
302
552
  # Wrap the array or hash in a Postgres::JSONBArray or Postgres::JSONBHash.
553
+ # Also handles Postgres::JSONObject and JSONBObjects.
554
+ # For other objects, calls +Sequel.pg_json_op+ (which is defined
555
+ # by the pg_json_ops extension).
303
556
  def pg_jsonb(v)
304
557
  case v
305
- when Postgres::JSONBArray, Postgres::JSONBHash
558
+ when Postgres::JSONBObject
306
559
  v
307
560
  when Array
308
561
  Postgres::JSONBArray.new(v)
309
562
  when Hash
310
563
  Postgres::JSONBHash.new(v)
311
- when Postgres::JSONArray
312
- Postgres::JSONBArray.new(v.to_a)
313
- when Postgres::JSONHash
314
- Postgres::JSONBHash.new(v.to_hash)
564
+ when Postgres::JSONObject
565
+ v = v.__getobj__
566
+ Postgres::JSONDatabaseMethods.jsonb_primitive_wrapper(v).new(v)
315
567
  else
316
568
  Sequel.pg_jsonb_op(v)
317
569
  end
318
570
  end
571
+
572
+ # Wraps Ruby array, hash, string, integer, float, true, false, and nil
573
+ # values with the appropriate JSONB wrapper. Raises an exception for
574
+ # other types.
575
+ def pg_jsonb_wrap(v)
576
+ case v
577
+ when *Postgres::JSON_WRAP_CLASSES
578
+ Postgres::JSONDatabaseMethods.jsonb_primitive_wrapper(v).new(v)
579
+ else
580
+ raise Error, "invalid value passed to Sequel.pg_jsonb_wrap: #{v.inspect}"
581
+ end
582
+ end
319
583
  end
320
584
 
321
585
  Database.register_extension(:pg_json, Postgres::JSONDatabaseMethods)