arel 2.0.10 → 2.1.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/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
|