sequel 3.5.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +108 -0
- data/README.rdoc +25 -14
- data/Rakefile +20 -1
- data/doc/advanced_associations.rdoc +61 -64
- data/doc/cheat_sheet.rdoc +16 -7
- data/doc/opening_databases.rdoc +3 -3
- data/doc/prepared_statements.rdoc +1 -1
- data/doc/reflection.rdoc +2 -1
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/schema.rdoc +19 -14
- data/lib/sequel/adapters/amalgalite.rb +5 -27
- data/lib/sequel/adapters/jdbc.rb +13 -3
- data/lib/sequel/adapters/jdbc/h2.rb +17 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +20 -7
- data/lib/sequel/adapters/mysql.rb +4 -3
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +87 -28
- data/lib/sequel/adapters/shared/mssql.rb +47 -6
- data/lib/sequel/adapters/shared/mysql.rb +12 -31
- data/lib/sequel/adapters/shared/postgres.rb +15 -12
- data/lib/sequel/adapters/shared/sqlite.rb +18 -0
- data/lib/sequel/adapters/sqlite.rb +1 -16
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +2 -0
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +5 -179
- data/lib/sequel/dataset/actions.rb +123 -0
- data/lib/sequel/dataset/convenience.rb +18 -10
- data/lib/sequel/dataset/features.rb +65 -0
- data/lib/sequel/dataset/prepared_statements.rb +29 -23
- data/lib/sequel/dataset/query.rb +429 -0
- data/lib/sequel/dataset/sql.rb +67 -435
- data/lib/sequel/model/associations.rb +77 -13
- data/lib/sequel/model/base.rb +30 -8
- data/lib/sequel/model/errors.rb +4 -4
- data/lib/sequel/plugins/caching.rb +38 -15
- data/lib/sequel/plugins/force_encoding.rb +18 -7
- data/lib/sequel/plugins/hook_class_methods.rb +4 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +40 -11
- data/lib/sequel/plugins/serialization.rb +17 -3
- data/lib/sequel/plugins/validation_helpers.rb +65 -18
- data/lib/sequel/sql.rb +23 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +96 -10
- data/spec/adapters/mysql_spec.rb +19 -0
- data/spec/adapters/postgres_spec.rb +65 -2
- data/spec/adapters/sqlite_spec.rb +10 -0
- data/spec/core/core_sql_spec.rb +9 -0
- data/spec/core/database_spec.rb +8 -4
- data/spec/core/dataset_spec.rb +122 -29
- data/spec/core/expression_filters_spec.rb +17 -0
- data/spec/extensions/caching_spec.rb +43 -3
- data/spec/extensions/force_encoding_spec.rb +43 -1
- data/spec/extensions/nested_attributes_spec.rb +55 -2
- data/spec/extensions/validation_helpers_spec.rb +71 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/dataset_test.rb +383 -9
- data/spec/integration/eager_loader_test.rb +0 -65
- data/spec/integration/model_test.rb +110 -0
- data/spec/integration/plugin_test.rb +306 -0
- data/spec/integration/prepared_statement_test.rb +32 -0
- data/spec/integration/schema_test.rb +8 -3
- data/spec/integration/spec_helper.rb +1 -25
- data/spec/model/association_reflection_spec.rb +38 -0
- data/spec/model/associations_spec.rb +184 -8
- data/spec/model/eager_loading_spec.rb +23 -0
- data/spec/model/model_spec.rb +8 -0
- data/spec/model/record_spec.rb +84 -1
- metadata +9 -2
@@ -1,4 +1,7 @@
|
|
1
1
|
module Sequel
|
2
|
+
Dataset::NON_SQL_OPTIONS << :insert_ignore
|
3
|
+
Dataset::NON_SQL_OPTIONS << :on_duplicate_key_update
|
4
|
+
|
2
5
|
module MySQL
|
3
6
|
class << self
|
4
7
|
# Set the default options used for CREATE TABLE
|
@@ -311,37 +314,7 @@ module Sequel
|
|
311
314
|
# MySQL specific syntax for REPLACE (aka UPSERT, or update if exists,
|
312
315
|
# insert if it doesn't).
|
313
316
|
def replace_sql(*values)
|
314
|
-
|
315
|
-
if values.empty?
|
316
|
-
"REPLACE INTO #{from} DEFAULT VALUES"
|
317
|
-
else
|
318
|
-
values = values[0] if values.size == 1
|
319
|
-
|
320
|
-
case values
|
321
|
-
when Array
|
322
|
-
if values.empty?
|
323
|
-
"REPLACE INTO #{from} DEFAULT VALUES"
|
324
|
-
else
|
325
|
-
"REPLACE INTO #{from} VALUES #{literal(values)}"
|
326
|
-
end
|
327
|
-
when Hash
|
328
|
-
if values.empty?
|
329
|
-
"REPLACE INTO #{from} DEFAULT VALUES"
|
330
|
-
else
|
331
|
-
fl, vl = [], []
|
332
|
-
values.each {|k, v| fl << literal(k.is_a?(String) ? k.to_sym : k); vl << literal(v)}
|
333
|
-
"REPLACE INTO #{from} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
334
|
-
end
|
335
|
-
when Dataset
|
336
|
-
"REPLACE INTO #{from} #{literal(values)}"
|
337
|
-
else
|
338
|
-
if values.respond_to?(:values)
|
339
|
-
replace_sql(values.values)
|
340
|
-
else
|
341
|
-
"REPLACE INTO #{from} VALUES (#{literal(values)})"
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
317
|
+
clone(:replace=>true).insert_sql(*values)
|
345
318
|
end
|
346
319
|
|
347
320
|
# does not support DISTINCT ON
|
@@ -360,6 +333,13 @@ module Sequel
|
|
360
333
|
def supports_timestamp_usecs?
|
361
334
|
false
|
362
335
|
end
|
336
|
+
|
337
|
+
protected
|
338
|
+
|
339
|
+
# If this is an replace instead of an insert, use replace instead
|
340
|
+
def _insert_sql
|
341
|
+
@opts[:replace] ? clause_sql(:replace) : super
|
342
|
+
end
|
363
343
|
|
364
344
|
private
|
365
345
|
|
@@ -372,6 +352,7 @@ module Sequel
|
|
372
352
|
def insert_clause_methods
|
373
353
|
INSERT_CLAUSE_METHODS
|
374
354
|
end
|
355
|
+
alias replace_clause_methods insert_clause_methods
|
375
356
|
|
376
357
|
# MySQL doesn't use the SQL standard DEFAULT VALUES.
|
377
358
|
def insert_columns_sql(sql)
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module Sequel
|
2
|
+
Dataset::NON_SQL_OPTIONS << :disable_insert_returning
|
3
|
+
|
2
4
|
# Top level module for holding all PostgreSQL-related modules and classes
|
3
5
|
# for Sequel. There are a few module level accessors that are added via
|
4
6
|
# metaprogramming. These are:
|
@@ -601,7 +603,7 @@ module Sequel
|
|
601
603
|
return @prepared_sql if @prepared_sql
|
602
604
|
super
|
603
605
|
if @prepared_type == :insert and !@opts[:disable_insert_returning] and server_version >= 80200
|
604
|
-
@prepared_sql = insert_returning_pk_sql(
|
606
|
+
@prepared_sql = insert_returning_pk_sql(*@prepared_modify_values)
|
605
607
|
meta_def(:insert_returning_pk_sql){|*args| prepared_sql}
|
606
608
|
end
|
607
609
|
@prepared_sql
|
@@ -672,17 +674,18 @@ module Sequel
|
|
672
674
|
naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
|
673
675
|
end
|
674
676
|
|
675
|
-
# Locks
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
677
|
+
# Locks all tables in the dataset's FROM clause (but not in JOINs) with
|
678
|
+
# the specified mode (e.g. 'EXCLUSIVE'). If a block is given, starts
|
679
|
+
# a new transaction, locks the table, and yields. If a block is not given
|
680
|
+
# just locks the tables. Note that PostgreSQL will probably raise an error
|
681
|
+
# if you lock the table outside of an existing transaction. Returns nil.
|
682
|
+
def lock(mode, opts={})
|
683
|
+
if block_given? # perform locking inside a transaction and yield to block
|
684
|
+
@db.transaction(opts){lock(mode, opts); yield}
|
685
|
+
else
|
686
|
+
@db.execute(LOCK % [source_list(@opts[:from]), mode], opts) # lock without a transaction
|
685
687
|
end
|
688
|
+
nil
|
686
689
|
end
|
687
690
|
|
688
691
|
# For PostgreSQL version > 8.2, allow inserting multiple rows at once.
|
@@ -705,7 +708,7 @@ module Sequel
|
|
705
708
|
|
706
709
|
# Return a clone of the dataset with an addition named window that can be referenced in window functions.
|
707
710
|
def window(name, opts)
|
708
|
-
clone(:window=>(@opts[:
|
711
|
+
clone(:window=>(@opts[:window]||[]) + [[name, SQL::Window.new(opts)]])
|
709
712
|
end
|
710
713
|
|
711
714
|
private
|
@@ -265,6 +265,19 @@ module Sequel
|
|
265
265
|
@opts[:where] ? super : filter(1=>1).delete
|
266
266
|
end
|
267
267
|
|
268
|
+
# Return an array of strings specifying a query explanation for a SELECT of the
|
269
|
+
# current dataset.
|
270
|
+
def explain
|
271
|
+
db.send(:metadata_dataset).clone(:sql=>"EXPLAIN #{select_sql}").
|
272
|
+
map{|x| "#{x[:addr]}|#{x[:opcode]}|#{(1..5).map{|i| x[:"p#{i}"]}.join('|')}|#{x[:comment]}"}
|
273
|
+
end
|
274
|
+
|
275
|
+
# HAVING requires GROUP BY on SQLite
|
276
|
+
def having(*cond, &block)
|
277
|
+
raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") unless @opts[:group]
|
278
|
+
super
|
279
|
+
end
|
280
|
+
|
268
281
|
# SQLite uses the nonstandard ` (backtick) for quoting identifiers.
|
269
282
|
def quoted_identifier(c)
|
270
283
|
"`#{c}`"
|
@@ -280,6 +293,11 @@ module Sequel
|
|
280
293
|
false
|
281
294
|
end
|
282
295
|
|
296
|
+
# SQLite does not support multiple columns for the IN/NOT IN operators
|
297
|
+
def supports_multiple_column_in?
|
298
|
+
false
|
299
|
+
end
|
300
|
+
|
283
301
|
# SQLite supports timezones in literal timestamps, since it stores them
|
284
302
|
# as text.
|
285
303
|
def supports_timestamp_timezones?
|
@@ -122,7 +122,6 @@ module Sequel
|
|
122
122
|
class Dataset < Sequel::Dataset
|
123
123
|
include ::Sequel::SQLite::DatasetMethods
|
124
124
|
|
125
|
-
EXPLAIN = 'EXPLAIN %s'.freeze
|
126
125
|
PREPARED_ARG_PLACEHOLDER = ':'.freeze
|
127
126
|
|
128
127
|
# SQLite already supports named bind arguments, so use directly.
|
@@ -172,20 +171,6 @@ module Sequel
|
|
172
171
|
end
|
173
172
|
end
|
174
173
|
|
175
|
-
# Prepare an unnamed statement of the given type and call it with the
|
176
|
-
# given values.
|
177
|
-
def call(type, hash, values=nil, &block)
|
178
|
-
prepare(type, nil, values).call(hash, &block)
|
179
|
-
end
|
180
|
-
|
181
|
-
# Return an array of strings specifying a query explanation for the
|
182
|
-
# current dataset.
|
183
|
-
def explain
|
184
|
-
res = []
|
185
|
-
@db.result_set(EXPLAIN % select_sql(opts), nil) {|r| res << r}
|
186
|
-
res
|
187
|
-
end
|
188
|
-
|
189
174
|
# Yield a hash for each row in the dataset.
|
190
175
|
def fetch_rows(sql)
|
191
176
|
execute(sql) do |result|
|
@@ -203,7 +188,7 @@ module Sequel
|
|
203
188
|
# Prepare the given type of query with the given name and store
|
204
189
|
# it in the database. Note that a new native prepared statement is
|
205
190
|
# created on each call to this prepared statement.
|
206
|
-
def prepare(type, name=nil, values
|
191
|
+
def prepare(type, name=nil, *values)
|
207
192
|
ps = to_prepared_statement(type, values)
|
208
193
|
ps.extend(PreparedStatementMethods)
|
209
194
|
db.prepared_statements[name] = ps if name
|
@@ -11,7 +11,7 @@ class Sequel::ConnectionPool
|
|
11
11
|
# The maximum number of connections.
|
12
12
|
attr_reader :max_size
|
13
13
|
|
14
|
-
# The mutex that protects access to the other internal
|
14
|
+
# The mutex that protects access to the other internal variables. You must use
|
15
15
|
# this if you want to manipulate the variables safely.
|
16
16
|
attr_reader :mutex
|
17
17
|
|
data/lib/sequel/core.rb
CHANGED
@@ -249,7 +249,7 @@ module Sequel
|
|
249
249
|
|
250
250
|
require(%w"metaprogramming sql connection_pool exceptions dataset database timezones version")
|
251
251
|
require(%w"schema_generator schema_methods schema_sql", 'database')
|
252
|
-
require(%w"convenience graph prepared_statements sql", 'dataset')
|
252
|
+
require(%w"actions convenience features graph prepared_statements query sql", 'dataset')
|
253
253
|
require('core_sql') if !defined?(::SEQUEL_NO_CORE_EXTENSIONS) && !ENV.has_key?('SEQUEL_NO_CORE_EXTENSIONS')
|
254
254
|
|
255
255
|
# Add the database adapter class methods to Sequel via metaprogramming
|
data/lib/sequel/database.rb
CHANGED
@@ -78,6 +78,8 @@ module Sequel
|
|
78
78
|
# See Schema::SQL#on_delete_clause for options.
|
79
79
|
# * :size - The size of the column, generally used with string
|
80
80
|
# columns to specify the maximum number of characters the column will hold.
|
81
|
+
# An array of two integers can be provided to set the size and the
|
82
|
+
# precision, respectively, of decimal columns.
|
81
83
|
# * :unique - Mark the column as unique, generally has the same effect as
|
82
84
|
# creating a unique index on the column.
|
83
85
|
# * :unsigned - Make the column type unsigned, only useful for integer
|
@@ -159,7 +159,7 @@ module Sequel
|
|
159
159
|
elsif index[:where]
|
160
160
|
raise Error, "Partial indexes are not supported for this database"
|
161
161
|
else
|
162
|
-
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{quote_identifier(index_name)} ON #{
|
162
|
+
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{literal(index[:columns])}"
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
data/lib/sequel/dataset.rb
CHANGED
@@ -20,17 +20,6 @@ module Sequel
|
|
20
20
|
#
|
21
21
|
# Datasets are Enumerable objects, so they can be manipulated using any
|
22
22
|
# of the Enumerable methods, such as map, inject, etc.
|
23
|
-
#
|
24
|
-
# === Methods added via metaprogramming
|
25
|
-
#
|
26
|
-
# Some methods are added via metaprogramming:
|
27
|
-
#
|
28
|
-
# * ! methods - These methods are the same as their non-! counterparts,
|
29
|
-
# but they modify the receiver instead of returning a modified copy
|
30
|
-
# of the dataset.
|
31
|
-
# * inner_join, full_outer_join, right_outer_join, left_outer_join -
|
32
|
-
# This methods are shortcuts to join_table with the join type
|
33
|
-
# already specified.
|
34
23
|
class Dataset
|
35
24
|
extend Metaprogramming
|
36
25
|
include Metaprogramming
|
@@ -50,6 +39,10 @@ module Sequel
|
|
50
39
|
set_defaults set_graph_aliases set_overrides unfiltered ungraphed ungrouped union
|
51
40
|
unlimited unordered where with with_recursive with_sql'.collect{|x| x.to_sym}
|
52
41
|
|
42
|
+
# Which options don't affect the SQL generation. Used by simple_select_all?
|
43
|
+
# to determine if this is a simple SELECT * FROM table.
|
44
|
+
NON_SQL_OPTIONS = [:server, :defaults, :overrides]
|
45
|
+
|
53
46
|
NOTIMPL_MSG = "This method must be overridden in Sequel adapters".freeze
|
54
47
|
WITH_SUPPORTED=:select_with_sql
|
55
48
|
|
@@ -103,12 +96,6 @@ module Sequel
|
|
103
96
|
|
104
97
|
### Instance Methods ###
|
105
98
|
|
106
|
-
# Alias for insert, but not aliased directly so subclasses
|
107
|
-
# don't have to override both methods.
|
108
|
-
def <<(*args)
|
109
|
-
insert(*args)
|
110
|
-
end
|
111
|
-
|
112
99
|
# Return the dataset as an aliased expression with the given alias. You can
|
113
100
|
# use this as a FROM or JOIN dataset, or as a column if this dataset
|
114
101
|
# returns a single row and column.
|
@@ -116,16 +103,6 @@ module Sequel
|
|
116
103
|
::Sequel::SQL::AliasedExpression.new(self, aliaz)
|
117
104
|
end
|
118
105
|
|
119
|
-
# Returns an array with all records in the dataset. If a block is given,
|
120
|
-
# the array is iterated over after all items have been loaded.
|
121
|
-
def all(&block)
|
122
|
-
a = []
|
123
|
-
each{|r| a << r}
|
124
|
-
post_load(a)
|
125
|
-
a.each(&block) if block
|
126
|
-
a
|
127
|
-
end
|
128
|
-
|
129
106
|
# Returns a new clone of the dataset with with the given options merged.
|
130
107
|
# If the options changed include options in COLUMN_CHANGE_OPTS, the cached
|
131
108
|
# columns are deleted.
|
@@ -136,30 +113,6 @@ module Sequel
|
|
136
113
|
c
|
137
114
|
end
|
138
115
|
|
139
|
-
# Returns the columns in the result set in order.
|
140
|
-
# If the columns are currently cached, returns the cached value. Otherwise,
|
141
|
-
# a SELECT query is performed to get a single row. Adapters are expected
|
142
|
-
# to fill the columns cache with the column information when a query is performed.
|
143
|
-
# If the dataset does not have any rows, this may be an empty array depending on how
|
144
|
-
# the adapter is programmed.
|
145
|
-
#
|
146
|
-
# If you are looking for all columns for a single table and maybe some information about
|
147
|
-
# each column (e.g. type), see Database#schema.
|
148
|
-
def columns
|
149
|
-
return @columns if @columns
|
150
|
-
ds = unfiltered.unordered.clone(:distinct => nil, :limit => 1)
|
151
|
-
ds.each{break}
|
152
|
-
@columns = ds.instance_variable_get(:@columns)
|
153
|
-
@columns || []
|
154
|
-
end
|
155
|
-
|
156
|
-
# Remove the cached list of columns and do a SELECT query to find
|
157
|
-
# the columns.
|
158
|
-
def columns!
|
159
|
-
@columns = nil
|
160
|
-
columns
|
161
|
-
end
|
162
|
-
|
163
116
|
# Add a mutation method to this dataset instance.
|
164
117
|
def def_mutation_method(*meths)
|
165
118
|
meths.each do |meth|
|
@@ -167,44 +120,6 @@ module Sequel
|
|
167
120
|
end
|
168
121
|
end
|
169
122
|
|
170
|
-
# Deletes the records in the dataset. The returned value is generally the
|
171
|
-
# number of records deleted, but that is adapter dependent. See delete_sql.
|
172
|
-
def delete
|
173
|
-
execute_dui(delete_sql)
|
174
|
-
end
|
175
|
-
|
176
|
-
# Iterates over the records in the dataset as they are yielded from the
|
177
|
-
# database adapter, and returns self.
|
178
|
-
#
|
179
|
-
# Note that this method is not safe to use on many adapters if you are
|
180
|
-
# running additional queries inside the provided block. If you are
|
181
|
-
# running queries inside the block, you use should all instead of each.
|
182
|
-
def each(&block)
|
183
|
-
if @opts[:graph]
|
184
|
-
graph_each(&block)
|
185
|
-
else
|
186
|
-
if row_proc = @row_proc
|
187
|
-
fetch_rows(select_sql){|r| yield row_proc.call(r)}
|
188
|
-
else
|
189
|
-
fetch_rows(select_sql, &block)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
self
|
193
|
-
end
|
194
|
-
|
195
|
-
# Executes a select query and fetches records, passing each record to the
|
196
|
-
# supplied block. The yielded records should be hashes with symbol keys.
|
197
|
-
def fetch_rows(sql, &block)
|
198
|
-
raise NotImplementedError, NOTIMPL_MSG
|
199
|
-
end
|
200
|
-
|
201
|
-
# Inserts values into the associated table. The returned value is generally
|
202
|
-
# the value of the primary key for the inserted row, but that is adapter dependent.
|
203
|
-
# See insert_sql.
|
204
|
-
def insert(*values)
|
205
|
-
execute_insert(insert_sql(*values))
|
206
|
-
end
|
207
|
-
|
208
123
|
# Returns a string representation of the dataset including the class name
|
209
124
|
# and the corresponding SQL select statement.
|
210
125
|
def inspect
|
@@ -219,17 +134,6 @@ module Sequel
|
|
219
134
|
ds
|
220
135
|
end
|
221
136
|
|
222
|
-
# Whether this dataset quotes identifiers.
|
223
|
-
def quote_identifiers?
|
224
|
-
@quote_identifiers
|
225
|
-
end
|
226
|
-
|
227
|
-
# Whether the dataset requires SQL standard datetimes (false by default,
|
228
|
-
# as most allow strings with ISO 8601 format.
|
229
|
-
def requires_sql_standard_datetimes?
|
230
|
-
false
|
231
|
-
end
|
232
|
-
|
233
137
|
# Set the server for this dataset to use. Used to pick a specific database
|
234
138
|
# shard to run a query against, or to override the default (which is SELECT uses
|
235
139
|
# :read_only database and all other queries use the :default database).
|
@@ -237,12 +141,6 @@ module Sequel
|
|
237
141
|
clone(:server=>servr)
|
238
142
|
end
|
239
143
|
|
240
|
-
# Alias for set, but not aliased directly so subclasses
|
241
|
-
# don't have to override both methods.
|
242
|
-
def set(*args)
|
243
|
-
update(*args)
|
244
|
-
end
|
245
|
-
|
246
144
|
# Set the default values for insert and update statements. The values hash passed
|
247
145
|
# to insert or update are merged into this hash.
|
248
146
|
def set_defaults(hash)
|
@@ -255,57 +153,6 @@ module Sequel
|
|
255
153
|
clone(:overrides=>hash.merge(@opts[:overrides]||{}))
|
256
154
|
end
|
257
155
|
|
258
|
-
# Whether the dataset supports common table expressions (the WITH clause).
|
259
|
-
def supports_cte?
|
260
|
-
select_clause_methods.include?(WITH_SUPPORTED)
|
261
|
-
end
|
262
|
-
|
263
|
-
# Whether the dataset supports the DISTINCT ON clause, true by default.
|
264
|
-
def supports_distinct_on?
|
265
|
-
true
|
266
|
-
end
|
267
|
-
|
268
|
-
# Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
|
269
|
-
def supports_intersect_except?
|
270
|
-
true
|
271
|
-
end
|
272
|
-
|
273
|
-
# Whether the dataset supports the INTERSECT ALL and EXCEPT ALL compound operations, true by default.
|
274
|
-
def supports_intersect_except_all?
|
275
|
-
true
|
276
|
-
end
|
277
|
-
|
278
|
-
# Whether the dataset supports the IS TRUE syntax.
|
279
|
-
def supports_is_true?
|
280
|
-
true
|
281
|
-
end
|
282
|
-
|
283
|
-
# Whether the dataset supports timezones in literal timestamps
|
284
|
-
def supports_timestamp_timezones?
|
285
|
-
false
|
286
|
-
end
|
287
|
-
|
288
|
-
# Whether the dataset supports fractional seconds in literal timestamps
|
289
|
-
def supports_timestamp_usecs?
|
290
|
-
true
|
291
|
-
end
|
292
|
-
|
293
|
-
# Whether the dataset supports window functions.
|
294
|
-
def supports_window_functions?
|
295
|
-
false
|
296
|
-
end
|
297
|
-
|
298
|
-
# Truncates the dataset. Returns nil.
|
299
|
-
def truncate
|
300
|
-
execute_ddl(truncate_sql)
|
301
|
-
end
|
302
|
-
|
303
|
-
# Updates values for the dataset. The returned value is generally the
|
304
|
-
# number of rows updated, but that is adapter dependent. See update_sql.
|
305
|
-
def update(values={})
|
306
|
-
execute_dui(update_sql(values))
|
307
|
-
end
|
308
|
-
|
309
156
|
# Add the mutation methods via metaprogramming
|
310
157
|
def_mutation_method(*MUTATION_METHODS)
|
311
158
|
|
@@ -318,7 +165,7 @@ module Sequel
|
|
318
165
|
|
319
166
|
# Whether this dataset is a simple SELECT * FROM table.
|
320
167
|
def simple_select_all?
|
321
|
-
o = @opts.reject{|k,v| v.nil?}
|
168
|
+
o = @opts.reject{|k,v| v.nil? || NON_SQL_OPTIONS.include?(k)}
|
322
169
|
o.length == 1 && (f = o[:from]) && f.length == 1 && f.first.is_a?(Symbol)
|
323
170
|
end
|
324
171
|
|
@@ -329,27 +176,6 @@ module Sequel
|
|
329
176
|
{:server=>@opts[:server] || :default}.merge(opts)
|
330
177
|
end
|
331
178
|
|
332
|
-
# Execute the given SQL on the database using execute.
|
333
|
-
def execute(sql, opts={}, &block)
|
334
|
-
@db.execute(sql, {:server=>@opts[:server] || :read_only}.merge(opts), &block)
|
335
|
-
end
|
336
|
-
|
337
|
-
# Execute the given SQL on the database using execute_ddl.
|
338
|
-
def execute_ddl(sql, opts={}, &block)
|
339
|
-
@db.execute_ddl(sql, default_server_opts(opts), &block)
|
340
|
-
nil
|
341
|
-
end
|
342
|
-
|
343
|
-
# Execute the given SQL on the database using execute_dui.
|
344
|
-
def execute_dui(sql, opts={}, &block)
|
345
|
-
@db.execute_dui(sql, default_server_opts(opts), &block)
|
346
|
-
end
|
347
|
-
|
348
|
-
# Execute the given SQL on the database using execute_insert.
|
349
|
-
def execute_insert(sql, opts={}, &block)
|
350
|
-
@db.execute_insert(sql, default_server_opts(opts), &block)
|
351
|
-
end
|
352
|
-
|
353
179
|
# Modify the identifier returned from the database based on the
|
354
180
|
# identifier_output_method.
|
355
181
|
def input_identifier(v)
|