arel 2.0.10 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +51 -4
- data/Manifest.txt +15 -31
- data/README.markdown +27 -3
- data/Rakefile +0 -2
- data/arel.gemspec +20 -19
- data/lib/arel.rb +9 -1
- data/lib/arel/alias_predication.rb +7 -0
- data/lib/arel/attributes/attribute.rb +10 -1
- data/lib/arel/crud.rb +43 -8
- data/lib/arel/expression.rb +1 -0
- data/lib/arel/factory_methods.rb +35 -0
- data/lib/arel/insert_manager.rb +5 -1
- data/lib/arel/math.rb +19 -0
- data/lib/arel/nodes.rb +32 -42
- data/lib/arel/nodes/and.rb +18 -1
- data/lib/arel/nodes/binary.rb +28 -0
- data/lib/arel/nodes/count.rb +0 -3
- data/lib/arel/nodes/function.rb +13 -2
- data/lib/arel/nodes/infix_operation.rb +43 -0
- data/lib/arel/nodes/join_source.rb +14 -0
- data/lib/arel/nodes/named_function.rb +14 -0
- data/lib/arel/nodes/node.rb +5 -2
- data/lib/arel/nodes/select_core.rb +24 -10
- data/lib/arel/nodes/select_statement.rb +8 -6
- data/lib/arel/nodes/sql_literal.rb +2 -0
- data/lib/arel/nodes/string_join.rb +2 -4
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/{as.rb → terminal.rb} +1 -1
- data/lib/arel/nodes/unary.rb +17 -0
- data/lib/arel/nodes/unqualified_column.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes/with.rb +10 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +6 -24
- data/lib/arel/select_manager.rb +95 -40
- data/lib/arel/table.rb +32 -19
- data/lib/arel/tree_manager.rb +1 -0
- data/lib/arel/update_manager.rb +4 -0
- data/lib/arel/visitors.rb +2 -0
- data/lib/arel/visitors/depth_first.rb +19 -9
- data/lib/arel/visitors/dot.rb +42 -25
- data/lib/arel/visitors/ibm_db.rb +12 -0
- data/lib/arel/visitors/join_sql.rb +2 -23
- data/lib/arel/visitors/mssql.rb +7 -0
- data/lib/arel/visitors/mysql.rb +4 -0
- data/lib/arel/visitors/oracle.rb +2 -2
- data/lib/arel/visitors/postgresql.rb +2 -38
- data/lib/arel/visitors/to_sql.rb +148 -67
- data/test/attributes/test_attribute.rb +3 -3
- data/test/helper.rb +1 -1
- data/test/nodes/test_as.rb +6 -0
- data/test/nodes/test_bin.rb +23 -0
- data/test/nodes/test_named_function.rb +30 -0
- data/test/nodes/test_node.rb +10 -0
- data/test/nodes/test_not.rb +4 -7
- data/test/nodes/test_select_core.rb +23 -14
- data/test/support/fake_record.rb +21 -4
- data/test/test_attributes.rb +8 -0
- data/test/test_crud.rb +6 -12
- data/test/test_factory_methods.rb +34 -0
- data/test/test_insert_manager.rb +19 -0
- data/test/test_select_manager.rb +343 -64
- data/test/test_table.rb +36 -45
- data/test/visitors/test_depth_first.rb +29 -11
- data/test/visitors/test_dot.rb +47 -0
- data/test/visitors/test_ibm_db.rb +27 -0
- data/test/visitors/test_join_sql.rb +14 -7
- data/test/visitors/test_mssql.rb +9 -0
- data/test/visitors/test_oracle.rb +11 -10
- data/test/visitors/test_postgres.rb +12 -0
- data/test/visitors/test_to_sql.rb +80 -17
- metadata +80 -101
- data/lib/arel/nodes/assignment.rb +0 -6
- data/lib/arel/nodes/avg.rb +0 -6
- data/lib/arel/nodes/between.rb +0 -6
- data/lib/arel/nodes/does_not_match.rb +0 -6
- data/lib/arel/nodes/except.rb +0 -7
- data/lib/arel/nodes/exists.rb +0 -7
- data/lib/arel/nodes/greater_than.rb +0 -6
- data/lib/arel/nodes/greater_than_or_equal.rb +0 -6
- data/lib/arel/nodes/group.rb +0 -6
- data/lib/arel/nodes/grouping.rb +0 -6
- data/lib/arel/nodes/having.rb +0 -6
- data/lib/arel/nodes/intersect.rb +0 -7
- data/lib/arel/nodes/join.rb +0 -13
- data/lib/arel/nodes/less_than.rb +0 -6
- data/lib/arel/nodes/less_than_or_equal.rb +0 -6
- data/lib/arel/nodes/limit.rb +0 -7
- data/lib/arel/nodes/lock.rb +0 -6
- data/lib/arel/nodes/matches.rb +0 -6
- data/lib/arel/nodes/max.rb +0 -6
- data/lib/arel/nodes/min.rb +0 -6
- data/lib/arel/nodes/not.rb +0 -6
- data/lib/arel/nodes/not_equal.rb +0 -6
- data/lib/arel/nodes/not_in.rb +0 -6
- data/lib/arel/nodes/offset.rb +0 -7
- data/lib/arel/nodes/on.rb +0 -6
- data/lib/arel/nodes/or.rb +0 -6
- data/lib/arel/nodes/sum.rb +0 -6
- data/lib/arel/nodes/top.rb +0 -6
- data/lib/arel/nodes/union.rb +0 -7
- data/lib/arel/nodes/union_all.rb +0 -7
data/lib/arel/tree_manager.rb
CHANGED
data/lib/arel/update_manager.rb
CHANGED
data/lib/arel/visitors.rb
CHANGED
@@ -10,6 +10,7 @@ require 'arel/visitors/join_sql'
|
|
10
10
|
require 'arel/visitors/where_sql'
|
11
11
|
require 'arel/visitors/order_clauses'
|
12
12
|
require 'arel/visitors/dot'
|
13
|
+
require 'arel/visitors/ibm_db'
|
13
14
|
|
14
15
|
module Arel
|
15
16
|
module Visitors
|
@@ -22,6 +23,7 @@ module Arel
|
|
22
23
|
'oracle_enhanced' => Arel::Visitors::Oracle,
|
23
24
|
'sqlite' => Arel::Visitors::SQLite,
|
24
25
|
'sqlite3' => Arel::Visitors::SQLite,
|
26
|
+
'ibm_db' => Arel::Visitors::IBM_DB,
|
25
27
|
}
|
26
28
|
|
27
29
|
ENGINE_VISITORS = Hash.new do |hash, engine|
|
@@ -28,6 +28,7 @@ module Arel
|
|
28
28
|
def function o
|
29
29
|
visit o.expressions
|
30
30
|
visit o.alias
|
31
|
+
visit o.distinct
|
31
32
|
end
|
32
33
|
alias :visit_Arel_Nodes_Avg :function
|
33
34
|
alias :visit_Arel_Nodes_Exists :function
|
@@ -35,25 +36,28 @@ module Arel
|
|
35
36
|
alias :visit_Arel_Nodes_Min :function
|
36
37
|
alias :visit_Arel_Nodes_Sum :function
|
37
38
|
|
39
|
+
def visit_Arel_Nodes_NamedFunction o
|
40
|
+
visit o.name
|
41
|
+
visit o.expressions
|
42
|
+
visit o.distinct
|
43
|
+
visit o.alias
|
44
|
+
end
|
45
|
+
|
38
46
|
def visit_Arel_Nodes_Count o
|
39
47
|
visit o.expressions
|
40
48
|
visit o.alias
|
41
49
|
visit o.distinct
|
42
50
|
end
|
43
51
|
|
44
|
-
def
|
45
|
-
visit
|
46
|
-
visit o.right
|
47
|
-
visit o.constraint
|
52
|
+
def nary o
|
53
|
+
o.children.each { |child| visit child }
|
48
54
|
end
|
49
|
-
alias :
|
50
|
-
alias :visit_Arel_Nodes_OuterJoin :join
|
55
|
+
alias :visit_Arel_Nodes_And :nary
|
51
56
|
|
52
57
|
def binary o
|
53
58
|
visit o.left
|
54
59
|
visit o.right
|
55
60
|
end
|
56
|
-
alias :visit_Arel_Nodes_And :binary
|
57
61
|
alias :visit_Arel_Nodes_As :binary
|
58
62
|
alias :visit_Arel_Nodes_Assignment :binary
|
59
63
|
alias :visit_Arel_Nodes_Between :binary
|
@@ -63,6 +67,8 @@ module Arel
|
|
63
67
|
alias :visit_Arel_Nodes_GreaterThan :binary
|
64
68
|
alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
|
65
69
|
alias :visit_Arel_Nodes_In :binary
|
70
|
+
alias :visit_Arel_Nodes_JoinSource :binary
|
71
|
+
alias :visit_Arel_Nodes_InnerJoin :binary
|
66
72
|
alias :visit_Arel_Nodes_LessThan :binary
|
67
73
|
alias :visit_Arel_Nodes_LessThanOrEqual :binary
|
68
74
|
alias :visit_Arel_Nodes_Matches :binary
|
@@ -70,10 +76,14 @@ module Arel
|
|
70
76
|
alias :visit_Arel_Nodes_NotIn :binary
|
71
77
|
alias :visit_Arel_Nodes_Or :binary
|
72
78
|
alias :visit_Arel_Nodes_Ordering :binary
|
73
|
-
alias :
|
79
|
+
alias :visit_Arel_Nodes_OuterJoin :binary
|
74
80
|
alias :visit_Arel_Nodes_TableAlias :binary
|
75
81
|
alias :visit_Arel_Nodes_Values :binary
|
76
82
|
|
83
|
+
def visit_Arel_Nodes_StringJoin o
|
84
|
+
visit o.left
|
85
|
+
end
|
86
|
+
|
77
87
|
def visit_Arel_Attribute o
|
78
88
|
visit o.relation
|
79
89
|
visit o.name
|
@@ -120,7 +130,7 @@ module Arel
|
|
120
130
|
|
121
131
|
def visit_Arel_Nodes_SelectCore o
|
122
132
|
visit o.projections
|
123
|
-
visit o.
|
133
|
+
visit o.source
|
124
134
|
visit o.wheres
|
125
135
|
visit o.groups
|
126
136
|
visit o.having
|
data/lib/arel/visitors/dot.rb
CHANGED
@@ -36,15 +36,7 @@ module Arel
|
|
36
36
|
def visit_Arel_Nodes_TableAlias o
|
37
37
|
visit_edge o, "name"
|
38
38
|
visit_edge o, "relation"
|
39
|
-
visit_edge o, "columns"
|
40
|
-
end
|
41
|
-
|
42
|
-
def visit_Arel_Nodes_Sum o
|
43
|
-
visit_edge o, "expressions"
|
44
|
-
visit_edge o, "alias"
|
45
39
|
end
|
46
|
-
alias :visit_Arel_Nodes_Max :visit_Arel_Nodes_Sum
|
47
|
-
alias :visit_Arel_Nodes_Avg :visit_Arel_Nodes_Sum
|
48
40
|
|
49
41
|
def visit_Arel_Nodes_Count o
|
50
42
|
visit_edge o, "expressions"
|
@@ -57,13 +49,11 @@ module Arel
|
|
57
49
|
|
58
50
|
def visit_Arel_Nodes_StringJoin o
|
59
51
|
visit_edge o, "left"
|
60
|
-
visit_edge o, "right"
|
61
52
|
end
|
62
53
|
|
63
54
|
def visit_Arel_Nodes_InnerJoin o
|
64
55
|
visit_edge o, "left"
|
65
56
|
visit_edge o, "right"
|
66
|
-
visit_edge o, "constraint"
|
67
57
|
end
|
68
58
|
alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin
|
69
59
|
|
@@ -85,6 +75,24 @@ module Arel
|
|
85
75
|
alias :visit_Arel_Nodes_Top :unary
|
86
76
|
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
|
87
77
|
|
78
|
+
def function o
|
79
|
+
visit_edge o, "expressions"
|
80
|
+
visit_edge o, "distinct"
|
81
|
+
visit_edge o, "alias"
|
82
|
+
end
|
83
|
+
alias :visit_Arel_Nodes_Exists :function
|
84
|
+
alias :visit_Arel_Nodes_Min :function
|
85
|
+
alias :visit_Arel_Nodes_Max :function
|
86
|
+
alias :visit_Arel_Nodes_Avg :function
|
87
|
+
alias :visit_Arel_Nodes_Sum :function
|
88
|
+
|
89
|
+
def visit_Arel_Nodes_NamedFunction o
|
90
|
+
visit_edge o, "name"
|
91
|
+
visit_edge o, "expressions"
|
92
|
+
visit_edge o, "distinct"
|
93
|
+
visit_edge o, "alias"
|
94
|
+
end
|
95
|
+
|
88
96
|
def visit_Arel_Nodes_InsertStatement o
|
89
97
|
visit_edge o, "relation"
|
90
98
|
visit_edge o, "columns"
|
@@ -92,7 +100,7 @@ module Arel
|
|
92
100
|
end
|
93
101
|
|
94
102
|
def visit_Arel_Nodes_SelectCore o
|
95
|
-
visit_edge o, "
|
103
|
+
visit_edge o, "source"
|
96
104
|
visit_edge o, "projections"
|
97
105
|
visit_edge o, "wheres"
|
98
106
|
end
|
@@ -125,23 +133,32 @@ module Arel
|
|
125
133
|
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
|
126
134
|
alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
|
127
135
|
|
128
|
-
def
|
136
|
+
def nary o
|
137
|
+
o.children.each_with_index do |x,i|
|
138
|
+
edge(i) { visit x }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
alias :visit_Arel_Nodes_And :nary
|
142
|
+
|
143
|
+
def binary o
|
129
144
|
visit_edge o, "left"
|
130
145
|
visit_edge o, "right"
|
131
146
|
end
|
132
|
-
alias :
|
133
|
-
alias :
|
134
|
-
alias :
|
135
|
-
alias :
|
136
|
-
alias :
|
137
|
-
alias :
|
138
|
-
alias :
|
139
|
-
alias :
|
140
|
-
alias :
|
141
|
-
alias :
|
142
|
-
alias :
|
143
|
-
alias :
|
144
|
-
alias :
|
147
|
+
alias :visit_Arel_Nodes_As :binary
|
148
|
+
alias :visit_Arel_Nodes_Assignment :binary
|
149
|
+
alias :visit_Arel_Nodes_Between :binary
|
150
|
+
alias :visit_Arel_Nodes_DoesNotMatch :binary
|
151
|
+
alias :visit_Arel_Nodes_Equality :binary
|
152
|
+
alias :visit_Arel_Nodes_GreaterThan :binary
|
153
|
+
alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
|
154
|
+
alias :visit_Arel_Nodes_In :binary
|
155
|
+
alias :visit_Arel_Nodes_JoinSource :binary
|
156
|
+
alias :visit_Arel_Nodes_LessThan :binary
|
157
|
+
alias :visit_Arel_Nodes_LessThanOrEqual :binary
|
158
|
+
alias :visit_Arel_Nodes_Matches :binary
|
159
|
+
alias :visit_Arel_Nodes_NotEqual :binary
|
160
|
+
alias :visit_Arel_Nodes_NotIn :binary
|
161
|
+
alias :visit_Arel_Nodes_Or :binary
|
145
162
|
|
146
163
|
def visit_String o
|
147
164
|
@node_stack.last.fields << o
|
@@ -8,32 +8,11 @@ module Arel
|
|
8
8
|
#
|
9
9
|
# This visitor is used in SelectManager#join_sql and is for backwards
|
10
10
|
# compatibility with Arel V1.0
|
11
|
-
|
11
|
+
module JoinSql
|
12
12
|
private
|
13
13
|
|
14
14
|
def visit_Arel_Nodes_SelectCore o
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def visit_Arel_Nodes_StringJoin o
|
19
|
-
[
|
20
|
-
(visit o.left if Nodes::Join === o.left),
|
21
|
-
visit(o.right)
|
22
|
-
].compact.join ' '
|
23
|
-
end
|
24
|
-
|
25
|
-
def visit_Arel_Nodes_OuterJoin o
|
26
|
-
[
|
27
|
-
(visit o.left if Nodes::Join === o.left),
|
28
|
-
"LEFT OUTER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
|
29
|
-
].compact.join ' '
|
30
|
-
end
|
31
|
-
|
32
|
-
def visit_Arel_Nodes_InnerJoin o
|
33
|
-
[
|
34
|
-
(visit o.left if Nodes::Join === o.left),
|
35
|
-
"INNER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
|
36
|
-
].compact.join ' '
|
15
|
+
o.source.right.map { |j| visit j }.join ' '
|
37
16
|
end
|
38
17
|
end
|
39
18
|
end
|
data/lib/arel/visitors/mssql.rb
CHANGED
data/lib/arel/visitors/mysql.rb
CHANGED
data/lib/arel/visitors/oracle.rb
CHANGED
@@ -25,7 +25,7 @@ module Arel
|
|
25
25
|
SELECT * FROM (
|
26
26
|
SELECT raw_sql_.*, rownum raw_rnum_
|
27
27
|
FROM (#{sql}) raw_sql_
|
28
|
-
WHERE rownum <= #{offset.
|
28
|
+
WHERE rownum <= #{offset.expr.to_i + limit}
|
29
29
|
)
|
30
30
|
WHERE #{visit offset}
|
31
31
|
eosql
|
@@ -58,7 +58,7 @@ module Arel
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def visit_Arel_Nodes_Offset o
|
61
|
-
"raw_rnum_ > #{visit o.
|
61
|
+
"raw_rnum_ > #{visit o.expr}"
|
62
62
|
end
|
63
63
|
|
64
64
|
def visit_Arel_Nodes_Except o
|
@@ -6,25 +6,6 @@ module Arel
|
|
6
6
|
visit o.expr
|
7
7
|
end
|
8
8
|
|
9
|
-
def visit_Arel_Nodes_SelectStatement o
|
10
|
-
if !o.orders.empty? && using_distinct_on?(o)
|
11
|
-
subquery = o.dup
|
12
|
-
subquery.orders = []
|
13
|
-
subquery.limit = nil
|
14
|
-
subquery.offset = nil
|
15
|
-
|
16
|
-
sql = super(subquery)
|
17
|
-
[
|
18
|
-
"SELECT * FROM (#{sql}) AS id_list",
|
19
|
-
"ORDER BY #{aliased_orders(o.orders).join(', ')}",
|
20
|
-
(visit(o.limit) if o.limit),
|
21
|
-
(visit(o.offset) if o.offset),
|
22
|
-
].compact.join ' '
|
23
|
-
else
|
24
|
-
super
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
9
|
def visit_Arel_Nodes_Matches o
|
29
10
|
"#{visit o.left} ILIKE #{visit o.right}"
|
30
11
|
end
|
@@ -33,25 +14,8 @@ module Arel
|
|
33
14
|
"#{visit o.left} NOT ILIKE #{visit o.right}"
|
34
15
|
end
|
35
16
|
|
36
|
-
def
|
37
|
-
o.
|
38
|
-
core.projections.any? do |projection|
|
39
|
-
/DISTINCT ON/ === projection
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def aliased_orders orders
|
45
|
-
#orders = o.orders.map { |x| visit x }.join(', ').split(',')
|
46
|
-
list = []
|
47
|
-
orders.each_with_index do |o,i|
|
48
|
-
list <<
|
49
|
-
[
|
50
|
-
"id_list.alias_#{i}",
|
51
|
-
(o.index(/desc/i) && 'DESC')
|
52
|
-
].compact.join(' ')
|
53
|
-
end
|
54
|
-
list
|
17
|
+
def visit_Arel_Nodes_DistinctOn o
|
18
|
+
"DISTINCT ON ( #{visit o.expr} )"
|
55
19
|
end
|
56
20
|
end
|
57
21
|
end
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -7,13 +7,16 @@ module Arel
|
|
7
7
|
def initialize engine
|
8
8
|
@engine = engine
|
9
9
|
@connection = nil
|
10
|
+
@pool = nil
|
11
|
+
@last_column = nil
|
10
12
|
@quoted_tables = {}
|
11
13
|
@quoted_columns = {}
|
12
14
|
end
|
13
15
|
|
14
16
|
def accept object
|
15
|
-
|
16
|
-
@engine.connection_pool
|
17
|
+
@last_column = nil
|
18
|
+
@pool = @engine.connection_pool
|
19
|
+
@pool.with_connection do |conn|
|
17
20
|
@connection = conn
|
18
21
|
super
|
19
22
|
end
|
@@ -27,24 +30,39 @@ module Arel
|
|
27
30
|
].compact.join ' '
|
28
31
|
end
|
29
32
|
|
33
|
+
# FIXME: we should probably have a 2-pass visitor for this
|
34
|
+
def build_subselect key, o
|
35
|
+
stmt = Nodes::SelectStatement.new
|
36
|
+
core = stmt.cores.first
|
37
|
+
core.froms = o.relation
|
38
|
+
core.wheres = o.wheres
|
39
|
+
core.projections = [key]
|
40
|
+
stmt.limit = o.limit
|
41
|
+
stmt.orders = o.orders
|
42
|
+
stmt
|
43
|
+
end
|
44
|
+
|
30
45
|
def visit_Arel_Nodes_UpdateStatement o
|
31
46
|
if o.orders.empty? && o.limit.nil?
|
32
47
|
wheres = o.wheres
|
33
48
|
else
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
49
|
+
key = o.key
|
50
|
+
unless key
|
51
|
+
warn(<<-eowarn) if $VERBOSE
|
52
|
+
(#{caller.first}) Using UpdateManager without setting UpdateManager#key is
|
53
|
+
deprecated and support will be removed in ARel 3.0.0. Please set the primary
|
54
|
+
key on UpdateManager using UpdateManager#key=
|
55
|
+
eowarn
|
56
|
+
key = o.relation.primary_key
|
57
|
+
end
|
58
|
+
|
59
|
+
wheres = [Nodes::In.new(key, [build_subselect(key, o)])]
|
42
60
|
end
|
43
61
|
|
44
62
|
[
|
45
63
|
"UPDATE #{visit o.relation}",
|
46
64
|
("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
|
47
|
-
("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?)
|
65
|
+
("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?),
|
48
66
|
].compact.join ' '
|
49
67
|
end
|
50
68
|
|
@@ -53,26 +71,48 @@ module Arel
|
|
53
71
|
"INSERT INTO #{visit o.relation}",
|
54
72
|
|
55
73
|
("(#{o.columns.map { |x|
|
56
|
-
|
57
|
-
|
74
|
+
quote_column_name x.name
|
75
|
+
}.join ', '})" unless o.columns.empty?),
|
58
76
|
|
59
77
|
(visit o.values if o.values),
|
60
78
|
].compact.join ' '
|
61
79
|
end
|
62
80
|
|
63
81
|
def visit_Arel_Nodes_Exists o
|
64
|
-
"EXISTS (#{visit o.
|
82
|
+
"EXISTS (#{visit o.expressions})#{
|
65
83
|
o.alias ? " AS #{visit o.alias}" : ''}"
|
66
84
|
end
|
67
85
|
|
86
|
+
def table_exists? name
|
87
|
+
@pool.table_exists? name
|
88
|
+
end
|
89
|
+
|
90
|
+
def column_for attr
|
91
|
+
name = attr.name.to_s
|
92
|
+
table = attr.relation.table_name
|
93
|
+
|
94
|
+
return nil unless table_exists? table
|
95
|
+
|
96
|
+
column_cache[table][name]
|
97
|
+
end
|
98
|
+
|
99
|
+
def column_cache
|
100
|
+
@pool.columns_hash
|
101
|
+
end
|
102
|
+
|
68
103
|
def visit_Arel_Nodes_Values o
|
69
|
-
"VALUES (#{o.expressions.zip(o.columns).map { |value,
|
70
|
-
|
104
|
+
"VALUES (#{o.expressions.zip(o.columns).map { |value, attr|
|
105
|
+
if Nodes::SqlLiteral === value
|
106
|
+
visit_Arel_Nodes_SqlLiteral value
|
107
|
+
else
|
108
|
+
quote(value, attr && column_for(attr))
|
109
|
+
end
|
71
110
|
}.join ', '})"
|
72
111
|
end
|
73
112
|
|
74
113
|
def visit_Arel_Nodes_SelectStatement o
|
75
114
|
[
|
115
|
+
(visit(o.with) if o.with),
|
76
116
|
o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
|
77
117
|
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
|
78
118
|
(visit(o.limit) if o.limit),
|
@@ -85,14 +125,51 @@ module Arel
|
|
85
125
|
[
|
86
126
|
"SELECT",
|
87
127
|
(visit(o.top) if o.top),
|
88
|
-
|
89
|
-
("
|
128
|
+
(visit(o.set_quantifier) if o.set_quantifier),
|
129
|
+
("#{o.projections.map { |x| visit x }.join ', '}" unless o.projections.empty?),
|
130
|
+
(visit(o.source) if o.source),
|
90
131
|
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
|
91
132
|
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
|
92
133
|
(visit(o.having) if o.having),
|
93
134
|
].compact.join ' '
|
94
135
|
end
|
95
136
|
|
137
|
+
def visit_Arel_Nodes_Bin o
|
138
|
+
visit o.expr
|
139
|
+
end
|
140
|
+
|
141
|
+
def visit_Arel_Nodes_Distinct o
|
142
|
+
'DISTINCT'
|
143
|
+
end
|
144
|
+
|
145
|
+
def visit_Arel_Nodes_DistinctOn o
|
146
|
+
raise NotImplementedError, 'DISTINCT ON not implemented for this db'
|
147
|
+
end
|
148
|
+
|
149
|
+
def visit_Arel_Nodes_With o
|
150
|
+
"WITH #{o.children.map { |x| visit x }.join(', ')}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def visit_Arel_Nodes_WithRecursive o
|
154
|
+
"WITH RECURSIVE #{o.children.map { |x| visit x }.join(', ')}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def visit_Arel_Nodes_Union o
|
158
|
+
"( #{visit o.left} UNION #{visit o.right} )"
|
159
|
+
end
|
160
|
+
|
161
|
+
def visit_Arel_Nodes_UnionAll o
|
162
|
+
"( #{visit o.left} UNION ALL #{visit o.right} )"
|
163
|
+
end
|
164
|
+
|
165
|
+
def visit_Arel_Nodes_Intersect o
|
166
|
+
"( #{visit o.left} INTERSECT #{visit o.right} )"
|
167
|
+
end
|
168
|
+
|
169
|
+
def visit_Arel_Nodes_Except o
|
170
|
+
"( #{visit o.left} EXCEPT #{visit o.right} )"
|
171
|
+
end
|
172
|
+
|
96
173
|
def visit_Arel_Nodes_Having o
|
97
174
|
"HAVING #{visit o.expr}"
|
98
175
|
end
|
@@ -127,6 +204,12 @@ module Arel
|
|
127
204
|
visit o.expr
|
128
205
|
end
|
129
206
|
|
207
|
+
def visit_Arel_Nodes_NamedFunction o
|
208
|
+
"#{o.name}(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
209
|
+
visit x
|
210
|
+
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
211
|
+
end
|
212
|
+
|
130
213
|
def visit_Arel_Nodes_Count o
|
131
214
|
"COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
132
215
|
visit x
|
@@ -185,16 +268,26 @@ module Arel
|
|
185
268
|
"#{visit o.left} NOT LIKE #{visit o.right}"
|
186
269
|
end
|
187
270
|
|
271
|
+
def visit_Arel_Nodes_JoinSource o
|
272
|
+
return unless o.left || !o.right.empty?
|
273
|
+
|
274
|
+
[
|
275
|
+
"FROM",
|
276
|
+
(visit(o.left) if o.left),
|
277
|
+
o.right.map { |j| visit j }.join(' ')
|
278
|
+
].compact.join ' '
|
279
|
+
end
|
280
|
+
|
188
281
|
def visit_Arel_Nodes_StringJoin o
|
189
|
-
|
282
|
+
visit o.left
|
190
283
|
end
|
191
284
|
|
192
285
|
def visit_Arel_Nodes_OuterJoin o
|
193
|
-
"
|
286
|
+
"LEFT OUTER JOIN #{visit o.left} #{visit o.right}"
|
194
287
|
end
|
195
288
|
|
196
289
|
def visit_Arel_Nodes_InnerJoin o
|
197
|
-
"
|
290
|
+
"INNER JOIN #{visit o.left} #{visit o.right if o.right}"
|
198
291
|
end
|
199
292
|
|
200
293
|
def visit_Arel_Nodes_On o
|
@@ -205,22 +298,6 @@ module Arel
|
|
205
298
|
"NOT (#{visit o.expr})"
|
206
299
|
end
|
207
300
|
|
208
|
-
def visit_Arel_Nodes_Union o
|
209
|
-
"( #{visit o.left} UNION #{visit o.right} )"
|
210
|
-
end
|
211
|
-
|
212
|
-
def visit_Arel_Nodes_UnionAll o
|
213
|
-
"( #{visit o.left} UNION ALL #{visit o.right} )"
|
214
|
-
end
|
215
|
-
|
216
|
-
def visit_Arel_Nodes_Intersect o
|
217
|
-
"( #{visit o.left} INTERSECT #{visit o.right} )"
|
218
|
-
end
|
219
|
-
|
220
|
-
def visit_Arel_Nodes_Except o
|
221
|
-
"( #{visit o.left} EXCEPT #{visit o.right} )"
|
222
|
-
end
|
223
|
-
|
224
301
|
def visit_Arel_Table o
|
225
302
|
if o.table_alias
|
226
303
|
"#{quote_table_name o.name} #{quote_table_name o.table_alias}"
|
@@ -230,15 +307,15 @@ module Arel
|
|
230
307
|
end
|
231
308
|
|
232
309
|
def visit_Arel_Nodes_In o
|
233
|
-
|
310
|
+
"#{visit o.left} IN (#{visit o.right})"
|
234
311
|
end
|
235
312
|
|
236
313
|
def visit_Arel_Nodes_NotIn o
|
237
|
-
|
314
|
+
"#{visit o.left} NOT IN (#{visit o.right})"
|
238
315
|
end
|
239
316
|
|
240
317
|
def visit_Arel_Nodes_And o
|
241
|
-
|
318
|
+
o.children.map { |x| visit x }.join ' AND '
|
242
319
|
end
|
243
320
|
|
244
321
|
def visit_Arel_Nodes_Or o
|
@@ -246,7 +323,7 @@ module Arel
|
|
246
323
|
end
|
247
324
|
|
248
325
|
def visit_Arel_Nodes_Assignment o
|
249
|
-
right = quote(o.right, o.left
|
326
|
+
right = quote(o.right, column_for(o.left))
|
250
327
|
"#{visit o.left} = #{right}"
|
251
328
|
end
|
252
329
|
|
@@ -279,7 +356,7 @@ module Arel
|
|
279
356
|
end
|
280
357
|
|
281
358
|
def visit_Arel_Attributes_Attribute o
|
282
|
-
|
359
|
+
@last_column = column_for o
|
283
360
|
join_name = o.relation.table_alias || o.relation.name
|
284
361
|
"#{quote_table_name join_name}.#{quote_column_name o.name}"
|
285
362
|
end
|
@@ -290,34 +367,38 @@ module Arel
|
|
290
367
|
alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
|
291
368
|
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
|
292
369
|
|
293
|
-
def
|
294
|
-
alias :visit_Arel_Nodes_SqlLiteral :visit_Fixnum
|
295
|
-
alias :visit_Arel_SqlLiteral :visit_Fixnum # This is deprecated
|
296
|
-
alias :visit_Bignum :visit_Fixnum
|
370
|
+
def literal o; o end
|
297
371
|
|
298
|
-
|
372
|
+
alias :visit_Arel_Nodes_SqlLiteral :literal
|
373
|
+
alias :visit_Arel_SqlLiteral :literal # This is deprecated
|
374
|
+
alias :visit_Bignum :literal
|
375
|
+
alias :visit_Fixnum :literal
|
299
376
|
|
300
|
-
def last_column
|
301
|
-
|
302
|
-
|
377
|
+
def quoted o; quote(o, @last_column) end
|
378
|
+
|
379
|
+
alias :visit_ActiveSupport_Multibyte_Chars :quoted
|
380
|
+
alias :visit_ActiveSupport_StringInquirer :quoted
|
381
|
+
alias :visit_BigDecimal :quoted
|
382
|
+
alias :visit_Class :quoted
|
383
|
+
alias :visit_Date :quoted
|
384
|
+
alias :visit_DateTime :quoted
|
385
|
+
alias :visit_FalseClass :quoted
|
386
|
+
alias :visit_Float :quoted
|
387
|
+
alias :visit_Hash :quoted
|
388
|
+
alias :visit_NilClass :quoted
|
389
|
+
alias :visit_String :quoted
|
390
|
+
alias :visit_Symbol :quoted
|
391
|
+
alias :visit_Time :quoted
|
392
|
+
alias :visit_TrueClass :quoted
|
303
393
|
|
304
|
-
def
|
305
|
-
|
394
|
+
def visit_Arel_Nodes_InfixOperation o
|
395
|
+
"#{visit o.left} #{o.operator} #{visit o.right}"
|
306
396
|
end
|
307
397
|
|
308
|
-
alias :
|
309
|
-
alias :
|
310
|
-
alias :
|
311
|
-
alias :
|
312
|
-
alias :visit_FalseClass :visit_String
|
313
|
-
alias :visit_Float :visit_String
|
314
|
-
alias :visit_Hash :visit_String
|
315
|
-
alias :visit_Symbol :visit_String
|
316
|
-
alias :visit_Time :visit_String
|
317
|
-
alias :visit_TrueClass :visit_String
|
318
|
-
alias :visit_NilClass :visit_String
|
319
|
-
alias :visit_ActiveSupport_StringInquirer :visit_String
|
320
|
-
alias :visit_Class :visit_String
|
398
|
+
alias :visit_Arel_Nodes_Addition :visit_Arel_Nodes_InfixOperation
|
399
|
+
alias :visit_Arel_Nodes_Subtraction :visit_Arel_Nodes_InfixOperation
|
400
|
+
alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation
|
401
|
+
alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation
|
321
402
|
|
322
403
|
def visit_Array o
|
323
404
|
o.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
|
@@ -328,11 +409,11 @@ module Arel
|
|
328
409
|
end
|
329
410
|
|
330
411
|
def quote_table_name name
|
331
|
-
@quoted_tables[name] ||= @connection.quote_table_name(name)
|
412
|
+
@quoted_tables[name] ||= Arel::Nodes::SqlLiteral === name ? name : @connection.quote_table_name(name)
|
332
413
|
end
|
333
414
|
|
334
415
|
def quote_column_name name
|
335
|
-
@quoted_columns[name] ||= @connection.quote_column_name(name)
|
416
|
+
@quoted_columns[name] ||= Arel::Nodes::SqlLiteral === name ? name : @connection.quote_column_name(name)
|
336
417
|
end
|
337
418
|
end
|
338
419
|
end
|