sequel 3.21.0 → 3.39.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.
- data/CHANGELOG +1061 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +103 -63
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +67 -51
- data/doc/advanced_associations.rdoc +189 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +547 -0
- data/doc/opening_databases.rdoc +114 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +56 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +279 -97
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +125 -222
- data/lib/sequel/adapters/mysql2.rb +65 -56
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +368 -138
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +343 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +401 -116
- data/lib/sequel/adapters/shared/mysql.rb +424 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +257 -45
- data/lib/sequel/adapters/shared/postgres.rb +675 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +285 -96
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +28 -19
- data/lib/sequel/adapters/tinytds.rb +174 -22
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +43 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +190 -46
- data/lib/sequel/database/query.rb +272 -110
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +300 -67
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +305 -54
- data/lib/sequel/dataset/sql.rb +720 -292
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +537 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +313 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +208 -0
- data/lib/sequel/extensions/pg_range.rb +512 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +55 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +649 -122
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +194 -66
- data/spec/adapters/mysql_spec.rb +475 -306
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +1982 -325
- data/spec/adapters/spec_helper.rb +9 -6
- data/spec/adapters/sqlite_spec.rb +203 -75
- data/spec/core/connection_pool_spec.rb +218 -93
- data/spec/core/database_spec.rb +956 -522
- data/spec/core/dataset_spec.rb +1631 -1242
- data/spec/core/expression_filters_spec.rb +690 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +320 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +194 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +58 -67
- data/spec/extensions/validation_helpers_spec.rb +31 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +11 -5
- data/spec/integration/dataset_test.rb +717 -129
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +604 -147
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +367 -57
- data/spec/integration/spec_helper.rb +42 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +31 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +209 -80
- data/spec/core/core_sql_spec.rb +0 -451
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Methods that return modified datasets
|
|
4
|
+
# :section: 1 - Methods that return modified datasets
|
|
5
5
|
# These methods all return modified copies of the receiver.
|
|
6
6
|
# ---------------------
|
|
7
7
|
|
|
8
|
+
# Hash of extension name symbols to callable objects to load the extension
|
|
9
|
+
# into the Dataset object (usually by extending it with a module defined
|
|
10
|
+
# in the extension).
|
|
11
|
+
EXTENSIONS = {}
|
|
12
|
+
|
|
8
13
|
# The dataset options that require the removal of cached columns
|
|
9
14
|
# if changed.
|
|
10
15
|
COLUMN_CHANGE_OPTS = [:select, :sql, :from, :join].freeze
|
|
@@ -28,12 +33,35 @@ module Sequel
|
|
|
28
33
|
JOIN_METHODS = (CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES).map{|x| "#{x}_join".to_sym} + [:join, :join_table]
|
|
29
34
|
|
|
30
35
|
# Methods that return modified datasets
|
|
31
|
-
QUERY_METHODS =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
QUERY_METHODS = (<<-METHS).split.map{|x| x.to_sym} + JOIN_METHODS
|
|
37
|
+
add_graph_aliases and distinct except exclude exclude_having exclude_where
|
|
38
|
+
filter for_update from from_self graph grep group group_and_count group_by having intersect invert
|
|
39
|
+
limit lock_style naked or order order_append order_by order_more order_prepend paginate qualify query
|
|
40
|
+
reverse reverse_order select select_all select_append select_group select_more server
|
|
41
|
+
set_defaults set_graph_aliases set_overrides unfiltered ungraphed ungrouped union
|
|
42
|
+
unlimited unordered where with with_recursive with_sql
|
|
43
|
+
METHS
|
|
44
|
+
|
|
45
|
+
# Register an extension callback for Dataset objects. ext should be the
|
|
46
|
+
# extension name symbol, and mod should either be a Module that the
|
|
47
|
+
# dataset is extended with, or a callable object called with the database
|
|
48
|
+
# object. If mod is not provided, a block can be provided and is treated
|
|
49
|
+
# as the mod object.
|
|
50
|
+
#
|
|
51
|
+
# If mod is a module, this also registers a Database extension that will
|
|
52
|
+
# extend all of the database's datasets.
|
|
53
|
+
def self.register_extension(ext, mod=nil, &block)
|
|
54
|
+
if mod
|
|
55
|
+
raise(Error, "cannot provide both mod and block to Dataset.register_extension") if block
|
|
56
|
+
if mod.is_a?(Module)
|
|
57
|
+
block = proc{|ds| ds.extend(mod)}
|
|
58
|
+
Sequel::Database.register_extension(ext){|db| db.extend_datasets(mod)}
|
|
59
|
+
else
|
|
60
|
+
block = mod
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
64
|
+
end
|
|
37
65
|
|
|
38
66
|
# Adds an further filter to an existing filter using AND. If no filter
|
|
39
67
|
# exists an error is raised. This method is identical to #filter except
|
|
@@ -80,7 +108,7 @@ module Sequel
|
|
|
80
108
|
# :from_self :: Set to false to not wrap the returned dataset in a from_self, use with care.
|
|
81
109
|
#
|
|
82
110
|
# DB[:items].except(DB[:other_items])
|
|
83
|
-
# # SELECT * FROM items EXCEPT SELECT * FROM other_items
|
|
111
|
+
# # SELECT * FROM (SELECT * FROM items EXCEPT SELECT * FROM other_items) AS t1
|
|
84
112
|
#
|
|
85
113
|
# DB[:items].except(DB[:other_items], :all=>true, :from_self=>false)
|
|
86
114
|
# # SELECT * FROM items EXCEPT ALL SELECT * FROM other_items
|
|
@@ -103,12 +131,51 @@ module Sequel
|
|
|
103
131
|
# DB[:items].exclude(:category => 'software', :id=>3)
|
|
104
132
|
# # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
|
|
105
133
|
def exclude(*cond, &block)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
134
|
+
_filter_or_exclude(true, @opts[:having] ? :having : :where, *cond, &block)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Inverts the given conditions and adds them to the HAVING clause.
|
|
138
|
+
#
|
|
139
|
+
# DB[:items].select_group(:name).exclude_having{count(name) < 2}
|
|
140
|
+
# # SELECT name FROM items GROUP BY name HAVING (count(name) >= 2)
|
|
141
|
+
def exclude_having(*cond, &block)
|
|
142
|
+
_filter_or_exclude(true, :having, *cond, &block)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Inverts the given conditions and adds them to the WHERE clause.
|
|
146
|
+
#
|
|
147
|
+
# DB[:items].select_group(:name).exclude_where(:category => 'software')
|
|
148
|
+
# # SELECT * FROM items WHERE (category != 'software')
|
|
149
|
+
#
|
|
150
|
+
# DB[:items].select_group(:name).
|
|
151
|
+
# exclude_having{count(name) < 2}.
|
|
152
|
+
# exclude_where(:category => 'software')
|
|
153
|
+
# # SELECT name FROM items WHERE (category != 'software')
|
|
154
|
+
# # GROUP BY name HAVING (count(name) >= 2)
|
|
155
|
+
def exclude_where(*cond, &block)
|
|
156
|
+
_filter_or_exclude(true, :where, *cond, &block)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Return a clone of the dataset loaded with the extensions, see #extension!.
|
|
160
|
+
def extension(*exts)
|
|
161
|
+
clone.extension!(*exts)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Load an extension into the receiver. In addition to requiring the extension file, this
|
|
165
|
+
# also modifies the dataset to work with the extension (usually extending it with a
|
|
166
|
+
# module defined in the extension file). If no related extension file exists or the
|
|
167
|
+
# extension does not have specific support for Database objects, an Error will be raised.
|
|
168
|
+
# Returns self.
|
|
169
|
+
def extension!(*exts)
|
|
170
|
+
Sequel.extension(*exts)
|
|
171
|
+
exts.each do |ext|
|
|
172
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
|
173
|
+
pr.call(self)
|
|
174
|
+
else
|
|
175
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets")
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
self
|
|
112
179
|
end
|
|
113
180
|
|
|
114
181
|
# Returns a copy of the dataset with the given conditions imposed upon it.
|
|
@@ -145,7 +212,7 @@ module Sequel
|
|
|
145
212
|
# DB[:items].filter('price < ?', 100)
|
|
146
213
|
# # SELECT * FROM items WHERE price < 100
|
|
147
214
|
#
|
|
148
|
-
# DB[:items].filter([[:id,
|
|
215
|
+
# DB[:items].filter([[:id, [1,2,3]], [:id, 0..10]])
|
|
149
216
|
# # SELECT * FROM items WHERE ((id IN (1, 2, 3)) AND ((id >= 0) AND (id <= 10)))
|
|
150
217
|
#
|
|
151
218
|
# DB[:items].filter('price < 100')
|
|
@@ -184,16 +251,22 @@ module Sequel
|
|
|
184
251
|
def from(*source)
|
|
185
252
|
table_alias_num = 0
|
|
186
253
|
sources = []
|
|
254
|
+
ctes = nil
|
|
187
255
|
source.each do |s|
|
|
188
256
|
case s
|
|
189
257
|
when Hash
|
|
190
258
|
s.each{|k,v| sources << SQL::AliasedExpression.new(k,v)}
|
|
191
259
|
when Dataset
|
|
260
|
+
if hoist_cte?(s)
|
|
261
|
+
ctes ||= []
|
|
262
|
+
ctes += s.opts[:with]
|
|
263
|
+
s = s.clone(:with=>nil)
|
|
264
|
+
end
|
|
192
265
|
sources << SQL::AliasedExpression.new(s, dataset_alias(table_alias_num+=1))
|
|
193
266
|
when Symbol
|
|
194
267
|
sch, table, aliaz = split_symbol(s)
|
|
195
268
|
if aliaz
|
|
196
|
-
s = sch ? SQL::QualifiedIdentifier.new(sch
|
|
269
|
+
s = sch ? SQL::QualifiedIdentifier.new(sch, table) : SQL::Identifier.new(table)
|
|
197
270
|
sources << SQL::AliasedExpression.new(s, aliaz.to_sym)
|
|
198
271
|
else
|
|
199
272
|
sources << s
|
|
@@ -203,6 +276,7 @@ module Sequel
|
|
|
203
276
|
end
|
|
204
277
|
end
|
|
205
278
|
o = {:from=>sources.empty? ? nil : sources}
|
|
279
|
+
o[:with] = (opts[:with] || []) + ctes if ctes
|
|
206
280
|
o[:num_dataset_sources] = table_alias_num if table_alias_num > 0
|
|
207
281
|
clone(o)
|
|
208
282
|
end
|
|
@@ -270,21 +344,25 @@ module Sequel
|
|
|
270
344
|
end
|
|
271
345
|
|
|
272
346
|
# Returns a copy of the dataset with the results grouped by the value of
|
|
273
|
-
# the given columns.
|
|
347
|
+
# the given columns. If a block is given, it is treated
|
|
348
|
+
# as a virtual row block, similar to +filter+.
|
|
274
349
|
#
|
|
275
350
|
# DB[:items].group(:id) # SELECT * FROM items GROUP BY id
|
|
276
351
|
# DB[:items].group(:id, :name) # SELECT * FROM items GROUP BY id, name
|
|
277
|
-
|
|
352
|
+
# DB[:items].group{[a, sum(b)]} # SELECT * FROM items GROUP BY a, sum(b)
|
|
353
|
+
def group(*columns, &block)
|
|
354
|
+
virtual_row_columns(columns, block)
|
|
278
355
|
clone(:group => (columns.compact.empty? ? nil : columns))
|
|
279
356
|
end
|
|
280
357
|
|
|
281
358
|
# Alias of group
|
|
282
|
-
def group_by(*columns)
|
|
283
|
-
group(*columns)
|
|
359
|
+
def group_by(*columns, &block)
|
|
360
|
+
group(*columns, &block)
|
|
284
361
|
end
|
|
285
362
|
|
|
286
363
|
# Returns a dataset grouped by the given column with count by group.
|
|
287
364
|
# Column aliases may be supplied, and will be included in the select clause.
|
|
365
|
+
# If a block is given, it is treated as a virtual row block, similar to +filter+.
|
|
288
366
|
#
|
|
289
367
|
# Examples:
|
|
290
368
|
#
|
|
@@ -299,8 +377,24 @@ module Sequel
|
|
|
299
377
|
# DB[:items].group_and_count(:first_name___name).all
|
|
300
378
|
# # SELECT first_name AS name, count(*) AS count FROM items GROUP BY first_name
|
|
301
379
|
# # => [{:name=>'a', :count=>1}, ...]
|
|
302
|
-
|
|
303
|
-
|
|
380
|
+
#
|
|
381
|
+
# DB[:items].group_and_count{substr(first_name, 1, 1).as(initial)}.all
|
|
382
|
+
# # SELECT substr(first_name, 1, 1) AS initial, count(*) AS count FROM items GROUP BY substr(first_name, 1, 1)
|
|
383
|
+
# # => [{:initial=>'a', :count=>1}, ...]
|
|
384
|
+
def group_and_count(*columns, &block)
|
|
385
|
+
select_group(*columns, &block).select_more(COUNT_OF_ALL_AS_COUNT)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Adds the appropriate CUBE syntax to GROUP BY.
|
|
389
|
+
def group_cube
|
|
390
|
+
raise Error, "GROUP BY CUBE not supported on #{db.database_type}" unless supports_group_cube?
|
|
391
|
+
clone(:group_options=>:cube)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Adds the appropriate ROLLUP syntax to GROUP BY.
|
|
395
|
+
def group_rollup
|
|
396
|
+
raise Error, "GROUP BY ROLLUP not supported on #{db.database_type}" unless supports_group_rollup?
|
|
397
|
+
clone(:group_options=>:rollup)
|
|
304
398
|
end
|
|
305
399
|
|
|
306
400
|
# Returns a copy of the dataset with the HAVING conditions changed. See #filter for argument types.
|
|
@@ -356,12 +450,15 @@ module Sequel
|
|
|
356
450
|
inner_join(*args, &block)
|
|
357
451
|
end
|
|
358
452
|
|
|
359
|
-
# Returns a joined dataset.
|
|
453
|
+
# Returns a joined dataset. Not usually called directly, users should use the
|
|
454
|
+
# appropriate join method (e.g. join, left_join, natural_join, cross_join) which fills
|
|
455
|
+
# in the +type+ argument.
|
|
456
|
+
#
|
|
457
|
+
# Takes the following arguments:
|
|
360
458
|
#
|
|
361
459
|
# * type - The type of join to do (e.g. :inner)
|
|
362
460
|
# * table - Depends on type:
|
|
363
461
|
# * Dataset - a subselect is performed with an alias of tN for some value of N
|
|
364
|
-
# * Model (or anything responding to :table_name) - table.table_name
|
|
365
462
|
# * String, Symbol: table
|
|
366
463
|
# * expr - specifies conditions, depends on type:
|
|
367
464
|
# * Hash, Array of two element arrays - Assumes key (1st arg) is column of joined table (unless already
|
|
@@ -382,11 +479,36 @@ module Sequel
|
|
|
382
479
|
# to the same table more than once. No alias is used by default.
|
|
383
480
|
# * :implicit_qualifier - The name to use for qualifying implicit conditions. By default,
|
|
384
481
|
# the last joined or primary table is used.
|
|
482
|
+
# * :qualify - Can be set to false to not do any implicit qualification. Can be set
|
|
483
|
+
# to :deep to use the Qualifier AST Transformer, which will attempt to qualify
|
|
484
|
+
# subexpressions of the expression tree.
|
|
385
485
|
# * block - The block argument should only be given if a JOIN with an ON clause is used,
|
|
386
486
|
# in which case it yields the table alias/name for the table currently being joined,
|
|
387
487
|
# the table alias/name for the last joined (or first table), and an array of previous
|
|
388
488
|
# SQL::JoinClause. Unlike +filter+, this block is not treated as a virtual row block.
|
|
489
|
+
#
|
|
490
|
+
# Examples:
|
|
491
|
+
#
|
|
492
|
+
# DB[:a].join_table(:cross, :b)
|
|
493
|
+
# # SELECT * FROM a CROSS JOIN b
|
|
494
|
+
#
|
|
495
|
+
# DB[:a].join_table(:inner, DB[:b], :c=>d)
|
|
496
|
+
# # SELECT * FROM a INNER JOIN (SELECT * FROM b) AS t1 ON (t1.c = a.d)
|
|
497
|
+
#
|
|
498
|
+
# DB[:a].join_table(:left, :b___c, [:d])
|
|
499
|
+
# # SELECT * FROM a LEFT JOIN b AS c USING (d)
|
|
500
|
+
#
|
|
501
|
+
# DB[:a].natural_join(:b).join_table(:inner, :c) do |ta, jta, js|
|
|
502
|
+
# (Sequel.qualify(ta, :d) > Sequel.qualify(jta, :e)) & {Sequel.qualify(ta, :f)=>DB.from(js.first.table).select(:g)}
|
|
503
|
+
# end
|
|
504
|
+
# # SELECT * FROM a NATURAL JOIN b INNER JOIN c
|
|
505
|
+
# # ON ((c.d > b.e) AND (c.f IN (SELECT g FROM b)))
|
|
389
506
|
def join_table(type, table, expr=nil, options={}, &block)
|
|
507
|
+
if hoist_cte?(table)
|
|
508
|
+
s, ds = hoist_cte(table)
|
|
509
|
+
return s.join_table(type, ds, expr, options, &block)
|
|
510
|
+
end
|
|
511
|
+
|
|
390
512
|
using_join = expr.is_a?(Array) && !expr.empty? && expr.all?{|x| x.is_a?(Symbol)}
|
|
391
513
|
if using_join && !supports_join_using?
|
|
392
514
|
h = {}
|
|
@@ -398,6 +520,7 @@ module Sequel
|
|
|
398
520
|
when Hash
|
|
399
521
|
table_alias = options[:table_alias]
|
|
400
522
|
last_alias = options[:implicit_qualifier]
|
|
523
|
+
qualify_type = options[:qualify]
|
|
401
524
|
when Symbol, String, SQL::Identifier
|
|
402
525
|
table_alias = options
|
|
403
526
|
last_alias = nil
|
|
@@ -412,7 +535,6 @@ module Sequel
|
|
|
412
535
|
end
|
|
413
536
|
table_name = table_alias
|
|
414
537
|
else
|
|
415
|
-
table = table.table_name if table.respond_to?(:table_name)
|
|
416
538
|
table, implicit_table_alias = split_alias(table)
|
|
417
539
|
table_alias ||= implicit_table_alias
|
|
418
540
|
table_name = table_alias || table
|
|
@@ -427,10 +549,19 @@ module Sequel
|
|
|
427
549
|
last_alias ||= @opts[:last_joined_table] || first_source_alias
|
|
428
550
|
if Sequel.condition_specifier?(expr)
|
|
429
551
|
expr = expr.collect do |k, v|
|
|
430
|
-
|
|
431
|
-
|
|
552
|
+
case qualify_type
|
|
553
|
+
when false
|
|
554
|
+
nil # Do no qualification
|
|
555
|
+
when :deep
|
|
556
|
+
k = Sequel::Qualifier.new(self, table_name).transform(k)
|
|
557
|
+
v = Sequel::Qualifier.new(self, last_alias).transform(v)
|
|
558
|
+
else
|
|
559
|
+
k = qualified_column_name(k, table_name) if k.is_a?(Symbol)
|
|
560
|
+
v = qualified_column_name(v, last_alias) if v.is_a?(Symbol)
|
|
561
|
+
end
|
|
432
562
|
[k,v]
|
|
433
563
|
end
|
|
564
|
+
expr = SQL::BooleanExpression.from_value_pairs(expr)
|
|
434
565
|
end
|
|
435
566
|
if block
|
|
436
567
|
expr2 = yield(table_name, last_alias, @opts[:join] || [])
|
|
@@ -524,14 +655,14 @@ module Sequel
|
|
|
524
655
|
#
|
|
525
656
|
# DB[:items].order(:name) # SELECT * FROM items ORDER BY name
|
|
526
657
|
# DB[:items].order(:a, :b) # SELECT * FROM items ORDER BY a, b
|
|
527
|
-
# DB[:items].order('a + b'
|
|
658
|
+
# DB[:items].order(Sequel.lit('a + b')) # SELECT * FROM items ORDER BY a + b
|
|
528
659
|
# DB[:items].order(:a + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
529
|
-
# DB[:items].order(:name
|
|
530
|
-
# DB[:items].order(
|
|
660
|
+
# DB[:items].order(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name DESC
|
|
661
|
+
# DB[:items].order(Sequel.asc(:name, :nulls=>:last)) # SELECT * FROM items ORDER BY name ASC NULLS LAST
|
|
531
662
|
# DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
|
|
532
663
|
# DB[:items].order(nil) # SELECT * FROM items
|
|
533
664
|
def order(*columns, &block)
|
|
534
|
-
columns
|
|
665
|
+
virtual_row_columns(columns, block)
|
|
535
666
|
clone(:order => (columns.compact.empty?) ? nil : columns)
|
|
536
667
|
end
|
|
537
668
|
|
|
@@ -565,7 +696,7 @@ module Sequel
|
|
|
565
696
|
@opts[:order] ? ds.order_more(*@opts[:order]) : ds
|
|
566
697
|
end
|
|
567
698
|
|
|
568
|
-
# Qualify to the given table, or first source if
|
|
699
|
+
# Qualify to the given table, or first source if no table is given.
|
|
569
700
|
#
|
|
570
701
|
# DB[:items].filter(:id=>1).qualify
|
|
571
702
|
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
@@ -606,12 +737,24 @@ module Sequel
|
|
|
606
737
|
qualify_to(first_source)
|
|
607
738
|
end
|
|
608
739
|
|
|
740
|
+
# Modify the RETURNING clause, only supported on a few databases. If returning
|
|
741
|
+
# is used, instead of insert returning the autogenerated primary key or
|
|
742
|
+
# update/delete returning the number of modified rows, results are
|
|
743
|
+
# returned using +fetch_rows+.
|
|
744
|
+
#
|
|
745
|
+
# DB[:items].returning # RETURNING *
|
|
746
|
+
# DB[:items].returning(nil) # RETURNING NULL
|
|
747
|
+
# DB[:items].returning(:id, :name) # RETURNING id, name
|
|
748
|
+
def returning(*values)
|
|
749
|
+
clone(:returning=>values)
|
|
750
|
+
end
|
|
751
|
+
|
|
609
752
|
# Returns a copy of the dataset with the order reversed. If no order is
|
|
610
753
|
# given, the existing order is inverted.
|
|
611
754
|
#
|
|
612
755
|
# DB[:items].reverse(:id) # SELECT * FROM items ORDER BY id DESC
|
|
613
756
|
# DB[:items].order(:id).reverse # SELECT * FROM items ORDER BY id DESC
|
|
614
|
-
# DB[:items].order(:id).reverse(:name
|
|
757
|
+
# DB[:items].order(:id).reverse(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name ASC
|
|
615
758
|
def reverse(*order)
|
|
616
759
|
order(*invert_order(order.empty? ? @opts[:order] : order))
|
|
617
760
|
end
|
|
@@ -629,7 +772,7 @@ module Sequel
|
|
|
629
772
|
# DB[:items].select(:a, :b) # SELECT a, b FROM items
|
|
630
773
|
# DB[:items].select{[a, sum(b)]} # SELECT a, sum(b) FROM items
|
|
631
774
|
def select(*columns, &block)
|
|
632
|
-
columns
|
|
775
|
+
virtual_row_columns(columns, block)
|
|
633
776
|
m = []
|
|
634
777
|
columns.each do |i|
|
|
635
778
|
i.is_a?(Hash) ? m.concat(i.map{|k, v| SQL::AliasedExpression.new(k,v)}) : m << i
|
|
@@ -637,11 +780,19 @@ module Sequel
|
|
|
637
780
|
clone(:select => m)
|
|
638
781
|
end
|
|
639
782
|
|
|
640
|
-
# Returns a copy of the dataset selecting the wildcard
|
|
783
|
+
# Returns a copy of the dataset selecting the wildcard if no arguments
|
|
784
|
+
# are given. If arguments are given, treat them as tables and select
|
|
785
|
+
# all columns (using the wildcard) from each table.
|
|
641
786
|
#
|
|
642
787
|
# DB[:items].select(:a).select_all # SELECT * FROM items
|
|
643
|
-
|
|
644
|
-
|
|
788
|
+
# DB[:items].select_all(:items) # SELECT items.* FROM items
|
|
789
|
+
# DB[:items].select_all(:items, :foo) # SELECT items.*, foo.* FROM items
|
|
790
|
+
def select_all(*tables)
|
|
791
|
+
if tables.empty?
|
|
792
|
+
clone(:select => nil)
|
|
793
|
+
else
|
|
794
|
+
select(*tables.map{|t| i, a = split_alias(t); a || i}.map{|t| SQL::ColumnAll.new(t)})
|
|
795
|
+
end
|
|
645
796
|
end
|
|
646
797
|
|
|
647
798
|
# Returns a copy of the dataset with the given columns added
|
|
@@ -653,10 +804,29 @@ module Sequel
|
|
|
653
804
|
# DB[:items].select_append(:b) # SELECT *, b FROM items
|
|
654
805
|
def select_append(*columns, &block)
|
|
655
806
|
cur_sel = @opts[:select]
|
|
656
|
-
|
|
807
|
+
if !cur_sel || cur_sel.empty?
|
|
808
|
+
unless supports_select_all_and_column?
|
|
809
|
+
return select_all(*(Array(@opts[:from]) + Array(@opts[:join]))).select_more(*columns, &block)
|
|
810
|
+
end
|
|
811
|
+
cur_sel = [WILDCARD]
|
|
812
|
+
end
|
|
657
813
|
select(*(cur_sel + columns), &block)
|
|
658
814
|
end
|
|
659
815
|
|
|
816
|
+
# Set both the select and group clauses with the given +columns+.
|
|
817
|
+
# Column aliases may be supplied, and will be included in the select clause.
|
|
818
|
+
# This also takes a virtual row block similar to +filter+.
|
|
819
|
+
#
|
|
820
|
+
# DB[:items].select_group(:a, :b)
|
|
821
|
+
# # SELECT a, b FROM items GROUP BY a, b
|
|
822
|
+
#
|
|
823
|
+
# DB[:items].select_group(:c___a){f(c2)}
|
|
824
|
+
# # SELECT c AS a, f(c2) FROM items GROUP BY c, f(c2)
|
|
825
|
+
def select_group(*columns, &block)
|
|
826
|
+
virtual_row_columns(columns, block)
|
|
827
|
+
select(*columns).group(*columns.map{|c| unaliased_identifier(c)})
|
|
828
|
+
end
|
|
829
|
+
|
|
660
830
|
# Returns a copy of the dataset with the given columns added
|
|
661
831
|
# to the existing selected columns. If no columns are currently selected
|
|
662
832
|
# it will just select the columns given.
|
|
@@ -670,7 +840,7 @@ module Sequel
|
|
|
670
840
|
end
|
|
671
841
|
|
|
672
842
|
# Set the server for this dataset to use. Used to pick a specific database
|
|
673
|
-
# shard to run a query against, or to override the default (
|
|
843
|
+
# shard to run a query against, or to override the default (where SELECT uses
|
|
674
844
|
# :read_only database and all other queries use the :default database). This
|
|
675
845
|
# method is always available but is only useful when database sharding is being
|
|
676
846
|
# used.
|
|
@@ -702,6 +872,22 @@ module Sequel
|
|
|
702
872
|
clone(:overrides=>hash.merge(@opts[:overrides]||{}))
|
|
703
873
|
end
|
|
704
874
|
|
|
875
|
+
# Unbind bound variables from this dataset's filter and return an array of two
|
|
876
|
+
# objects. The first object is a modified dataset where the filter has been
|
|
877
|
+
# replaced with one that uses bound variable placeholders. The second object
|
|
878
|
+
# is the hash of unbound variables. You can then prepare and execute (or just
|
|
879
|
+
# call) the dataset with the bound variables to get results.
|
|
880
|
+
#
|
|
881
|
+
# ds, bv = DB[:items].filter(:a=>1).unbind
|
|
882
|
+
# ds # SELECT * FROM items WHERE (a = $a)
|
|
883
|
+
# bv # {:a => 1}
|
|
884
|
+
# ds.call(:select, bv)
|
|
885
|
+
def unbind
|
|
886
|
+
u = Unbinder.new
|
|
887
|
+
ds = clone(:where=>u.transform(opts[:where]), :join=>u.transform(opts[:join]))
|
|
888
|
+
[ds, u.binds]
|
|
889
|
+
end
|
|
890
|
+
|
|
705
891
|
# Returns a copy of the dataset with no filters (HAVING or WHERE clause) applied.
|
|
706
892
|
#
|
|
707
893
|
# DB[:items].group(:a).having(:a=>1).where(:b).unfiltered
|
|
@@ -726,8 +912,8 @@ module Sequel
|
|
|
726
912
|
# :all :: Set to true to use UNION ALL instead of UNION, so duplicate rows can occur
|
|
727
913
|
# :from_self :: Set to false to not wrap the returned dataset in a from_self, use with care.
|
|
728
914
|
#
|
|
729
|
-
# DB[:items].union(DB[:other_items])
|
|
730
|
-
#
|
|
915
|
+
# DB[:items].union(DB[:other_items])
|
|
916
|
+
# # SELECT * FROM (SELECT * FROM items UNION SELECT * FROM other_items) AS t1
|
|
731
917
|
#
|
|
732
918
|
# DB[:items].union(DB[:other_items], :all=>true, :from_self=>false)
|
|
733
919
|
# # SELECT * FROM items UNION ALL SELECT * FROM other_items
|
|
@@ -774,7 +960,12 @@ module Sequel
|
|
|
774
960
|
# # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%')) SELECT * FROM items
|
|
775
961
|
def with(name, dataset, opts={})
|
|
776
962
|
raise(Error, 'This datatset does not support common table expressions') unless supports_cte?
|
|
777
|
-
|
|
963
|
+
if hoist_cte?(dataset)
|
|
964
|
+
s, ds = hoist_cte(dataset)
|
|
965
|
+
s.with(name, ds, opts)
|
|
966
|
+
else
|
|
967
|
+
clone(:with=>(@opts[:with]||[]) + [opts.merge(:name=>name, :dataset=>dataset)])
|
|
968
|
+
end
|
|
778
969
|
end
|
|
779
970
|
|
|
780
971
|
# Add a recursive common table expression (CTE) with the given name, a dataset that
|
|
@@ -796,20 +987,50 @@ module Sequel
|
|
|
796
987
|
# # SELECT i AS id, pi AS parent_id FROM t
|
|
797
988
|
def with_recursive(name, nonrecursive, recursive, opts={})
|
|
798
989
|
raise(Error, 'This datatset does not support common table expressions') unless supports_cte?
|
|
799
|
-
|
|
990
|
+
if hoist_cte?(nonrecursive)
|
|
991
|
+
s, ds = hoist_cte(nonrecursive)
|
|
992
|
+
s.with_recursive(name, ds, recursive, opts)
|
|
993
|
+
elsif hoist_cte?(recursive)
|
|
994
|
+
s, ds = hoist_cte(recursive)
|
|
995
|
+
s.with_recursive(name, nonrecursive, ds, opts)
|
|
996
|
+
else
|
|
997
|
+
clone(:with=>(@opts[:with]||[]) + [opts.merge(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))])
|
|
998
|
+
end
|
|
800
999
|
end
|
|
801
1000
|
|
|
802
1001
|
# Returns a copy of the dataset with the static SQL used. This is useful if you want
|
|
803
1002
|
# to keep the same row_proc/graph, but change the SQL used to custom SQL.
|
|
804
1003
|
#
|
|
805
1004
|
# DB[:items].with_sql('SELECT * FROM foo') # SELECT * FROM foo
|
|
1005
|
+
#
|
|
1006
|
+
# You can use placeholders in your SQL and provide arguments for those placeholders:
|
|
1007
|
+
#
|
|
1008
|
+
# DB[:items].with_sql('SELECT ? FROM foo', 1) # SELECT 1 FROM foo
|
|
1009
|
+
#
|
|
1010
|
+
# You can also provide a method name and arguments to call to get the SQL:
|
|
1011
|
+
#
|
|
1012
|
+
# DB[:items].with_sql(:insert_sql, :b=>1) # INSERT INTO items (b) VALUES (1)
|
|
806
1013
|
def with_sql(sql, *args)
|
|
807
|
-
sql
|
|
1014
|
+
if sql.is_a?(Symbol)
|
|
1015
|
+
sql = send(sql, *args)
|
|
1016
|
+
else
|
|
1017
|
+
sql = SQL::PlaceholderLiteralString.new(sql, args) unless args.empty?
|
|
1018
|
+
end
|
|
808
1019
|
clone(:sql=>sql)
|
|
809
1020
|
end
|
|
810
1021
|
|
|
811
1022
|
protected
|
|
812
1023
|
|
|
1024
|
+
# Add the dataset to the list of compounds
|
|
1025
|
+
def compound_clone(type, dataset, opts)
|
|
1026
|
+
if hoist_cte?(dataset)
|
|
1027
|
+
s, ds = hoist_cte(dataset)
|
|
1028
|
+
return s.compound_clone(type, ds, opts)
|
|
1029
|
+
end
|
|
1030
|
+
ds = compound_from_self.clone(:compounds=>Array(@opts[:compounds]).map{|x| x.dup} + [[type, dataset.compound_from_self, opts[:all]]])
|
|
1031
|
+
opts[:from_self] == false ? ds : ds.from_self(opts)
|
|
1032
|
+
end
|
|
1033
|
+
|
|
813
1034
|
# Return true if the dataset has a non-nil value for any key in opts.
|
|
814
1035
|
def options_overlap(opts)
|
|
815
1036
|
!(@opts.collect{|k,v| k unless v.nil?}.compact & opts).empty?
|
|
@@ -823,22 +1044,22 @@ module Sequel
|
|
|
823
1044
|
|
|
824
1045
|
private
|
|
825
1046
|
|
|
826
|
-
# Internal filter method so it works on either the having or where clauses.
|
|
827
|
-
def
|
|
1047
|
+
# Internal filter/exclude method so it works on either the having or where clauses.
|
|
1048
|
+
def _filter_or_exclude(invert, clause, *cond, &block)
|
|
828
1049
|
cond = cond.first if cond.size == 1
|
|
829
1050
|
if cond.respond_to?(:empty?) && cond.empty? && !block
|
|
830
1051
|
clone
|
|
831
1052
|
else
|
|
832
1053
|
cond = filter_expr(cond, &block)
|
|
1054
|
+
cond = SQL::BooleanExpression.invert(cond) if invert
|
|
833
1055
|
cond = SQL::BooleanExpression.new(:AND, @opts[clause], cond) if @opts[clause]
|
|
834
1056
|
clone(clause => cond)
|
|
835
1057
|
end
|
|
836
1058
|
end
|
|
837
|
-
|
|
838
|
-
#
|
|
839
|
-
def
|
|
840
|
-
|
|
841
|
-
opts[:from_self] == false ? ds : ds.from_self(opts)
|
|
1059
|
+
|
|
1060
|
+
# Internal filter method so it works on either the having or where clauses.
|
|
1061
|
+
def _filter(clause, *cond, &block)
|
|
1062
|
+
_filter_or_exclude(false, clause, *cond, &block)
|
|
842
1063
|
end
|
|
843
1064
|
|
|
844
1065
|
# SQL expression object based on the expr type. See +filter+.
|
|
@@ -867,7 +1088,13 @@ module Sequel
|
|
|
867
1088
|
when Symbol, SQL::Expression
|
|
868
1089
|
expr
|
|
869
1090
|
when TrueClass, FalseClass
|
|
870
|
-
|
|
1091
|
+
if supports_where_true?
|
|
1092
|
+
SQL::BooleanExpression.new(:NOOP, expr)
|
|
1093
|
+
elsif expr
|
|
1094
|
+
SQL::Constants::SQLTRUE
|
|
1095
|
+
else
|
|
1096
|
+
SQL::Constants::SQLFALSE
|
|
1097
|
+
end
|
|
871
1098
|
when String
|
|
872
1099
|
LiteralString.new("(#{expr})")
|
|
873
1100
|
else
|
|
@@ -875,11 +1102,23 @@ module Sequel
|
|
|
875
1102
|
end
|
|
876
1103
|
end
|
|
877
1104
|
|
|
1105
|
+
# Return two datasets, the first a clone of the receiver with the WITH
|
|
1106
|
+
# clause from the given dataset added to it, and the second a clone of
|
|
1107
|
+
# the given dataset with the WITH clause removed.
|
|
1108
|
+
def hoist_cte(ds)
|
|
1109
|
+
[clone(:with => (opts[:with] || []) + ds.opts[:with]), ds.clone(:with => nil)]
|
|
1110
|
+
end
|
|
1111
|
+
|
|
1112
|
+
# Whether CTEs need to be hoisted from the given ds into the current ds.
|
|
1113
|
+
def hoist_cte?(ds)
|
|
1114
|
+
ds.is_a?(Dataset) && ds.opts[:with] && !supports_cte_in_subqueries?
|
|
1115
|
+
end
|
|
1116
|
+
|
|
878
1117
|
# Inverts the given order by breaking it into a list of column references
|
|
879
1118
|
# and inverting them.
|
|
880
1119
|
#
|
|
881
|
-
# DB[:items].invert_order([:id
|
|
882
|
-
# DB[:items].invert_order(:category, :price
|
|
1120
|
+
# DB[:items].invert_order([Sequel.desc(:id)]]) #=> [Sequel.asc(:id)]
|
|
1121
|
+
# DB[:items].invert_order([:category, Sequel.desc(:price)]) #=> [Sequel.desc(:category), Sequel.asc(:price)]
|
|
883
1122
|
def invert_order(order)
|
|
884
1123
|
return nil unless order
|
|
885
1124
|
new_order = []
|
|
@@ -892,5 +1131,17 @@ module Sequel
|
|
|
892
1131
|
end
|
|
893
1132
|
end
|
|
894
1133
|
end
|
|
1134
|
+
|
|
1135
|
+
# Return self if the dataset already has a server, or a cloned dataset with the
|
|
1136
|
+
# default server otherwise.
|
|
1137
|
+
def default_server
|
|
1138
|
+
@opts[:server] ? self : clone(:server=>:default)
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
# Treat the +block+ as a virtual_row block if not +nil+ and
|
|
1142
|
+
# add the resulting columns to the +columns+ array (modifies +columns+).
|
|
1143
|
+
def virtual_row_columns(columns, block)
|
|
1144
|
+
columns.concat(Array(Sequel.virtual_row(&block))) if block
|
|
1145
|
+
end
|
|
895
1146
|
end
|
|
896
1147
|
end
|