sequel 3.1.0 → 3.2.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 +76 -0
- data/Rakefile +2 -2
- data/bin/sequel +9 -4
- data/doc/opening_databases.rdoc +279 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/virtual_rows.rdoc +42 -51
- data/lib/sequel/adapters/ado.rb +2 -5
- data/lib/sequel/adapters/db2.rb +5 -0
- data/lib/sequel/adapters/do.rb +3 -0
- data/lib/sequel/adapters/firebird.rb +6 -4
- data/lib/sequel/adapters/informix.rb +5 -3
- data/lib/sequel/adapters/jdbc.rb +10 -8
- data/lib/sequel/adapters/jdbc/h2.rb +17 -4
- data/lib/sequel/adapters/mysql.rb +6 -19
- data/lib/sequel/adapters/odbc.rb +14 -18
- data/lib/sequel/adapters/openbase.rb +8 -0
- data/lib/sequel/adapters/shared/mssql.rb +14 -8
- data/lib/sequel/adapters/shared/mysql.rb +53 -28
- data/lib/sequel/adapters/shared/oracle.rb +21 -12
- data/lib/sequel/adapters/shared/postgres.rb +46 -26
- data/lib/sequel/adapters/shared/progress.rb +10 -5
- data/lib/sequel/adapters/shared/sqlite.rb +28 -12
- data/lib/sequel/adapters/sqlite.rb +4 -3
- data/lib/sequel/adapters/utils/stored_procedures.rb +18 -9
- data/lib/sequel/connection_pool.rb +4 -3
- data/lib/sequel/database.rb +110 -10
- data/lib/sequel/database/schema_sql.rb +12 -3
- data/lib/sequel/dataset.rb +40 -3
- data/lib/sequel/dataset/convenience.rb +0 -11
- data/lib/sequel/dataset/graph.rb +25 -11
- data/lib/sequel/dataset/sql.rb +176 -68
- data/lib/sequel/extensions/migration.rb +37 -21
- data/lib/sequel/extensions/schema_dumper.rb +8 -61
- data/lib/sequel/model.rb +3 -3
- data/lib/sequel/model/associations.rb +9 -1
- data/lib/sequel/model/base.rb +8 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/sql.rb +125 -18
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/ado_spec.rb +1 -0
- data/spec/adapters/firebird_spec.rb +1 -0
- data/spec/adapters/informix_spec.rb +1 -0
- data/spec/adapters/mysql_spec.rb +23 -8
- data/spec/adapters/oracle_spec.rb +1 -0
- data/spec/adapters/postgres_spec.rb +52 -4
- data/spec/adapters/spec_helper.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +2 -1
- data/spec/core/connection_pool_spec.rb +16 -0
- data/spec/core/database_spec.rb +174 -0
- data/spec/core/dataset_spec.rb +121 -26
- data/spec/core/expression_filters_spec.rb +156 -0
- data/spec/core/object_graph_spec.rb +20 -1
- data/spec/core/schema_spec.rb +5 -5
- data/spec/extensions/migration_spec.rb +140 -74
- data/spec/extensions/schema_dumper_spec.rb +3 -69
- data/spec/extensions/single_table_inheritance_spec.rb +6 -0
- data/spec/integration/dataset_test.rb +84 -2
- data/spec/integration/schema_test.rb +24 -5
- data/spec/integration/spec_helper.rb +8 -6
- data/spec/model/eager_loading_spec.rb +9 -0
- data/spec/model/record_spec.rb +35 -8
- metadata +8 -7
- data/lib/sequel/adapters/utils/date_format.rb +0 -21
- data/lib/sequel/adapters/utils/savepoint_transactions.rb +0 -80
- data/lib/sequel/adapters/utils/unsupported.rb +0 -50
data/doc/virtual_rows.rdoc
CHANGED
@@ -1,65 +1,56 @@
|
|
1
1
|
= Virtual Row Blocks
|
2
2
|
|
3
|
-
Dataset methods filter, order, and select all take blocks that yield
|
4
|
-
instances of Sequel::SQL::VirtualRow
|
3
|
+
Dataset methods filter, order, and select all take blocks that either yield
|
4
|
+
instances of Sequel::SQL::VirtualRow (if the block takes an argument), or
|
5
|
+
are evaluated in the context of an instance of Sequel::SQL::VirtualRow. These are referred to as
|
5
6
|
virtual row blocks. Many other dataset methods pass the blocks
|
6
7
|
they are given into one of those three methods, so there are actually
|
7
8
|
many Sequel methods that take virtual row blocks.
|
8
9
|
|
9
10
|
VirtualRow is a class that returns SQL::Indentifiers,
|
10
|
-
SQL::QualifiedIdentifiers, or SQL::
|
11
|
+
SQL::QualifiedIdentifiers, SQL::Functions, or SQL::WindowFunctions depending on how it is
|
11
12
|
called. This is best shown by example:
|
12
13
|
|
13
14
|
ds = DB[:items]
|
14
|
-
ds.filter{|o| o.column > 1} # column > 1
|
15
|
-
ds.filter{|o| o.table__column > 1} # table.column > 1
|
16
|
-
ds.filter{|o| o.function(1) > 1} # function(1) > 1
|
17
|
-
|
18
|
-
Basically, the rules are:
|
19
|
-
|
20
|
-
* If there are arguments, an SQL::Function is returned with the
|
21
|
-
name of the method used and the arguments given.
|
22
|
-
|
23
|
-
* If there are no arguments and the method contains a double
|
24
|
-
underscore, split on the double underscore and return an
|
25
|
-
SQL::QualifiedIdentifier with the table and column.
|
26
|
-
|
27
|
-
* Otherwise, create an SQL::Identifier with the name of the
|
28
|
-
method.
|
29
|
-
|
30
|
-
One of the consequences of these rules is that you cannot
|
31
|
-
create an SQL::Function that takes no arguments using a VirtualRow
|
32
|
-
instance.
|
33
|
-
|
34
|
-
In Sequel 2.12, the following is deprecated by default, as
|
35
|
-
virtual row blocks are required to accept an argument:
|
36
|
-
|
37
|
-
ds.filter{:column > 1} # column > 1
|
38
|
-
ds.filter{:table__column > 1} # table.column > 1
|
39
|
-
ds.filter{:function.sql_function(1) > 1} # function(1) > 1
|
40
|
-
|
41
|
-
This is to keep backwards compatibility while notifying people
|
42
|
-
to change their code. In Sequel 3.0, you will be able to
|
43
|
-
do:
|
44
|
-
|
45
15
|
ds.filter{column > 1} # column > 1
|
46
16
|
ds.filter{table__column > 1} # table.column > 1
|
47
17
|
ds.filter{function(1) > 1} # function(1) > 1
|
18
|
+
ds.select{version{}} # version()
|
19
|
+
ds.select{count(:*){}} # count(*)
|
20
|
+
ds.select{count(:distinct, col1){}} # count(DISTINCT col1)
|
21
|
+
ds.select{rank(:over){}} # rank() OVER ()
|
22
|
+
ds.select{count(:over, :*=>true){}} # count(*) OVER ()
|
23
|
+
ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}} # sum(col1) OVER (PARTITION BY col2 ORDER BY col3)
|
24
|
+
|
25
|
+
Basically, the rules are:
|
48
26
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
If
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
27
|
+
* If a block is given:
|
28
|
+
* The block is currently not called. This may change in a future version.
|
29
|
+
* If there are no arguments, an SQL::Function with the name of
|
30
|
+
method used, and no arguments.
|
31
|
+
* If the first argument is :*, an SQL::Function is created with a single
|
32
|
+
wildcard argument (*).
|
33
|
+
* If the first argument is :distinct, an SQL::Function is created with
|
34
|
+
the keyword DISTINCT prefacing all remaining arguments.
|
35
|
+
* If the first argument is :over, the second argument if provided should
|
36
|
+
be a hash of options to pass to SQL::Window. The options hash can also
|
37
|
+
contain :*=>true to use a wildcard argument as the function argument, or
|
38
|
+
:args=>... to specify an array of arguments to use as the function arguments.
|
39
|
+
* If a block is not given:
|
40
|
+
* If there are arguments, an SQL::Function is returned with the
|
41
|
+
name of the method used and the arguments given.
|
42
|
+
* If there are no arguments and the method contains a double
|
43
|
+
underscore, split on the double underscore and return an
|
44
|
+
SQL::QualifiedIdentifier with the table and column.
|
45
|
+
* Otherwise, create an SQL::Identifier with the name of the
|
46
|
+
method.
|
47
|
+
|
48
|
+
If you use a virtual row block that doesn't take an argument,
|
49
|
+
the block is instance_evaled, so you can't reference methods
|
50
|
+
in the enclosing scope. If you need to call methods of the
|
51
|
+
enclosing scope, you should assign the results to local variables
|
52
|
+
before the block, or just make the block take an argument and use
|
53
|
+
that. If you want to create identifiers or qualified identifiers
|
54
|
+
with the same name as existing local variables, make sure ruby
|
55
|
+
knows it is a method call instead of a local variable reference
|
56
|
+
by not ommiting the parentheses at the end of the method call.
|
data/lib/sequel/adapters/ado.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
Sequel.require 'adapters/utils/date_format'
|
2
1
|
require 'win32ole'
|
3
2
|
|
4
3
|
module Sequel
|
@@ -28,9 +27,9 @@ module Sequel
|
|
28
27
|
# Connect to the database. In addition to the usual database options,
|
29
28
|
# the following option has effect:
|
30
29
|
#
|
31
|
-
# * :
|
30
|
+
# * :command_timeout - Sets the time in seconds to wait while attempting
|
32
31
|
# to execute a command before cancelling the attempt and generating
|
33
|
-
# an error.
|
32
|
+
# an error. Specifically, it sets the ADO CommandTimeout property.
|
34
33
|
# If this property is not set, the default of 30 seconds is used.
|
35
34
|
# * :provider - Sets the Provider of this ADO connection (for example, "SQLOLEDB")
|
36
35
|
|
@@ -66,8 +65,6 @@ module Sequel
|
|
66
65
|
end
|
67
66
|
|
68
67
|
class Dataset < Sequel::Dataset
|
69
|
-
include Dataset::SQLStandardDateFormat
|
70
|
-
|
71
68
|
def fetch_rows(sql)
|
72
69
|
execute(sql) do |s|
|
73
70
|
@columns = s.Fields.extend(Enumerable).map do |column|
|
data/lib/sequel/adapters/db2.rb
CHANGED
data/lib/sequel/adapters/do.rb
CHANGED
@@ -130,6 +130,7 @@ module Sequel
|
|
130
130
|
# to do a transaction. So we close the connection created and
|
131
131
|
# substitute our own.
|
132
132
|
def begin_transaction(conn)
|
133
|
+
return super if supports_savepoints?
|
133
134
|
log_info(TRANSACTION_BEGIN)
|
134
135
|
t = ::DataObjects::Transaction.create_for_uri(uri)
|
135
136
|
t.instance_variable_get(:@connection).close
|
@@ -141,6 +142,7 @@ module Sequel
|
|
141
142
|
# DataObjects requires transactions be prepared before being
|
142
143
|
# committed, so we do that.
|
143
144
|
def commit_transaction(t)
|
145
|
+
return super if supports_savepoints?
|
144
146
|
log_info(TRANSACTION_ROLLBACK)
|
145
147
|
t.prepare
|
146
148
|
t.commit
|
@@ -170,6 +172,7 @@ module Sequel
|
|
170
172
|
|
171
173
|
# We use the transactions rollback method to rollback.
|
172
174
|
def rollback_transaction(t)
|
175
|
+
return super if supports_savepoints?
|
173
176
|
log_info(TRANSACTION_COMMIT)
|
174
177
|
t.rollback
|
175
178
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'fb'
|
2
|
-
Sequel.require 'adapters/utils/unsupported'
|
3
2
|
|
4
3
|
module Sequel
|
5
4
|
# The Sequel Firebird adapter requires the ruby fb driver located at
|
@@ -199,14 +198,12 @@ module Sequel
|
|
199
198
|
|
200
199
|
# Dataset class for Firebird datasets
|
201
200
|
class Dataset < Sequel::Dataset
|
202
|
-
include UnsupportedIntersectExcept
|
203
|
-
|
204
201
|
BOOL_TRUE = '1'.freeze
|
205
202
|
BOOL_FALSE = '0'.freeze
|
206
203
|
NULL = LiteralString.new('NULL').freeze
|
207
204
|
COMMA_SEPARATOR = ', '.freeze
|
208
205
|
FIREBIRD_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
209
|
-
SELECT_CLAUSE_ORDER = %w'distinct limit columns from join where group having compounds order'.freeze
|
206
|
+
SELECT_CLAUSE_ORDER = %w'with distinct limit columns from join where group having compounds order'.freeze
|
210
207
|
|
211
208
|
# Yield all rows returned by executing the given SQL and converting
|
212
209
|
# the types.
|
@@ -262,6 +259,11 @@ module Sequel
|
|
262
259
|
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
263
260
|
end
|
264
261
|
|
262
|
+
# Firebird does not support INTERSECT or EXCEPT
|
263
|
+
def supports_intersect_except?
|
264
|
+
false
|
265
|
+
end
|
266
|
+
|
265
267
|
private
|
266
268
|
|
267
269
|
def hash_row(stmt, row)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
Sequel.require 'adapters/utils/unsupported'
|
2
1
|
require 'informix'
|
3
2
|
|
4
3
|
module Sequel
|
@@ -38,8 +37,6 @@ module Sequel
|
|
38
37
|
end
|
39
38
|
|
40
39
|
class Dataset < Sequel::Dataset
|
41
|
-
include UnsupportedIntersectExcept
|
42
|
-
|
43
40
|
SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where having group compounds order'.freeze
|
44
41
|
|
45
42
|
def fetch_rows(sql, &block)
|
@@ -64,6 +61,11 @@ module Sequel
|
|
64
61
|
|
65
62
|
private
|
66
63
|
|
64
|
+
# Informix does not support INTERSECT or EXCEPT
|
65
|
+
def supports_intersect_except?
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
67
69
|
def select_clause_order
|
68
70
|
SELECT_CLAUSE_ORDER
|
69
71
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -134,7 +134,9 @@ module Sequel
|
|
134
134
|
|
135
135
|
# Connect to the database using JavaSQL::DriverManager.getConnection.
|
136
136
|
def connect(server)
|
137
|
-
|
137
|
+
args = [uri(server_opts(server))]
|
138
|
+
args.concat([opts[:user], opts[:password]]) if opts[:user] && opts[:password]
|
139
|
+
setup_connection(JavaSQL::DriverManager.getConnection(*args))
|
138
140
|
end
|
139
141
|
|
140
142
|
# Return instances of JDBC::Dataset with the given opts.
|
@@ -223,7 +225,7 @@ module Sequel
|
|
223
225
|
|
224
226
|
# JDBC uses a statement object to execute SQL on the database
|
225
227
|
def begin_transaction(conn)
|
226
|
-
conn = conn.createStatement
|
228
|
+
conn = conn.createStatement unless supports_savepoints?
|
227
229
|
super
|
228
230
|
end
|
229
231
|
|
@@ -304,7 +306,7 @@ module Sequel
|
|
304
306
|
|
305
307
|
# Close the given statement when removing the transaction
|
306
308
|
def remove_transaction(stmt)
|
307
|
-
stmt.close if stmt
|
309
|
+
stmt.close if stmt && !supports_savepoints?
|
308
310
|
super
|
309
311
|
end
|
310
312
|
|
@@ -464,14 +466,14 @@ module Sequel
|
|
464
466
|
def process_result_set(result)
|
465
467
|
# get column names
|
466
468
|
meta = result.getMetaData
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
469
|
+
cols = []
|
470
|
+
i = 0
|
471
|
+
meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
|
472
|
+
@columns = cols.map{|c| c.at(0)}
|
471
473
|
# get rows
|
472
474
|
while result.next
|
473
475
|
row = {}
|
474
|
-
|
476
|
+
cols.each{|n, i| row[n] = convert_type(result.getObject(i))}
|
475
477
|
yield row
|
476
478
|
end
|
477
479
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
Sequel.require %w'date_format unsupported', 'adapters/utils'
|
2
|
-
|
3
1
|
module Sequel
|
4
2
|
module JDBC
|
5
3
|
# Database and Dataset support for H2 databases accessed via JDBC.
|
@@ -65,8 +63,23 @@ module Sequel
|
|
65
63
|
|
66
64
|
# Dataset class for H2 datasets accessed via JDBC.
|
67
65
|
class Dataset < JDBC::Dataset
|
68
|
-
|
69
|
-
|
66
|
+
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
|
67
|
+
|
68
|
+
# H2 requires SQL standard datetimes
|
69
|
+
def requires_sql_standard_datetimes?
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
# H2 doesn't support IS TRUE
|
74
|
+
def supports_is_true?
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def select_clause_order
|
81
|
+
SELECT_CLAUSE_ORDER
|
82
|
+
end
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|
@@ -16,7 +16,8 @@ module Sequel
|
|
16
16
|
# Use only a single proc for each type to save on memory
|
17
17
|
MYSQL_TYPE_PROCS = {
|
18
18
|
[0, 246] => lambda{|v| BigDecimal.new(v)}, # decimal
|
19
|
-
[1
|
19
|
+
[1] => lambda{|v| Sequel.convert_tinyint_to_bool ? v.to_i != 0 : v.to_i}, # tinyint
|
20
|
+
[2, 3, 8, 9, 13, 247, 248] => lambda{|v| v.to_i}, # integer
|
20
21
|
[4, 5] => lambda{|v| v.to_f}, # float
|
21
22
|
[10, 14] => lambda{|v| convert_date_time(:string_to_date, v)}, # date
|
22
23
|
[7, 12] => lambda{|v| convert_date_time(:string_to_datetime, v)}, # datetime
|
@@ -295,11 +296,12 @@ module Sequel
|
|
295
296
|
# Yield all rows matching this dataset
|
296
297
|
def fetch_rows(sql)
|
297
298
|
execute(sql) do |r|
|
298
|
-
|
299
|
-
|
299
|
+
i = -1
|
300
|
+
cols = r.fetch_fields.map{|f| [output_identifier(f.name), MYSQL_TYPES[f.type], i+=1]}
|
301
|
+
@columns = cols.map{|c| c.first}
|
300
302
|
while row = r.fetch_row
|
301
303
|
h = {}
|
302
|
-
|
304
|
+
cols.each{|n, p, i| v = row[i]; h[n] = (v && p) ? p.call(v) : v}
|
303
305
|
yield h
|
304
306
|
end
|
305
307
|
end
|
@@ -335,21 +337,6 @@ module Sequel
|
|
335
337
|
|
336
338
|
private
|
337
339
|
|
338
|
-
# Convert the type of v using the method in MYSQL_TYPES[type].
|
339
|
-
def convert_type(v, type)
|
340
|
-
if v
|
341
|
-
if type == 1 && Sequel.convert_tinyint_to_bool
|
342
|
-
# We special case tinyint here to avoid adding
|
343
|
-
# a method to an ancestor of Fixnum
|
344
|
-
v.to_i == 0 ? false : true
|
345
|
-
else
|
346
|
-
(b = MYSQL_TYPES[type]) ? b.call(v) : v
|
347
|
-
end
|
348
|
-
else
|
349
|
-
nil
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
340
|
# Set the :type option to :select if it hasn't been set.
|
354
341
|
def execute(sql, opts={}, &block)
|
355
342
|
super(sql, {:type=>:select}.merge(opts), &block)
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -44,16 +44,16 @@ module Sequel
|
|
44
44
|
ODBC::Dataset.new(self, opts)
|
45
45
|
end
|
46
46
|
|
47
|
-
# ODBC returns native statement objects, which must be dropped if
|
48
|
-
# you call execute manually, or you will get warnings. See the
|
49
|
-
# fetch_rows method source code for an example of how to drop
|
50
|
-
# the statements.
|
51
47
|
def execute(sql, opts={})
|
52
48
|
log_info(sql)
|
53
49
|
synchronize(opts[:server]) do |conn|
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
begin
|
51
|
+
r = conn.run(sql)
|
52
|
+
yield(r) if block_given?
|
53
|
+
ensure
|
54
|
+
r.drop if r
|
55
|
+
end
|
56
|
+
nil
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
@@ -85,19 +85,15 @@ module Sequel
|
|
85
85
|
|
86
86
|
def fetch_rows(sql, &block)
|
87
87
|
execute(sql) do |s|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
n = UNTITLED_COLUMN % (untitled_count += 1)
|
93
|
-
end
|
94
|
-
output_identifier(n)
|
88
|
+
untitled_count = 0
|
89
|
+
@columns = s.columns(true).map do |c|
|
90
|
+
if (n = c.name).empty?
|
91
|
+
n = UNTITLED_COLUMN % (untitled_count += 1)
|
95
92
|
end
|
96
|
-
|
97
|
-
rows.each {|row| yield hash_row(row)} if rows
|
98
|
-
ensure
|
99
|
-
s.drop unless s.nil? rescue nil
|
93
|
+
output_identifier(n)
|
100
94
|
end
|
95
|
+
rows = s.fetch_all
|
96
|
+
rows.each {|row| yield hash_row(row)} if rows
|
101
97
|
end
|
102
98
|
self
|
103
99
|
end
|
@@ -37,6 +37,8 @@ module Sequel
|
|
37
37
|
end
|
38
38
|
|
39
39
|
class Dataset < Sequel::Dataset
|
40
|
+
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
|
41
|
+
|
40
42
|
def fetch_rows(sql)
|
41
43
|
execute(sql) do |result|
|
42
44
|
begin
|
@@ -52,6 +54,12 @@ module Sequel
|
|
52
54
|
end
|
53
55
|
self
|
54
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def select_clause_order
|
61
|
+
SELECT_CLAUSE_ORDER
|
62
|
+
end
|
55
63
|
end
|
56
64
|
end
|
57
65
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
Sequel.require 'adapters/utils/unsupported'
|
2
|
-
|
3
1
|
module Sequel
|
4
2
|
module MSSQL
|
5
3
|
module DatabaseMethods
|
@@ -48,9 +46,7 @@ module Sequel
|
|
48
46
|
end
|
49
47
|
|
50
48
|
module DatasetMethods
|
51
|
-
|
52
|
-
|
53
|
-
SELECT_CLAUSE_ORDER = %w'limit distinct columns from with join where group order having compounds'.freeze
|
49
|
+
SELECT_CLAUSE_ORDER = %w'with limit distinct columns from table_options join where group order having compounds'.freeze
|
54
50
|
|
55
51
|
def complex_expression_sql(op, args)
|
56
52
|
case op
|
@@ -72,13 +68,23 @@ module Sequel
|
|
72
68
|
|
73
69
|
# Allows you to do .nolock on a query
|
74
70
|
def nolock
|
75
|
-
clone(:
|
71
|
+
clone(:table_options => "(NOLOCK)")
|
76
72
|
end
|
77
73
|
|
78
74
|
def quoted_identifier(name)
|
79
75
|
"[#{name}]"
|
80
76
|
end
|
81
77
|
|
78
|
+
# Microsoft SQL Server does not support INTERSECT or EXCEPT
|
79
|
+
def supports_intersect_except?
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# MSSQL 2005+ supports window functions
|
84
|
+
def supports_window_functions?
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
82
88
|
private
|
83
89
|
|
84
90
|
def literal_string(v)
|
@@ -96,8 +102,8 @@ module Sequel
|
|
96
102
|
end
|
97
103
|
|
98
104
|
# MSSQL uses the WITH statement to lock tables
|
99
|
-
def
|
100
|
-
sql << " WITH #{@opts[:
|
105
|
+
def select_table_options_sql(sql)
|
106
|
+
sql << " WITH #{@opts[:table_options]}" if @opts[:table_options]
|
101
107
|
end
|
102
108
|
end
|
103
109
|
end
|