sequel 3.48.0 → 4.0.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 +4 -4
- data/CHANGELOG +114 -0
- data/Rakefile +10 -7
- data/doc/association_basics.rdoc +25 -23
- data/doc/code_order.rdoc +7 -0
- data/doc/core_extensions.rdoc +0 -10
- data/doc/object_model.rdoc +4 -1
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.0.0.txt +262 -0
- data/doc/security.rdoc +0 -28
- data/doc/testing.rdoc +8 -14
- data/lib/sequel/adapters/ado.rb +7 -11
- data/lib/sequel/adapters/ado/access.rb +8 -8
- data/lib/sequel/adapters/ado/mssql.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +6 -6
- data/lib/sequel/adapters/cubrid.rb +7 -7
- data/lib/sequel/adapters/db2.rb +5 -9
- data/lib/sequel/adapters/dbi.rb +2 -6
- data/lib/sequel/adapters/do.rb +4 -4
- data/lib/sequel/adapters/firebird.rb +4 -4
- data/lib/sequel/adapters/ibmdb.rb +8 -8
- data/lib/sequel/adapters/informix.rb +2 -10
- data/lib/sequel/adapters/jdbc.rb +17 -17
- data/lib/sequel/adapters/jdbc/as400.rb +2 -2
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/informix.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
- data/lib/sequel/adapters/mock.rb +7 -7
- data/lib/sequel/adapters/mysql.rb +3 -3
- data/lib/sequel/adapters/mysql2.rb +4 -4
- data/lib/sequel/adapters/odbc.rb +2 -6
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -5
- data/lib/sequel/adapters/oracle.rb +13 -17
- data/lib/sequel/adapters/postgres.rb +20 -25
- data/lib/sequel/adapters/shared/cubrid.rb +3 -3
- data/lib/sequel/adapters/shared/db2.rb +2 -2
- data/lib/sequel/adapters/shared/firebird.rb +7 -7
- data/lib/sequel/adapters/shared/mssql.rb +9 -9
- data/lib/sequel/adapters/shared/mysql.rb +29 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
- data/lib/sequel/adapters/shared/oracle.rb +22 -13
- data/lib/sequel/adapters/shared/postgres.rb +61 -46
- data/lib/sequel/adapters/shared/sqlite.rb +9 -9
- data/lib/sequel/adapters/sqlite.rb +17 -11
- data/lib/sequel/adapters/swift.rb +3 -3
- data/lib/sequel/adapters/swift/mysql.rb +1 -1
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +8 -8
- data/lib/sequel/ast_transformer.rb +3 -1
- data/lib/sequel/connection_pool.rb +4 -2
- data/lib/sequel/connection_pool/sharded_single.rb +2 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
- data/lib/sequel/connection_pool/threaded.rb +7 -7
- data/lib/sequel/core.rb +4 -67
- data/lib/sequel/database.rb +1 -0
- data/lib/sequel/database/connecting.rb +2 -8
- data/lib/sequel/database/dataset.rb +2 -7
- data/lib/sequel/database/dataset_defaults.rb +0 -18
- data/lib/sequel/database/features.rb +4 -4
- data/lib/sequel/database/misc.rb +6 -8
- data/lib/sequel/database/query.rb +5 -61
- data/lib/sequel/database/schema_generator.rb +22 -20
- data/lib/sequel/database/schema_methods.rb +48 -20
- data/lib/sequel/database/transactions.rb +7 -17
- data/lib/sequel/dataset.rb +2 -0
- data/lib/sequel/dataset/actions.rb +23 -91
- data/lib/sequel/dataset/features.rb +1 -4
- data/lib/sequel/dataset/graph.rb +3 -47
- data/lib/sequel/dataset/misc.rb +4 -33
- data/lib/sequel/dataset/prepared_statements.rb +3 -1
- data/lib/sequel/dataset/query.rb +116 -240
- data/lib/sequel/dataset/sql.rb +19 -97
- data/lib/sequel/deprecated.rb +0 -16
- data/lib/sequel/exceptions.rb +0 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/columns_introspection.rb +1 -12
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/core_extensions.rb +0 -9
- data/lib/sequel/extensions/date_arithmetic.rb +1 -2
- data/lib/sequel/extensions/graph_each.rb +11 -0
- data/lib/sequel/extensions/migration.rb +5 -5
- data/lib/sequel/extensions/null_dataset.rb +11 -13
- data/lib/sequel/extensions/pagination.rb +3 -6
- data/lib/sequel/extensions/pg_array.rb +6 -4
- data/lib/sequel/extensions/pg_array_ops.rb +35 -1
- data/lib/sequel/extensions/pg_json.rb +12 -2
- data/lib/sequel/extensions/pg_json_ops.rb +266 -0
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_range_ops.rb +0 -8
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pretty_table.rb +0 -4
- data/lib/sequel/extensions/query.rb +3 -8
- data/lib/sequel/extensions/schema_caching.rb +0 -7
- data/lib/sequel/extensions/schema_dumper.rb +10 -17
- data/lib/sequel/extensions/select_remove.rb +0 -4
- data/lib/sequel/extensions/set_overrides.rb +28 -0
- data/lib/sequel/extensions/to_dot.rb +6 -10
- data/lib/sequel/model.rb +6 -7
- data/lib/sequel/model/associations.rb +127 -182
- data/lib/sequel/model/base.rb +88 -211
- data/lib/sequel/model/errors.rb +0 -13
- data/lib/sequel/model/plugins.rb +2 -2
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/after_initialize.rb +11 -17
- data/lib/sequel/plugins/association_autoreloading.rb +1 -47
- data/lib/sequel/plugins/association_dependencies.rb +2 -2
- data/lib/sequel/plugins/auto_validations.rb +2 -8
- data/lib/sequel/plugins/blacklist_security.rb +32 -2
- data/lib/sequel/plugins/caching.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +10 -8
- data/lib/sequel/plugins/constraint_validations.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +4 -0
- data/lib/sequel/plugins/defaults_setter.rb +8 -6
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/force_encoding.rb +13 -8
- data/lib/sequel/plugins/hook_class_methods.rb +1 -7
- data/lib/sequel/plugins/json_serializer.rb +13 -74
- data/lib/sequel/plugins/lazy_attributes.rb +2 -4
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +4 -11
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +3 -5
- data/lib/sequel/plugins/pg_array_associations.rb +453 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +5 -4
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +7 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -2
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +19 -4
- data/lib/sequel/plugins/validation_class_methods.rb +0 -30
- data/lib/sequel/plugins/validation_helpers.rb +13 -31
- data/lib/sequel/plugins/xml_serializer.rb +18 -57
- data/lib/sequel/sql.rb +20 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/db2_spec.rb +14 -23
- data/spec/adapters/firebird_spec.rb +25 -29
- data/spec/adapters/informix_spec.rb +11 -14
- data/spec/adapters/mssql_spec.rb +71 -77
- data/spec/adapters/mysql_spec.rb +165 -172
- data/spec/adapters/oracle_spec.rb +36 -39
- data/spec/adapters/postgres_spec.rb +175 -100
- data/spec/adapters/spec_helper.rb +13 -11
- data/spec/adapters/sqlite_spec.rb +36 -44
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +55 -55
- data/spec/core/dataset_spec.rb +45 -249
- data/spec/core/deprecated_spec.rb +0 -8
- data/spec/core/expression_filters_spec.rb +23 -5
- data/spec/core/object_graph_spec.rb +4 -66
- data/spec/core/schema_spec.rb +35 -12
- data/spec/core/spec_helper.rb +3 -2
- data/spec/core_extensions_spec.rb +17 -19
- data/spec/extensions/arbitrary_servers_spec.rb +2 -3
- data/spec/extensions/association_dependencies_spec.rb +14 -14
- data/spec/extensions/auto_validations_spec.rb +7 -0
- data/spec/extensions/blacklist_security_spec.rb +5 -5
- data/spec/extensions/blank_spec.rb +2 -0
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/extensions/columns_introspection_spec.rb +2 -29
- data/spec/extensions/composition_spec.rb +10 -17
- data/spec/extensions/core_refinements_spec.rb +5 -1
- data/spec/extensions/dataset_associations_spec.rb +18 -0
- data/spec/extensions/date_arithmetic_spec.rb +2 -2
- data/spec/extensions/defaults_setter_spec.rb +9 -9
- data/spec/extensions/dirty_spec.rb +0 -5
- data/spec/extensions/eval_inspect_spec.rb +2 -0
- data/spec/extensions/force_encoding_spec.rb +2 -18
- data/spec/extensions/hash_aliases_spec.rb +8 -0
- data/spec/extensions/hook_class_methods_spec.rb +39 -58
- data/spec/extensions/inflector_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +8 -8
- data/spec/extensions/json_serializer_spec.rb +1 -41
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +106 -109
- data/spec/extensions/migration_spec.rb +2 -0
- data/spec/extensions/named_timezones_spec.rb +1 -0
- data/spec/extensions/pg_array_associations_spec.rb +603 -0
- data/spec/extensions/pg_array_ops_spec.rb +25 -0
- data/spec/extensions/pg_array_spec.rb +9 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
- data/spec/extensions/pg_hstore_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +131 -0
- data/spec/extensions/pg_json_spec.rb +10 -4
- data/spec/extensions/pg_range_ops_spec.rb +2 -5
- data/spec/extensions/pg_range_spec.rb +6 -2
- data/spec/extensions/pg_row_ops_spec.rb +2 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
- data/spec/extensions/rcte_tree_spec.rb +15 -15
- data/spec/extensions/schema_dumper_spec.rb +0 -1
- data/spec/extensions/schema_spec.rb +9 -9
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +18 -29
- data/spec/extensions/set_overrides_spec.rb +4 -0
- data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
- data/spec/extensions/single_table_inheritance_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +8 -9
- data/spec/extensions/sql_expr_spec.rb +2 -0
- data/spec/extensions/string_date_time_spec.rb +2 -0
- data/spec/extensions/string_stripper_spec.rb +2 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
- data/spec/extensions/thread_local_timezones_spec.rb +2 -0
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +24 -24
- data/spec/extensions/tree_spec.rb +7 -7
- data/spec/extensions/typecast_on_load_spec.rb +8 -1
- data/spec/extensions/update_primary_key_spec.rb +10 -10
- data/spec/extensions/validation_class_methods_spec.rb +10 -39
- data/spec/extensions/validation_helpers_spec.rb +29 -47
- data/spec/extensions/xml_serializer_spec.rb +1 -23
- data/spec/integration/associations_test.rb +231 -40
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +64 -64
- data/spec/integration/eager_loader_test.rb +28 -28
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +21 -21
- data/spec/integration/prepared_statement_test.rb +7 -7
- data/spec/integration/schema_test.rb +115 -110
- data/spec/integration/spec_helper.rb +17 -27
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +10 -10
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +2 -28
- data/spec/model/associations_spec.rb +239 -188
- data/spec/model/base_spec.rb +27 -68
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +160 -172
- data/spec/model/hooks_spec.rb +62 -79
- data/spec/model/model_spec.rb +36 -51
- data/spec/model/plugins_spec.rb +5 -19
- data/spec/model/record_spec.rb +125 -151
- data/spec/model/spec_helper.rb +8 -6
- data/spec/model/validations_spec.rb +4 -17
- data/spec/spec_config.rb +2 -10
- metadata +50 -56
- data/lib/sequel/deprecated_core_extensions.rb +0 -135
- data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
- data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
- data/lib/sequel/plugins/identity_map.rb +0 -260
- data/lib/sequel_core.rb +0 -2
- data/lib/sequel_model.rb +0 -2
- data/spec/extensions/association_autoreloading_spec.rb +0 -102
- data/spec/extensions/identity_map_spec.rb +0 -337
- data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
- data/spec/extensions/pg_statement_cache_spec.rb +0 -208
- data/spec/rcov.opts +0 -8
- data/spec/spec_config.rb.example +0 -10
|
@@ -10,11 +10,8 @@ module Sequel
|
|
|
10
10
|
def quote_identifiers?
|
|
11
11
|
if defined?(@quote_identifiers)
|
|
12
12
|
@quote_identifiers
|
|
13
|
-
elsif db.respond_to?(:quote_identifiers?)
|
|
14
|
-
@quote_identifiers = db.quote_identifiers?
|
|
15
13
|
else
|
|
16
|
-
|
|
17
|
-
@quote_identifiers = false
|
|
14
|
+
@quote_identifiers = db.quote_identifiers?
|
|
18
15
|
end
|
|
19
16
|
end
|
|
20
17
|
|
data/lib/sequel/dataset/graph.rb
CHANGED
|
@@ -14,10 +14,8 @@ module Sequel
|
|
|
14
14
|
# DB[:table].add_graph_aliases(:some_alias=>[:table, :column])
|
|
15
15
|
# # SELECT ..., table.column AS some_alias
|
|
16
16
|
def add_graph_aliases(graph_aliases)
|
|
17
|
-
unless ga = opts[:graph_aliases]
|
|
18
|
-
|
|
19
|
-
Sequel::Deprecation.deprecate('Calling Dataset#add_graph_aliases before #graph or #set_graph_aliases', 'Please call it after #graph or #set_graph_aliases')
|
|
20
|
-
end
|
|
17
|
+
unless (ga = opts[:graph_aliases]) || (opts[:graph] && (ga = opts[:graph][:column_aliases]))
|
|
18
|
+
raise Error, "cannot call add_graph_aliases on a dataset that has not been called with graph or set_graph_aliases"
|
|
21
19
|
end
|
|
22
20
|
columns, graph_aliases = graph_alias_columns(graph_aliases)
|
|
23
21
|
select_more(*columns).clone(:graph_aliases => ga.merge(graph_aliases))
|
|
@@ -48,7 +46,7 @@ module Sequel
|
|
|
48
46
|
# :table_alias :: The alias to use for the table. If not specified, doesn't
|
|
49
47
|
# alias the table. You will get an error if the the alias (or table) name is
|
|
50
48
|
# used more than once.
|
|
51
|
-
def graph(dataset, join_conditions = nil, options =
|
|
49
|
+
def graph(dataset, join_conditions = nil, options = OPTS, &block)
|
|
52
50
|
# Allow the use of a dataset or symbol as the first argument
|
|
53
51
|
# Find the table name/dataset based on the argument
|
|
54
52
|
table_alias = options[:table_alias]
|
|
@@ -232,47 +230,5 @@ module Sequel
|
|
|
232
230
|
end
|
|
233
231
|
[identifiers, gas]
|
|
234
232
|
end
|
|
235
|
-
|
|
236
|
-
# Fetch the rows, split them into component table parts,
|
|
237
|
-
# tranform and run the row_proc on each part (if applicable),
|
|
238
|
-
# and yield a hash of the parts.
|
|
239
|
-
def graph_each
|
|
240
|
-
Sequel::Deprecation.deprecate('Dataset#graph_each', 'Load the graph_each extension if you want to continue using it')
|
|
241
|
-
# Reject tables with nil datasets, as they are excluded from
|
|
242
|
-
# the result set
|
|
243
|
-
datasets = @opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
|
|
244
|
-
# Get just the list of table aliases into a local variable, for speed
|
|
245
|
-
table_aliases = datasets.collect{|ta,ds| ta}
|
|
246
|
-
# Get an array of arrays, one for each dataset, with
|
|
247
|
-
# the necessary information about each dataset, for speed
|
|
248
|
-
datasets = datasets.collect{|ta, ds| [ta, ds, ds.row_proc]}
|
|
249
|
-
# Use the manually set graph aliases, if any, otherwise
|
|
250
|
-
# use the ones automatically created by .graph
|
|
251
|
-
column_aliases = @opts[:graph_aliases] || @opts[:graph][:column_aliases]
|
|
252
|
-
fetch_rows(select_sql) do |r|
|
|
253
|
-
graph = {}
|
|
254
|
-
# Create the sub hashes, one per table
|
|
255
|
-
table_aliases.each{|ta| graph[ta]={}}
|
|
256
|
-
# Split the result set based on the column aliases
|
|
257
|
-
# If there are columns in the result set that are
|
|
258
|
-
# not in column_aliases, they are ignored
|
|
259
|
-
column_aliases.each do |col_alias, tc|
|
|
260
|
-
ta, column = tc
|
|
261
|
-
graph[ta][column] = r[col_alias]
|
|
262
|
-
end
|
|
263
|
-
# For each dataset run the row_proc if applicable
|
|
264
|
-
datasets.each do |ta,ds,rp|
|
|
265
|
-
g = graph[ta]
|
|
266
|
-
graph[ta] = if g.values.any?{|x| !x.nil?}
|
|
267
|
-
rp ? rp.call(g) : g
|
|
268
|
-
else
|
|
269
|
-
nil
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
yield graph
|
|
274
|
-
end
|
|
275
|
-
self
|
|
276
|
-
end
|
|
277
233
|
end
|
|
278
234
|
end
|
data/lib/sequel/dataset/misc.rb
CHANGED
|
@@ -17,27 +17,6 @@ module Sequel
|
|
|
17
17
|
# The hash of options for this dataset, keys are symbols.
|
|
18
18
|
attr_reader :opts
|
|
19
19
|
|
|
20
|
-
# REMOVE40
|
|
21
|
-
def db=(v)
|
|
22
|
-
Sequel::Deprecation.deprecate('Dataset#db=', 'Please load the sequel_3_dataset_methods extension to continue using it')
|
|
23
|
-
@db = v
|
|
24
|
-
end
|
|
25
|
-
def opts=(v)
|
|
26
|
-
Sequel::Deprecation.deprecate('Dataset#opts=', 'Please load the sequel_3_dataset_methods extension to continue using it')
|
|
27
|
-
@opts = v
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
module DeprecateModifyHash
|
|
31
|
-
%w'[]= merge! update clear delete delete_if keep_if reject! select! shift store'.each do |meth|
|
|
32
|
-
class_eval(<<-END, __FILE__, __LINE__+1)
|
|
33
|
-
def #{meth}(*)
|
|
34
|
-
Sequel::Deprecation.deprecate('Modifying the initial dataset opts hash is deprecated. Please dup the hash.')
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
END
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
20
|
# Constructs a new Dataset instance with an associated database and
|
|
42
21
|
# options. Datasets are usually constructed by invoking the Database#[] method:
|
|
43
22
|
#
|
|
@@ -46,11 +25,9 @@ module Sequel
|
|
|
46
25
|
# Sequel::Dataset is an abstract class that is not useful by itself. Each
|
|
47
26
|
# database adapter provides a subclass of Sequel::Dataset, and has
|
|
48
27
|
# the Database#dataset method return an instance of that subclass.
|
|
49
|
-
def initialize(db
|
|
28
|
+
def initialize(db)
|
|
50
29
|
@db = db
|
|
51
|
-
|
|
52
|
-
Sequel::Deprecation.deprecate('Passing the opts argument to Database#dataset or Dataset#initialize', 'Clone the dataset afterward to change the opts') unless no_arg_given
|
|
53
|
-
@opts = opts || {}.extend(DeprecateModifyHash)
|
|
30
|
+
@opts = OPTS
|
|
54
31
|
end
|
|
55
32
|
|
|
56
33
|
# Define a hash value such that datasets with the same DB, opts, and SQL
|
|
@@ -147,11 +124,8 @@ module Sequel
|
|
|
147
124
|
def identifier_input_method
|
|
148
125
|
if defined?(@identifier_input_method)
|
|
149
126
|
@identifier_input_method
|
|
150
|
-
elsif db.respond_to?(:identifier_input_method)
|
|
151
|
-
@identifier_input_method = db.identifier_input_method
|
|
152
127
|
else
|
|
153
|
-
|
|
154
|
-
@identifier_input_method = nil
|
|
128
|
+
@identifier_input_method = db.identifier_input_method
|
|
155
129
|
end
|
|
156
130
|
end
|
|
157
131
|
|
|
@@ -160,11 +134,8 @@ module Sequel
|
|
|
160
134
|
def identifier_output_method
|
|
161
135
|
if defined?(@identifier_output_method)
|
|
162
136
|
@identifier_output_method
|
|
163
|
-
elsif db.respond_to?(:identifier_output_method)
|
|
164
|
-
@identifier_output_method = db.identifier_output_method
|
|
165
137
|
else
|
|
166
|
-
|
|
167
|
-
@identifier_output_method = nil
|
|
138
|
+
@identifier_output_method = db.identifier_output_method
|
|
168
139
|
end
|
|
169
140
|
end
|
|
170
141
|
|
|
@@ -118,7 +118,9 @@ module Sequel
|
|
|
118
118
|
# with the prepared SQL it represents (which in general won't have
|
|
119
119
|
# substituted variables).
|
|
120
120
|
def inspect
|
|
121
|
-
|
|
121
|
+
c = self.class
|
|
122
|
+
c = c.superclass while c.name.nil? || c.name == ''
|
|
123
|
+
"<#{c.name}/PreparedStatement #{prepared_sql.inspect}>"
|
|
122
124
|
end
|
|
123
125
|
|
|
124
126
|
protected
|
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -64,22 +64,9 @@ module Sequel
|
|
|
64
64
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
#
|
|
68
|
-
# exists an error is raised. This method is identical to #filter except
|
|
69
|
-
# it expects an existing filter.
|
|
70
|
-
#
|
|
71
|
-
# DB[:table].filter(:a).and(:b) # SELECT * FROM table WHERE a AND b
|
|
67
|
+
# Alias for where.
|
|
72
68
|
def and(*cond, &block)
|
|
73
|
-
|
|
74
|
-
Sequel::Deprecation.deprecate('Dataset#and will no longer raise for an unfilered dataset starting in Sequel 4.')
|
|
75
|
-
raise(InvalidOperation, "No existing filter found.")
|
|
76
|
-
end
|
|
77
|
-
if @opts[:having]
|
|
78
|
-
Sequel::Deprecation.deprecate('Dataset#and will no longer modify the HAVING clause starting in Sequel 4. Switch to using Dataset#having or use the filter_having extension.')
|
|
79
|
-
having(*cond, &block)
|
|
80
|
-
else
|
|
81
|
-
where(*cond, &block)
|
|
82
|
-
end
|
|
69
|
+
where(*cond, &block)
|
|
83
70
|
end
|
|
84
71
|
|
|
85
72
|
# Returns a new clone of the dataset with with the given options merged.
|
|
@@ -128,17 +115,13 @@ module Sequel
|
|
|
128
115
|
#
|
|
129
116
|
# DB[:items].except(DB[:other_items], :alias=>:i)
|
|
130
117
|
# # SELECT * FROM (SELECT * FROM items EXCEPT SELECT * FROM other_items) AS i
|
|
131
|
-
def except(dataset, opts=
|
|
132
|
-
unless opts.is_a?(Hash)
|
|
133
|
-
Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#except', "Please switch to an options hash with the :all option")
|
|
134
|
-
opts = {:all=>opts}
|
|
135
|
-
end
|
|
118
|
+
def except(dataset, opts=OPTS)
|
|
136
119
|
raise(InvalidOperation, "EXCEPT not supported") unless supports_intersect_except?
|
|
137
120
|
raise(InvalidOperation, "EXCEPT ALL not supported") if opts[:all] && !supports_intersect_except_all?
|
|
138
121
|
compound_clone(:except, dataset, opts)
|
|
139
122
|
end
|
|
140
123
|
|
|
141
|
-
# Performs the inverse of Dataset#
|
|
124
|
+
# Performs the inverse of Dataset#where. Note that if you have multiple filter
|
|
142
125
|
# conditions, this is not the same as a negation of all conditions.
|
|
143
126
|
#
|
|
144
127
|
# DB[:items].exclude(:category => 'software')
|
|
@@ -147,8 +130,7 @@ module Sequel
|
|
|
147
130
|
# DB[:items].exclude(:category => 'software', :id=>3)
|
|
148
131
|
# # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
|
|
149
132
|
def exclude(*cond, &block)
|
|
150
|
-
|
|
151
|
-
_filter_or_exclude(true, @opts[:having] ? :having : :where, *cond, &block)
|
|
133
|
+
_filter_or_exclude(true, :where, *cond, &block)
|
|
152
134
|
end
|
|
153
135
|
|
|
154
136
|
# Inverts the given conditions and adds them to the HAVING clause.
|
|
@@ -159,18 +141,9 @@ module Sequel
|
|
|
159
141
|
_filter_or_exclude(true, :having, *cond, &block)
|
|
160
142
|
end
|
|
161
143
|
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
# DB[:items].select_group(:name).exclude_where(:category => 'software')
|
|
165
|
-
# # SELECT * FROM items WHERE (category != 'software')
|
|
166
|
-
#
|
|
167
|
-
# DB[:items].select_group(:name).
|
|
168
|
-
# exclude_having{count(name) < 2}.
|
|
169
|
-
# exclude_where(:category => 'software')
|
|
170
|
-
# # SELECT name FROM items WHERE (category != 'software')
|
|
171
|
-
# # GROUP BY name HAVING (count(name) >= 2)
|
|
144
|
+
# Alias for exclude.
|
|
172
145
|
def exclude_where(*cond, &block)
|
|
173
|
-
|
|
146
|
+
exclude(*cond, &block)
|
|
174
147
|
end
|
|
175
148
|
|
|
176
149
|
# Return a clone of the dataset loaded with the extensions, see #extension!.
|
|
@@ -178,61 +151,9 @@ module Sequel
|
|
|
178
151
|
clone.extension!(*exts)
|
|
179
152
|
end
|
|
180
153
|
|
|
181
|
-
#
|
|
182
|
-
# If the query already has a HAVING clause, then the conditions are imposed in the
|
|
183
|
-
# HAVING clause. If not, then they are imposed in the WHERE clause.
|
|
184
|
-
#
|
|
185
|
-
# filter accepts the following argument types:
|
|
186
|
-
#
|
|
187
|
-
# * Hash - list of equality/inclusion expressions
|
|
188
|
-
# * Array - depends:
|
|
189
|
-
# * If first member is a string, assumes the rest of the arguments
|
|
190
|
-
# are parameters and interpolates them into the string.
|
|
191
|
-
# * If all members are arrays of length two, treats the same way
|
|
192
|
-
# as a hash, except it allows for duplicate keys to be
|
|
193
|
-
# specified.
|
|
194
|
-
# * Otherwise, treats each argument as a separate condition.
|
|
195
|
-
# * String - taken literally
|
|
196
|
-
# * Symbol - taken as a boolean column argument (e.g. WHERE active)
|
|
197
|
-
# * Sequel::SQL::BooleanExpression - an existing condition expression,
|
|
198
|
-
# probably created using the Sequel expression filter DSL.
|
|
199
|
-
#
|
|
200
|
-
# filter also takes a block, which should return one of the above argument
|
|
201
|
-
# types, and is treated the same way. This block yields a virtual row object,
|
|
202
|
-
# which is easy to use to create identifiers and functions. For more details
|
|
203
|
-
# on the virtual row support, see the {"Virtual Rows" guide}[link:files/doc/virtual_rows_rdoc.html]
|
|
204
|
-
#
|
|
205
|
-
# If both a block and regular argument are provided, they get ANDed together.
|
|
206
|
-
#
|
|
207
|
-
# Examples:
|
|
208
|
-
#
|
|
209
|
-
# DB[:items].filter(:id => 3)
|
|
210
|
-
# # SELECT * FROM items WHERE (id = 3)
|
|
211
|
-
#
|
|
212
|
-
# DB[:items].filter('price < ?', 100)
|
|
213
|
-
# # SELECT * FROM items WHERE price < 100
|
|
214
|
-
#
|
|
215
|
-
# DB[:items].filter([[:id, [1,2,3]], [:id, 0..10]])
|
|
216
|
-
# # SELECT * FROM items WHERE ((id IN (1, 2, 3)) AND ((id >= 0) AND (id <= 10)))
|
|
217
|
-
#
|
|
218
|
-
# DB[:items].filter('price < 100')
|
|
219
|
-
# # SELECT * FROM items WHERE price < 100
|
|
220
|
-
#
|
|
221
|
-
# DB[:items].filter(:active)
|
|
222
|
-
# # SELECT * FROM items WHERE :active
|
|
223
|
-
#
|
|
224
|
-
# DB[:items].filter{price < 100}
|
|
225
|
-
# # SELECT * FROM items WHERE (price < 100)
|
|
226
|
-
#
|
|
227
|
-
# Multiple filter calls can be chained for scoping:
|
|
228
|
-
#
|
|
229
|
-
# software = dataset.filter(:category => 'software').filter{price < 100}
|
|
230
|
-
# # SELECT * FROM items WHERE ((category = 'software') AND (price < 100))
|
|
231
|
-
#
|
|
232
|
-
# See the the {"Dataset Filtering" guide}[link:files/doc/dataset_filtering_rdoc.html] for more examples and details.
|
|
154
|
+
# Alias for where.
|
|
233
155
|
def filter(*cond, &block)
|
|
234
|
-
|
|
235
|
-
_filter(@opts[:having] ? :having : :where, *cond, &block)
|
|
156
|
+
where(*cond, &block)
|
|
236
157
|
end
|
|
237
158
|
|
|
238
159
|
# Returns a cloned dataset with a :update lock style.
|
|
@@ -245,39 +166,38 @@ module Sequel
|
|
|
245
166
|
# Returns a copy of the dataset with the source changed. If no
|
|
246
167
|
# source is given, removes all tables. If multiple sources
|
|
247
168
|
# are given, it is the same as using a CROSS JOIN (cartesian product) between all tables.
|
|
169
|
+
# If a block is given, it is treated as a virtual row block, similar to +where+.
|
|
248
170
|
#
|
|
249
171
|
# DB[:items].from # SQL: SELECT *
|
|
250
172
|
# DB[:items].from(:blah) # SQL: SELECT * FROM blah
|
|
251
173
|
# DB[:items].from(:blah, :foo) # SQL: SELECT * FROM blah, foo
|
|
252
|
-
|
|
174
|
+
# DB[:items].from{fun(arg)} # SQL: SELECT * FROM fun(arg)
|
|
175
|
+
def from(*source, &block)
|
|
176
|
+
virtual_row_columns(source, block)
|
|
253
177
|
table_alias_num = 0
|
|
254
|
-
sources = []
|
|
255
178
|
ctes = nil
|
|
256
|
-
source.
|
|
179
|
+
source.map! do |s|
|
|
257
180
|
case s
|
|
258
|
-
when Hash
|
|
259
|
-
Sequel::Deprecation.deprecate('Dataset#from will no longer treat an input hash as an alias specifier. Switch to aliasing using Sequel.as or use the hash_aliases extension.')
|
|
260
|
-
s.each{|k,v| sources << SQL::AliasedExpression.new(k,v)}
|
|
261
181
|
when Dataset
|
|
262
182
|
if hoist_cte?(s)
|
|
263
183
|
ctes ||= []
|
|
264
184
|
ctes += s.opts[:with]
|
|
265
185
|
s = s.clone(:with=>nil)
|
|
266
186
|
end
|
|
267
|
-
|
|
187
|
+
SQL::AliasedExpression.new(s, dataset_alias(table_alias_num+=1))
|
|
268
188
|
when Symbol
|
|
269
189
|
sch, table, aliaz = split_symbol(s)
|
|
270
190
|
if aliaz
|
|
271
191
|
s = sch ? SQL::QualifiedIdentifier.new(sch, table) : SQL::Identifier.new(table)
|
|
272
|
-
|
|
192
|
+
SQL::AliasedExpression.new(s, aliaz.to_sym)
|
|
273
193
|
else
|
|
274
|
-
|
|
194
|
+
s
|
|
275
195
|
end
|
|
276
196
|
else
|
|
277
|
-
|
|
197
|
+
s
|
|
278
198
|
end
|
|
279
199
|
end
|
|
280
|
-
o = {:from=>
|
|
200
|
+
o = {:from=>source.empty? ? nil : source}
|
|
281
201
|
o[:with] = (opts[:with] || []) + ctes if ctes
|
|
282
202
|
o[:num_dataset_sources] = table_alias_num if table_alias_num > 0
|
|
283
203
|
clone(o)
|
|
@@ -294,7 +214,7 @@ module Sequel
|
|
|
294
214
|
#
|
|
295
215
|
# ds.from_self(:alias=>:foo)
|
|
296
216
|
# # SELECT * FROM (SELECT id, name FROM items ORDER BY name) AS foo
|
|
297
|
-
def from_self(opts=
|
|
217
|
+
def from_self(opts=OPTS)
|
|
298
218
|
fs = {}
|
|
299
219
|
@opts.keys.each{|k| fs[k] = nil unless NON_SQL_OPTIONS.include?(k)}
|
|
300
220
|
clone(fs).from(opts[:alias] ? as(opts[:alias]) : self)
|
|
@@ -331,23 +251,23 @@ module Sequel
|
|
|
331
251
|
#
|
|
332
252
|
# dataset.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true, :all_columns=>true)
|
|
333
253
|
# # SELECT * FROM a WHERE ((a LIKE '%foo%') AND (b LIKE '%foo%') AND (a LIKE '%bar%') AND (b LIKE '%bar%'))
|
|
334
|
-
def grep(columns, patterns, opts=
|
|
254
|
+
def grep(columns, patterns, opts=OPTS)
|
|
335
255
|
if opts[:all_patterns]
|
|
336
256
|
conds = Array(patterns).map do |pat|
|
|
337
257
|
SQL::BooleanExpression.new(opts[:all_columns] ? :AND : :OR, *Array(columns).map{|c| SQL::StringExpression.like(c, pat, opts)})
|
|
338
258
|
end
|
|
339
|
-
|
|
259
|
+
where(SQL::BooleanExpression.new(opts[:all_patterns] ? :AND : :OR, *conds))
|
|
340
260
|
else
|
|
341
261
|
conds = Array(columns).map do |c|
|
|
342
262
|
SQL::BooleanExpression.new(:OR, *Array(patterns).map{|pat| SQL::StringExpression.like(c, pat, opts)})
|
|
343
263
|
end
|
|
344
|
-
|
|
264
|
+
where(SQL::BooleanExpression.new(opts[:all_columns] ? :AND : :OR, *conds))
|
|
345
265
|
end
|
|
346
266
|
end
|
|
347
267
|
|
|
348
268
|
# Returns a copy of the dataset with the results grouped by the value of
|
|
349
269
|
# the given columns. If a block is given, it is treated
|
|
350
|
-
# as a virtual row block, similar to +
|
|
270
|
+
# as a virtual row block, similar to +where+.
|
|
351
271
|
#
|
|
352
272
|
# DB[:items].group(:id) # SELECT * FROM items GROUP BY id
|
|
353
273
|
# DB[:items].group(:id, :name) # SELECT * FROM items GROUP BY id, name
|
|
@@ -364,7 +284,7 @@ module Sequel
|
|
|
364
284
|
|
|
365
285
|
# Returns a dataset grouped by the given column with count by group.
|
|
366
286
|
# Column aliases may be supplied, and will be included in the select clause.
|
|
367
|
-
# If a block is given, it is treated as a virtual row block, similar to +
|
|
287
|
+
# If a block is given, it is treated as a virtual row block, similar to +where+.
|
|
368
288
|
#
|
|
369
289
|
# Examples:
|
|
370
290
|
#
|
|
@@ -399,7 +319,7 @@ module Sequel
|
|
|
399
319
|
clone(:group_options=>:rollup)
|
|
400
320
|
end
|
|
401
321
|
|
|
402
|
-
# Returns a copy of the dataset with the HAVING conditions changed. See #
|
|
322
|
+
# Returns a copy of the dataset with the HAVING conditions changed. See #where for argument types.
|
|
403
323
|
#
|
|
404
324
|
# DB[:items].group(:sum).having(:sum=>10)
|
|
405
325
|
# # SELECT * FROM items GROUP BY sum HAVING (sum = 10)
|
|
@@ -424,33 +344,30 @@ module Sequel
|
|
|
424
344
|
#
|
|
425
345
|
# DB[:items].intersect(DB[:other_items], :alias=>:i)
|
|
426
346
|
# # SELECT * FROM (SELECT * FROM items INTERSECT SELECT * FROM other_items) AS i
|
|
427
|
-
def intersect(dataset, opts=
|
|
428
|
-
unless opts.is_a?(Hash)
|
|
429
|
-
Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#intersect', "Please switch to an options hash with the :all option")
|
|
430
|
-
opts = {:all=>opts}
|
|
431
|
-
end
|
|
347
|
+
def intersect(dataset, opts=OPTS)
|
|
432
348
|
raise(InvalidOperation, "INTERSECT not supported") unless supports_intersect_except?
|
|
433
349
|
raise(InvalidOperation, "INTERSECT ALL not supported") if opts[:all] && !supports_intersect_except_all?
|
|
434
350
|
compound_clone(:intersect, dataset, opts)
|
|
435
351
|
end
|
|
436
352
|
|
|
437
|
-
# Inverts the current
|
|
353
|
+
# Inverts the current WHERE and HAVING clauses. If there is neither a
|
|
354
|
+
# WHERE or HAVING clause, adds a WHERE clause that is always false.
|
|
438
355
|
#
|
|
439
|
-
# DB[:items].
|
|
356
|
+
# DB[:items].where(:category => 'software').invert
|
|
440
357
|
# # SELECT * FROM items WHERE (category != 'software')
|
|
441
358
|
#
|
|
442
|
-
# DB[:items].
|
|
359
|
+
# DB[:items].where(:category => 'software', :id=>3).invert
|
|
443
360
|
# # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
|
|
444
361
|
def invert
|
|
445
|
-
having, where = @opts
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
362
|
+
having, where = @opts.values_at(:having, :where)
|
|
363
|
+
if having.nil? && where.nil?
|
|
364
|
+
where(false)
|
|
365
|
+
else
|
|
366
|
+
o = {}
|
|
367
|
+
o[:having] = SQL::BooleanExpression.invert(having) if having
|
|
368
|
+
o[:where] = SQL::BooleanExpression.invert(where) if where
|
|
369
|
+
clone(o)
|
|
449
370
|
end
|
|
450
|
-
o = {}
|
|
451
|
-
o[:having] = SQL::BooleanExpression.invert(having) if having
|
|
452
|
-
o[:where] = SQL::BooleanExpression.invert(where) if where
|
|
453
|
-
clone(o)
|
|
454
371
|
end
|
|
455
372
|
|
|
456
373
|
# Alias of +inner_join+
|
|
@@ -479,7 +396,7 @@ module Sequel
|
|
|
479
396
|
# the result set if this is used.
|
|
480
397
|
# * nil - If a block is not given, doesn't use ON or USING, so the JOIN should be a NATURAL
|
|
481
398
|
# or CROSS join. If a block is given, uses an ON clause based on the block, see below.
|
|
482
|
-
# * Everything else - pretty much the same as a using the argument in a call to
|
|
399
|
+
# * Everything else - pretty much the same as a using the argument in a call to where,
|
|
483
400
|
# so strings are considered literal, symbols specify boolean columns, and Sequel
|
|
484
401
|
# expressions can be used. Uses a JOIN with an ON clause.
|
|
485
402
|
# * options - a hash of options, with any of the following keys:
|
|
@@ -489,12 +406,12 @@ module Sequel
|
|
|
489
406
|
# the last joined or primary table is used.
|
|
490
407
|
# * :qualify - Can be set to false to not do any implicit qualification. Can be set
|
|
491
408
|
# to :deep to use the Qualifier AST Transformer, which will attempt to qualify
|
|
492
|
-
# subexpressions of the expression tree.
|
|
493
|
-
# default_join_table_qualification.
|
|
409
|
+
# subexpressions of the expression tree. Can be set to :symbol to only qualify
|
|
410
|
+
# symbols. Defaults to the value of default_join_table_qualification.
|
|
494
411
|
# * block - The block argument should only be given if a JOIN with an ON clause is used,
|
|
495
412
|
# in which case it yields the table alias/name for the table currently being joined,
|
|
496
413
|
# the table alias/name for the last joined (or first table), and an array of previous
|
|
497
|
-
# SQL::JoinClause. Unlike +
|
|
414
|
+
# SQL::JoinClause. Unlike +where+, this block is not treated as a virtual row block.
|
|
498
415
|
#
|
|
499
416
|
# Examples:
|
|
500
417
|
#
|
|
@@ -512,7 +429,7 @@ module Sequel
|
|
|
512
429
|
# end
|
|
513
430
|
# # SELECT * FROM a NATURAL JOIN b INNER JOIN c
|
|
514
431
|
# # ON ((c.d > b.e) AND (c.f IN (SELECT g FROM b)))
|
|
515
|
-
def join_table(type, table, expr=nil, options=
|
|
432
|
+
def join_table(type, table, expr=nil, options=OPTS, &block)
|
|
516
433
|
if hoist_cte?(table)
|
|
517
434
|
s, ds = hoist_cte(table)
|
|
518
435
|
return s.join_table(type, ds, expr, options, &block)
|
|
@@ -525,18 +442,9 @@ module Sequel
|
|
|
525
442
|
return join_table(type, table, h, options)
|
|
526
443
|
end
|
|
527
444
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
last_alias = options[:implicit_qualifier]
|
|
532
|
-
qualify_type = options[:qualify]
|
|
533
|
-
when Symbol, String, SQL::Identifier
|
|
534
|
-
Sequel::Deprecation.deprecate('Passing a non-hash as the options hash to Dataset#join_table', "Please switch to an options hash with the :table_alias option")
|
|
535
|
-
table_alias = options
|
|
536
|
-
last_alias = nil
|
|
537
|
-
else
|
|
538
|
-
raise Error, "invalid options format for join_table: #{options.inspect}"
|
|
539
|
-
end
|
|
445
|
+
table_alias = options[:table_alias]
|
|
446
|
+
last_alias = options[:implicit_qualifier]
|
|
447
|
+
qualify_type = options[:qualify]
|
|
540
448
|
|
|
541
449
|
if table.is_a?(Dataset)
|
|
542
450
|
if table_alias.nil?
|
|
@@ -655,19 +563,14 @@ module Sequel
|
|
|
655
563
|
# Adds an alternate filter to an existing filter using OR. If no filter
|
|
656
564
|
# exists an +Error+ is raised.
|
|
657
565
|
#
|
|
658
|
-
# DB[:items].
|
|
566
|
+
# DB[:items].where(:a).or(:b) # SELECT * FROM items WHERE a OR b
|
|
659
567
|
def or(*cond, &block)
|
|
660
|
-
clause = (@opts[:having] ? :having : :where)
|
|
661
|
-
unless @opts[clause]
|
|
662
|
-
Sequel::Deprecation.deprecate('Dataset#or will no longer raise for an unfilered dataset starting in Sequel 4.')
|
|
663
|
-
raise(InvalidOperation, "No existing filter found.")
|
|
664
|
-
end
|
|
665
|
-
Sequel::Deprecation.deprecate('Dataset#or will no longer modify the HAVING clause starting in Sequel 4. You can use the filter_having extension to continue to use the current behavior.') if clause == :having
|
|
666
568
|
cond = cond.first if cond.size == 1
|
|
667
|
-
|
|
569
|
+
v = @opts[:where]
|
|
570
|
+
if v.nil? || (cond.respond_to?(:empty?) && cond.empty? && !block)
|
|
668
571
|
clone
|
|
669
572
|
else
|
|
670
|
-
clone(
|
|
573
|
+
clone(:where => SQL::BooleanExpression.new(:OR, v, filter_expr(cond, &block)))
|
|
671
574
|
end
|
|
672
575
|
end
|
|
673
576
|
|
|
@@ -675,7 +578,7 @@ module Sequel
|
|
|
675
578
|
# existing order, it is ignored and overwritten with this order. If a nil is given
|
|
676
579
|
# the returned dataset has no order. This can accept multiple arguments
|
|
677
580
|
# of varying kinds, such as SQL functions. If a block is given, it is treated
|
|
678
|
-
# as a virtual row block, similar to +
|
|
581
|
+
# as a virtual row block, similar to +where+.
|
|
679
582
|
#
|
|
680
583
|
# DB[:items].order(:name) # SELECT * FROM items ORDER BY name
|
|
681
584
|
# DB[:items].order(:a, :b) # SELECT * FROM items ORDER BY a, b
|
|
@@ -722,10 +625,10 @@ module Sequel
|
|
|
722
625
|
|
|
723
626
|
# Qualify to the given table, or first source if no table is given.
|
|
724
627
|
#
|
|
725
|
-
# DB[:items].
|
|
628
|
+
# DB[:items].where(:id=>1).qualify
|
|
726
629
|
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
727
630
|
#
|
|
728
|
-
# DB[:items].
|
|
631
|
+
# DB[:items].where(:id=>1).qualify(:i)
|
|
729
632
|
# # SELECT i.* FROM items WHERE (i.id = 1)
|
|
730
633
|
def qualify(table=first_source)
|
|
731
634
|
o = @opts
|
|
@@ -738,31 +641,6 @@ module Sequel
|
|
|
738
641
|
clone(h)
|
|
739
642
|
end
|
|
740
643
|
|
|
741
|
-
# Return a copy of the dataset with unqualified identifiers in the
|
|
742
|
-
# SELECT, WHERE, GROUP, HAVING, and ORDER clauses qualified by the
|
|
743
|
-
# given table. If no columns are currently selected, select all
|
|
744
|
-
# columns of the given table.
|
|
745
|
-
#
|
|
746
|
-
# DB[:items].filter(:id=>1).qualify_to(:i)
|
|
747
|
-
# # SELECT i.* FROM items WHERE (i.id = 1)
|
|
748
|
-
def qualify_to(table)
|
|
749
|
-
Sequel::Deprecation.deprecate('Dataset#qualify_to', 'Switch to Dataset#qualify or use the sequel_3_dataset_methods extension')
|
|
750
|
-
qualify(table)
|
|
751
|
-
end
|
|
752
|
-
|
|
753
|
-
# Qualify the dataset to its current first source. This is useful
|
|
754
|
-
# if you have unqualified identifiers in the query that all refer to
|
|
755
|
-
# the first source, and you want to join to another table which
|
|
756
|
-
# has columns with the same name as columns in the current dataset.
|
|
757
|
-
# See +qualify_to+.
|
|
758
|
-
#
|
|
759
|
-
# DB[:items].filter(:id=>1).qualify_to_first_source
|
|
760
|
-
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
761
|
-
def qualify_to_first_source
|
|
762
|
-
Sequel::Deprecation.deprecate('Dataset#qualify_to_first_source', 'Switch to Dataset#qualify or use the sequel_3_dataset_methods extension')
|
|
763
|
-
qualify
|
|
764
|
-
end
|
|
765
|
-
|
|
766
644
|
# Modify the RETURNING clause, only supported on a few databases. If returning
|
|
767
645
|
# is used, instead of insert returning the autogenerated primary key or
|
|
768
646
|
# update/delete returning the number of modified rows, results are
|
|
@@ -794,23 +672,14 @@ module Sequel
|
|
|
794
672
|
|
|
795
673
|
# Returns a copy of the dataset with the columns selected changed
|
|
796
674
|
# to the given columns. This also takes a virtual row block,
|
|
797
|
-
# similar to +
|
|
675
|
+
# similar to +where+.
|
|
798
676
|
#
|
|
799
677
|
# DB[:items].select(:a) # SELECT a FROM items
|
|
800
678
|
# DB[:items].select(:a, :b) # SELECT a, b FROM items
|
|
801
679
|
# DB[:items].select{[a, sum(b)]} # SELECT a, sum(b) FROM items
|
|
802
680
|
def select(*columns, &block)
|
|
803
681
|
virtual_row_columns(columns, block)
|
|
804
|
-
|
|
805
|
-
columns.each do |i|
|
|
806
|
-
if i.is_a?(Hash)
|
|
807
|
-
Sequel::Deprecation.deprecate('Dataset#select will no longer treat an input hash as an alias specifier. Switch to aliasing using Sequel.as or use the hash_aliases extension.')
|
|
808
|
-
m.concat(i.map{|k, v| SQL::AliasedExpression.new(k,v)})
|
|
809
|
-
else
|
|
810
|
-
m << i
|
|
811
|
-
end
|
|
812
|
-
end
|
|
813
|
-
clone(:select => m)
|
|
682
|
+
clone(:select => columns)
|
|
814
683
|
end
|
|
815
684
|
|
|
816
685
|
# Returns a copy of the dataset selecting the wildcard if no arguments
|
|
@@ -848,7 +717,7 @@ module Sequel
|
|
|
848
717
|
|
|
849
718
|
# Set both the select and group clauses with the given +columns+.
|
|
850
719
|
# Column aliases may be supplied, and will be included in the select clause.
|
|
851
|
-
# This also takes a virtual row block similar to +
|
|
720
|
+
# This also takes a virtual row block similar to +where+.
|
|
852
721
|
#
|
|
853
722
|
# DB[:items].select_group(:a, :b)
|
|
854
723
|
# # SELECT a, b FROM items GROUP BY a, b
|
|
@@ -860,20 +729,9 @@ module Sequel
|
|
|
860
729
|
select(*columns).group(*columns.map{|c| unaliased_identifier(c)})
|
|
861
730
|
end
|
|
862
731
|
|
|
863
|
-
#
|
|
864
|
-
# to the existing selected columns. If no columns are currently selected
|
|
865
|
-
# it will just select the columns given.
|
|
866
|
-
#
|
|
867
|
-
# DB[:items].select(:a).select(:b) # SELECT b FROM items
|
|
868
|
-
# DB[:items].select(:a).select_more(:b) # SELECT a, b FROM items
|
|
869
|
-
# DB[:items].select_more(:b) # SELECT b FROM items
|
|
732
|
+
# Alias for select_append.
|
|
870
733
|
def select_more(*columns, &block)
|
|
871
|
-
|
|
872
|
-
columns = @opts[:select] + columns
|
|
873
|
-
else
|
|
874
|
-
Sequel::Deprecation.deprecate('Dataset#select_more will no longer remove the wildcard selection from the Dataset starting in Sequel 4. Switch to using Dataset#select if you want that behavior.')
|
|
875
|
-
end
|
|
876
|
-
select(*columns, &block)
|
|
734
|
+
select_append(*columns, &block)
|
|
877
735
|
end
|
|
878
736
|
|
|
879
737
|
# Set the server for this dataset to use. Used to pick a specific database
|
|
@@ -889,35 +747,13 @@ module Sequel
|
|
|
889
747
|
clone(:server=>servr)
|
|
890
748
|
end
|
|
891
749
|
|
|
892
|
-
# Set the default values for insert and update statements. The values hash passed
|
|
893
|
-
# to insert or update are merged into this hash, so any values in the hash passed
|
|
894
|
-
# to insert or update will override values passed to this method.
|
|
895
|
-
#
|
|
896
|
-
# DB[:items].set_defaults(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
|
|
897
|
-
# # INSERT INTO items (a, c, b) VALUES ('d', 'c', 'b')
|
|
898
|
-
def set_defaults(hash)
|
|
899
|
-
Sequel::Deprecation.deprecate('Dataset#set_defaults', 'Please use the dataset_set_overrides extension if you want to continue using it')
|
|
900
|
-
clone(:defaults=>(@opts[:defaults]||{}).merge(hash))
|
|
901
|
-
end
|
|
902
|
-
|
|
903
|
-
# Set values that override hash arguments given to insert and update statements.
|
|
904
|
-
# This hash is merged into the hash provided to insert or update, so values
|
|
905
|
-
# will override any values given in the insert/update hashes.
|
|
906
|
-
#
|
|
907
|
-
# DB[:items].set_overrides(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
|
|
908
|
-
# # INSERT INTO items (a, c, b) VALUES ('a', 'c', 'b')
|
|
909
|
-
def set_overrides(hash)
|
|
910
|
-
Sequel::Deprecation.deprecate('Dataset#set_overrides', 'Please use the dataset_set_overrides extension if you want to continue using it')
|
|
911
|
-
clone(:overrides=>hash.merge(@opts[:overrides]||{}))
|
|
912
|
-
end
|
|
913
|
-
|
|
914
750
|
# Unbind bound variables from this dataset's filter and return an array of two
|
|
915
751
|
# objects. The first object is a modified dataset where the filter has been
|
|
916
752
|
# replaced with one that uses bound variable placeholders. The second object
|
|
917
753
|
# is the hash of unbound variables. You can then prepare and execute (or just
|
|
918
754
|
# call) the dataset with the bound variables to get results.
|
|
919
755
|
#
|
|
920
|
-
# ds, bv = DB[:items].
|
|
756
|
+
# ds, bv = DB[:items].where(:a=>1).unbind
|
|
921
757
|
# ds # SELECT * FROM items WHERE (a = $a)
|
|
922
758
|
# bv # {:a => 1}
|
|
923
759
|
# ds.call(:select, bv)
|
|
@@ -959,11 +795,7 @@ module Sequel
|
|
|
959
795
|
#
|
|
960
796
|
# DB[:items].union(DB[:other_items], :alias=>:i)
|
|
961
797
|
# # SELECT * FROM (SELECT * FROM items UNION SELECT * FROM other_items) AS i
|
|
962
|
-
def union(dataset, opts=
|
|
963
|
-
unless opts.is_a?(Hash)
|
|
964
|
-
Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#union', "Please switch to an options hash with the :all option")
|
|
965
|
-
opts = {:all=>opts}
|
|
966
|
-
end
|
|
798
|
+
def union(dataset, opts=OPTS)
|
|
967
799
|
compound_clone(:union, dataset, opts)
|
|
968
800
|
end
|
|
969
801
|
|
|
@@ -981,13 +813,56 @@ module Sequel
|
|
|
981
813
|
order(nil)
|
|
982
814
|
end
|
|
983
815
|
|
|
984
|
-
#
|
|
816
|
+
# Returns a copy of the dataset with the given WHERE conditions imposed upon it.
|
|
817
|
+
#
|
|
818
|
+
# Accepts the following argument types:
|
|
819
|
+
#
|
|
820
|
+
# * Hash - list of equality/inclusion expressions
|
|
821
|
+
# * Array - depends:
|
|
822
|
+
# * If first member is a string, assumes the rest of the arguments
|
|
823
|
+
# are parameters and interpolates them into the string.
|
|
824
|
+
# * If all members are arrays of length two, treats the same way
|
|
825
|
+
# as a hash, except it allows for duplicate keys to be
|
|
826
|
+
# specified.
|
|
827
|
+
# * Otherwise, treats each argument as a separate condition.
|
|
828
|
+
# * String - taken literally
|
|
829
|
+
# * Symbol - taken as a boolean column argument (e.g. WHERE active)
|
|
830
|
+
# * Sequel::SQL::BooleanExpression - an existing condition expression,
|
|
831
|
+
# probably created using the Sequel expression filter DSL.
|
|
985
832
|
#
|
|
986
|
-
#
|
|
987
|
-
#
|
|
833
|
+
# where also accepts a block, which should return one of the above argument
|
|
834
|
+
# types, and is treated the same way. This block yields a virtual row object,
|
|
835
|
+
# which is easy to use to create identifiers and functions. For more details
|
|
836
|
+
# on the virtual row support, see the {"Virtual Rows" guide}[link:files/doc/virtual_rows_rdoc.html]
|
|
837
|
+
#
|
|
838
|
+
# If both a block and regular argument are provided, they get ANDed together.
|
|
839
|
+
#
|
|
840
|
+
# Examples:
|
|
841
|
+
#
|
|
842
|
+
# DB[:items].where(:id => 3)
|
|
843
|
+
# # SELECT * FROM items WHERE (id = 3)
|
|
988
844
|
#
|
|
989
|
-
# DB[:items].
|
|
990
|
-
# # SELECT * FROM items WHERE
|
|
845
|
+
# DB[:items].where('price < ?', 100)
|
|
846
|
+
# # SELECT * FROM items WHERE price < 100
|
|
847
|
+
#
|
|
848
|
+
# DB[:items].where([[:id, [1,2,3]], [:id, 0..10]])
|
|
849
|
+
# # SELECT * FROM items WHERE ((id IN (1, 2, 3)) AND ((id >= 0) AND (id <= 10)))
|
|
850
|
+
#
|
|
851
|
+
# DB[:items].where('price < 100')
|
|
852
|
+
# # SELECT * FROM items WHERE price < 100
|
|
853
|
+
#
|
|
854
|
+
# DB[:items].where(:active)
|
|
855
|
+
# # SELECT * FROM items WHERE :active
|
|
856
|
+
#
|
|
857
|
+
# DB[:items].where{price < 100}
|
|
858
|
+
# # SELECT * FROM items WHERE (price < 100)
|
|
859
|
+
#
|
|
860
|
+
# Multiple where calls can be chained for scoping:
|
|
861
|
+
#
|
|
862
|
+
# software = dataset.where(:category => 'software').where{price < 100}
|
|
863
|
+
# # SELECT * FROM items WHERE ((category = 'software') AND (price < 100))
|
|
864
|
+
#
|
|
865
|
+
# See the the {"Dataset Filtering" guide}[link:files/doc/dataset_filtering_rdoc.html] for more examples and details.
|
|
991
866
|
def where(*cond, &block)
|
|
992
867
|
_filter(:where, *cond, &block)
|
|
993
868
|
end
|
|
@@ -998,9 +873,9 @@ module Sequel
|
|
|
998
873
|
# :args :: Specify the arguments/columns for the CTE, should be an array of symbols.
|
|
999
874
|
# :recursive :: Specify that this is a recursive CTE
|
|
1000
875
|
#
|
|
1001
|
-
# DB[:items].with(:items, DB[:syx].
|
|
876
|
+
# DB[:items].with(:items, DB[:syx].where(:name.like('A%')))
|
|
1002
877
|
# # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%')) SELECT * FROM items
|
|
1003
|
-
def with(name, dataset, opts=
|
|
878
|
+
def with(name, dataset, opts=OPTS)
|
|
1004
879
|
raise(Error, 'This datatset does not support common table expressions') unless supports_cte?
|
|
1005
880
|
if hoist_cte?(dataset)
|
|
1006
881
|
s, ds = hoist_cte(dataset)
|
|
@@ -1017,7 +892,7 @@ module Sequel
|
|
|
1017
892
|
# :union_all :: Set to false to use UNION instead of UNION ALL combining the nonrecursive and recursive parts.
|
|
1018
893
|
#
|
|
1019
894
|
# DB[:t].with_recursive(:t,
|
|
1020
|
-
# DB[:i1].select(:id, :parent_id).
|
|
895
|
+
# DB[:i1].select(:id, :parent_id).where(:parent_id=>nil),
|
|
1021
896
|
# DB[:i1].join(:t, :id=>:parent_id).select(:i1__id, :i1__parent_id),
|
|
1022
897
|
# :args=>[:id, :parent_id])
|
|
1023
898
|
#
|
|
@@ -1026,7 +901,7 @@ module Sequel
|
|
|
1026
901
|
# # UNION ALL
|
|
1027
902
|
# # SELECT "i1"."id", "i1"."parent_id" FROM "i1" INNER JOIN "t" ON ("t"."id" = "i1"."parent_id")
|
|
1028
903
|
# # ) SELECT * FROM "t"
|
|
1029
|
-
def with_recursive(name, nonrecursive, recursive, opts=
|
|
904
|
+
def with_recursive(name, nonrecursive, recursive, opts=OPTS)
|
|
1030
905
|
raise(Error, 'This datatset does not support common table expressions') unless supports_cte?
|
|
1031
906
|
if hoist_cte?(nonrecursive)
|
|
1032
907
|
s, ds = hoist_cte(nonrecursive)
|
|
@@ -1085,7 +960,8 @@ module Sequel
|
|
|
1085
960
|
|
|
1086
961
|
private
|
|
1087
962
|
|
|
1088
|
-
# Internal
|
|
963
|
+
# Internal filtering method so it works on either the WHERE or HAVING clauses, with or
|
|
964
|
+
# without inversion.
|
|
1089
965
|
def _filter_or_exclude(invert, clause, *cond, &block)
|
|
1090
966
|
cond = cond.first if cond.size == 1
|
|
1091
967
|
if cond.respond_to?(:empty?) && cond.empty? && !block
|
|
@@ -1108,7 +984,7 @@ module Sequel
|
|
|
1108
984
|
:symbol
|
|
1109
985
|
end
|
|
1110
986
|
|
|
1111
|
-
# SQL expression object based on the expr type. See +
|
|
987
|
+
# SQL expression object based on the expr type. See +where+.
|
|
1112
988
|
def filter_expr(expr = nil, &block)
|
|
1113
989
|
expr = nil if expr == []
|
|
1114
990
|
if expr && block
|