activerecord-sqlserver-adapter 3.0.8 → 3.0.9
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
CHANGED
@@ -164,7 +164,7 @@ module ActiveRecord
|
|
164
164
|
include Sqlserver::Errors
|
165
165
|
|
166
166
|
ADAPTER_NAME = 'SQLServer'.freeze
|
167
|
-
VERSION = '3.0.
|
167
|
+
VERSION = '3.0.9'.freeze
|
168
168
|
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
|
169
169
|
SUPPORTED_VERSIONS = [2005,2008].freeze
|
170
170
|
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Arel
|
2
|
-
|
2
|
+
|
3
3
|
module Nodes
|
4
|
-
|
4
|
+
|
5
5
|
# See the SelectManager#lock method on why this custom class is needed.
|
6
6
|
class LockWithSQLServer < Arel::Nodes::Unary
|
7
7
|
end
|
8
|
-
|
9
|
-
# In versions of ActiveRecord prior to v3.0.3 limits and offset were always integers via
|
10
|
-
# a #to_i. Somewhere between ActiveRecord and ARel this is not happening anymore nor are they
|
11
|
-
# in agreement which should be responsible. Since we need to make sure that these are visited
|
8
|
+
|
9
|
+
# In versions of ActiveRecord prior to v3.0.3 limits and offset were always integers via
|
10
|
+
# a #to_i. Somewhere between ActiveRecord and ARel this is not happening anymore nor are they
|
11
|
+
# in agreement which should be responsible. Since we need to make sure that these are visited
|
12
12
|
# correctly and that we can do math with them, these are here to cast to integers.
|
13
13
|
class Limit < Arel::Nodes::Unary
|
14
14
|
def initialize expr
|
@@ -20,7 +20,7 @@ module Arel
|
|
20
20
|
@expr = expr.to_i
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Extending the Ordering class to be comparrison friendly which allows us to call #uniq on a
|
25
25
|
# collection of them. See SelectManager#order for more details.
|
26
26
|
class Ordering < Arel::Nodes::Binary
|
@@ -33,16 +33,16 @@ module Arel
|
|
33
33
|
def eql?(other)
|
34
34
|
self == other
|
35
35
|
end
|
36
|
-
end
|
37
|
-
|
36
|
+
end
|
37
|
+
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
class SelectManager < Arel::TreeManager
|
41
|
-
|
41
|
+
|
42
42
|
alias :lock_without_sqlserver :lock
|
43
|
-
|
44
|
-
# Getting real Ordering objects is very important for us. We need to be able to call #uniq on
|
45
|
-
# a colleciton of them reliably as well as using their true object attributes to mutate them
|
43
|
+
|
44
|
+
# Getting real Ordering objects is very important for us. We need to be able to call #uniq on
|
45
|
+
# a colleciton of them reliably as well as using their true object attributes to mutate them
|
46
46
|
# to grouping objects for the inner sql during a select statment with an offset/rownumber. So this
|
47
47
|
# is here till ActiveRecord & ARel does this for us instead of using SqlLiteral objects.
|
48
48
|
def order(*exprs)
|
@@ -67,8 +67,8 @@ module Arel
|
|
67
67
|
}.flatten)
|
68
68
|
self
|
69
69
|
end
|
70
|
-
|
71
|
-
# A friendly over ride that allows us to put a special lock object that can have a default or pass
|
70
|
+
|
71
|
+
# A friendly over ride that allows us to put a special lock object that can have a default or pass
|
72
72
|
# custom string hints down. See the visit_Arel_Nodes_LockWithSQLServer delegation method.
|
73
73
|
def lock(locking=true)
|
74
74
|
if Arel::Visitors::SQLServer === @visitor
|
@@ -78,16 +78,16 @@ module Arel
|
|
78
78
|
lock_without_sqlserver(locking)
|
79
79
|
end
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
module Visitors
|
85
85
|
class SQLServer < Arel::Visitors::ToSql
|
86
|
-
|
86
|
+
|
87
87
|
private
|
88
|
-
|
88
|
+
|
89
89
|
# SQLServer ToSql/Visitor (Overides)
|
90
|
-
|
90
|
+
|
91
91
|
def visit_Arel_Nodes_SelectStatement(o)
|
92
92
|
if complex_count_sql?(o)
|
93
93
|
visit_Arel_Nodes_SelectStatementForComplexCount(o)
|
@@ -97,19 +97,19 @@ module Arel
|
|
97
97
|
visit_Arel_Nodes_SelectStatementWithOutOffset(o)
|
98
98
|
end
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
def visit_Arel_Nodes_Offset(o)
|
102
102
|
"WHERE [__rnt].[__rn] > #{visit o.expr}"
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def visit_Arel_Nodes_Limit(o)
|
106
106
|
"TOP (#{visit o.expr})"
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def visit_Arel_Nodes_Lock o
|
110
110
|
"WITH(HOLDLOCK, ROWLOCK)"
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
def visit_Arel_Nodes_LockWithSQLServer o
|
114
114
|
case o.expr
|
115
115
|
when TrueClass
|
@@ -120,10 +120,10 @@ module Arel
|
|
120
120
|
""
|
121
121
|
end
|
122
122
|
end
|
123
|
-
|
124
|
-
|
123
|
+
|
124
|
+
|
125
125
|
# SQLServer ToSql/Visitor (Additions)
|
126
|
-
|
126
|
+
|
127
127
|
def visit_Arel_Nodes_SelectStatementWithOutOffset(o, windowed=false)
|
128
128
|
find_and_fix_uncorrelated_joins_in_select_statement(o)
|
129
129
|
core = o.cores.first
|
@@ -150,7 +150,7 @@ module Arel
|
|
150
150
|
("ORDER BY #{orders.map{ |x| visit(x) }.join(', ')}" if !orders.empty? && !windowed)
|
151
151
|
].compact.join ' '
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
def visit_Arel_Nodes_SelectStatementWithOffset(o)
|
155
155
|
orders = rowtable_orders(o)
|
156
156
|
[ "SELECT",
|
@@ -163,7 +163,7 @@ module Arel
|
|
163
163
|
(visit(o.offset) if o.offset),
|
164
164
|
].compact.join ' '
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
def visit_Arel_Nodes_SelectStatementForComplexCount(o)
|
168
168
|
core = o.cores.first
|
169
169
|
o.limit.expr = o.limit.expr + (o.offset ? o.offset.expr : 0) if o.limit
|
@@ -183,10 +183,10 @@ module Arel
|
|
183
183
|
(visit(o.offset) if o.offset)
|
184
184
|
].compact.join ' '
|
185
185
|
end
|
186
|
-
|
187
|
-
|
186
|
+
|
187
|
+
|
188
188
|
# SQLServer Helpers
|
189
|
-
|
189
|
+
|
190
190
|
def source_with_lock_for_select_statement(o)
|
191
191
|
# TODO: [ARel 2.2] Use #from/#source vs. #froms
|
192
192
|
core = o.cores.first
|
@@ -194,12 +194,12 @@ module Arel
|
|
194
194
|
if source && o.lock
|
195
195
|
lock = visit o.lock
|
196
196
|
index = source.match(/FROM [\w\[\]\.]+/)[0].length
|
197
|
-
source.insert index, " #{lock}"
|
197
|
+
source.insert index, " #{lock}"
|
198
198
|
else
|
199
199
|
source
|
200
200
|
end
|
201
201
|
end
|
202
|
-
|
202
|
+
|
203
203
|
def table_from_select_statement(o)
|
204
204
|
core = o.cores.first
|
205
205
|
# TODO: [ARel 2.2] Use #from/#source vs. #froms
|
@@ -220,49 +220,49 @@ module Arel
|
|
220
220
|
table_finder.call(x.left)
|
221
221
|
end
|
222
222
|
}
|
223
|
-
table_finder.call(core.froms)
|
223
|
+
table_finder.call(core.froms)
|
224
224
|
end
|
225
|
-
|
225
|
+
|
226
226
|
def single_distinct_select_statement?(o)
|
227
227
|
projections = o.cores.first.projections
|
228
228
|
p1 = projections.first
|
229
|
-
projections.size == 1 &&
|
230
|
-
((p1.respond_to?(:distinct) && p1.distinct) ||
|
229
|
+
projections.size == 1 &&
|
230
|
+
((p1.respond_to?(:distinct) && p1.distinct) ||
|
231
231
|
p1.respond_to?(:include?) && p1.include?('DISTINCT'))
|
232
232
|
end
|
233
|
-
|
233
|
+
|
234
234
|
def all_projections_aliased_in_select_statement?(o)
|
235
235
|
projections = o.cores.first.projections
|
236
236
|
projections.all? do |x|
|
237
237
|
x.split(',').all? { |y| y.include?(' AS ') }
|
238
238
|
end
|
239
239
|
end
|
240
|
-
|
240
|
+
|
241
241
|
def function_select_statement?(o)
|
242
242
|
core = o.cores.first
|
243
243
|
core.projections.any? { |x| Arel::Nodes::Function === x }
|
244
244
|
end
|
245
|
-
|
245
|
+
|
246
246
|
def eager_limiting_select_statement?(o)
|
247
247
|
core = o.cores.first
|
248
248
|
single_distinct_select_statement?(o) && (o.limit && !o.offset) && core.groups.empty?
|
249
249
|
end
|
250
|
-
|
250
|
+
|
251
251
|
def join_in_select_statement?(o)
|
252
252
|
core = o.cores.first
|
253
253
|
# TODO: [ARel 2.2] Use #from/#source vs. #froms
|
254
254
|
# core.source.right.any? { |x| Arel::Nodes::Join === x }
|
255
255
|
Arel::Nodes::Join === core.froms
|
256
256
|
end
|
257
|
-
|
257
|
+
|
258
258
|
def complex_count_sql?(o)
|
259
259
|
core = o.cores.first
|
260
260
|
core.projections.size == 1 &&
|
261
|
-
Arel::Nodes::Count === core.projections.first &&
|
261
|
+
Arel::Nodes::Count === core.projections.first &&
|
262
262
|
(o.limit || !core.wheres.empty?) &&
|
263
263
|
!join_in_select_statement?(o)
|
264
264
|
end
|
265
|
-
|
265
|
+
|
266
266
|
def find_and_fix_uncorrelated_joins_in_select_statement(o)
|
267
267
|
core = o.cores.first
|
268
268
|
# TODO: [ARel 2.2] Use #from/#source vs. #froms
|
@@ -287,7 +287,7 @@ module Arel
|
|
287
287
|
j2.insert on_index, " AS [#{j2_tn}_crltd]"
|
288
288
|
j2.sub! "[#{j2_tn}].", "[#{j2_tn}_crltd]."
|
289
289
|
end
|
290
|
-
|
290
|
+
|
291
291
|
def rowtable_projections(o)
|
292
292
|
core = o.cores.first
|
293
293
|
if single_distinct_select_statement?(o)
|
@@ -305,13 +305,13 @@ module Arel
|
|
305
305
|
end
|
306
306
|
elsif function_select_statement?(o)
|
307
307
|
# TODO: [ARel 2.2] Use Arel.star
|
308
|
-
[Arel::Nodes::SqlLiteral.new
|
308
|
+
[Arel::Nodes::SqlLiteral.new('*')]
|
309
309
|
else
|
310
310
|
tn = table_from_select_statement(o).name
|
311
311
|
core.projections.map { |x| x.gsub /\[#{tn}\]\./, '[__rnt].' }
|
312
312
|
end
|
313
313
|
end
|
314
|
-
|
314
|
+
|
315
315
|
def rowtable_orders(o)
|
316
316
|
core = o.cores.first
|
317
317
|
if !o.orders.empty?
|
@@ -322,7 +322,7 @@ module Arel
|
|
322
322
|
[table_from_select_statement(o).primary_key.asc]
|
323
323
|
end.uniq
|
324
324
|
end
|
325
|
-
|
325
|
+
|
326
326
|
# TODO: We use this for grouping too, maybe make Grouping objects vs SqlLiteral.
|
327
327
|
def projection_without_expression(projection)
|
328
328
|
Arel::Nodes::SqlLiteral.new(projection.split(',').map do |x|
|
@@ -333,10 +333,10 @@ module Arel
|
|
333
333
|
x.strip
|
334
334
|
end.join(', '))
|
335
335
|
end
|
336
|
-
|
336
|
+
|
337
337
|
end
|
338
338
|
end
|
339
|
-
|
339
|
+
|
340
340
|
end
|
341
341
|
|
342
342
|
Arel::Visitors::VISITORS['sqlserver'] = Arel::Visitors::SQLServer
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-sqlserver-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 3
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 3.0.
|
8
|
+
- 9
|
9
|
+
version: 3.0.9
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Ken Collins
|
@@ -19,7 +18,7 @@ autorequire:
|
|
19
18
|
bindir: bin
|
20
19
|
cert_chain: []
|
21
20
|
|
22
|
-
date: 2011-01-
|
21
|
+
date: 2011-01-17 00:00:00 -05:00
|
23
22
|
default_executable:
|
24
23
|
dependencies:
|
25
24
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +29,6 @@ dependencies:
|
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
hash: 1
|
34
32
|
segments:
|
35
33
|
- 3
|
36
34
|
- 0
|
@@ -46,7 +44,6 @@ dependencies:
|
|
46
44
|
requirements:
|
47
45
|
- - ~>
|
48
46
|
- !ruby/object:Gem::Version
|
49
|
-
hash: 1
|
50
47
|
segments:
|
51
48
|
- 2
|
52
49
|
- 0
|
@@ -92,7 +89,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
89
|
requirements:
|
93
90
|
- - ">="
|
94
91
|
- !ruby/object:Gem::Version
|
95
|
-
hash: 3
|
96
92
|
segments:
|
97
93
|
- 0
|
98
94
|
version: "0"
|
@@ -101,7 +97,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
97
|
requirements:
|
102
98
|
- - ">="
|
103
99
|
- !ruby/object:Gem::Version
|
104
|
-
hash: 3
|
105
100
|
segments:
|
106
101
|
- 0
|
107
102
|
version: "0"
|