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