sequel 3.48.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|