sequel 4.9.0 → 4.10.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 +79 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +2 -12
- data/bin/sequel +1 -0
- data/doc/advanced_associations.rdoc +82 -25
- data/doc/association_basics.rdoc +21 -22
- data/doc/core_extensions.rdoc +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.10.0.txt +226 -0
- data/doc/security.rdoc +1 -0
- data/doc/testing.rdoc +7 -7
- data/doc/transactions.rdoc +8 -0
- data/lib/sequel/adapters/jdbc.rb +160 -168
- data/lib/sequel/adapters/jdbc/db2.rb +17 -18
- data/lib/sequel/adapters/jdbc/derby.rb +5 -28
- data/lib/sequel/adapters/jdbc/h2.rb +11 -22
- data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
- data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
- data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
- data/lib/sequel/adapters/openbase.rb +1 -7
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +3 -6
- data/lib/sequel/adapters/shared/cubrid.rb +24 -9
- data/lib/sequel/adapters/shared/db2.rb +13 -5
- data/lib/sequel/adapters/shared/firebird.rb +16 -16
- data/lib/sequel/adapters/shared/informix.rb +2 -5
- data/lib/sequel/adapters/shared/mssql.rb +72 -63
- data/lib/sequel/adapters/shared/mysql.rb +72 -40
- data/lib/sequel/adapters/shared/oracle.rb +27 -15
- data/lib/sequel/adapters/shared/postgres.rb +24 -44
- data/lib/sequel/adapters/shared/progress.rb +1 -5
- data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
- data/lib/sequel/adapters/shared/sqlite.rb +21 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
- data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
- data/lib/sequel/core.rb +14 -9
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +12 -0
- data/lib/sequel/database/query.rb +4 -1
- data/lib/sequel/database/schema_methods.rb +3 -2
- data/lib/sequel/database/transactions.rb +47 -17
- data/lib/sequel/dataset/features.rb +12 -2
- data/lib/sequel/dataset/mutation.rb +2 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/dataset/sql.rb +132 -70
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +8 -4
- data/lib/sequel/extensions/pg_array.rb +4 -4
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/model/associations.rb +468 -188
- data/lib/sequel/model/base.rb +88 -13
- data/lib/sequel/plugins/association_pks.rb +23 -64
- data/lib/sequel/plugins/auto_validations.rb +3 -2
- data/lib/sequel/plugins/dataset_associations.rb +1 -3
- data/lib/sequel/plugins/many_through_many.rb +18 -65
- data/lib/sequel/plugins/pg_array_associations.rb +97 -86
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
- data/lib/sequel/plugins/rcte_tree.rb +12 -16
- data/lib/sequel/plugins/sharding.rb +21 -3
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
- data/lib/sequel/plugins/subclasses.rb +1 -9
- data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +57 -15
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/bin_spec.rb +2 -2
- data/spec/core/database_spec.rb +38 -4
- data/spec/core/dataset_spec.rb +45 -7
- data/spec/core/placeholder_literalizer_spec.rb +17 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/active_model_spec.rb +18 -9
- data/spec/extensions/association_pks_spec.rb +20 -18
- data/spec/extensions/association_proxies_spec.rb +9 -9
- data/spec/extensions/auto_validations_spec.rb +6 -0
- data/spec/extensions/columns_introspection_spec.rb +1 -0
- data/spec/extensions/constraint_validations_spec.rb +3 -1
- data/spec/extensions/many_through_many_spec.rb +191 -111
- data/spec/extensions/pg_array_associations_spec.rb +133 -103
- data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
- data/spec/extensions/rcte_tree_spec.rb +35 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
- data/spec/extensions/sharding_spec.rb +2 -2
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
- data/spec/extensions/to_dot_spec.rb +1 -0
- data/spec/extensions/touch_spec.rb +2 -2
- data/spec/integration/associations_test.rb +130 -37
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/model_test.rb +17 -0
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/transaction_test.rb +25 -1
- data/spec/model/association_reflection_spec.rb +63 -24
- data/spec/model/associations_spec.rb +104 -57
- data/spec/model/base_spec.rb +14 -1
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +221 -74
- data/spec/model/model_spec.rb +119 -1
- metadata +4 -2
@@ -44,7 +44,7 @@ module Sequel
|
|
44
44
|
# If given, +type+ can be :select, :insert, :update, or :delete, in which case it
|
45
45
|
# determines whether WITH is supported for the respective statement type.
|
46
46
|
def supports_cte?(type=:select)
|
47
|
-
|
47
|
+
false
|
48
48
|
end
|
49
49
|
|
50
50
|
# Whether the dataset supports common table expressions (the WITH clause)
|
@@ -99,6 +99,11 @@ module Sequel
|
|
99
99
|
def supports_lateral_subqueries?
|
100
100
|
false
|
101
101
|
end
|
102
|
+
|
103
|
+
# Whether limits are supported in correlated subqueries. True by default.
|
104
|
+
def supports_limits_in_correlated_subqueries?
|
105
|
+
true
|
106
|
+
end
|
102
107
|
|
103
108
|
# Whether modifying joined datasets is supported.
|
104
109
|
def supports_modifying_joins?
|
@@ -111,6 +116,11 @@ module Sequel
|
|
111
116
|
true
|
112
117
|
end
|
113
118
|
|
119
|
+
# Whether offsets are supported in correlated subqueries, true by default.
|
120
|
+
def supports_offsets_in_correlated_subqueries?
|
121
|
+
true
|
122
|
+
end
|
123
|
+
|
114
124
|
# Whether the dataset supports or can fully emulate the DISTINCT ON clause,
|
115
125
|
# including respecting the ORDER BY clause, false by default
|
116
126
|
def supports_ordered_distinct_on?
|
@@ -130,7 +140,7 @@ module Sequel
|
|
130
140
|
# Whether the RETURNING clause is supported for the given type of query.
|
131
141
|
# +type+ can be :insert, :update, or :delete.
|
132
142
|
def supports_returning?(type)
|
133
|
-
|
143
|
+
false
|
134
144
|
end
|
135
145
|
|
136
146
|
# Whether the database supports SELECT *, column FROM table
|
@@ -58,6 +58,7 @@ module Sequel
|
|
58
58
|
# Set the method to call on identifiers going into the database for this dataset
|
59
59
|
def identifier_input_method=(v)
|
60
60
|
raise_if_frozen!
|
61
|
+
skip_symbol_cache!
|
61
62
|
@identifier_input_method = v
|
62
63
|
end
|
63
64
|
|
@@ -77,6 +78,7 @@ module Sequel
|
|
77
78
|
# Set whether to quote identifiers for this dataset
|
78
79
|
def quote_identifiers=(v)
|
79
80
|
raise_if_frozen!
|
81
|
+
skip_symbol_cache!
|
80
82
|
@quote_identifiers = v
|
81
83
|
end
|
82
84
|
|
@@ -54,7 +54,11 @@ module Sequel
|
|
54
54
|
# Record the SQL query offset, argument position, and transforming block where the
|
55
55
|
# argument should be literalized.
|
56
56
|
def sql_literal_append(ds, sql)
|
57
|
-
|
57
|
+
if ds.opts[:placeholder_literal_null]
|
58
|
+
ds.send(:literal_append, sql, nil)
|
59
|
+
else
|
60
|
+
@recorder.use(sql, @pos, @transformer)
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
60
64
|
# Return a new Argument object for the same recorder and argument position, but with a
|
@@ -74,7 +78,7 @@ module Sequel
|
|
74
78
|
@argn = -1
|
75
79
|
@args = []
|
76
80
|
ds = yield self, dataset
|
77
|
-
sql = ds.sql
|
81
|
+
sql = ds.clone(:placeholder_literalizer=>self).sql
|
78
82
|
|
79
83
|
last_offset = 0
|
80
84
|
fragments = @args.map do |used_sql, offset, arg, t|
|
@@ -150,8 +154,12 @@ module Sequel
|
|
150
154
|
ds = @dataset
|
151
155
|
@fragments.each do |sql, i, transformer|
|
152
156
|
s << sql
|
153
|
-
|
154
|
-
|
157
|
+
if i.is_a?(Integer)
|
158
|
+
v = args.fetch(i)
|
159
|
+
v = transformer.call(v) if transformer
|
160
|
+
else
|
161
|
+
v = i.call
|
162
|
+
end
|
155
163
|
ds.literal_append(s, v)
|
156
164
|
end
|
157
165
|
if sql = @final_sql
|
@@ -165,6 +165,12 @@ module Sequel
|
|
165
165
|
@opts[:bind_vars].has_key?(k)
|
166
166
|
end
|
167
167
|
|
168
|
+
# The symbol cache should always be skipped, since placeholders
|
169
|
+
# are symbols.
|
170
|
+
def skip_symbol_cache?
|
171
|
+
true
|
172
|
+
end
|
173
|
+
|
168
174
|
# Use a clone of the dataset extended with prepared statement
|
169
175
|
# support and using the same argument hash so that you can use
|
170
176
|
# bind variables/prepared arguments in subselects.
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -892,7 +892,7 @@ module Sequel
|
|
892
892
|
# DB[:items].with(:items, DB[:syx].where(:name.like('A%')))
|
893
893
|
# # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%')) SELECT * FROM items
|
894
894
|
def with(name, dataset, opts=OPTS)
|
895
|
-
raise(Error, 'This
|
895
|
+
raise(Error, 'This dataset does not support common table expressions') unless supports_cte?
|
896
896
|
if hoist_cte?(dataset)
|
897
897
|
s, ds = hoist_cte(dataset)
|
898
898
|
s.with(name, ds, opts)
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -5,16 +5,6 @@ module Sequel
|
|
5
5
|
# These are methods you can call to see what SQL will be generated by the dataset.
|
6
6
|
# ---------------------
|
7
7
|
|
8
|
-
# Returns a DELETE SQL query string. See +delete+.
|
9
|
-
#
|
10
|
-
# dataset.filter{|o| o.price >= 100}.delete_sql
|
11
|
-
# # => "DELETE FROM items WHERE (price >= 100)"
|
12
|
-
def delete_sql
|
13
|
-
return static_sql(opts[:sql]) if opts[:sql]
|
14
|
-
check_modification_allowed!
|
15
|
-
clause_sql(:delete)
|
16
|
-
end
|
17
|
-
|
18
8
|
# Returns an EXISTS clause for the dataset as a +LiteralString+.
|
19
9
|
#
|
20
10
|
# DB.select(1).where(DB[:items].exists)
|
@@ -59,7 +49,7 @@ module Sequel
|
|
59
49
|
columns = [columns().last]
|
60
50
|
values = [DEFAULT]
|
61
51
|
end
|
62
|
-
clone(:columns=>columns, :values=>values)._insert_sql
|
52
|
+
clone(:columns=>columns, :values=>values).send(:_insert_sql)
|
63
53
|
end
|
64
54
|
|
65
55
|
# Append a literal representation of a value to the given SQL string.
|
@@ -68,7 +58,16 @@ module Sequel
|
|
68
58
|
def literal_append(sql, v)
|
69
59
|
case v
|
70
60
|
when Symbol
|
71
|
-
|
61
|
+
if skip_symbol_cache?
|
62
|
+
literal_symbol_append(sql, v)
|
63
|
+
else
|
64
|
+
unless l = db.literal_symbol(v)
|
65
|
+
l = ''
|
66
|
+
literal_symbol_append(l, v)
|
67
|
+
db.literal_symbol_set(v, l)
|
68
|
+
end
|
69
|
+
sql << l
|
70
|
+
end
|
72
71
|
when String
|
73
72
|
case v
|
74
73
|
when LiteralString
|
@@ -116,17 +115,32 @@ module Sequel
|
|
116
115
|
# This method should be overridden by descendants if the support
|
117
116
|
# inserting multiple records in a single SQL statement.
|
118
117
|
def multi_insert_sql(columns, values)
|
119
|
-
|
118
|
+
case multi_insert_sql_strategy
|
119
|
+
when :values
|
120
|
+
sql = LiteralString.new('VALUES ')
|
121
|
+
expression_list_append(sql, values.map{|r| Array(r)})
|
122
|
+
[insert_sql(columns, sql)]
|
123
|
+
when :union
|
124
|
+
c = false
|
125
|
+
sql = LiteralString.new('')
|
126
|
+
u = UNION_ALL_SELECT
|
127
|
+
f = empty_from_sql
|
128
|
+
values.each do |v|
|
129
|
+
if c
|
130
|
+
sql << u
|
131
|
+
else
|
132
|
+
sql << SELECT << SPACE
|
133
|
+
c = true
|
134
|
+
end
|
135
|
+
expression_list_append(sql, v)
|
136
|
+
sql << f if f
|
137
|
+
end
|
138
|
+
[insert_sql(columns, sql)]
|
139
|
+
else
|
140
|
+
values.map{|r| insert_sql(columns, r)}
|
141
|
+
end
|
120
142
|
end
|
121
143
|
|
122
|
-
# Returns a SELECT SQL query string.
|
123
|
-
#
|
124
|
-
# dataset.select_sql # => "SELECT * FROM items"
|
125
|
-
def select_sql
|
126
|
-
return static_sql(@opts[:sql]) if @opts[:sql]
|
127
|
-
clause_sql(:select)
|
128
|
-
end
|
129
|
-
|
130
144
|
# Same as +select_sql+, not aliased directly to make subclassing simpler.
|
131
145
|
def sql
|
132
146
|
select_sql
|
@@ -157,7 +171,7 @@ module Sequel
|
|
157
171
|
def update_sql(values = OPTS)
|
158
172
|
return static_sql(opts[:sql]) if opts[:sql]
|
159
173
|
check_modification_allowed!
|
160
|
-
clone(:values=>values)._update_sql
|
174
|
+
clone(:values=>values).send(:_update_sql)
|
161
175
|
end
|
162
176
|
|
163
177
|
# ---------------------
|
@@ -171,6 +185,47 @@ module Sequel
|
|
171
185
|
clauses.map{|clause| :"#{type}_#{clause}_sql"}.freeze
|
172
186
|
end
|
173
187
|
|
188
|
+
# Define a dataset literalization method for the given type in the given module,
|
189
|
+
# using the given clauses.
|
190
|
+
#
|
191
|
+
# Arguments:
|
192
|
+
# mod :: Module in which to define method
|
193
|
+
# type :: Type of SQL literalization method to create, either :select, :insert, :update, or :delete
|
194
|
+
# clauses :: array of clauses that make up the SQL query for the type. This can either be a single
|
195
|
+
# array of symbols/strings, or it can be an array of pairs, with the first element in
|
196
|
+
# each pair being an if/elsif/else code fragment, and the second element in each pair
|
197
|
+
# being an array of symbol/strings for the appropriate branch.
|
198
|
+
def self.def_sql_method(mod, type, clauses)
|
199
|
+
priv = type == :update || type == :insert
|
200
|
+
|
201
|
+
lines = []
|
202
|
+
lines << 'private' if priv
|
203
|
+
lines << "def #{'_' if priv}#{type}_sql"
|
204
|
+
lines << 'if sql = opts[:sql]; return static_sql(sql) end' unless priv
|
205
|
+
lines << 'check_modification_allowed!' if type == :delete
|
206
|
+
lines << 'sql = @opts[:append_sql] || sql_string_origin'
|
207
|
+
|
208
|
+
if clauses.all?{|c| c.is_a?(Array)}
|
209
|
+
clauses.each do |i, cs|
|
210
|
+
lines << i
|
211
|
+
lines.concat(clause_methods(type, cs).map{|x| "#{x}(sql)"})
|
212
|
+
end
|
213
|
+
lines << 'end'
|
214
|
+
else
|
215
|
+
lines.concat(clause_methods(type, clauses).map{|x| "#{x}(sql)"})
|
216
|
+
end
|
217
|
+
|
218
|
+
lines << 'sql'
|
219
|
+
lines << 'end'
|
220
|
+
|
221
|
+
mod.class_eval lines.join("\n"), __FILE__, __LINE__
|
222
|
+
end
|
223
|
+
|
224
|
+
def_sql_method(self, :delete, %w'delete from where')
|
225
|
+
def_sql_method(self, :insert, %w'insert into columns values')
|
226
|
+
def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order limit lock')
|
227
|
+
def_sql_method(self, :update, %w'update table set where')
|
228
|
+
|
174
229
|
# Map of emulated function names to native function names.
|
175
230
|
EMULATED_FUNCTION_MAP = {}
|
176
231
|
|
@@ -210,7 +265,6 @@ module Sequel
|
|
210
265
|
DEFAULT = LiteralString.new('DEFAULT').freeze
|
211
266
|
DEFAULT_VALUES = " DEFAULT VALUES".freeze
|
212
267
|
DELETE = 'DELETE'.freeze
|
213
|
-
DELETE_CLAUSE_METHODS = clause_methods(:delete, %w'delete from where')
|
214
268
|
DESC = ' DESC'.freeze
|
215
269
|
DISTINCT = " DISTINCT".freeze
|
216
270
|
DOT = '.'.freeze
|
@@ -234,7 +288,6 @@ module Sequel
|
|
234
288
|
GROUP_BY = " GROUP BY ".freeze
|
235
289
|
HAVING = " HAVING ".freeze
|
236
290
|
INSERT = "INSERT".freeze
|
237
|
-
INSERT_CLAUSE_METHODS = clause_methods(:insert, %w'insert into columns values')
|
238
291
|
INTO = " INTO ".freeze
|
239
292
|
IS_LITERALS = {nil=>'NULL'.freeze, true=>'TRUE'.freeze, false=>'FALSE'.freeze}.freeze
|
240
293
|
IS_OPERATORS = ::Sequel::SQL::ComplexExpression::IS_OPERATORS
|
@@ -263,7 +316,6 @@ module Sequel
|
|
263
316
|
QUOTE_RE = /"/.freeze
|
264
317
|
RETURNING = " RETURNING ".freeze
|
265
318
|
SELECT = 'SELECT'.freeze
|
266
|
-
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with select distinct columns from join where group having compounds order limit lock')
|
267
319
|
SET = ' SET '.freeze
|
268
320
|
SPACE = ' '.freeze
|
269
321
|
SQL_WITH = "WITH ".freeze
|
@@ -275,8 +327,8 @@ module Sequel
|
|
275
327
|
REGEXP_OPERATORS = ::Sequel::SQL::ComplexExpression::REGEXP_OPERATORS
|
276
328
|
UNDERSCORE = '_'.freeze
|
277
329
|
UPDATE = 'UPDATE'.freeze
|
278
|
-
UPDATE_CLAUSE_METHODS = clause_methods(:update, %w'update table set where')
|
279
330
|
USING = ' USING ('.freeze
|
331
|
+
UNION_ALL_SELECT = ' UNION ALL SELECT '.freeze
|
280
332
|
VALUES = " VALUES ".freeze
|
281
333
|
V190 = '1.9.0'.freeze
|
282
334
|
WHERE = " WHERE ".freeze
|
@@ -463,7 +515,11 @@ module Sequel
|
|
463
515
|
# Append literalization of delayed evaluation to SQL string,
|
464
516
|
# causing the delayed evaluation proc to be evaluated.
|
465
517
|
def delayed_evaluation_sql_append(sql, callable)
|
466
|
-
|
518
|
+
if recorder = @opts[:placeholder_literalizer]
|
519
|
+
recorder.use(sql, callable, nil)
|
520
|
+
else
|
521
|
+
literal_append(sql, callable.call)
|
522
|
+
end
|
467
523
|
end
|
468
524
|
|
469
525
|
# Append literalization of emulated function call to SQL string.
|
@@ -718,16 +774,6 @@ module Sequel
|
|
718
774
|
|
719
775
|
protected
|
720
776
|
|
721
|
-
# Formats in INSERT statement using the stored columns and values.
|
722
|
-
def _insert_sql
|
723
|
-
clause_sql(:insert)
|
724
|
-
end
|
725
|
-
|
726
|
-
# Formats an UPDATE statement using the stored values.
|
727
|
-
def _update_sql
|
728
|
-
clause_sql(:update)
|
729
|
-
end
|
730
|
-
|
731
777
|
# Return a from_self dataset if an order or limit is specified, so it works as expected
|
732
778
|
# with UNION, EXCEPT, and INTERSECT clauses.
|
733
779
|
def compound_from_self
|
@@ -828,13 +874,6 @@ module Sequel
|
|
828
874
|
check_modification_allowed!
|
829
875
|
end
|
830
876
|
|
831
|
-
# Prepare an SQL statement by calling all clause methods for the given statement type.
|
832
|
-
def clause_sql(type)
|
833
|
-
sql = @opts[:append_sql] || sql_string_origin
|
834
|
-
send("#{type}_clause_methods").each{|x| send(x, sql)}
|
835
|
-
sql
|
836
|
-
end
|
837
|
-
|
838
877
|
# Append column list to SQL string.
|
839
878
|
# Converts an array of column names into a comma seperated string of
|
840
879
|
# column names. If the array is empty, a wildcard (*) is returned.
|
@@ -904,15 +943,23 @@ module Sequel
|
|
904
943
|
requires_sql_standard_datetimes? ? STANDARD_TIMESTAMP_FORMAT : TIMESTAMP_FORMAT
|
905
944
|
end
|
906
945
|
|
907
|
-
# The order of methods to call to build the DELETE SQL statement
|
908
|
-
def delete_clause_methods
|
909
|
-
DELETE_CLAUSE_METHODS
|
910
|
-
end
|
911
|
-
|
912
946
|
def delete_delete_sql(sql)
|
913
947
|
sql << DELETE
|
914
948
|
end
|
915
949
|
|
950
|
+
def delete_from_sql(sql)
|
951
|
+
if f = @opts[:from]
|
952
|
+
sql << FROM
|
953
|
+
source_list_append(sql, f)
|
954
|
+
end
|
955
|
+
end
|
956
|
+
|
957
|
+
# An SQL FROM clause to use in SELECT statements where the dataset has
|
958
|
+
# no from tables.
|
959
|
+
def empty_from_sql
|
960
|
+
nil
|
961
|
+
end
|
962
|
+
|
916
963
|
# Append literalization of array of expressions to SQL string.
|
917
964
|
def expression_list_append(sql, columns)
|
918
965
|
c = false
|
@@ -1001,11 +1048,6 @@ module Sequel
|
|
1001
1048
|
source_list_append(sql, @opts[:from])
|
1002
1049
|
end
|
1003
1050
|
|
1004
|
-
# The order of methods to call to build the INSERT SQL statement
|
1005
|
-
def insert_clause_methods
|
1006
|
-
INSERT_CLAUSE_METHODS
|
1007
|
-
end
|
1008
|
-
|
1009
1051
|
def insert_columns_sql(sql)
|
1010
1052
|
columns = opts[:columns]
|
1011
1053
|
if columns && !columns.empty?
|
@@ -1191,6 +1233,14 @@ module Sequel
|
|
1191
1233
|
BOOL_TRUE
|
1192
1234
|
end
|
1193
1235
|
|
1236
|
+
# What strategy to use for import/multi_insert. While SQL-92 defaults
|
1237
|
+
# to allowing multiple rows in a VALUES clause, there are enough databases
|
1238
|
+
# that don't allow that that it can't be the default. Use separate queries
|
1239
|
+
# by default, which works everywhere.
|
1240
|
+
def multi_insert_sql_strategy
|
1241
|
+
:separate
|
1242
|
+
end
|
1243
|
+
|
1194
1244
|
# Get the native function name given the emulated function name.
|
1195
1245
|
def native_function_name(emulated_function)
|
1196
1246
|
self.class.const_get(:EMULATED_FUNCTION_MAP).fetch(emulated_function, emulated_function)
|
@@ -1222,11 +1272,6 @@ module Sequel
|
|
1222
1272
|
Qualifier.new(self, table).transform(e)
|
1223
1273
|
end
|
1224
1274
|
|
1225
|
-
# The order of methods to call to build the SELECT SQL statement
|
1226
|
-
def select_clause_methods
|
1227
|
-
SELECT_CLAUSE_METHODS
|
1228
|
-
end
|
1229
|
-
|
1230
1275
|
def select_columns_sql(sql)
|
1231
1276
|
sql << SPACE
|
1232
1277
|
column_list_append(sql, @opts[:select])
|
@@ -1260,9 +1305,10 @@ module Sequel
|
|
1260
1305
|
if f = @opts[:from]
|
1261
1306
|
sql << FROM
|
1262
1307
|
source_list_append(sql, f)
|
1308
|
+
elsif f = empty_from_sql
|
1309
|
+
sql << f
|
1263
1310
|
end
|
1264
1311
|
end
|
1265
|
-
alias delete_from_sql select_from_sql
|
1266
1312
|
|
1267
1313
|
def select_group_sql(sql)
|
1268
1314
|
if group = @opts[:group]
|
@@ -1299,13 +1345,15 @@ module Sequel
|
|
1299
1345
|
if l = @opts[:limit]
|
1300
1346
|
sql << LIMIT
|
1301
1347
|
literal_append(sql, l)
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1348
|
+
if o = @opts[:offset]
|
1349
|
+
sql << OFFSET
|
1350
|
+
literal_append(sql, o)
|
1351
|
+
end
|
1352
|
+
elsif @opts[:offset]
|
1353
|
+
select_only_offset_sql(sql)
|
1306
1354
|
end
|
1307
1355
|
end
|
1308
|
-
|
1356
|
+
|
1309
1357
|
def select_lock_sql(sql)
|
1310
1358
|
case l = @opts[:lock]
|
1311
1359
|
when :update
|
@@ -1315,6 +1363,14 @@ module Sequel
|
|
1315
1363
|
end
|
1316
1364
|
end
|
1317
1365
|
|
1366
|
+
# Used only if there is an offset and no limit, making it easier to override
|
1367
|
+
# in the adapter, as many databases do not support just a plain offset with
|
1368
|
+
# no limit.
|
1369
|
+
def select_only_offset_sql(sql)
|
1370
|
+
sql << OFFSET
|
1371
|
+
literal_append(sql, @opts[:offset])
|
1372
|
+
end
|
1373
|
+
|
1318
1374
|
def select_order_sql(sql)
|
1319
1375
|
if o = @opts[:order]
|
1320
1376
|
sql << ORDER_BY
|
@@ -1338,6 +1394,7 @@ module Sequel
|
|
1338
1394
|
alias update_where_sql select_where_sql
|
1339
1395
|
|
1340
1396
|
def select_with_sql(sql)
|
1397
|
+
return unless supports_cte?
|
1341
1398
|
ws = opts[:with]
|
1342
1399
|
return if !ws || ws.empty?
|
1343
1400
|
sql << select_with_sql_base
|
@@ -1366,6 +1423,16 @@ module Sequel
|
|
1366
1423
|
SQL_WITH
|
1367
1424
|
end
|
1368
1425
|
|
1426
|
+
# Whether the symbol cache should be skipped when literalizing the dataset
|
1427
|
+
def skip_symbol_cache?
|
1428
|
+
@skip_symbol_cache
|
1429
|
+
end
|
1430
|
+
|
1431
|
+
# Set the dataset to skip the symbol cache
|
1432
|
+
def skip_symbol_cache!
|
1433
|
+
@skip_symbol_cache = true
|
1434
|
+
end
|
1435
|
+
|
1369
1436
|
# Append literalization of array of sources/tables to SQL string, raising an Error if there
|
1370
1437
|
# are no sources.
|
1371
1438
|
def source_list_append(sql, sources)
|
@@ -1409,11 +1476,6 @@ module Sequel
|
|
1409
1476
|
ds.clone(:append_sql=>sql).sql
|
1410
1477
|
end
|
1411
1478
|
|
1412
|
-
# The order of methods to call to build the UPDATE SQL statement
|
1413
|
-
def update_clause_methods
|
1414
|
-
UPDATE_CLAUSE_METHODS
|
1415
|
-
end
|
1416
|
-
|
1417
1479
|
def update_table_sql(sql)
|
1418
1480
|
sql << SPACE
|
1419
1481
|
source_list_append(sql, @opts[:from])
|