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.
- checksums.yaml +5 -5
- data/CHANGELOG +405 -5656
- data/MIT-LICENSE +1 -1
- data/README.rdoc +232 -157
- data/bin/sequel +32 -9
- data/doc/advanced_associations.rdoc +252 -188
- data/doc/association_basics.rdoc +231 -273
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +75 -48
- data/doc/code_order.rdoc +28 -10
- data/doc/core_extensions.rdoc +104 -63
- data/doc/dataset_basics.rdoc +12 -21
- data/doc/dataset_filtering.rdoc +99 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/mass_assignment.rdoc +74 -31
- data/doc/migration.rdoc +72 -46
- data/doc/model_dataset_method_design.rdoc +129 -0
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +12 -12
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +59 -69
- data/doc/opening_databases.rdoc +84 -94
- data/doc/postgresql.rdoc +268 -38
- data/doc/prepared_statements.rdoc +29 -24
- data/doc/querying.rdoc +184 -164
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/release_notes/5.1.0.txt +31 -0
- data/doc/release_notes/5.10.0.txt +84 -0
- data/doc/release_notes/5.11.0.txt +83 -0
- data/doc/release_notes/5.12.0.txt +141 -0
- data/doc/release_notes/5.13.0.txt +27 -0
- data/doc/release_notes/5.14.0.txt +63 -0
- data/doc/release_notes/5.15.0.txt +39 -0
- data/doc/release_notes/5.16.0.txt +110 -0
- data/doc/release_notes/5.17.0.txt +31 -0
- data/doc/release_notes/5.18.0.txt +69 -0
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.2.0.txt +33 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/release_notes/5.21.0.txt +87 -0
- data/doc/release_notes/5.22.0.txt +48 -0
- data/doc/release_notes/5.23.0.txt +56 -0
- data/doc/release_notes/5.24.0.txt +56 -0
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/release_notes/5.3.0.txt +121 -0
- data/doc/release_notes/5.30.0.txt +20 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/release_notes/5.5.0.txt +61 -0
- data/doc/release_notes/5.6.0.txt +31 -0
- data/doc/release_notes/5.7.0.txt +108 -0
- data/doc/release_notes/5.8.0.txt +170 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/schema_modification.rdoc +102 -77
- data/doc/security.rdoc +160 -87
- data/doc/sharding.rdoc +74 -47
- data/doc/sql.rdoc +135 -122
- data/doc/testing.rdoc +34 -18
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +101 -19
- data/doc/validations.rdoc +64 -51
- data/doc/virtual_rows.rdoc +90 -109
- data/lib/sequel.rb +3 -1
- data/lib/sequel/adapters/ado.rb +154 -22
- data/lib/sequel/adapters/ado/access.rb +21 -21
- data/lib/sequel/adapters/ado/mssql.rb +8 -15
- data/lib/sequel/adapters/amalgalite.rb +17 -25
- data/lib/sequel/adapters/ibmdb.rb +52 -58
- data/lib/sequel/adapters/jdbc.rb +149 -127
- data/lib/sequel/adapters/jdbc/db2.rb +32 -40
- data/lib/sequel/adapters/jdbc/derby.rb +56 -58
- data/lib/sequel/adapters/jdbc/h2.rb +40 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
- data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
- data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
- data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
- data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
- data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
- data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
- data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
- data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
- data/lib/sequel/adapters/mock.rb +104 -113
- data/lib/sequel/adapters/mysql.rb +42 -61
- data/lib/sequel/adapters/mysql2.rb +126 -35
- data/lib/sequel/adapters/odbc.rb +21 -28
- data/lib/sequel/adapters/odbc/db2.rb +3 -1
- data/lib/sequel/adapters/odbc/mssql.rb +11 -15
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/oracle.rb +62 -68
- data/lib/sequel/adapters/postgres.rb +257 -311
- data/lib/sequel/adapters/postgresql.rb +3 -1
- data/lib/sequel/adapters/shared/access.rb +75 -79
- data/lib/sequel/adapters/shared/db2.rb +96 -74
- data/lib/sequel/adapters/shared/mssql.rb +258 -213
- data/lib/sequel/adapters/shared/mysql.rb +284 -216
- data/lib/sequel/adapters/shared/oracle.rb +175 -60
- data/lib/sequel/adapters/shared/postgres.rb +829 -383
- data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
- data/lib/sequel/adapters/shared/sqlite.rb +382 -159
- data/lib/sequel/adapters/sqlanywhere.rb +53 -38
- data/lib/sequel/adapters/sqlite.rb +111 -105
- data/lib/sequel/adapters/tinytds.rb +38 -46
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
- data/lib/sequel/adapters/utils/replace.rb +3 -4
- data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
- data/lib/sequel/ast_transformer.rb +13 -89
- data/lib/sequel/connection_pool.rb +54 -26
- data/lib/sequel/connection_pool/sharded_single.rb +19 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
- data/lib/sequel/connection_pool/single.rb +21 -12
- data/lib/sequel/connection_pool/threaded.rb +137 -119
- data/lib/sequel/core.rb +352 -320
- data/lib/sequel/database.rb +19 -2
- data/lib/sequel/database/connecting.rb +70 -55
- data/lib/sequel/database/dataset.rb +15 -5
- data/lib/sequel/database/dataset_defaults.rb +20 -102
- data/lib/sequel/database/features.rb +20 -4
- data/lib/sequel/database/logging.rb +25 -7
- data/lib/sequel/database/misc.rb +132 -118
- data/lib/sequel/database/query.rb +51 -28
- data/lib/sequel/database/schema_generator.rb +188 -75
- data/lib/sequel/database/schema_methods.rb +161 -92
- data/lib/sequel/database/transactions.rb +260 -58
- data/lib/sequel/dataset.rb +28 -12
- data/lib/sequel/dataset/actions.rb +354 -170
- data/lib/sequel/dataset/dataset_module.rb +46 -0
- data/lib/sequel/dataset/features.rb +81 -34
- data/lib/sequel/dataset/graph.rb +82 -58
- data/lib/sequel/dataset/misc.rb +139 -47
- data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
- data/lib/sequel/dataset/prepared_statements.rb +188 -85
- data/lib/sequel/dataset/query.rb +428 -214
- data/lib/sequel/dataset/sql.rb +446 -339
- data/lib/sequel/deprecated.rb +14 -2
- data/lib/sequel/exceptions.rb +48 -16
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +43 -0
- data/lib/sequel/extensions/_pretty_table.rb +10 -9
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/blank.rb +2 -0
- data/lib/sequel/extensions/caller_logging.rb +79 -0
- data/lib/sequel/extensions/columns_introspection.rb +9 -4
- data/lib/sequel/extensions/connection_expiration.rb +99 -0
- data/lib/sequel/extensions/connection_validator.rb +26 -13
- data/lib/sequel/extensions/constant_sql_override.rb +65 -0
- data/lib/sequel/extensions/constraint_validations.rb +93 -38
- data/lib/sequel/extensions/core_extensions.rb +45 -53
- data/lib/sequel/extensions/core_refinements.rb +44 -46
- data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
- data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
- data/lib/sequel/extensions/date_arithmetic.rb +42 -16
- data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
- data/lib/sequel/extensions/error_sql.rb +7 -3
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +14 -15
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/freeze_datasets.rb +3 -0
- data/lib/sequel/extensions/from_block.rb +2 -31
- data/lib/sequel/extensions/graph_each.rb +19 -6
- data/lib/sequel/extensions/identifier_mangling.rb +180 -0
- data/lib/sequel/extensions/implicit_subquery.rb +48 -0
- data/lib/sequel/extensions/index_caching.rb +109 -0
- data/lib/sequel/extensions/inflector.rb +8 -4
- data/lib/sequel/extensions/integer64.rb +32 -0
- data/lib/sequel/extensions/looser_typecasting.rb +19 -9
- data/lib/sequel/extensions/migration.rb +132 -80
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
- data/lib/sequel/extensions/named_timezones.rb +88 -23
- data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +12 -8
- data/lib/sequel/extensions/pagination.rb +35 -28
- data/lib/sequel/extensions/pg_array.rb +227 -316
- data/lib/sequel/extensions/pg_array_ops.rb +19 -7
- data/lib/sequel/extensions/pg_enum.rb +69 -24
- data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
- data/lib/sequel/extensions/pg_hstore.rb +50 -59
- data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
- data/lib/sequel/extensions/pg_inet.rb +34 -15
- data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
- data/lib/sequel/extensions/pg_interval.rb +26 -26
- data/lib/sequel/extensions/pg_json.rb +422 -141
- data/lib/sequel/extensions/pg_json_ops.rb +248 -9
- data/lib/sequel/extensions/pg_loose_count.rb +5 -1
- data/lib/sequel/extensions/pg_range.rb +162 -146
- data/lib/sequel/extensions/pg_range_ops.rb +10 -5
- data/lib/sequel/extensions/pg_row.rb +53 -87
- data/lib/sequel/extensions/pg_row_ops.rb +36 -13
- data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
- data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
- data/lib/sequel/extensions/pretty_table.rb +4 -0
- data/lib/sequel/extensions/query.rb +12 -7
- data/lib/sequel/extensions/round_timestamps.rb +6 -9
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +59 -0
- data/lib/sequel/extensions/schema_caching.rb +14 -1
- data/lib/sequel/extensions/schema_dumper.rb +83 -55
- data/lib/sequel/extensions/select_remove.rb +8 -4
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
- data/lib/sequel/extensions/server_block.rb +50 -17
- data/lib/sequel/extensions/server_logging.rb +61 -0
- data/lib/sequel/extensions/split_array_nil.rb +8 -4
- data/lib/sequel/extensions/sql_comments.rb +96 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -1
- data/lib/sequel/extensions/string_agg.rb +181 -0
- data/lib/sequel/extensions/string_date_time.rb +2 -0
- data/lib/sequel/extensions/symbol_aref.rb +53 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
- data/lib/sequel/extensions/synchronize_sql.rb +45 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
- data/lib/sequel/extensions/to_dot.rb +15 -5
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +36 -126
- data/lib/sequel/model/associations.rb +850 -257
- data/lib/sequel/model/base.rb +652 -764
- data/lib/sequel/model/dataset_module.rb +13 -10
- data/lib/sequel/model/default_inflections.rb +3 -1
- data/lib/sequel/model/errors.rb +3 -3
- data/lib/sequel/model/exceptions.rb +12 -12
- data/lib/sequel/model/inflections.rb +8 -19
- data/lib/sequel/model/plugins.rb +111 -0
- data/lib/sequel/plugins/accessed_columns.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +32 -7
- data/lib/sequel/plugins/after_initialize.rb +3 -1
- data/lib/sequel/plugins/association_dependencies.rb +27 -18
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
- data/lib/sequel/plugins/association_pks.rb +181 -83
- data/lib/sequel/plugins/association_proxies.rb +33 -9
- data/lib/sequel/plugins/auto_validations.rb +58 -23
- data/lib/sequel/plugins/before_after_save.rb +8 -0
- data/lib/sequel/plugins/blacklist_security.rb +23 -12
- data/lib/sequel/plugins/boolean_readers.rb +9 -6
- data/lib/sequel/plugins/boolean_subsets.rb +64 -0
- data/lib/sequel/plugins/caching.rb +27 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
- data/lib/sequel/plugins/column_conflicts.rb +18 -3
- data/lib/sequel/plugins/column_select.rb +9 -5
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +36 -24
- data/lib/sequel/plugins/constraint_validations.rb +37 -16
- data/lib/sequel/plugins/csv_serializer.rb +58 -35
- data/lib/sequel/plugins/dataset_associations.rb +60 -18
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/defaults_setter.rb +74 -13
- data/lib/sequel/plugins/delay_add_association.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +65 -24
- data/lib/sequel/plugins/eager_each.rb +27 -3
- data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/error_splitter.rb +19 -12
- data/lib/sequel/plugins/finder.rb +246 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/force_encoding.rb +9 -12
- data/lib/sequel/plugins/hook_class_methods.rb +39 -54
- data/lib/sequel/plugins/input_transformer.rb +20 -10
- data/lib/sequel/plugins/insert_conflict.rb +72 -0
- data/lib/sequel/plugins/insert_returning_select.rb +4 -2
- data/lib/sequel/plugins/instance_filters.rb +12 -8
- data/lib/sequel/plugins/instance_hooks.rb +36 -17
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/inverted_subsets.rb +24 -13
- data/lib/sequel/plugins/json_serializer.rb +123 -47
- data/lib/sequel/plugins/lazy_attributes.rb +20 -14
- data/lib/sequel/plugins/list.rb +40 -26
- data/lib/sequel/plugins/many_through_many.rb +28 -12
- data/lib/sequel/plugins/modification_detection.rb +17 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
- data/lib/sequel/plugins/nested_attributes.rb +55 -28
- data/lib/sequel/plugins/optimistic_locking.rb +5 -3
- data/lib/sequel/plugins/pg_array_associations.rb +52 -18
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
- data/lib/sequel/plugins/pg_row.rb +7 -51
- data/lib/sequel/plugins/prepared_statements.rb +53 -72
- data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
- data/lib/sequel/plugins/rcte_tree.rb +43 -63
- data/lib/sequel/plugins/serialization.rb +37 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
- data/lib/sequel/plugins/sharding.rb +17 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
- data/lib/sequel/plugins/singular_table_names.rb +2 -0
- data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/split_values.rb +13 -6
- data/lib/sequel/plugins/static_cache.rb +79 -53
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +5 -3
- data/lib/sequel/plugins/subclasses.rb +20 -2
- data/lib/sequel/plugins/subset_conditions.rb +48 -0
- data/lib/sequel/plugins/table_select.rb +4 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
- data/lib/sequel/plugins/throw_failures.rb +110 -0
- data/lib/sequel/plugins/timestamps.rb +22 -8
- data/lib/sequel/plugins/touch.rb +21 -8
- data/lib/sequel/plugins/tree.rb +57 -30
- data/lib/sequel/plugins/typecast_on_load.rb +14 -4
- data/lib/sequel/plugins/unlimited_update.rb +3 -7
- data/lib/sequel/plugins/update_or_create.rb +6 -4
- data/lib/sequel/plugins/update_primary_key.rb +3 -1
- data/lib/sequel/plugins/update_refresh.rb +28 -15
- data/lib/sequel/plugins/uuid.rb +70 -0
- data/lib/sequel/plugins/validate_associated.rb +20 -0
- data/lib/sequel/plugins/validation_class_methods.rb +40 -19
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +49 -31
- data/lib/sequel/plugins/whitelist_security.rb +122 -0
- data/lib/sequel/plugins/xml_serializer.rb +31 -30
- data/lib/sequel/sql.rb +479 -329
- data/lib/sequel/timezones.rb +62 -32
- data/lib/sequel/version.rb +10 -3
- metadata +177 -477
- data/Rakefile +0 -165
- data/doc/active_record.rdoc +0 -912
- data/doc/release_notes/1.0.txt +0 -38
- data/doc/release_notes/1.1.txt +0 -143
- data/doc/release_notes/1.3.txt +0 -101
- data/doc/release_notes/1.4.0.txt +0 -53
- data/doc/release_notes/1.5.0.txt +0 -155
- data/doc/release_notes/2.0.0.txt +0 -298
- data/doc/release_notes/2.1.0.txt +0 -271
- data/doc/release_notes/2.10.0.txt +0 -328
- data/doc/release_notes/2.11.0.txt +0 -215
- data/doc/release_notes/2.12.0.txt +0 -534
- data/doc/release_notes/2.2.0.txt +0 -253
- data/doc/release_notes/2.3.0.txt +0 -88
- data/doc/release_notes/2.4.0.txt +0 -106
- data/doc/release_notes/2.5.0.txt +0 -137
- data/doc/release_notes/2.6.0.txt +0 -157
- data/doc/release_notes/2.7.0.txt +0 -166
- data/doc/release_notes/2.8.0.txt +0 -171
- data/doc/release_notes/2.9.0.txt +0 -97
- data/doc/release_notes/3.0.0.txt +0 -221
- data/doc/release_notes/3.1.0.txt +0 -406
- data/doc/release_notes/3.10.0.txt +0 -286
- data/doc/release_notes/3.11.0.txt +0 -254
- data/doc/release_notes/3.12.0.txt +0 -304
- data/doc/release_notes/3.13.0.txt +0 -210
- data/doc/release_notes/3.14.0.txt +0 -118
- data/doc/release_notes/3.15.0.txt +0 -78
- data/doc/release_notes/3.16.0.txt +0 -45
- data/doc/release_notes/3.17.0.txt +0 -58
- data/doc/release_notes/3.18.0.txt +0 -120
- data/doc/release_notes/3.19.0.txt +0 -67
- data/doc/release_notes/3.2.0.txt +0 -268
- data/doc/release_notes/3.20.0.txt +0 -41
- data/doc/release_notes/3.21.0.txt +0 -87
- data/doc/release_notes/3.22.0.txt +0 -39
- data/doc/release_notes/3.23.0.txt +0 -172
- data/doc/release_notes/3.24.0.txt +0 -420
- data/doc/release_notes/3.25.0.txt +0 -88
- data/doc/release_notes/3.26.0.txt +0 -88
- data/doc/release_notes/3.27.0.txt +0 -82
- data/doc/release_notes/3.28.0.txt +0 -304
- data/doc/release_notes/3.29.0.txt +0 -459
- data/doc/release_notes/3.3.0.txt +0 -192
- data/doc/release_notes/3.30.0.txt +0 -135
- data/doc/release_notes/3.31.0.txt +0 -146
- data/doc/release_notes/3.32.0.txt +0 -202
- data/doc/release_notes/3.33.0.txt +0 -157
- data/doc/release_notes/3.34.0.txt +0 -671
- data/doc/release_notes/3.35.0.txt +0 -144
- data/doc/release_notes/3.36.0.txt +0 -245
- data/doc/release_notes/3.37.0.txt +0 -338
- data/doc/release_notes/3.38.0.txt +0 -234
- data/doc/release_notes/3.39.0.txt +0 -237
- data/doc/release_notes/3.4.0.txt +0 -325
- data/doc/release_notes/3.40.0.txt +0 -73
- data/doc/release_notes/3.41.0.txt +0 -155
- data/doc/release_notes/3.42.0.txt +0 -74
- data/doc/release_notes/3.43.0.txt +0 -105
- data/doc/release_notes/3.44.0.txt +0 -152
- data/doc/release_notes/3.45.0.txt +0 -179
- data/doc/release_notes/3.46.0.txt +0 -122
- data/doc/release_notes/3.47.0.txt +0 -270
- data/doc/release_notes/3.48.0.txt +0 -477
- data/doc/release_notes/3.5.0.txt +0 -510
- data/doc/release_notes/3.6.0.txt +0 -366
- data/doc/release_notes/3.7.0.txt +0 -179
- data/doc/release_notes/3.8.0.txt +0 -151
- data/doc/release_notes/3.9.0.txt +0 -233
- data/doc/release_notes/4.0.0.txt +0 -262
- data/doc/release_notes/4.1.0.txt +0 -85
- data/doc/release_notes/4.10.0.txt +0 -226
- data/doc/release_notes/4.11.0.txt +0 -147
- data/doc/release_notes/4.12.0.txt +0 -105
- data/doc/release_notes/4.13.0.txt +0 -169
- data/doc/release_notes/4.14.0.txt +0 -68
- data/doc/release_notes/4.15.0.txt +0 -56
- data/doc/release_notes/4.16.0.txt +0 -36
- data/doc/release_notes/4.17.0.txt +0 -38
- data/doc/release_notes/4.18.0.txt +0 -36
- data/doc/release_notes/4.19.0.txt +0 -45
- data/doc/release_notes/4.2.0.txt +0 -129
- data/doc/release_notes/4.20.0.txt +0 -79
- data/doc/release_notes/4.21.0.txt +0 -94
- data/doc/release_notes/4.22.0.txt +0 -72
- data/doc/release_notes/4.23.0.txt +0 -65
- data/doc/release_notes/4.24.0.txt +0 -99
- data/doc/release_notes/4.25.0.txt +0 -181
- data/doc/release_notes/4.26.0.txt +0 -44
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.5.0.txt +0 -34
- data/doc/release_notes/4.6.0.txt +0 -30
- data/doc/release_notes/4.7.0.txt +0 -103
- data/doc/release_notes/4.8.0.txt +0 -175
- data/doc/release_notes/4.9.0.txt +0 -190
- data/lib/sequel/adapters/cubrid.rb +0 -142
- data/lib/sequel/adapters/do.rb +0 -156
- data/lib/sequel/adapters/do/mysql.rb +0 -64
- data/lib/sequel/adapters/do/postgres.rb +0 -42
- data/lib/sequel/adapters/do/sqlite3.rb +0 -40
- data/lib/sequel/adapters/jdbc/as400.rb +0 -82
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
- data/lib/sequel/adapters/odbc/progress.rb +0 -8
- data/lib/sequel/adapters/shared/cubrid.rb +0 -243
- data/lib/sequel/adapters/shared/firebird.rb +0 -245
- data/lib/sequel/adapters/shared/informix.rb +0 -52
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
- data/lib/sequel/adapters/shared/progress.rb +0 -38
- data/lib/sequel/adapters/swift.rb +0 -158
- data/lib/sequel/adapters/swift/mysql.rb +0 -47
- data/lib/sequel/adapters/swift/postgres.rb +0 -45
- data/lib/sequel/adapters/swift/sqlite.rb +0 -47
- data/lib/sequel/adapters/utils/pg_types.rb +0 -68
- data/lib/sequel/dataset/mutation.rb +0 -109
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
- data/lib/sequel/extensions/filter_having.rb +0 -59
- data/lib/sequel/extensions/hash_aliases.rb +0 -45
- data/lib/sequel/extensions/meta_def.rb +0 -31
- data/lib/sequel/extensions/query_literals.rb +0 -80
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
- data/lib/sequel/extensions/set_overrides.rb +0 -72
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/association_autoreloading.rb +0 -7
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
- data/lib/sequel/plugins/schema.rb +0 -80
- data/lib/sequel/plugins/scissors.rb +0 -33
- data/spec/adapters/db2_spec.rb +0 -160
- data/spec/adapters/firebird_spec.rb +0 -411
- data/spec/adapters/informix_spec.rb +0 -100
- data/spec/adapters/mssql_spec.rb +0 -706
- data/spec/adapters/mysql_spec.rb +0 -1287
- data/spec/adapters/oracle_spec.rb +0 -313
- data/spec/adapters/postgres_spec.rb +0 -3725
- data/spec/adapters/spec_helper.rb +0 -43
- data/spec/adapters/sqlanywhere_spec.rb +0 -170
- data/spec/adapters/sqlite_spec.rb +0 -653
- data/spec/bin_spec.rb +0 -254
- data/spec/core/connection_pool_spec.rb +0 -1016
- data/spec/core/database_spec.rb +0 -2531
- data/spec/core/dataset_spec.rb +0 -5098
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1243
- data/spec/core/mock_adapter_spec.rb +0 -462
- data/spec/core/object_graph_spec.rb +0 -303
- data/spec/core/placeholder_literalizer_spec.rb +0 -163
- data/spec/core/schema_generator_spec.rb +0 -179
- data/spec/core/schema_spec.rb +0 -1659
- data/spec/core/spec_helper.rb +0 -34
- data/spec/core/version_spec.rb +0 -7
- data/spec/core_extensions_spec.rb +0 -699
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -123
- data/spec/extensions/after_initialize_spec.rb +0 -24
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -117
- data/spec/extensions/association_pks_spec.rb +0 -365
- data/spec/extensions/association_proxies_spec.rb +0 -86
- data/spec/extensions/auto_validations_spec.rb +0 -192
- data/spec/extensions/blacklist_security_spec.rb +0 -88
- data/spec/extensions/blank_spec.rb +0 -69
- data/spec/extensions/boolean_readers_spec.rb +0 -93
- data/spec/extensions/caching_spec.rb +0 -270
- data/spec/extensions/class_table_inheritance_spec.rb +0 -420
- data/spec/extensions/column_conflicts_spec.rb +0 -60
- data/spec/extensions/column_select_spec.rb +0 -108
- data/spec/extensions/columns_introspection_spec.rb +0 -91
- data/spec/extensions/composition_spec.rb +0 -242
- data/spec/extensions/connection_validator_spec.rb +0 -120
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
- data/spec/extensions/constraint_validations_spec.rb +0 -325
- data/spec/extensions/core_refinements_spec.rb +0 -519
- data/spec/extensions/csv_serializer_spec.rb +0 -173
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -311
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -150
- data/spec/extensions/defaults_setter_spec.rb +0 -101
- data/spec/extensions/delay_add_association_spec.rb +0 -52
- data/spec/extensions/dirty_spec.rb +0 -180
- data/spec/extensions/eager_each_spec.rb +0 -42
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/eval_inspect_spec.rb +0 -73
- data/spec/extensions/filter_having_spec.rb +0 -40
- data/spec/extensions/force_encoding_spec.rb +0 -114
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/graph_each_spec.rb +0 -109
- data/spec/extensions/hash_aliases_spec.rb +0 -24
- data/spec/extensions/hook_class_methods_spec.rb +0 -429
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -54
- data/spec/extensions/insert_returning_select_spec.rb +0 -46
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -276
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -291
- data/spec/extensions/lazy_attributes_spec.rb +0 -170
- data/spec/extensions/list_spec.rb +0 -267
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2172
- data/spec/extensions/meta_def_spec.rb +0 -21
- data/spec/extensions/migration_spec.rb +0 -712
- data/spec/extensions/modification_detection_spec.rb +0 -80
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
- data/spec/extensions/named_timezones_spec.rb +0 -108
- data/spec/extensions/nested_attributes_spec.rb +0 -697
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -128
- data/spec/extensions/pagination_spec.rb +0 -118
- data/spec/extensions/pg_array_associations_spec.rb +0 -736
- data/spec/extensions/pg_array_ops_spec.rb +0 -143
- data/spec/extensions/pg_array_spec.rb +0 -395
- data/spec/extensions/pg_enum_spec.rb +0 -92
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
- data/spec/extensions/pg_hstore_spec.rb +0 -206
- data/spec/extensions/pg_inet_ops_spec.rb +0 -101
- data/spec/extensions/pg_inet_spec.rb +0 -52
- data/spec/extensions/pg_interval_spec.rb +0 -76
- data/spec/extensions/pg_json_ops_spec.rb +0 -229
- data/spec/extensions/pg_json_spec.rb +0 -218
- data/spec/extensions/pg_loose_count_spec.rb +0 -17
- data/spec/extensions/pg_range_ops_spec.rb +0 -58
- data/spec/extensions/pg_range_spec.rb +0 -404
- data/spec/extensions/pg_row_ops_spec.rb +0 -60
- data/spec/extensions/pg_row_plugin_spec.rb +0 -62
- data/spec/extensions/pg_row_spec.rb +0 -360
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
- data/spec/extensions/prepared_statements_spec.rb +0 -103
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
- data/spec/extensions/pretty_table_spec.rb +0 -92
- data/spec/extensions/query_literals_spec.rb +0 -183
- data/spec/extensions/query_spec.rb +0 -102
- data/spec/extensions/rcte_tree_spec.rb +0 -392
- data/spec/extensions/round_timestamps_spec.rb +0 -43
- data/spec/extensions/schema_caching_spec.rb +0 -41
- data/spec/extensions/schema_dumper_spec.rb +0 -789
- data/spec/extensions/schema_spec.rb +0 -117
- data/spec/extensions/scissors_spec.rb +0 -26
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -362
- data/spec/extensions/server_block_spec.rb +0 -90
- data/spec/extensions/set_overrides_spec.rb +0 -61
- data/spec/extensions/sharding_spec.rb +0 -198
- data/spec/extensions/shared_caching_spec.rb +0 -175
- data/spec/extensions/single_table_inheritance_spec.rb +0 -297
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -17
- data/spec/extensions/spec_helper.rb +0 -71
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -22
- data/spec/extensions/sql_expr_spec.rb +0 -60
- data/spec/extensions/static_cache_spec.rb +0 -361
- data/spec/extensions/string_date_time_spec.rb +0 -95
- data/spec/extensions/string_stripper_spec.rb +0 -68
- data/spec/extensions/subclasses_spec.rb +0 -66
- data/spec/extensions/table_select_spec.rb +0 -71
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/timestamps_spec.rb +0 -175
- data/spec/extensions/to_dot_spec.rb +0 -154
- data/spec/extensions/touch_spec.rb +0 -203
- data/spec/extensions/tree_spec.rb +0 -274
- data/spec/extensions/typecast_on_load_spec.rb +0 -80
- data/spec/extensions/unlimited_update_spec.rb +0 -20
- data/spec/extensions/update_or_create_spec.rb +0 -87
- data/spec/extensions/update_primary_key_spec.rb +0 -100
- data/spec/extensions/update_refresh_spec.rb +0 -53
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1027
- data/spec/extensions/validation_helpers_spec.rb +0 -541
- data/spec/extensions/xml_serializer_spec.rb +0 -207
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
- data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
- data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
- data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
- data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/reversible_migrations/001_reversible.rb +0 -5
- data/spec/files/reversible_migrations/002_reversible.rb +0 -5
- data/spec/files/reversible_migrations/003_reversible.rb +0 -5
- data/spec/files/reversible_migrations/004_reversible.rb +0 -5
- data/spec/files/reversible_migrations/005_reversible.rb +0 -10
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
- data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
- data/spec/guards_helper.rb +0 -55
- data/spec/integration/associations_test.rb +0 -2454
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1808
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -240
- data/spec/integration/model_test.rb +0 -226
- data/spec/integration/plugin_test.rb +0 -2240
- data/spec/integration/prepared_statement_test.rb +0 -467
- data/spec/integration/schema_test.rb +0 -817
- data/spec/integration/spec_helper.rb +0 -48
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -374
- data/spec/integration/type_test.rb +0 -133
- data/spec/model/association_reflection_spec.rb +0 -525
- data/spec/model/associations_spec.rb +0 -4426
- data/spec/model/base_spec.rb +0 -759
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -149
- data/spec/model/eager_loading_spec.rb +0 -2137
- data/spec/model/hooks_spec.rb +0 -604
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -982
- data/spec/model/plugins_spec.rb +0 -299
- data/spec/model/record_spec.rb +0 -2147
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -193
- data/spec/sequel_coverage.rb +0 -15
- 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
|
|
25
|
+
# or pg_jsonb method:
|
|
24
26
|
#
|
|
25
|
-
# j = Sequel
|
|
26
|
-
# jb = Sequel
|
|
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
|
|
62
|
-
# j.
|
|
63
|
-
# j.
|
|
64
|
-
# j.
|
|
65
|
-
# j.
|
|
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(:
|
|
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
|
-
#
|
|
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
|
|
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 ==
|
|
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 =
|
|
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!(
|
|
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!(
|
|
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
|
-
#
|
|
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.
|
|
137
|
+
db.instance_exec do
|
|
138
|
+
@pg_range_schema_types ||= {}
|
|
193
139
|
extend_datasets(DatasetMethods)
|
|
194
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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 =
|
|
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 <<
|
|
445
|
+
sql << s.to_s << "("
|
|
420
446
|
ds.literal_append(sql, self.begin)
|
|
421
|
-
sql <<
|
|
447
|
+
sql << ','
|
|
422
448
|
ds.literal_append(sql, self.end)
|
|
423
|
-
sql <<
|
|
424
|
-
ds.literal_append(sql, "#{exclude_begin? ?
|
|
425
|
-
sql <<
|
|
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 <<
|
|
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
|
-
|
|
440
|
-
raise(Error, "cannot create ruby range when PostgreSQL range has unbounded
|
|
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
|
-
|
|
496
|
+
'empty'
|
|
466
497
|
else
|
|
467
|
-
"#{exclude_begin? ?
|
|
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
|
-
|
|
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
|
-
|
|
520
|
+
'""'
|
|
490
521
|
else
|
|
491
|
-
k.gsub(
|
|
522
|
+
k.gsub(/("|,|\\|\[|\]|\(|\))/, '\\\\\1')
|
|
492
523
|
end
|
|
493
524
|
else
|
|
494
|
-
ds.literal(k).gsub(
|
|
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
|