|
1 | 1 | require 'arel' |
2 | 2 |
|
3 | 3 | module Arel |
4 | | - |
5 | | - class SelectManager < Arel::TreeManager |
6 | | - |
7 | | - AR_CA_SQLSA_NAME = 'ActiveRecord::ConnectionAdapters::SQLServerAdapter'.freeze |
8 | | - |
9 | | - # Getting real Ordering objects is very important for us. We need to be able to call #uniq on |
10 | | - # a colleciton of them reliably as well as using their true object attributes to mutate them |
11 | | - # to grouping objects for the inner sql during a select statment with an offset/rownumber. So this |
12 | | - # is here till ActiveRecord & ARel does this for us instead of using SqlLiteral objects. |
13 | | - alias :order_without_sqlserver :order |
14 | | - def order(*expr) |
15 | | - return order_without_sqlserver(*expr) unless engine_activerecord_sqlserver_adapter? |
16 | | - @ast.orders.concat(expr.map{ |x| |
17 | | - case x |
18 | | - when Arel::Attributes::Attribute |
19 | | - table = Arel::Table.new(x.relation.table_alias || x.relation.name) |
20 | | - e = table[x.name] |
21 | | - Arel::Nodes::Ascending.new e |
22 | | - when Arel::Nodes::Ordering |
23 | | - x |
24 | | - when String |
25 | | - x.split(',').map do |s| |
26 | | - s = x if x.strip =~ /\A\b\w+\b\(.*,.*\)(\s+(ASC|DESC))?\Z/i # Allow functions with comma(s) to pass thru. |
27 | | - s.strip! |
28 | | - d = s =~ /(ASC|DESC)\Z/i ? $1.upcase : nil |
29 | | - e = d.nil? ? s : s.mb_chars[0...-d.length].strip |
30 | | - e = Arel.sql(e) |
31 | | - d && d == "DESC" ? Arel::Nodes::Descending.new(e) : Arel::Nodes::Ascending.new(e) |
32 | | - end |
33 | | - else |
34 | | - e = Arel.sql(x.to_s) |
35 | | - Arel::Nodes::Ascending.new e |
36 | | - end |
37 | | - }.flatten) |
38 | | - self |
39 | | - end |
40 | | - |
41 | | - # A friendly over ride that allows us to put a special lock object that can have a default or pass |
42 | | - # custom string hints down. See the visit_Arel_Nodes_LockWithSQLServer delegation method. |
43 | | - alias :lock_without_sqlserver :lock |
44 | | - def lock(locking=true) |
45 | | - if engine_activerecord_sqlserver_adapter? |
46 | | - case locking |
47 | | - when true |
48 | | - locking = Arel.sql('WITH(HOLDLOCK, ROWLOCK)') |
49 | | - when Arel::Nodes::SqlLiteral |
50 | | - when String |
51 | | - locking = Arel.sql locking |
52 | | - end |
53 | | - @ast.lock = Arel::Nodes::Lock.new(locking) |
54 | | - self |
55 | | - else |
56 | | - lock_without_sqlserver(locking) |
57 | | - end |
58 | | - end |
59 | | - |
60 | | - private |
61 | | - |
62 | | - def engine_activerecord_sqlserver_adapter? |
63 | | - @engine.connection && @engine.connection.class.name == AR_CA_SQLSA_NAME |
64 | | - end |
65 | | - |
66 | | - end |
67 | | - |
68 | 4 | module Visitors |
69 | 5 | class SQLServer < Arel::Visitors::ToSql |
70 | 6 |
|
|
0 commit comments