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
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
module Sequel
|
|
2
4
|
class Dataset
|
|
3
5
|
# ---------------------
|
|
@@ -10,30 +12,31 @@ module Sequel
|
|
|
10
12
|
# in the extension).
|
|
11
13
|
EXTENSIONS = {}
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
EMPTY_ARRAY = [].freeze
|
|
16
|
+
|
|
17
|
+
# The dataset options that require the removal of cached columns if changed.
|
|
15
18
|
COLUMN_CHANGE_OPTS = [:select, :sql, :from, :join].freeze
|
|
16
19
|
|
|
17
20
|
# Which options don't affect the SQL generation. Used by simple_select_all?
|
|
18
21
|
# to determine if this is a simple SELECT * FROM table.
|
|
19
|
-
NON_SQL_OPTIONS = [:server, :
|
|
22
|
+
NON_SQL_OPTIONS = [:server, :graph, :row_proc, :quote_identifiers, :skip_symbol_cache].freeze
|
|
20
23
|
|
|
21
24
|
# These symbols have _join methods created (e.g. inner_join) that
|
|
22
25
|
# call join_table with the symbol, passing along the arguments and
|
|
23
26
|
# block from the method call.
|
|
24
|
-
CONDITIONED_JOIN_TYPES = [:inner, :full_outer, :right_outer, :left_outer, :full, :right, :left]
|
|
27
|
+
CONDITIONED_JOIN_TYPES = [:inner, :full_outer, :right_outer, :left_outer, :full, :right, :left].freeze
|
|
25
28
|
|
|
26
29
|
# These symbols have _join methods created (e.g. natural_join).
|
|
27
30
|
# They accept a table argument and options hash which is passed to join_table,
|
|
28
31
|
# and they raise an error if called with a block.
|
|
29
|
-
UNCONDITIONED_JOIN_TYPES = [:natural, :natural_left, :natural_right, :natural_full, :cross]
|
|
32
|
+
UNCONDITIONED_JOIN_TYPES = [:natural, :natural_left, :natural_right, :natural_full, :cross].freeze
|
|
30
33
|
|
|
31
34
|
# All methods that return modified datasets with a joined table added.
|
|
32
|
-
JOIN_METHODS = (CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES).map{|x| "#{x}_join".to_sym} + [:join, :join_table]
|
|
35
|
+
JOIN_METHODS = ((CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES).map{|x| "#{x}_join".to_sym} + [:join, :join_table]).freeze
|
|
33
36
|
|
|
34
37
|
# Methods that return modified datasets
|
|
35
|
-
QUERY_METHODS = (<<-METHS).split.map(&:to_sym) + JOIN_METHODS
|
|
36
|
-
add_graph_aliases
|
|
38
|
+
QUERY_METHODS = ((<<-METHS).split.map(&:to_sym) + JOIN_METHODS).freeze
|
|
39
|
+
add_graph_aliases distinct except exclude exclude_having
|
|
37
40
|
filter for_update from from_self graph grep group group_and_count group_append group_by having intersect invert
|
|
38
41
|
limit lock_style naked offset or order order_append order_by order_more order_prepend qualify
|
|
39
42
|
reverse reverse_order select select_all select_append select_group select_more server
|
|
@@ -62,24 +65,44 @@ module Sequel
|
|
|
62
65
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
63
66
|
end
|
|
64
67
|
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
# On Ruby 2.4+, use clone(:freeze=>false) to create clones, because
|
|
69
|
+
# we use true freezing in that case, and we need to modify the opts
|
|
70
|
+
# in the frozen copy.
|
|
71
|
+
#
|
|
72
|
+
# On Ruby <2.4, just use Object#clone directly, since we don't
|
|
73
|
+
# use true freezing as it isn't possible.
|
|
74
|
+
if TRUE_FREEZE
|
|
75
|
+
# Save original clone implementation, as some other methods need
|
|
76
|
+
# to call it internally.
|
|
77
|
+
alias _clone clone
|
|
78
|
+
private :_clone
|
|
79
|
+
|
|
80
|
+
# Returns a new clone of the dataset with the given options merged.
|
|
81
|
+
# If the options changed include options in COLUMN_CHANGE_OPTS, the cached
|
|
82
|
+
# columns are deleted. This method should generally not be called
|
|
83
|
+
# directly by user code.
|
|
84
|
+
def clone(opts = nil || (return self))
|
|
85
|
+
# return self used above because clone is called by almost all
|
|
86
|
+
# other query methods, and it is the fastest approach
|
|
87
|
+
c = super(:freeze=>false)
|
|
88
|
+
c.opts.merge!(opts)
|
|
89
|
+
unless opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
|
|
90
|
+
c.clear_columns_cache
|
|
91
|
+
end
|
|
92
|
+
c.freeze
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
# :nocov:
|
|
96
|
+
def clone(opts = OPTS) # :nodoc:
|
|
97
|
+
c = super()
|
|
98
|
+
c.opts.merge!(opts)
|
|
99
|
+
unless opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
|
|
100
|
+
c.clear_columns_cache
|
|
101
|
+
end
|
|
102
|
+
c.opts.freeze
|
|
103
|
+
c
|
|
81
104
|
end
|
|
82
|
-
|
|
105
|
+
# :nocov:
|
|
83
106
|
end
|
|
84
107
|
|
|
85
108
|
# Returns a copy of the dataset with the SQL DISTINCT clause. The DISTINCT
|
|
@@ -92,10 +115,19 @@ module Sequel
|
|
|
92
115
|
# DB[:items].distinct # SQL: SELECT DISTINCT * FROM items
|
|
93
116
|
# DB[:items].order(:id).distinct(:id) # SQL: SELECT DISTINCT ON (id) * FROM items ORDER BY id
|
|
94
117
|
# DB[:items].order(:id).distinct{func(:id)} # SQL: SELECT DISTINCT ON (func(id)) * FROM items ORDER BY id
|
|
118
|
+
#
|
|
119
|
+
# There is support for emualting the DISTINCT ON support in MySQL, but it
|
|
120
|
+
# does not support the ORDER of the dataset, and also doesn't work in many
|
|
121
|
+
# cases if the ONLY_FULL_GROUP_BY sql_mode is used, which is the default on
|
|
122
|
+
# MySQL 5.7.5+.
|
|
95
123
|
def distinct(*args, &block)
|
|
96
124
|
virtual_row_columns(args, block)
|
|
97
|
-
|
|
98
|
-
|
|
125
|
+
if args.empty?
|
|
126
|
+
cached_dataset(:_distinct_ds){clone(:distinct => EMPTY_ARRAY)}
|
|
127
|
+
else
|
|
128
|
+
raise(InvalidOperation, "DISTINCT ON not supported") unless supports_distinct_on?
|
|
129
|
+
clone(:distinct => args.freeze)
|
|
130
|
+
end
|
|
99
131
|
end
|
|
100
132
|
|
|
101
133
|
# Adds an EXCEPT clause using a second dataset object.
|
|
@@ -110,10 +142,10 @@ module Sequel
|
|
|
110
142
|
# DB[:items].except(DB[:other_items])
|
|
111
143
|
# # SELECT * FROM (SELECT * FROM items EXCEPT SELECT * FROM other_items) AS t1
|
|
112
144
|
#
|
|
113
|
-
# DB[:items].except(DB[:other_items], :
|
|
145
|
+
# DB[:items].except(DB[:other_items], all: true, from_self: false)
|
|
114
146
|
# # SELECT * FROM items EXCEPT ALL SELECT * FROM other_items
|
|
115
147
|
#
|
|
116
|
-
# DB[:items].except(DB[:other_items], :
|
|
148
|
+
# DB[:items].except(DB[:other_items], alias: :i)
|
|
117
149
|
# # SELECT * FROM (SELECT * FROM items EXCEPT SELECT * FROM other_items) AS i
|
|
118
150
|
def except(dataset, opts=OPTS)
|
|
119
151
|
raise(InvalidOperation, "EXCEPT not supported") unless supports_intersect_except?
|
|
@@ -124,31 +156,59 @@ module Sequel
|
|
|
124
156
|
# Performs the inverse of Dataset#where. Note that if you have multiple filter
|
|
125
157
|
# conditions, this is not the same as a negation of all conditions.
|
|
126
158
|
#
|
|
127
|
-
# DB[:items].exclude(:
|
|
159
|
+
# DB[:items].exclude(category: 'software')
|
|
128
160
|
# # SELECT * FROM items WHERE (category != 'software')
|
|
129
161
|
#
|
|
130
|
-
# DB[:items].exclude(:
|
|
162
|
+
# DB[:items].exclude(category: 'software', id: 3)
|
|
131
163
|
# # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
|
|
164
|
+
#
|
|
165
|
+
# Also note that SQL uses 3-valued boolean logic (+true+, +false+, +NULL+), so
|
|
166
|
+
# the inverse of a true condition is a false condition, and will still
|
|
167
|
+
# not match rows that were NULL originally. If you take the earlier
|
|
168
|
+
# example:
|
|
169
|
+
#
|
|
170
|
+
# DB[:items].exclude(category: 'software')
|
|
171
|
+
# # SELECT * FROM items WHERE (category != 'software')
|
|
172
|
+
#
|
|
173
|
+
# Note that this does not match rows where +category+ is +NULL+. This
|
|
174
|
+
# is because +NULL+ is an unknown value, and you do not know whether
|
|
175
|
+
# or not the +NULL+ category is +software+. You can explicitly
|
|
176
|
+
# specify how to handle +NULL+ values if you want:
|
|
177
|
+
#
|
|
178
|
+
# DB[:items].exclude(Sequel.~(category: nil) & {category: 'software'})
|
|
179
|
+
# # SELECT * FROM items WHERE ((category IS NULL) OR (category != 'software'))
|
|
132
180
|
def exclude(*cond, &block)
|
|
133
|
-
|
|
181
|
+
add_filter(:where, cond, true, &block)
|
|
134
182
|
end
|
|
135
183
|
|
|
136
184
|
# Inverts the given conditions and adds them to the HAVING clause.
|
|
137
185
|
#
|
|
138
186
|
# DB[:items].select_group(:name).exclude_having{count(name) < 2}
|
|
139
187
|
# # SELECT name FROM items GROUP BY name HAVING (count(name) >= 2)
|
|
188
|
+
#
|
|
189
|
+
# See documentation for exclude for how inversion is handled in regards
|
|
190
|
+
# to SQL 3-valued boolean logic.
|
|
140
191
|
def exclude_having(*cond, &block)
|
|
141
|
-
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Alias for exclude.
|
|
145
|
-
def exclude_where(*cond, &block)
|
|
146
|
-
exclude(*cond, &block)
|
|
192
|
+
add_filter(:having, cond, true, &block)
|
|
147
193
|
end
|
|
148
194
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
195
|
+
if TRUE_FREEZE
|
|
196
|
+
# Return a clone of the dataset loaded with the given dataset extensions.
|
|
197
|
+
# If no related extension file exists or the extension does not have
|
|
198
|
+
# specific support for Dataset objects, an Error will be raised.
|
|
199
|
+
def extension(*a)
|
|
200
|
+
c = _clone(:freeze=>false)
|
|
201
|
+
c.send(:_extension!, a)
|
|
202
|
+
c.freeze
|
|
203
|
+
end
|
|
204
|
+
else
|
|
205
|
+
# :nocov:
|
|
206
|
+
def extension(*exts) # :nodoc:
|
|
207
|
+
c = clone
|
|
208
|
+
c.send(:_extension!, exts)
|
|
209
|
+
c
|
|
210
|
+
end
|
|
211
|
+
# :nocov:
|
|
152
212
|
end
|
|
153
213
|
|
|
154
214
|
# Alias for where.
|
|
@@ -160,7 +220,7 @@ module Sequel
|
|
|
160
220
|
#
|
|
161
221
|
# DB[:table].for_update # SELECT * FROM table FOR UPDATE
|
|
162
222
|
def for_update
|
|
163
|
-
lock_style(:update)
|
|
223
|
+
cached_dataset(:_for_update_ds){lock_style(:update)}
|
|
164
224
|
end
|
|
165
225
|
|
|
166
226
|
# Returns a copy of the dataset with the source changed. If no
|
|
@@ -197,14 +257,17 @@ module Sequel
|
|
|
197
257
|
s
|
|
198
258
|
end
|
|
199
259
|
end
|
|
200
|
-
o = {:from=>source.empty? ? nil : source}
|
|
201
|
-
o[:with] = (opts[:with] ||
|
|
260
|
+
o = {:from=>source.empty? ? nil : source.freeze}
|
|
261
|
+
o[:with] = ((opts[:with] || EMPTY_ARRAY) + ctes).freeze if ctes
|
|
202
262
|
o[:num_dataset_sources] = table_alias_num if table_alias_num > 0
|
|
203
263
|
clone(o)
|
|
204
264
|
end
|
|
205
265
|
|
|
206
266
|
# Returns a dataset selecting from the current dataset.
|
|
207
|
-
#
|
|
267
|
+
# Options:
|
|
268
|
+
# :alias :: Controls the alias of the table
|
|
269
|
+
# :column_aliases :: Also aliases columns, using derived column lists.
|
|
270
|
+
# Only used in conjunction with :alias.
|
|
208
271
|
#
|
|
209
272
|
# ds = DB[:items].order(:name).select(:id, :name)
|
|
210
273
|
# # SELECT id,name FROM items ORDER BY name
|
|
@@ -212,21 +275,29 @@ module Sequel
|
|
|
212
275
|
# ds.from_self
|
|
213
276
|
# # SELECT * FROM (SELECT id, name FROM items ORDER BY name) AS t1
|
|
214
277
|
#
|
|
215
|
-
# ds.from_self(:
|
|
278
|
+
# ds.from_self(alias: :foo)
|
|
216
279
|
# # SELECT * FROM (SELECT id, name FROM items ORDER BY name) AS foo
|
|
217
280
|
#
|
|
218
|
-
# ds.from_self(:
|
|
281
|
+
# ds.from_self(alias: :foo, column_aliases: [:c1, :c2])
|
|
219
282
|
# # SELECT * FROM (SELECT id, name FROM items ORDER BY name) AS foo(c1, c2)
|
|
220
283
|
def from_self(opts=OPTS)
|
|
221
284
|
fs = {}
|
|
222
|
-
@opts.keys.each{|k| fs[k] = nil unless
|
|
223
|
-
|
|
285
|
+
@opts.keys.each{|k| fs[k] = nil unless non_sql_option?(k)}
|
|
286
|
+
pr = proc do
|
|
287
|
+
c = clone(fs).from(opts[:alias] ? as(opts[:alias], opts[:column_aliases]) : self)
|
|
288
|
+
if cols = _columns
|
|
289
|
+
c.send(:columns=, cols)
|
|
290
|
+
end
|
|
291
|
+
c
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
opts.empty? ? cached_dataset(:_from_self_ds, &pr) : pr.call
|
|
224
295
|
end
|
|
225
296
|
|
|
226
297
|
# Match any of the columns to any of the patterns. The terms can be
|
|
227
|
-
# strings (which use LIKE) or regular expressions
|
|
228
|
-
#
|
|
229
|
-
#
|
|
298
|
+
# strings (which use LIKE) or regular expressions if the database supports that.
|
|
299
|
+
# Note that the total number of pattern matches will be
|
|
300
|
+
# Array(columns).length * Array(terms).length,
|
|
230
301
|
# which could cause performance issues.
|
|
231
302
|
#
|
|
232
303
|
# Options (all are boolean):
|
|
@@ -247,28 +318,29 @@ module Sequel
|
|
|
247
318
|
# # SELECT * FROM items WHERE ((a LIKE '%test%' ESCAPE '\') OR (a LIKE 'foo' ESCAPE '\')
|
|
248
319
|
# # OR (b LIKE '%test%' ESCAPE '\') OR (b LIKE 'foo' ESCAPE '\'))
|
|
249
320
|
#
|
|
250
|
-
# dataset.grep([:a, :b], %w'%foo% %bar%', :
|
|
321
|
+
# dataset.grep([:a, :b], %w'%foo% %bar%', all_patterns: true)
|
|
251
322
|
# # SELECT * FROM a WHERE (((a LIKE '%foo%' ESCAPE '\') OR (b LIKE '%foo%' ESCAPE '\'))
|
|
252
323
|
# # AND ((a LIKE '%bar%' ESCAPE '\') OR (b LIKE '%bar%' ESCAPE '\')))
|
|
253
324
|
#
|
|
254
|
-
# dataset.grep([:a, :b], %w'%foo% %bar%', :
|
|
325
|
+
# dataset.grep([:a, :b], %w'%foo% %bar%', all_columns: true)
|
|
255
326
|
# # SELECT * FROM a WHERE (((a LIKE '%foo%' ESCAPE '\') OR (a LIKE '%bar%' ESCAPE '\'))
|
|
256
327
|
# # AND ((b LIKE '%foo%' ESCAPE '\') OR (b LIKE '%bar%' ESCAPE '\')))
|
|
257
328
|
#
|
|
258
|
-
# dataset.grep([:a, :b], %w'%foo% %bar%', :
|
|
329
|
+
# dataset.grep([:a, :b], %w'%foo% %bar%', all_patterns: true, all_columns: true)
|
|
259
330
|
# # SELECT * FROM a WHERE ((a LIKE '%foo%' ESCAPE '\') AND (b LIKE '%foo%' ESCAPE '\')
|
|
260
331
|
# # AND (a LIKE '%bar%' ESCAPE '\') AND (b LIKE '%bar%' ESCAPE '\'))
|
|
261
332
|
def grep(columns, patterns, opts=OPTS)
|
|
333
|
+
column_op = opts[:all_columns] ? :AND : :OR
|
|
262
334
|
if opts[:all_patterns]
|
|
263
335
|
conds = Array(patterns).map do |pat|
|
|
264
|
-
SQL::BooleanExpression.new(
|
|
336
|
+
SQL::BooleanExpression.new(column_op, *Array(columns).map{|c| SQL::StringExpression.like(c, pat, opts)})
|
|
265
337
|
end
|
|
266
|
-
where(SQL::BooleanExpression.new(
|
|
338
|
+
where(SQL::BooleanExpression.new(:AND, *conds))
|
|
267
339
|
else
|
|
268
340
|
conds = Array(columns).map do |c|
|
|
269
341
|
SQL::BooleanExpression.new(:OR, *Array(patterns).map{|pat| SQL::StringExpression.like(c, pat, opts)})
|
|
270
342
|
end
|
|
271
|
-
where(SQL::BooleanExpression.new(
|
|
343
|
+
where(SQL::BooleanExpression.new(column_op, *conds))
|
|
272
344
|
end
|
|
273
345
|
end
|
|
274
346
|
|
|
@@ -281,7 +353,7 @@ module Sequel
|
|
|
281
353
|
# DB[:items].group{[a, sum(b)]} # SELECT * FROM items GROUP BY a, sum(b)
|
|
282
354
|
def group(*columns, &block)
|
|
283
355
|
virtual_row_columns(columns, block)
|
|
284
|
-
clone(:group => (columns.compact.empty? ? nil : columns))
|
|
356
|
+
clone(:group => (columns.compact.empty? ? nil : columns.freeze))
|
|
285
357
|
end
|
|
286
358
|
|
|
287
359
|
# Alias of group
|
|
@@ -303,15 +375,15 @@ module Sequel
|
|
|
303
375
|
# # SELECT first_name, last_name, count(*) AS count FROM items GROUP BY first_name, last_name
|
|
304
376
|
# # => [{:first_name=>'a', :last_name=>'b', :count=>1}, ...]
|
|
305
377
|
#
|
|
306
|
-
# DB[:items].group_and_count(:
|
|
378
|
+
# DB[:items].group_and_count(Sequel[:first_name].as(:name)).all
|
|
307
379
|
# # SELECT first_name AS name, count(*) AS count FROM items GROUP BY first_name
|
|
308
380
|
# # => [{:name=>'a', :count=>1}, ...]
|
|
309
381
|
#
|
|
310
|
-
# DB[:items].group_and_count{substr(first_name, 1, 1).as(initial)}.all
|
|
382
|
+
# DB[:items].group_and_count{substr(:first_name, 1, 1).as(:initial)}.all
|
|
311
383
|
# # SELECT substr(first_name, 1, 1) AS initial, count(*) AS count FROM items GROUP BY substr(first_name, 1, 1)
|
|
312
384
|
# # => [{:initial=>'a', :count=>1}, ...]
|
|
313
385
|
def group_and_count(*columns, &block)
|
|
314
|
-
select_group(*columns, &block).
|
|
386
|
+
select_group(*columns, &block).select_append(COUNT_OF_ALL_AS_COUNT)
|
|
315
387
|
end
|
|
316
388
|
|
|
317
389
|
# Returns a copy of the dataset with the given columns added to the list of
|
|
@@ -345,10 +417,10 @@ module Sequel
|
|
|
345
417
|
|
|
346
418
|
# Returns a copy of the dataset with the HAVING conditions changed. See #where for argument types.
|
|
347
419
|
#
|
|
348
|
-
# DB[:items].group(:sum).having(:
|
|
420
|
+
# DB[:items].group(:sum).having(sum: 10)
|
|
349
421
|
# # SELECT * FROM items GROUP BY sum HAVING (sum = 10)
|
|
350
422
|
def having(*cond, &block)
|
|
351
|
-
|
|
423
|
+
add_filter(:having, cond, &block)
|
|
352
424
|
end
|
|
353
425
|
|
|
354
426
|
# Adds an INTERSECT clause using a second dataset object.
|
|
@@ -363,10 +435,10 @@ module Sequel
|
|
|
363
435
|
# DB[:items].intersect(DB[:other_items])
|
|
364
436
|
# # SELECT * FROM (SELECT * FROM items INTERSECT SELECT * FROM other_items) AS t1
|
|
365
437
|
#
|
|
366
|
-
# DB[:items].intersect(DB[:other_items], :
|
|
438
|
+
# DB[:items].intersect(DB[:other_items], all: true, from_self: false)
|
|
367
439
|
# # SELECT * FROM items INTERSECT ALL SELECT * FROM other_items
|
|
368
440
|
#
|
|
369
|
-
# DB[:items].intersect(DB[:other_items], :
|
|
441
|
+
# DB[:items].intersect(DB[:other_items], alias: :i)
|
|
370
442
|
# # SELECT * FROM (SELECT * FROM items INTERSECT SELECT * FROM other_items) AS i
|
|
371
443
|
def intersect(dataset, opts=OPTS)
|
|
372
444
|
raise(InvalidOperation, "INTERSECT not supported") unless supports_intersect_except?
|
|
@@ -377,20 +449,25 @@ module Sequel
|
|
|
377
449
|
# Inverts the current WHERE and HAVING clauses. If there is neither a
|
|
378
450
|
# WHERE or HAVING clause, adds a WHERE clause that is always false.
|
|
379
451
|
#
|
|
380
|
-
# DB[:items].where(:
|
|
452
|
+
# DB[:items].where(category: 'software').invert
|
|
381
453
|
# # SELECT * FROM items WHERE (category != 'software')
|
|
382
454
|
#
|
|
383
|
-
# DB[:items].where(:
|
|
455
|
+
# DB[:items].where(category: 'software', id: 3).invert
|
|
384
456
|
# # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
|
|
457
|
+
#
|
|
458
|
+
# See documentation for exclude for how inversion is handled in regards
|
|
459
|
+
# to SQL 3-valued boolean logic.
|
|
385
460
|
def invert
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
where
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
461
|
+
cached_dataset(:_invert_ds) do
|
|
462
|
+
having, where = @opts.values_at(:having, :where)
|
|
463
|
+
if having.nil? && where.nil?
|
|
464
|
+
where(false)
|
|
465
|
+
else
|
|
466
|
+
o = {}
|
|
467
|
+
o[:having] = SQL::BooleanExpression.invert(having) if having
|
|
468
|
+
o[:where] = SQL::BooleanExpression.invert(where) if where
|
|
469
|
+
clone(o)
|
|
470
|
+
end
|
|
394
471
|
end
|
|
395
472
|
end
|
|
396
473
|
|
|
@@ -447,10 +524,10 @@ module Sequel
|
|
|
447
524
|
# DB[:a].join_table(:cross, :b)
|
|
448
525
|
# # SELECT * FROM a CROSS JOIN b
|
|
449
526
|
#
|
|
450
|
-
# DB[:a].join_table(:inner, DB[:b], :
|
|
527
|
+
# DB[:a].join_table(:inner, DB[:b], c: d)
|
|
451
528
|
# # SELECT * FROM a INNER JOIN (SELECT * FROM b) AS t1 ON (t1.c = a.d)
|
|
452
529
|
#
|
|
453
|
-
# DB[:a].join_table(:left, :
|
|
530
|
+
# DB[:a].join_table(:left, Sequel[:b].as(:c), [:d])
|
|
454
531
|
# # SELECT * FROM a LEFT JOIN b AS c USING (d)
|
|
455
532
|
#
|
|
456
533
|
# DB[:a].natural_join(:b).join_table(:inner, :c) do |ta, jta, js|
|
|
@@ -472,8 +549,6 @@ module Sequel
|
|
|
472
549
|
end
|
|
473
550
|
|
|
474
551
|
table_alias = options[:table_alias]
|
|
475
|
-
last_alias = options[:implicit_qualifier]
|
|
476
|
-
qualify_type = options[:qualify]
|
|
477
552
|
|
|
478
553
|
if table.is_a?(SQL::AliasedExpression)
|
|
479
554
|
table_expr = if table_alias
|
|
@@ -503,16 +578,17 @@ module Sequel
|
|
|
503
578
|
raise(Sequel::Error, "can't use a block if providing an array of symbols as expr") if block
|
|
504
579
|
SQL::JoinUsingClause.new(expr, type, table_expr)
|
|
505
580
|
else
|
|
506
|
-
last_alias
|
|
581
|
+
last_alias = options[:implicit_qualifier] || @opts[:last_joined_table] || first_source_alias
|
|
582
|
+
qualify_type = options[:qualify]
|
|
507
583
|
if Sequel.condition_specifier?(expr)
|
|
508
|
-
expr = expr.
|
|
584
|
+
expr = expr.map do |k, v|
|
|
509
585
|
qualify_type = default_join_table_qualification if qualify_type.nil?
|
|
510
586
|
case qualify_type
|
|
511
587
|
when false
|
|
512
588
|
nil # Do no qualification
|
|
513
589
|
when :deep
|
|
514
|
-
k = Sequel::Qualifier.new(
|
|
515
|
-
v = Sequel::Qualifier.new(
|
|
590
|
+
k = Sequel::Qualifier.new(table_name).transform(k)
|
|
591
|
+
v = Sequel::Qualifier.new(last_alias).transform(v)
|
|
516
592
|
else
|
|
517
593
|
k = qualified_column_name(k, table_name) if k.is_a?(Symbol)
|
|
518
594
|
v = qualified_column_name(v, last_alias) if v.is_a?(Symbol)
|
|
@@ -522,13 +598,13 @@ module Sequel
|
|
|
522
598
|
expr = SQL::BooleanExpression.from_value_pairs(expr)
|
|
523
599
|
end
|
|
524
600
|
if block
|
|
525
|
-
expr2 = yield(table_name, last_alias, @opts[:join] ||
|
|
601
|
+
expr2 = yield(table_name, last_alias, @opts[:join] || EMPTY_ARRAY)
|
|
526
602
|
expr = expr ? SQL::BooleanExpression.new(:AND, expr, expr2) : expr2
|
|
527
603
|
end
|
|
528
604
|
SQL::JoinOnClause.new(expr, type, table_expr)
|
|
529
605
|
end
|
|
530
606
|
|
|
531
|
-
opts = {:join => (@opts[:join] ||
|
|
607
|
+
opts = {:join => ((@opts[:join] || EMPTY_ARRAY) + [join]).freeze}
|
|
532
608
|
opts[:last_joined_table] = table_name unless options[:reset_implicit_qualifier] == false
|
|
533
609
|
opts[:num_dataset_sources] = table_alias_num if table_alias_num
|
|
534
610
|
clone(opts)
|
|
@@ -551,10 +627,10 @@ module Sequel
|
|
|
551
627
|
# or JOIN clauses, it will surround the subquery with LATERAL to enable it
|
|
552
628
|
# to deal with previous tables in the query:
|
|
553
629
|
#
|
|
554
|
-
# DB.from(:a, DB[:b].where(:
|
|
630
|
+
# DB.from(:a, DB[:b].where(Sequel[:a][:c]=>Sequel[:b][:d]).lateral)
|
|
555
631
|
# # SELECT * FROM a, LATERAL (SELECT * FROM b WHERE (a.c = b.d))
|
|
556
632
|
def lateral
|
|
557
|
-
clone(:lateral=>true)
|
|
633
|
+
cached_dataset(:_lateral_ds){clone(:lateral=>true)}
|
|
558
634
|
end
|
|
559
635
|
|
|
560
636
|
# If given an integer, the dataset will contain only the first l results.
|
|
@@ -603,14 +679,23 @@ module Sequel
|
|
|
603
679
|
|
|
604
680
|
# Returns a cloned dataset without a row_proc.
|
|
605
681
|
#
|
|
606
|
-
# ds = DB[:items]
|
|
607
|
-
# ds.row_proc = proc(&:invert)
|
|
682
|
+
# ds = DB[:items].with_row_proc(:invert.to_proc)
|
|
608
683
|
# ds.all # => [{2=>:id}]
|
|
609
684
|
# ds.naked.all # => [{:id=>2}]
|
|
610
685
|
def naked
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
686
|
+
cached_dataset(:_naked_ds){with_row_proc(nil)}
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
# Returns a copy of the dataset that will raise a DatabaseLockTimeout instead
|
|
690
|
+
# of waiting for rows that are locked by another transaction
|
|
691
|
+
#
|
|
692
|
+
# DB[:items].for_update.nowait
|
|
693
|
+
# # SELECT * FROM items FOR UPDATE NOWAIT
|
|
694
|
+
def nowait
|
|
695
|
+
cached_dataset(:_nowait_ds) do
|
|
696
|
+
raise(Error, 'This dataset does not support raises errors instead of waiting for locked rows') unless supports_nowait?
|
|
697
|
+
clone(:nowait=>true)
|
|
698
|
+
end
|
|
614
699
|
end
|
|
615
700
|
|
|
616
701
|
# Returns a copy of the dataset with a specified order. Can be safely combined with limit.
|
|
@@ -626,17 +711,17 @@ module Sequel
|
|
|
626
711
|
clone(:offset => o)
|
|
627
712
|
end
|
|
628
713
|
|
|
629
|
-
# Adds an alternate filter to an existing
|
|
630
|
-
#
|
|
714
|
+
# Adds an alternate filter to an existing WHERE clause using OR. If there
|
|
715
|
+
# is no WHERE clause, then the default is WHERE true, and OR would be redundant,
|
|
716
|
+
# so return the dataset in that case.
|
|
631
717
|
#
|
|
632
718
|
# DB[:items].where(:a).or(:b) # SELECT * FROM items WHERE a OR b
|
|
719
|
+
# DB[:items].or(:b) # SELECT * FROM items
|
|
633
720
|
def or(*cond, &block)
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
if v.nil? || (cond.respond_to?(:empty?) && cond.empty? && !block)
|
|
637
|
-
clone
|
|
721
|
+
if @opts[:where].nil?
|
|
722
|
+
self
|
|
638
723
|
else
|
|
639
|
-
|
|
724
|
+
add_filter(:where, cond, false, :OR, &block)
|
|
640
725
|
end
|
|
641
726
|
end
|
|
642
727
|
|
|
@@ -649,19 +734,24 @@ module Sequel
|
|
|
649
734
|
# DB[:items].order(:name) # SELECT * FROM items ORDER BY name
|
|
650
735
|
# DB[:items].order(:a, :b) # SELECT * FROM items ORDER BY a, b
|
|
651
736
|
# DB[:items].order(Sequel.lit('a + b')) # SELECT * FROM items ORDER BY a + b
|
|
652
|
-
# DB[:items].order(:a + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
737
|
+
# DB[:items].order(Sequel[:a] + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
653
738
|
# DB[:items].order(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name DESC
|
|
654
739
|
# DB[:items].order(Sequel.asc(:name, :nulls=>:last)) # SELECT * FROM items ORDER BY name ASC NULLS LAST
|
|
655
740
|
# DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
|
|
656
741
|
# DB[:items].order(nil) # SELECT * FROM items
|
|
657
742
|
def order(*columns, &block)
|
|
658
743
|
virtual_row_columns(columns, block)
|
|
659
|
-
clone(:order => (columns.compact.empty?) ? nil : columns)
|
|
744
|
+
clone(:order => (columns.compact.empty?) ? nil : columns.freeze)
|
|
660
745
|
end
|
|
661
746
|
|
|
662
|
-
#
|
|
747
|
+
# Returns a copy of the dataset with the order columns added
|
|
748
|
+
# to the end of the existing order.
|
|
749
|
+
#
|
|
750
|
+
# DB[:items].order(:a).order(:b) # SELECT * FROM items ORDER BY b
|
|
751
|
+
# DB[:items].order(:a).order_append(:b) # SELECT * FROM items ORDER BY a, b
|
|
663
752
|
def order_append(*columns, &block)
|
|
664
|
-
|
|
753
|
+
columns = @opts[:order] + columns if @opts[:order]
|
|
754
|
+
order(*columns, &block)
|
|
665
755
|
end
|
|
666
756
|
|
|
667
757
|
# Alias of order
|
|
@@ -669,14 +759,9 @@ module Sequel
|
|
|
669
759
|
order(*columns, &block)
|
|
670
760
|
end
|
|
671
761
|
|
|
672
|
-
#
|
|
673
|
-
# to the end of the existing order.
|
|
674
|
-
#
|
|
675
|
-
# DB[:items].order(:a).order(:b) # SELECT * FROM items ORDER BY b
|
|
676
|
-
# DB[:items].order(:a).order_more(:b) # SELECT * FROM items ORDER BY a, b
|
|
762
|
+
# Alias of order_append.
|
|
677
763
|
def order_more(*columns, &block)
|
|
678
|
-
columns
|
|
679
|
-
order(*columns, &block)
|
|
764
|
+
order_append(*columns, &block)
|
|
680
765
|
end
|
|
681
766
|
|
|
682
767
|
# Returns a copy of the dataset with the order columns added
|
|
@@ -686,25 +771,30 @@ module Sequel
|
|
|
686
771
|
# DB[:items].order(:a).order_prepend(:b) # SELECT * FROM items ORDER BY b, a
|
|
687
772
|
def order_prepend(*columns, &block)
|
|
688
773
|
ds = order(*columns, &block)
|
|
689
|
-
@opts[:order] ? ds.
|
|
774
|
+
@opts[:order] ? ds.order_append(*@opts[:order]) : ds
|
|
690
775
|
end
|
|
691
776
|
|
|
692
777
|
# Qualify to the given table, or first source if no table is given.
|
|
693
778
|
#
|
|
694
|
-
# DB[:items].where(:
|
|
779
|
+
# DB[:items].where(id: 1).qualify
|
|
695
780
|
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
696
781
|
#
|
|
697
|
-
# DB[:items].where(:
|
|
782
|
+
# DB[:items].where(id: 1).qualify(:i)
|
|
698
783
|
# # SELECT i.* FROM items WHERE (i.id = 1)
|
|
699
|
-
def qualify(table=first_source)
|
|
784
|
+
def qualify(table=(cache=true; first_source))
|
|
700
785
|
o = @opts
|
|
701
|
-
return
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
h
|
|
786
|
+
return self if o[:sql]
|
|
787
|
+
|
|
788
|
+
pr = proc do
|
|
789
|
+
h = {}
|
|
790
|
+
(o.keys & QUALIFY_KEYS).each do |k|
|
|
791
|
+
h[k] = qualified_expression(o[k], table)
|
|
792
|
+
end
|
|
793
|
+
h[:select] = [SQL::ColumnAll.new(table)].freeze if !o[:select] || o[:select].empty?
|
|
794
|
+
clone(h)
|
|
705
795
|
end
|
|
706
|
-
|
|
707
|
-
|
|
796
|
+
|
|
797
|
+
cache ? cached_dataset(:_qualify_ds, &pr) : pr.call
|
|
708
798
|
end
|
|
709
799
|
|
|
710
800
|
# Modify the RETURNING clause, only supported on a few databases. If returning
|
|
@@ -715,9 +805,26 @@ module Sequel
|
|
|
715
805
|
# DB[:items].returning # RETURNING *
|
|
716
806
|
# DB[:items].returning(nil) # RETURNING NULL
|
|
717
807
|
# DB[:items].returning(:id, :name) # RETURNING id, name
|
|
808
|
+
#
|
|
809
|
+
# DB[:items].returning.insert(:a=>1) do |hash|
|
|
810
|
+
# # hash for each row inserted, with values for all columns
|
|
811
|
+
# end
|
|
812
|
+
# DB[:items].returning.update(:a=>1) do |hash|
|
|
813
|
+
# # hash for each row updated, with values for all columns
|
|
814
|
+
# end
|
|
815
|
+
# DB[:items].returning.delete(:a=>1) do |hash|
|
|
816
|
+
# # hash for each row deleted, with values for all columns
|
|
817
|
+
# end
|
|
718
818
|
def returning(*values)
|
|
719
|
-
|
|
720
|
-
|
|
819
|
+
if values.empty?
|
|
820
|
+
cached_dataset(:_returning_ds) do
|
|
821
|
+
raise Error, "RETURNING is not supported on #{db.database_type}" unless supports_returning?(:insert)
|
|
822
|
+
clone(:returning=>EMPTY_ARRAY)
|
|
823
|
+
end
|
|
824
|
+
else
|
|
825
|
+
raise Error, "RETURNING is not supported on #{db.database_type}" unless supports_returning?(:insert)
|
|
826
|
+
clone(:returning=>values.freeze)
|
|
827
|
+
end
|
|
721
828
|
end
|
|
722
829
|
|
|
723
830
|
# Returns a copy of the dataset with the order reversed. If no order is
|
|
@@ -728,8 +835,12 @@ module Sequel
|
|
|
728
835
|
# DB[:items].order(:id).reverse # SELECT * FROM items ORDER BY id DESC
|
|
729
836
|
# DB[:items].order(:id).reverse(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name ASC
|
|
730
837
|
def reverse(*order, &block)
|
|
731
|
-
|
|
732
|
-
|
|
838
|
+
if order.empty? && !block
|
|
839
|
+
cached_dataset(:_reverse_ds){order(*invert_order(@opts[:order]))}
|
|
840
|
+
else
|
|
841
|
+
virtual_row_columns(order, block)
|
|
842
|
+
order(*invert_order(order.empty? ? @opts[:order] : order.freeze))
|
|
843
|
+
end
|
|
733
844
|
end
|
|
734
845
|
|
|
735
846
|
# Alias of +reverse+
|
|
@@ -746,7 +857,7 @@ module Sequel
|
|
|
746
857
|
# DB[:items].select{[a, sum(b)]} # SELECT a, sum(b) FROM items
|
|
747
858
|
def select(*columns, &block)
|
|
748
859
|
virtual_row_columns(columns, block)
|
|
749
|
-
clone(:select => columns)
|
|
860
|
+
clone(:select => columns.freeze)
|
|
750
861
|
end
|
|
751
862
|
|
|
752
863
|
# Returns a copy of the dataset selecting the wildcard if no arguments
|
|
@@ -758,9 +869,9 @@ module Sequel
|
|
|
758
869
|
# DB[:items].select_all(:items, :foo) # SELECT items.*, foo.* FROM items
|
|
759
870
|
def select_all(*tables)
|
|
760
871
|
if tables.empty?
|
|
761
|
-
clone(:select => nil)
|
|
872
|
+
cached_dataset(:_select_all_ds){clone(:select => nil)}
|
|
762
873
|
else
|
|
763
|
-
select(*tables.map{|t| i, a = split_alias(t); a || i}.map{|t| SQL::ColumnAll.new(t)})
|
|
874
|
+
select(*tables.map{|t| i, a = split_alias(t); a || i}.map!{|t| SQL::ColumnAll.new(t)}.freeze)
|
|
764
875
|
end
|
|
765
876
|
end
|
|
766
877
|
|
|
@@ -775,7 +886,7 @@ module Sequel
|
|
|
775
886
|
cur_sel = @opts[:select]
|
|
776
887
|
if !cur_sel || cur_sel.empty?
|
|
777
888
|
unless supports_select_all_and_column?
|
|
778
|
-
return select_all(*(Array(@opts[:from]) + Array(@opts[:join]))).
|
|
889
|
+
return select_all(*(Array(@opts[:from]) + Array(@opts[:join]))).select_append(*columns, &block)
|
|
779
890
|
end
|
|
780
891
|
cur_sel = [WILDCARD]
|
|
781
892
|
end
|
|
@@ -789,7 +900,7 @@ module Sequel
|
|
|
789
900
|
# DB[:items].select_group(:a, :b)
|
|
790
901
|
# # SELECT a, b FROM items GROUP BY a, b
|
|
791
902
|
#
|
|
792
|
-
# DB[:items].select_group(:
|
|
903
|
+
# DB[:items].select_group(Sequel[:c].as(:a)){f(c2)}
|
|
793
904
|
# # SELECT c AS a, f(c2) FROM items GROUP BY c, f(c2)
|
|
794
905
|
def select_group(*columns, &block)
|
|
795
906
|
virtual_row_columns(columns, block)
|
|
@@ -825,36 +936,35 @@ module Sequel
|
|
|
825
936
|
end
|
|
826
937
|
end
|
|
827
938
|
|
|
828
|
-
#
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
#
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
[ds, u.binds]
|
|
939
|
+
# Specify that the check for limits/offsets when updating/deleting be skipped for the dataset.
|
|
940
|
+
def skip_limit_check
|
|
941
|
+
cached_dataset(:_skip_limit_check_ds) do
|
|
942
|
+
clone(:skip_limit_check=>true)
|
|
943
|
+
end
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
# Skip locked rows when returning results from this dataset.
|
|
947
|
+
def skip_locked
|
|
948
|
+
cached_dataset(:_skip_locked_ds) do
|
|
949
|
+
raise(Error, 'This dataset does not support skipping locked rows') unless supports_skip_locked?
|
|
950
|
+
clone(:skip_locked=>true)
|
|
951
|
+
end
|
|
842
952
|
end
|
|
843
953
|
|
|
844
954
|
# Returns a copy of the dataset with no filters (HAVING or WHERE clause) applied.
|
|
845
955
|
#
|
|
846
|
-
# DB[:items].group(:a).having(:
|
|
956
|
+
# DB[:items].group(:a).having(a: 1).where(:b).unfiltered
|
|
847
957
|
# # SELECT * FROM items GROUP BY a
|
|
848
958
|
def unfiltered
|
|
849
|
-
clone(:where => nil, :having => nil)
|
|
959
|
+
cached_dataset(:_unfiltered_ds){clone(:where => nil, :having => nil)}
|
|
850
960
|
end
|
|
851
961
|
|
|
852
962
|
# Returns a copy of the dataset with no grouping (GROUP or HAVING clause) applied.
|
|
853
963
|
#
|
|
854
|
-
# DB[:items].group(:a).having(:
|
|
964
|
+
# DB[:items].group(:a).having(a: 1).where(:b).ungrouped
|
|
855
965
|
# # SELECT * FROM items WHERE b
|
|
856
966
|
def ungrouped
|
|
857
|
-
clone(:group => nil, :having => nil)
|
|
967
|
+
cached_dataset(:_ungrouped_ds){clone(:group => nil, :having => nil)}
|
|
858
968
|
end
|
|
859
969
|
|
|
860
970
|
# Adds a UNION clause using a second dataset object.
|
|
@@ -868,10 +978,10 @@ module Sequel
|
|
|
868
978
|
# DB[:items].union(DB[:other_items])
|
|
869
979
|
# # SELECT * FROM (SELECT * FROM items UNION SELECT * FROM other_items) AS t1
|
|
870
980
|
#
|
|
871
|
-
# DB[:items].union(DB[:other_items], :
|
|
981
|
+
# DB[:items].union(DB[:other_items], all: true, from_self: false)
|
|
872
982
|
# # SELECT * FROM items UNION ALL SELECT * FROM other_items
|
|
873
983
|
#
|
|
874
|
-
# DB[:items].union(DB[:other_items], :
|
|
984
|
+
# DB[:items].union(DB[:other_items], alias: :i)
|
|
875
985
|
# # SELECT * FROM (SELECT * FROM items UNION SELECT * FROM other_items) AS i
|
|
876
986
|
def union(dataset, opts=OPTS)
|
|
877
987
|
compound_clone(:union, dataset, opts)
|
|
@@ -881,32 +991,24 @@ module Sequel
|
|
|
881
991
|
#
|
|
882
992
|
# DB[:items].limit(10, 20).unlimited # SELECT * FROM items
|
|
883
993
|
def unlimited
|
|
884
|
-
clone(:limit=>nil, :offset=>nil)
|
|
994
|
+
cached_dataset(:_unlimited_ds){clone(:limit=>nil, :offset=>nil)}
|
|
885
995
|
end
|
|
886
996
|
|
|
887
997
|
# Returns a copy of the dataset with no order.
|
|
888
998
|
#
|
|
889
999
|
# DB[:items].order(:a).unordered # SELECT * FROM items
|
|
890
1000
|
def unordered
|
|
891
|
-
order
|
|
1001
|
+
cached_dataset(:_unordered_ds){clone(:order=>nil)}
|
|
892
1002
|
end
|
|
893
1003
|
|
|
894
1004
|
# Returns a copy of the dataset with the given WHERE conditions imposed upon it.
|
|
895
1005
|
#
|
|
896
1006
|
# Accepts the following argument types:
|
|
897
1007
|
#
|
|
898
|
-
# Hash :: list of equality/inclusion expressions
|
|
899
|
-
# Array :: depends:
|
|
900
|
-
# * If first member is a string, assumes the rest of the arguments
|
|
901
|
-
# are parameters and interpolates them into the string.
|
|
902
|
-
# * If all members are arrays of length two, treats the same way
|
|
903
|
-
# as a hash, except it allows for duplicate keys to be
|
|
904
|
-
# specified.
|
|
905
|
-
# * Otherwise, treats each argument as a separate condition.
|
|
906
|
-
# String :: taken literally
|
|
1008
|
+
# Hash, Array of pairs :: list of equality/inclusion expressions
|
|
907
1009
|
# Symbol :: taken as a boolean column argument (e.g. WHERE active)
|
|
908
|
-
# Sequel::SQL::BooleanExpression :: an existing condition expression,
|
|
909
|
-
#
|
|
1010
|
+
# Sequel::SQL::BooleanExpression, Sequel::LiteralString :: an existing condition expression, probably created
|
|
1011
|
+
# using the Sequel expression filter DSL.
|
|
910
1012
|
#
|
|
911
1013
|
# where also accepts a block, which should return one of the above argument
|
|
912
1014
|
# types, and is treated the same way. This block yields a virtual row object,
|
|
@@ -917,16 +1019,16 @@ module Sequel
|
|
|
917
1019
|
#
|
|
918
1020
|
# Examples:
|
|
919
1021
|
#
|
|
920
|
-
# DB[:items].where(:
|
|
1022
|
+
# DB[:items].where(id: 3)
|
|
921
1023
|
# # SELECT * FROM items WHERE (id = 3)
|
|
922
1024
|
#
|
|
923
|
-
# DB[:items].where('price < ?', 100)
|
|
1025
|
+
# DB[:items].where(Sequel.lit('price < ?', 100))
|
|
924
1026
|
# # SELECT * FROM items WHERE price < 100
|
|
925
1027
|
#
|
|
926
1028
|
# DB[:items].where([[:id, [1,2,3]], [:id, 0..10]])
|
|
927
1029
|
# # SELECT * FROM items WHERE ((id IN (1, 2, 3)) AND ((id >= 0) AND (id <= 10)))
|
|
928
1030
|
#
|
|
929
|
-
# DB[:items].where('price < 100')
|
|
1031
|
+
# DB[:items].where(Sequel.lit('price < 100'))
|
|
930
1032
|
# # SELECT * FROM items WHERE price < 100
|
|
931
1033
|
#
|
|
932
1034
|
# DB[:items].where(:active)
|
|
@@ -937,21 +1039,35 @@ module Sequel
|
|
|
937
1039
|
#
|
|
938
1040
|
# Multiple where calls can be chained for scoping:
|
|
939
1041
|
#
|
|
940
|
-
# software = dataset.where(:
|
|
1042
|
+
# software = dataset.where(category: 'software').where{price < 100}
|
|
941
1043
|
# # SELECT * FROM items WHERE ((category = 'software') AND (price < 100))
|
|
942
1044
|
#
|
|
943
1045
|
# See the {"Dataset Filtering" guide}[rdoc-ref:doc/dataset_filtering.rdoc] for more examples and details.
|
|
944
1046
|
def where(*cond, &block)
|
|
945
|
-
|
|
1047
|
+
add_filter(:where, cond, &block)
|
|
946
1048
|
end
|
|
947
1049
|
|
|
1050
|
+
# Return a clone of the dataset with an addition named window that can be
|
|
1051
|
+
# referenced in window functions. See Sequel::SQL::Window for a list of
|
|
1052
|
+
# options that can be passed in. Example:
|
|
1053
|
+
#
|
|
1054
|
+
# DB[:items].window(:w, :partition=>:c1, :order=>:c2)
|
|
1055
|
+
# # SELECT * FROM items WINDOW w AS (PARTITION BY c1 ORDER BY c2)
|
|
1056
|
+
def window(name, opts)
|
|
1057
|
+
clone(:window=>((@opts[:window]||EMPTY_ARRAY) + [[name, SQL::Window.new(opts)].freeze]).freeze)
|
|
1058
|
+
end
|
|
1059
|
+
|
|
948
1060
|
# Add a common table expression (CTE) with the given name and a dataset that defines the CTE.
|
|
949
1061
|
# A common table expression acts as an inline view for the query.
|
|
950
1062
|
# Options:
|
|
951
1063
|
# :args :: Specify the arguments/columns for the CTE, should be an array of symbols.
|
|
952
1064
|
# :recursive :: Specify that this is a recursive CTE
|
|
953
1065
|
#
|
|
954
|
-
#
|
|
1066
|
+
# PostgreSQL Specific Options:
|
|
1067
|
+
# :materialized :: Set to false to force inlining of the CTE, or true to force not inlining
|
|
1068
|
+
# the CTE (PostgreSQL 12+).
|
|
1069
|
+
#
|
|
1070
|
+
# DB[:items].with(:items, DB[:syx].where(Sequel[:name].like('A%')))
|
|
955
1071
|
# # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%' ESCAPE '\')) SELECT * FROM items
|
|
956
1072
|
def with(name, dataset, opts=OPTS)
|
|
957
1073
|
raise(Error, 'This dataset does not support common table expressions') unless supports_cte?
|
|
@@ -959,7 +1075,7 @@ module Sequel
|
|
|
959
1075
|
s, ds = hoist_cte(dataset)
|
|
960
1076
|
s.with(name, ds, opts)
|
|
961
1077
|
else
|
|
962
|
-
clone(:with=>(@opts[:with]||
|
|
1078
|
+
clone(:with=>((@opts[:with]||EMPTY_ARRAY) + [Hash[opts].merge!(:name=>name, :dataset=>dataset)]).freeze)
|
|
963
1079
|
end
|
|
964
1080
|
end
|
|
965
1081
|
|
|
@@ -970,17 +1086,17 @@ module Sequel
|
|
|
970
1086
|
# :union_all :: Set to false to use UNION instead of UNION ALL combining the nonrecursive and recursive parts.
|
|
971
1087
|
#
|
|
972
1088
|
# DB[:t].with_recursive(:t,
|
|
973
|
-
# DB[:i1].select(:id, :parent_id).where(:
|
|
974
|
-
# DB[:i1].join(:t, :
|
|
1089
|
+
# DB[:i1].select(:id, :parent_id).where(parent_id: nil),
|
|
1090
|
+
# DB[:i1].join(:t, id: :parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]),
|
|
975
1091
|
# :args=>[:id, :parent_id])
|
|
976
1092
|
#
|
|
977
|
-
# # WITH RECURSIVE
|
|
978
|
-
# # SELECT
|
|
1093
|
+
# # WITH RECURSIVE t(id, parent_id) AS (
|
|
1094
|
+
# # SELECT id, parent_id FROM i1 WHERE (parent_id IS NULL)
|
|
979
1095
|
# # UNION ALL
|
|
980
|
-
# # SELECT
|
|
981
|
-
# # ) SELECT * FROM
|
|
1096
|
+
# # SELECT i1.id, i1.parent_id FROM i1 INNER JOIN t ON (t.id = i1.parent_id)
|
|
1097
|
+
# # ) SELECT * FROM t
|
|
982
1098
|
def with_recursive(name, nonrecursive, recursive, opts=OPTS)
|
|
983
|
-
raise(Error, 'This
|
|
1099
|
+
raise(Error, 'This dataset does not support common table expressions') unless supports_cte?
|
|
984
1100
|
if hoist_cte?(nonrecursive)
|
|
985
1101
|
s, ds = hoist_cte(nonrecursive)
|
|
986
1102
|
s.with_recursive(name, ds, recursive, opts)
|
|
@@ -988,10 +1104,42 @@ module Sequel
|
|
|
988
1104
|
s, ds = hoist_cte(recursive)
|
|
989
1105
|
s.with_recursive(name, nonrecursive, ds, opts)
|
|
990
1106
|
else
|
|
991
|
-
clone(:with=>(@opts[:with]||
|
|
1107
|
+
clone(:with=>((@opts[:with]||EMPTY_ARRAY) + [Hash[opts].merge!(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))]).freeze)
|
|
992
1108
|
end
|
|
993
1109
|
end
|
|
994
1110
|
|
|
1111
|
+
if TRUE_FREEZE
|
|
1112
|
+
# Return a clone of the dataset extended with the given modules.
|
|
1113
|
+
# Note that like Object#extend, when multiple modules are provided
|
|
1114
|
+
# as arguments the cloned dataset is extended with the modules in reverse
|
|
1115
|
+
# order. If a block is provided, a DatasetModule is created using the block and
|
|
1116
|
+
# the clone is extended with that module after any modules given as arguments.
|
|
1117
|
+
def with_extend(*mods, &block)
|
|
1118
|
+
c = _clone(:freeze=>false)
|
|
1119
|
+
c.extend(*mods) unless mods.empty?
|
|
1120
|
+
c.extend(DatasetModule.new(&block)) if block
|
|
1121
|
+
c.freeze
|
|
1122
|
+
end
|
|
1123
|
+
else
|
|
1124
|
+
# :nocov:
|
|
1125
|
+
def with_extend(*mods, &block) # :nodoc:
|
|
1126
|
+
c = clone
|
|
1127
|
+
c.extend(*mods) unless mods.empty?
|
|
1128
|
+
c.extend(DatasetModule.new(&block)) if block
|
|
1129
|
+
c
|
|
1130
|
+
end
|
|
1131
|
+
# :nocov:
|
|
1132
|
+
end
|
|
1133
|
+
|
|
1134
|
+
# Returns a cloned dataset with the given row_proc.
|
|
1135
|
+
#
|
|
1136
|
+
# ds = DB[:items]
|
|
1137
|
+
# ds.all # => [{:id=>2}]
|
|
1138
|
+
# ds.with_row_proc(:invert.to_proc).all # => [{2=>:id}]
|
|
1139
|
+
def with_row_proc(callable)
|
|
1140
|
+
clone(:row_proc=>callable)
|
|
1141
|
+
end
|
|
1142
|
+
|
|
995
1143
|
# Returns a copy of the dataset with the static SQL used. This is useful if you want
|
|
996
1144
|
# to keep the same row_proc/graph, but change the SQL used to custom SQL.
|
|
997
1145
|
#
|
|
@@ -1004,9 +1152,27 @@ module Sequel
|
|
|
1004
1152
|
# You can also provide a method name and arguments to call to get the SQL:
|
|
1005
1153
|
#
|
|
1006
1154
|
# DB[:items].with_sql(:insert_sql, :b=>1) # INSERT INTO items (b) VALUES (1)
|
|
1155
|
+
#
|
|
1156
|
+
# Note that datasets that specify custom SQL using this method will generally
|
|
1157
|
+
# ignore future dataset methods that modify the SQL used, as specifying custom SQL
|
|
1158
|
+
# overrides Sequel's SQL generator. You should probably limit yourself to the following
|
|
1159
|
+
# dataset methods when using this method, or use the implicit_subquery extension:
|
|
1160
|
+
#
|
|
1161
|
+
# * each
|
|
1162
|
+
# * all
|
|
1163
|
+
# * single_record (if only one record could be returned)
|
|
1164
|
+
# * single_value (if only one record could be returned, and a single column is selected)
|
|
1165
|
+
# * map
|
|
1166
|
+
# * as_hash
|
|
1167
|
+
# * to_hash
|
|
1168
|
+
# * to_hash_groups
|
|
1169
|
+
# * delete (if a DELETE statement)
|
|
1170
|
+
# * update (if an UPDATE statement, with no arguments)
|
|
1171
|
+
# * insert (if an INSERT statement, with no arguments)
|
|
1172
|
+
# * truncate (if a TRUNCATE statement, with no arguments)
|
|
1007
1173
|
def with_sql(sql, *args)
|
|
1008
1174
|
if sql.is_a?(Symbol)
|
|
1009
|
-
sql =
|
|
1175
|
+
sql = public_send(sql, *args)
|
|
1010
1176
|
else
|
|
1011
1177
|
sql = SQL::PlaceholderLiteralString.new(sql, args) unless args.empty?
|
|
1012
1178
|
end
|
|
@@ -1017,26 +1183,33 @@ module Sequel
|
|
|
1017
1183
|
|
|
1018
1184
|
# Add the dataset to the list of compounds
|
|
1019
1185
|
def compound_clone(type, dataset, opts)
|
|
1020
|
-
if
|
|
1186
|
+
if dataset.is_a?(Dataset) && dataset.opts[:with] && !supports_cte_in_compounds?
|
|
1021
1187
|
s, ds = hoist_cte(dataset)
|
|
1022
1188
|
return s.compound_clone(type, ds, opts)
|
|
1023
1189
|
end
|
|
1024
|
-
ds = compound_from_self.clone(:compounds=>Array(@opts[:compounds]).map(&:dup) + [[type, dataset.compound_from_self, opts[:all]]])
|
|
1190
|
+
ds = compound_from_self.clone(:compounds=>(Array(@opts[:compounds]).map(&:dup) + [[type, dataset.compound_from_self, opts[:all]].freeze]).freeze)
|
|
1025
1191
|
opts[:from_self] == false ? ds : ds.from_self(opts)
|
|
1026
1192
|
end
|
|
1027
1193
|
|
|
1028
1194
|
# Return true if the dataset has a non-nil value for any key in opts.
|
|
1029
1195
|
def options_overlap(opts)
|
|
1030
|
-
!(@opts.
|
|
1196
|
+
!(@opts.map{|k,v| k unless v.nil?}.compact & opts).empty?
|
|
1031
1197
|
end
|
|
1032
1198
|
|
|
1199
|
+
# From types allowed to be considered a simple_select_all
|
|
1200
|
+
SIMPLE_SELECT_ALL_ALLOWED_FROM = [Symbol, SQL::Identifier, SQL::QualifiedIdentifier].freeze
|
|
1201
|
+
|
|
1033
1202
|
# Whether this dataset is a simple select from an underlying table, such as:
|
|
1034
1203
|
#
|
|
1035
1204
|
# SELECT * FROM table
|
|
1036
1205
|
# SELECT table.* FROM table
|
|
1037
1206
|
def simple_select_all?
|
|
1038
|
-
|
|
1039
|
-
|
|
1207
|
+
return false unless (f = @opts[:from]) && f.length == 1
|
|
1208
|
+
o = @opts.reject{|k,v| v.nil? || non_sql_option?(k)}
|
|
1209
|
+
from = f.first
|
|
1210
|
+
from = from.expression if from.is_a?(SQL::AliasedExpression)
|
|
1211
|
+
|
|
1212
|
+
if SIMPLE_SELECT_ALL_ALLOWED_FROM.any?{|x| from.is_a?(x)}
|
|
1040
1213
|
case o.length
|
|
1041
1214
|
when 1
|
|
1042
1215
|
true
|
|
@@ -1052,23 +1225,61 @@ module Sequel
|
|
|
1052
1225
|
|
|
1053
1226
|
private
|
|
1054
1227
|
|
|
1055
|
-
#
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1228
|
+
# Load the extensions into the receiver, without checking if the receiver is frozen.
|
|
1229
|
+
def _extension!(exts)
|
|
1230
|
+
Sequel.extension(*exts)
|
|
1231
|
+
exts.each do |ext|
|
|
1232
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
|
1233
|
+
pr.call(self)
|
|
1234
|
+
else
|
|
1235
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
|
|
1236
|
+
end
|
|
1237
|
+
end
|
|
1238
|
+
self
|
|
1239
|
+
end
|
|
1240
|
+
|
|
1241
|
+
# If invert is true, invert the condition.
|
|
1242
|
+
def _invert_filter(cond, invert)
|
|
1243
|
+
if invert
|
|
1244
|
+
SQL::BooleanExpression.invert(cond)
|
|
1061
1245
|
else
|
|
1062
|
-
cond
|
|
1063
|
-
cond = SQL::BooleanExpression.invert(cond) if invert
|
|
1064
|
-
cond = SQL::BooleanExpression.new(:AND, @opts[clause], cond) if @opts[clause]
|
|
1065
|
-
clone(clause => cond)
|
|
1246
|
+
cond
|
|
1066
1247
|
end
|
|
1067
1248
|
end
|
|
1068
1249
|
|
|
1069
|
-
#
|
|
1070
|
-
|
|
1071
|
-
|
|
1250
|
+
# Add the given filter condition. Arguments:
|
|
1251
|
+
# clause :: Symbol or which SQL clause to effect, should be :where or :having
|
|
1252
|
+
# cond :: The filter condition to add
|
|
1253
|
+
# invert :: Whether the condition should be inverted (true or false)
|
|
1254
|
+
# combine :: How to combine the condition with an existing condition, should be :AND or :OR
|
|
1255
|
+
def add_filter(clause, cond, invert=false, combine=:AND, &block)
|
|
1256
|
+
if cond == EMPTY_ARRAY && !block
|
|
1257
|
+
raise Error, "must provide an argument to a filtering method if not passing a block"
|
|
1258
|
+
end
|
|
1259
|
+
|
|
1260
|
+
cond = cond.first if cond.size == 1
|
|
1261
|
+
|
|
1262
|
+
empty = cond == OPTS || cond == EMPTY_ARRAY
|
|
1263
|
+
|
|
1264
|
+
if empty && !block
|
|
1265
|
+
self
|
|
1266
|
+
else
|
|
1267
|
+
if cond == nil
|
|
1268
|
+
cond = Sequel::NULL
|
|
1269
|
+
end
|
|
1270
|
+
if empty && block
|
|
1271
|
+
cond = nil
|
|
1272
|
+
end
|
|
1273
|
+
|
|
1274
|
+
cond = _invert_filter(filter_expr(cond, &block), invert)
|
|
1275
|
+
cond = SQL::BooleanExpression.new(combine, @opts[clause], cond) if @opts[clause]
|
|
1276
|
+
|
|
1277
|
+
if cond.nil?
|
|
1278
|
+
cond = Sequel::NULL
|
|
1279
|
+
end
|
|
1280
|
+
|
|
1281
|
+
clone(clause => cond)
|
|
1282
|
+
end
|
|
1072
1283
|
end
|
|
1073
1284
|
|
|
1074
1285
|
# The default :qualify option to use for join tables if one is not specified.
|
|
@@ -1078,29 +1289,27 @@ module Sequel
|
|
|
1078
1289
|
|
|
1079
1290
|
# SQL expression object based on the expr type. See +where+.
|
|
1080
1291
|
def filter_expr(expr = nil, &block)
|
|
1081
|
-
expr = nil if expr ==
|
|
1292
|
+
expr = nil if expr == EMPTY_ARRAY
|
|
1082
1293
|
|
|
1083
|
-
if
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1294
|
+
if block
|
|
1295
|
+
cond = filter_expr(Sequel.virtual_row(&block))
|
|
1296
|
+
cond = SQL::BooleanExpression.new(:AND, filter_expr(expr), cond) if expr
|
|
1297
|
+
return cond
|
|
1087
1298
|
end
|
|
1088
1299
|
|
|
1089
1300
|
case expr
|
|
1090
1301
|
when Hash
|
|
1091
1302
|
SQL::BooleanExpression.from_value_pairs(expr)
|
|
1092
1303
|
when Array
|
|
1093
|
-
if
|
|
1094
|
-
SQL::PlaceholderLiteralString.new(sexpr, expr[1..-1], true)
|
|
1095
|
-
elsif Sequel.condition_specifier?(expr)
|
|
1304
|
+
if Sequel.condition_specifier?(expr)
|
|
1096
1305
|
SQL::BooleanExpression.from_value_pairs(expr)
|
|
1097
1306
|
else
|
|
1098
|
-
|
|
1307
|
+
raise Error, "Invalid filter expression: #{expr.inspect}"
|
|
1099
1308
|
end
|
|
1100
|
-
when
|
|
1101
|
-
|
|
1102
|
-
when Numeric, SQL::NumericExpression, SQL::StringExpression
|
|
1103
|
-
raise
|
|
1309
|
+
when LiteralString
|
|
1310
|
+
LiteralString.new("(#{expr})")
|
|
1311
|
+
when Numeric, SQL::NumericExpression, SQL::StringExpression, Proc, String
|
|
1312
|
+
raise Error, "Invalid filter expression: #{expr.inspect}"
|
|
1104
1313
|
when TrueClass, FalseClass
|
|
1105
1314
|
if supports_where_true?
|
|
1106
1315
|
SQL::BooleanExpression.new(:NOOP, expr)
|
|
@@ -1109,10 +1318,10 @@ module Sequel
|
|
|
1109
1318
|
else
|
|
1110
1319
|
SQL::Constants::SQLFALSE
|
|
1111
1320
|
end
|
|
1112
|
-
when String
|
|
1113
|
-
LiteralString.new("(#{expr})")
|
|
1114
1321
|
when PlaceholderLiteralizer::Argument
|
|
1115
1322
|
expr.transform{|v| filter_expr(v)}
|
|
1323
|
+
when SQL::PlaceholderLiteralString
|
|
1324
|
+
expr.with_parens
|
|
1116
1325
|
else
|
|
1117
1326
|
expr
|
|
1118
1327
|
end
|
|
@@ -1122,7 +1331,7 @@ module Sequel
|
|
|
1122
1331
|
# clause from the given dataset added to it, and the second a clone of
|
|
1123
1332
|
# the given dataset with the WITH clause removed.
|
|
1124
1333
|
def hoist_cte(ds)
|
|
1125
|
-
[clone(:with => (opts[:with] ||
|
|
1334
|
+
[clone(:with => ((opts[:with] || EMPTY_ARRAY) + ds.opts[:with]).freeze), ds.clone(:with => nil)]
|
|
1126
1335
|
end
|
|
1127
1336
|
|
|
1128
1337
|
# Whether CTEs need to be hoisted from the given ds into the current ds.
|
|
@@ -1136,7 +1345,7 @@ module Sequel
|
|
|
1136
1345
|
# DB[:items].invert_order([Sequel.desc(:id)]]) #=> [Sequel.asc(:id)]
|
|
1137
1346
|
# DB[:items].invert_order([:category, Sequel.desc(:price)]) #=> [Sequel.desc(:category), Sequel.asc(:price)]
|
|
1138
1347
|
def invert_order(order)
|
|
1139
|
-
return
|
|
1348
|
+
return unless order
|
|
1140
1349
|
order.map do |f|
|
|
1141
1350
|
case f
|
|
1142
1351
|
when SQL::OrderedExpression
|
|
@@ -1153,6 +1362,11 @@ module Sequel
|
|
|
1153
1362
|
server?(:default)
|
|
1154
1363
|
end
|
|
1155
1364
|
|
|
1365
|
+
# Whether the given option key does not affect the generated SQL.
|
|
1366
|
+
def non_sql_option?(key)
|
|
1367
|
+
NON_SQL_OPTIONS.include?(key)
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1156
1370
|
# Treat the +block+ as a virtual_row block if not +nil+ and
|
|
1157
1371
|
# add the resulting columns to the +columns+ array (modifies +columns+).
|
|
1158
1372
|
def virtual_row_columns(columns, block)
|