arel 1.0.1 → 2.0.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/MIT-LICENSE.txt +20 -0
- data/Manifest.txt +105 -0
- data/README.markdown +12 -32
- data/Rakefile +17 -0
- data/arel.gemspec +39 -0
- data/lib/arel.rb +30 -9
- data/lib/arel/attributes.rb +20 -0
- data/lib/arel/attributes/attribute.rb +190 -0
- data/lib/arel/compatibility/wheres.rb +33 -0
- data/lib/arel/crud.rb +37 -0
- data/lib/arel/delete_manager.rb +22 -0
- data/lib/arel/deprecated.rb +4 -0
- data/lib/arel/expression.rb +4 -0
- data/lib/arel/expressions.rb +23 -0
- data/lib/arel/insert_manager.rb +34 -0
- data/lib/arel/nodes.rb +44 -0
- data/lib/arel/nodes/and.rb +6 -0
- data/lib/arel/nodes/assignment.rb +6 -0
- data/lib/arel/nodes/avg.rb +6 -0
- data/lib/arel/nodes/between.rb +6 -0
- data/lib/arel/nodes/binary.rb +12 -0
- data/lib/arel/nodes/count.rb +13 -0
- data/lib/arel/nodes/delete_statement.rb +17 -0
- data/lib/arel/nodes/does_not_match.rb +6 -0
- data/lib/arel/nodes/equality.rb +9 -0
- data/lib/arel/nodes/exists.rb +11 -0
- data/lib/arel/nodes/function.rb +18 -0
- data/lib/arel/nodes/greater_than.rb +6 -0
- data/lib/arel/nodes/greater_than_or_equal.rb +6 -0
- data/lib/arel/nodes/group.rb +11 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/having.rb +11 -0
- data/lib/arel/nodes/in.rb +6 -0
- data/lib/arel/nodes/inner_join.rb +6 -0
- data/lib/arel/nodes/insert_statement.rb +19 -0
- data/lib/arel/nodes/join.rb +13 -0
- data/lib/arel/nodes/less_than.rb +6 -0
- data/lib/arel/nodes/less_than_or_equal.rb +6 -0
- data/lib/arel/nodes/lock.rb +6 -0
- data/lib/arel/nodes/matches.rb +6 -0
- data/lib/arel/nodes/max.rb +6 -0
- data/lib/arel/nodes/min.rb +6 -0
- data/lib/arel/nodes/node.rb +30 -0
- data/lib/arel/nodes/not_equal.rb +6 -0
- data/lib/arel/nodes/not_in.rb +6 -0
- data/lib/arel/nodes/offset.rb +11 -0
- data/lib/arel/nodes/on.rb +11 -0
- data/lib/arel/nodes/or.rb +6 -0
- data/lib/arel/nodes/ordering.rb +19 -0
- data/lib/arel/nodes/outer_join.rb +6 -0
- data/lib/arel/nodes/select_core.rb +25 -0
- data/lib/arel/nodes/select_statement.rb +22 -0
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/sum.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +21 -0
- data/lib/arel/nodes/unqualified_column.rb +19 -0
- data/lib/arel/nodes/update_statement.rb +21 -0
- data/lib/arel/nodes/values.rb +12 -0
- data/lib/arel/relation.rb +6 -0
- data/lib/arel/select_manager.rb +203 -0
- data/lib/arel/sql/engine.rb +10 -0
- data/lib/arel/sql_literal.rb +1 -10
- data/lib/arel/table.rb +126 -0
- data/lib/arel/tree_manager.rb +26 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors.rb +30 -0
- data/lib/arel/visitors/dot.rb +233 -0
- data/lib/arel/visitors/join_sql.rb +38 -0
- data/lib/arel/visitors/mysql.rb +16 -0
- data/lib/arel/visitors/oracle.rb +69 -0
- data/lib/arel/visitors/order_clauses.rb +9 -0
- data/lib/arel/visitors/postgresql.rb +54 -0
- data/lib/arel/visitors/to_sql.rb +301 -0
- data/lib/arel/visitors/where_sql.rb +9 -0
- data/spec/activerecord_compat_spec.rb +18 -0
- data/spec/attributes/attribute_spec.rb +648 -0
- data/spec/attributes_spec.rb +33 -6
- data/spec/crud_spec.rb +69 -0
- data/spec/delete_manager_spec.rb +53 -0
- data/spec/insert_manager_spec.rb +141 -0
- data/spec/nodes/count_spec.rb +18 -0
- data/spec/nodes/delete_statement_spec.rb +15 -0
- data/spec/nodes/equality_spec.rb +72 -0
- data/spec/nodes/insert_statement_spec.rb +18 -0
- data/spec/nodes/or_spec.rb +20 -0
- data/spec/nodes/select_core_spec.rb +21 -0
- data/spec/nodes/select_statement_spec.rb +14 -0
- data/spec/nodes/sql_literal_spec.rb +26 -0
- data/spec/nodes/sum_spec.rb +12 -0
- data/spec/nodes/update_statement_spec.rb +18 -0
- data/spec/select_manager_spec.rb +581 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +6 -21
- data/spec/support/fake_record.rb +89 -0
- data/spec/support/shared/tree_manager_shared.rb +9 -0
- data/spec/table_spec.rb +176 -0
- data/spec/update_manager_spec.rb +89 -0
- data/spec/visitors/join_sql_spec.rb +35 -0
- data/spec/visitors/oracle_spec.rb +111 -0
- data/spec/visitors/to_sql_spec.rb +134 -0
- metadata +160 -260
- data/lib/arel/algebra.rb +0 -10
- data/lib/arel/algebra/attributes.rb +0 -7
- data/lib/arel/algebra/attributes/attribute.rb +0 -304
- data/lib/arel/algebra/attributes/boolean.rb +0 -21
- data/lib/arel/algebra/attributes/decimal.rb +0 -9
- data/lib/arel/algebra/attributes/float.rb +0 -9
- data/lib/arel/algebra/attributes/integer.rb +0 -10
- data/lib/arel/algebra/attributes/string.rb +0 -10
- data/lib/arel/algebra/attributes/time.rb +0 -6
- data/lib/arel/algebra/core_extensions.rb +0 -3
- data/lib/arel/algebra/core_extensions/hash.rb +0 -7
- data/lib/arel/algebra/core_extensions/object.rb +0 -13
- data/lib/arel/algebra/core_extensions/symbol.rb +0 -9
- data/lib/arel/algebra/expression.rb +0 -56
- data/lib/arel/algebra/header.rb +0 -66
- data/lib/arel/algebra/ordering.rb +0 -31
- data/lib/arel/algebra/predicates.rb +0 -306
- data/lib/arel/algebra/relations.rb +0 -16
- data/lib/arel/algebra/relations/operations/from.rb +0 -14
- data/lib/arel/algebra/relations/operations/group.rb +0 -14
- data/lib/arel/algebra/relations/operations/having.rb +0 -14
- data/lib/arel/algebra/relations/operations/join.rb +0 -103
- data/lib/arel/algebra/relations/operations/lock.rb +0 -10
- data/lib/arel/algebra/relations/operations/order.rb +0 -23
- data/lib/arel/algebra/relations/operations/project.rb +0 -20
- data/lib/arel/algebra/relations/operations/skip.rb +0 -14
- data/lib/arel/algebra/relations/operations/take.rb +0 -18
- data/lib/arel/algebra/relations/operations/where.rb +0 -24
- data/lib/arel/algebra/relations/relation.rb +0 -205
- data/lib/arel/algebra/relations/row.rb +0 -29
- data/lib/arel/algebra/relations/utilities/compound.rb +0 -55
- data/lib/arel/algebra/relations/utilities/externalization.rb +0 -26
- data/lib/arel/algebra/relations/utilities/nil.rb +0 -7
- data/lib/arel/algebra/relations/writes.rb +0 -47
- data/lib/arel/algebra/value.rb +0 -53
- data/lib/arel/engines.rb +0 -2
- data/lib/arel/engines/memory.rb +0 -2
- data/lib/arel/engines/memory/engine.rb +0 -10
- data/lib/arel/engines/memory/relations.rb +0 -2
- data/lib/arel/engines/memory/relations/array.rb +0 -37
- data/lib/arel/engines/memory/relations/operations.rb +0 -9
- data/lib/arel/engines/sql.rb +0 -6
- data/lib/arel/engines/sql/attributes.rb +0 -45
- data/lib/arel/engines/sql/christener.rb +0 -20
- data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +0 -48
- data/lib/arel/engines/sql/compilers/mysql_compiler.rb +0 -11
- data/lib/arel/engines/sql/compilers/oracle_compiler.rb +0 -106
- data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +0 -50
- data/lib/arel/engines/sql/compilers/sqlite_compiler.rb +0 -9
- data/lib/arel/engines/sql/core_extensions.rb +0 -4
- data/lib/arel/engines/sql/core_extensions/array.rb +0 -24
- data/lib/arel/engines/sql/core_extensions/nil_class.rb +0 -15
- data/lib/arel/engines/sql/core_extensions/object.rb +0 -19
- data/lib/arel/engines/sql/core_extensions/range.rb +0 -19
- data/lib/arel/engines/sql/engine.rb +0 -47
- data/lib/arel/engines/sql/formatters.rb +0 -138
- data/lib/arel/engines/sql/relations.rb +0 -3
- data/lib/arel/engines/sql/relations/compiler.rb +0 -153
- data/lib/arel/engines/sql/relations/table.rb +0 -100
- data/lib/arel/engines/sql/relations/utilities/nil.rb +0 -6
- data/lib/arel/recursion/base_case.rb +0 -13
- data/lib/arel/session.rb +0 -35
- data/lib/arel/version.rb +0 -3
- data/spec/algebra/unit/predicates/binary_spec.rb +0 -35
- data/spec/algebra/unit/predicates/equality_spec.rb +0 -29
- data/spec/algebra/unit/predicates/in_spec.rb +0 -12
- data/spec/algebra/unit/predicates/inequality_spec.rb +0 -32
- data/spec/algebra/unit/predicates/predicate_spec.rb +0 -22
- data/spec/algebra/unit/primitives/attribute_spec.rb +0 -175
- data/spec/algebra/unit/primitives/expression_spec.rb +0 -39
- data/spec/algebra/unit/primitives/value_spec.rb +0 -15
- data/spec/algebra/unit/relations/alias_spec.rb +0 -16
- data/spec/algebra/unit/relations/delete_spec.rb +0 -9
- data/spec/algebra/unit/relations/group_spec.rb +0 -10
- data/spec/algebra/unit/relations/insert_spec.rb +0 -9
- data/spec/algebra/unit/relations/join_spec.rb +0 -18
- data/spec/algebra/unit/relations/order_spec.rb +0 -21
- data/spec/algebra/unit/relations/project_spec.rb +0 -34
- data/spec/algebra/unit/relations/relation_spec.rb +0 -241
- data/spec/algebra/unit/relations/skip_spec.rb +0 -10
- data/spec/algebra/unit/relations/table_spec.rb +0 -38
- data/spec/algebra/unit/relations/take_spec.rb +0 -10
- data/spec/algebra/unit/relations/update_spec.rb +0 -9
- data/spec/algebra/unit/relations/where_spec.rb +0 -19
- data/spec/algebra/unit/session/session_spec.rb +0 -84
- data/spec/attributes/boolean_spec.rb +0 -57
- data/spec/attributes/float_spec.rb +0 -119
- data/spec/attributes/header_spec.rb +0 -42
- data/spec/attributes/integer_spec.rb +0 -119
- data/spec/attributes/string_spec.rb +0 -43
- data/spec/attributes/time_spec.rb +0 -24
- data/spec/engines/memory/integration/joins/cross_engine_spec.rb +0 -61
- data/spec/engines/memory/unit/relations/array_spec.rb +0 -33
- data/spec/engines/memory/unit/relations/insert_spec.rb +0 -28
- data/spec/engines/memory/unit/relations/join_spec.rb +0 -32
- data/spec/engines/memory/unit/relations/order_spec.rb +0 -28
- data/spec/engines/memory/unit/relations/project_spec.rb +0 -27
- data/spec/engines/memory/unit/relations/skip_spec.rb +0 -31
- data/spec/engines/memory/unit/relations/take_spec.rb +0 -28
- data/spec/engines/memory/unit/relations/where_spec.rb +0 -43
- data/spec/engines/sql/integration/joins/with_adjacency_spec.rb +0 -258
- data/spec/engines/sql/integration/joins/with_aggregations_spec.rb +0 -221
- data/spec/engines/sql/integration/joins/with_compounds_spec.rb +0 -137
- data/spec/engines/sql/unit/engine_spec.rb +0 -65
- data/spec/engines/sql/unit/predicates/binary_spec.rb +0 -140
- data/spec/engines/sql/unit/predicates/equality_spec.rb +0 -75
- data/spec/engines/sql/unit/predicates/in_spec.rb +0 -179
- data/spec/engines/sql/unit/predicates/noteq_spec.rb +0 -75
- data/spec/engines/sql/unit/predicates/predicates_spec.rb +0 -79
- data/spec/engines/sql/unit/primitives/attribute_spec.rb +0 -36
- data/spec/engines/sql/unit/primitives/expression_spec.rb +0 -28
- data/spec/engines/sql/unit/primitives/literal_spec.rb +0 -43
- data/spec/engines/sql/unit/primitives/value_spec.rb +0 -29
- data/spec/engines/sql/unit/relations/alias_spec.rb +0 -53
- data/spec/engines/sql/unit/relations/delete_spec.rb +0 -83
- data/spec/engines/sql/unit/relations/from_spec.rb +0 -64
- data/spec/engines/sql/unit/relations/group_spec.rb +0 -72
- data/spec/engines/sql/unit/relations/having_spec.rb +0 -78
- data/spec/engines/sql/unit/relations/insert_spec.rb +0 -143
- data/spec/engines/sql/unit/relations/join_spec.rb +0 -180
- data/spec/engines/sql/unit/relations/lock_spec.rb +0 -86
- data/spec/engines/sql/unit/relations/order_spec.rb +0 -161
- data/spec/engines/sql/unit/relations/project_spec.rb +0 -143
- data/spec/engines/sql/unit/relations/skip_spec.rb +0 -41
- data/spec/engines/sql/unit/relations/table_spec.rb +0 -122
- data/spec/engines/sql/unit/relations/take_spec.rb +0 -75
- data/spec/engines/sql/unit/relations/update_spec.rb +0 -203
- data/spec/engines/sql/unit/relations/where_spec.rb +0 -72
- data/spec/relations/join_spec.rb +0 -42
- data/spec/relations/relation_spec.rb +0 -31
- data/spec/shared/relation_spec.rb +0 -255
- data/spec/sql/christener_spec.rb +0 -70
- data/spec/support/connections/mysql_connection.rb +0 -14
- data/spec/support/connections/oracle_connection.rb +0 -17
- data/spec/support/connections/postgresql_connection.rb +0 -13
- data/spec/support/connections/sqlite3_connection.rb +0 -24
- data/spec/support/guards.rb +0 -28
- data/spec/support/matchers/disambiguate_attributes.rb +0 -28
- data/spec/support/matchers/hash_the_same_as.rb +0 -26
- data/spec/support/matchers/have_rows.rb +0 -18
- data/spec/support/model.rb +0 -67
- data/spec/support/schemas/mysql_schema.rb +0 -26
- data/spec/support/schemas/oracle_schema.rb +0 -20
- data/spec/support/schemas/postgresql_schema.rb +0 -26
- data/spec/support/schemas/sqlite3_schema.rb +0 -26
@@ -0,0 +1,38 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
###
|
4
|
+
# This class produces SQL for JOIN clauses but omits the "single-source"
|
5
|
+
# part of the Join grammar:
|
6
|
+
#
|
7
|
+
# http://www.sqlite.org/syntaxdiagrams.html#join-source
|
8
|
+
#
|
9
|
+
# This visitor is used in SelectManager#join_sql and is for backwards
|
10
|
+
# compatibility with Arel V1.0
|
11
|
+
class JoinSql < Arel::Visitors::ToSql
|
12
|
+
def visit_Arel_Nodes_SelectCore o
|
13
|
+
[o.froms].grep(Nodes::Join).map { |x| visit x }.join ', '
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_Arel_Nodes_StringJoin o
|
17
|
+
[
|
18
|
+
(visit o.left if Nodes::Join === o.left),
|
19
|
+
visit(o.right)
|
20
|
+
].compact.join ' '
|
21
|
+
end
|
22
|
+
|
23
|
+
def visit_Arel_Nodes_OuterJoin o
|
24
|
+
[
|
25
|
+
(visit o.left if Nodes::Join === o.left),
|
26
|
+
"LEFT OUTER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
|
27
|
+
].compact.join ' '
|
28
|
+
end
|
29
|
+
|
30
|
+
def visit_Arel_Nodes_InnerJoin o
|
31
|
+
[
|
32
|
+
(visit o.left if Nodes::Join === o.left),
|
33
|
+
"INNER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
|
34
|
+
].compact.join ' '
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class MySQL < Arel::Visitors::ToSql
|
4
|
+
def visit_Arel_Nodes_UpdateStatement o
|
5
|
+
[
|
6
|
+
"UPDATE #{visit o.relation}",
|
7
|
+
("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
|
8
|
+
("WHERE #{o.wheres.map { |x| visit x }.join ' AND '}" unless o.wheres.empty?),
|
9
|
+
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
|
10
|
+
("LIMIT #{o.limit}" if o.limit),
|
11
|
+
].compact.join ' '
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class Oracle < Arel::Visitors::ToSql
|
4
|
+
private
|
5
|
+
|
6
|
+
def visit_Arel_Nodes_SelectStatement o
|
7
|
+
o = order_hacks(o)
|
8
|
+
|
9
|
+
# if need to select first records without ORDER BY and GROUP BY and without DISTINCT
|
10
|
+
# then can use simple ROWNUM in WHERE clause
|
11
|
+
if o.limit && o.orders.empty? && !o.offset && o.cores.first.projections.first !~ /^DISTINCT /
|
12
|
+
o.cores.last.wheres.push Nodes::LessThanOrEqual.new(
|
13
|
+
Nodes::SqlLiteral.new('ROWNUM'), o.limit
|
14
|
+
)
|
15
|
+
o.limit = nil
|
16
|
+
return super
|
17
|
+
end
|
18
|
+
|
19
|
+
if o.limit && o.offset
|
20
|
+
o = o.dup
|
21
|
+
limit = o.limit.to_i
|
22
|
+
offset = o.offset
|
23
|
+
o.limit = nil
|
24
|
+
o.offset = nil
|
25
|
+
sql = super(o)
|
26
|
+
return <<-eosql
|
27
|
+
SELECT * FROM (
|
28
|
+
SELECT raw_sql_.*, rownum raw_rnum_
|
29
|
+
FROM (#{sql}) raw_sql_
|
30
|
+
WHERE rownum <= #{offset.value.to_i + limit}
|
31
|
+
)
|
32
|
+
WHERE #{visit offset}
|
33
|
+
eosql
|
34
|
+
end
|
35
|
+
|
36
|
+
if o.limit
|
37
|
+
o = o.dup
|
38
|
+
limit = o.limit
|
39
|
+
o.limit = nil
|
40
|
+
return "SELECT * FROM (#{super(o)}) WHERE ROWNUM <= #{limit}"
|
41
|
+
end
|
42
|
+
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def visit_Arel_Nodes_Offset o
|
47
|
+
"raw_rnum_ > #{visit o.value}"
|
48
|
+
end
|
49
|
+
|
50
|
+
###
|
51
|
+
# Hacks for the order clauses specific to Oracle
|
52
|
+
def order_hacks o
|
53
|
+
return o if o.orders.empty?
|
54
|
+
return o unless o.cores.any? do |core|
|
55
|
+
core.projections.any? do |projection|
|
56
|
+
/DISTINCT.*FIRST_VALUE/ === projection
|
57
|
+
end
|
58
|
+
end
|
59
|
+
orders = o.orders.map { |x| visit x }.join(', ').split(',')
|
60
|
+
o.orders = []
|
61
|
+
orders.each_with_index do |order, i|
|
62
|
+
o.orders <<
|
63
|
+
Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}")
|
64
|
+
end
|
65
|
+
o
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class PostgreSQL < Arel::Visitors::ToSql
|
4
|
+
private
|
5
|
+
def visit_Arel_Nodes_SelectStatement o
|
6
|
+
if !o.orders.empty? && using_distinct_on?(o)
|
7
|
+
subquery = o.dup
|
8
|
+
subquery.orders = []
|
9
|
+
subquery.limit = nil
|
10
|
+
subquery.offset = nil
|
11
|
+
|
12
|
+
sql = super(subquery)
|
13
|
+
[
|
14
|
+
"SELECT * FROM (#{sql}) AS id_list",
|
15
|
+
"ORDER BY #{aliased_orders(o.orders).join(', ')}",
|
16
|
+
("LIMIT #{o.limit}" if o.limit),
|
17
|
+
(visit(o.offset) if o.offset),
|
18
|
+
].compact.join ' '
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def visit_Arel_Nodes_Matches o
|
25
|
+
"#{visit o.left} ILIKE #{visit o.right}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def visit_Arel_Nodes_DoesNotMatch o
|
29
|
+
"#{visit o.left} NOT ILIKE #{visit o.right}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def using_distinct_on?(o)
|
33
|
+
o.cores.any? do |core|
|
34
|
+
core.projections.any? do |projection|
|
35
|
+
/DISTINCT ON/ === projection
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def aliased_orders orders
|
41
|
+
#orders = o.orders.map { |x| visit x }.join(', ').split(',')
|
42
|
+
list = []
|
43
|
+
orders.each_with_index do |o,i|
|
44
|
+
list <<
|
45
|
+
[
|
46
|
+
"id_list.alias_#{i}",
|
47
|
+
(o.index(/desc/i) && 'DESC')
|
48
|
+
].compact.join(' ')
|
49
|
+
end
|
50
|
+
list
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Arel
|
5
|
+
module Visitors
|
6
|
+
class ToSql
|
7
|
+
def initialize engine
|
8
|
+
@engine = engine
|
9
|
+
@connection = nil
|
10
|
+
@last_column = nil
|
11
|
+
@quoted_tables = {}
|
12
|
+
@quoted_columns = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def accept object
|
16
|
+
@last_column = nil
|
17
|
+
@engine.connection_pool.with_connection do |conn|
|
18
|
+
@connection = conn
|
19
|
+
visit object
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def visit_Arel_Nodes_DeleteStatement o
|
25
|
+
[
|
26
|
+
"DELETE FROM #{visit o.relation}",
|
27
|
+
("WHERE #{o.wheres.map { |x| visit x }.join ' AND '}" unless o.wheres.empty?)
|
28
|
+
].compact.join ' '
|
29
|
+
end
|
30
|
+
|
31
|
+
def visit_Arel_Nodes_UpdateStatement o
|
32
|
+
if o.orders.empty? && o.limit.nil?
|
33
|
+
wheres = o.wheres
|
34
|
+
else
|
35
|
+
stmt = Nodes::SelectStatement.new
|
36
|
+
core = stmt.cores.first
|
37
|
+
core.froms = o.relation
|
38
|
+
core.projections = [o.relation.primary_key]
|
39
|
+
stmt.limit = o.limit
|
40
|
+
stmt.orders = o.orders
|
41
|
+
|
42
|
+
wheres = [Nodes::In.new(o.relation.primary_key, [stmt])]
|
43
|
+
end
|
44
|
+
|
45
|
+
[
|
46
|
+
"UPDATE #{visit o.relation}",
|
47
|
+
("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
|
48
|
+
("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?)
|
49
|
+
].compact.join ' '
|
50
|
+
end
|
51
|
+
def visit_Arel_Nodes_InsertStatement o
|
52
|
+
[
|
53
|
+
"INSERT INTO #{visit o.relation}",
|
54
|
+
|
55
|
+
("(#{o.columns.map { |x|
|
56
|
+
quote_column_name x.name
|
57
|
+
}.join ', '})" unless o.columns.empty?),
|
58
|
+
|
59
|
+
(visit o.values if o.values),
|
60
|
+
].compact.join ' '
|
61
|
+
end
|
62
|
+
|
63
|
+
def visit_Arel_Nodes_Exists o
|
64
|
+
"EXISTS (#{visit o.select_stmt})"
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_Arel_Nodes_Values o
|
68
|
+
"VALUES (#{o.expressions.zip(o.columns).map { |value, column|
|
69
|
+
quote(value, column && column.column)
|
70
|
+
}.join ', '})"
|
71
|
+
end
|
72
|
+
|
73
|
+
def visit_Arel_Nodes_SelectStatement o
|
74
|
+
[
|
75
|
+
o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
|
76
|
+
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
|
77
|
+
("LIMIT #{o.limit}" if o.limit),
|
78
|
+
(visit(o.offset) if o.offset),
|
79
|
+
(visit(o.lock) if o.lock),
|
80
|
+
].compact.join ' '
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_Arel_Nodes_SelectCore o
|
84
|
+
[
|
85
|
+
"SELECT #{o.projections.map { |x| visit x }.join ', '}",
|
86
|
+
("FROM #{visit o.froms}" if o.froms),
|
87
|
+
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
|
88
|
+
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
|
89
|
+
(visit(o.having) if o.having),
|
90
|
+
].compact.join ' '
|
91
|
+
end
|
92
|
+
|
93
|
+
def visit_Arel_Nodes_Having o
|
94
|
+
"HAVING #{visit o.expr}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def visit_Arel_Nodes_Offset o
|
98
|
+
"OFFSET #{visit o.value}"
|
99
|
+
end
|
100
|
+
|
101
|
+
# FIXME: this does nothing on SQLLite3, but should do things on other
|
102
|
+
# databases.
|
103
|
+
def visit_Arel_Nodes_Lock o
|
104
|
+
end
|
105
|
+
|
106
|
+
def visit_Arel_Nodes_Grouping o
|
107
|
+
"(#{visit o.expr})"
|
108
|
+
end
|
109
|
+
|
110
|
+
def visit_Arel_Nodes_Ordering o
|
111
|
+
"#{visit o.expr} #{o.descending? ? 'DESC' : 'ASC'}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def visit_Arel_Nodes_Group o
|
115
|
+
visit o.expr
|
116
|
+
end
|
117
|
+
|
118
|
+
def visit_Arel_Nodes_Count o
|
119
|
+
"COUNT(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
120
|
+
visit x
|
121
|
+
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
122
|
+
end
|
123
|
+
|
124
|
+
def visit_Arel_Nodes_Sum o
|
125
|
+
"SUM(#{o.expressions.map { |x|
|
126
|
+
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
127
|
+
end
|
128
|
+
|
129
|
+
def visit_Arel_Nodes_Max o
|
130
|
+
"MAX(#{o.expressions.map { |x|
|
131
|
+
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def visit_Arel_Nodes_Min o
|
135
|
+
"MIN(#{o.expressions.map { |x|
|
136
|
+
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def visit_Arel_Nodes_Avg o
|
140
|
+
"AVG(#{o.expressions.map { |x|
|
141
|
+
visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
142
|
+
end
|
143
|
+
|
144
|
+
def visit_Arel_Nodes_TableAlias o
|
145
|
+
"#{visit o.relation} #{quote_table_name o.name}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def visit_Arel_Nodes_Between o
|
149
|
+
"#{visit o.left} BETWEEN #{visit o.right}"
|
150
|
+
end
|
151
|
+
|
152
|
+
def visit_Arel_Nodes_GreaterThanOrEqual o
|
153
|
+
"#{visit o.left} >= #{visit o.right}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def visit_Arel_Nodes_GreaterThan o
|
157
|
+
"#{visit o.left} > #{visit o.right}"
|
158
|
+
end
|
159
|
+
|
160
|
+
def visit_Arel_Nodes_LessThanOrEqual o
|
161
|
+
"#{visit o.left} <= #{visit o.right}"
|
162
|
+
end
|
163
|
+
|
164
|
+
def visit_Arel_Nodes_LessThan o
|
165
|
+
"#{visit o.left} < #{visit o.right}"
|
166
|
+
end
|
167
|
+
|
168
|
+
def visit_Arel_Nodes_Matches o
|
169
|
+
"#{visit o.left} LIKE #{visit o.right}"
|
170
|
+
end
|
171
|
+
|
172
|
+
def visit_Arel_Nodes_DoesNotMatch o
|
173
|
+
"#{visit o.left} NOT LIKE #{visit o.right}"
|
174
|
+
end
|
175
|
+
|
176
|
+
def visit_Arel_Nodes_StringJoin o
|
177
|
+
"#{visit o.left} #{visit o.right}"
|
178
|
+
end
|
179
|
+
|
180
|
+
def visit_Arel_Nodes_OuterJoin o
|
181
|
+
"#{visit o.left} LEFT OUTER JOIN #{visit o.right} #{visit o.constraint}"
|
182
|
+
end
|
183
|
+
|
184
|
+
def visit_Arel_Nodes_InnerJoin o
|
185
|
+
"#{visit o.left} INNER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
|
186
|
+
end
|
187
|
+
|
188
|
+
def visit_Arel_Nodes_On o
|
189
|
+
"ON #{visit o.expr}"
|
190
|
+
end
|
191
|
+
|
192
|
+
def visit_Arel_Table o
|
193
|
+
if o.table_alias
|
194
|
+
"#{quote_table_name o.name} #{quote_table_name o.table_alias}"
|
195
|
+
else
|
196
|
+
quote_table_name o.name
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def visit_Arel_Nodes_In o
|
201
|
+
right = o.right
|
202
|
+
"#{visit o.left} IN (#{
|
203
|
+
right.empty? ? 'NULL' : right.map { |x| visit x }.join(', ')
|
204
|
+
})"
|
205
|
+
end
|
206
|
+
|
207
|
+
def visit_Arel_Nodes_NotIn o
|
208
|
+
right = o.right
|
209
|
+
"#{visit o.left} NOT IN (#{
|
210
|
+
right.empty? ? 'NULL' : right.map { |x| visit x }.join(', ')
|
211
|
+
})"
|
212
|
+
end
|
213
|
+
|
214
|
+
def visit_Arel_Nodes_And o
|
215
|
+
"#{visit o.left} AND #{visit o.right}"
|
216
|
+
end
|
217
|
+
|
218
|
+
def visit_Arel_Nodes_Or o
|
219
|
+
"#{visit o.left} OR #{visit o.right}"
|
220
|
+
end
|
221
|
+
|
222
|
+
def visit_Arel_Nodes_Assignment o
|
223
|
+
right = quote(o.right, o.left.column)
|
224
|
+
"#{visit o.left} = #{right}"
|
225
|
+
end
|
226
|
+
|
227
|
+
def visit_Arel_Nodes_Equality o
|
228
|
+
right = o.right
|
229
|
+
|
230
|
+
if right.nil?
|
231
|
+
"#{visit o.left} IS NULL"
|
232
|
+
else
|
233
|
+
"#{visit o.left} = #{visit right}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def visit_Arel_Nodes_NotEqual o
|
238
|
+
right = o.right
|
239
|
+
|
240
|
+
if right.nil?
|
241
|
+
"#{visit o.left} IS NOT NULL"
|
242
|
+
else
|
243
|
+
"#{visit o.left} != #{visit right}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def visit_Arel_Nodes_UnqualifiedColumn o
|
248
|
+
"#{quote_column_name o.name}"
|
249
|
+
end
|
250
|
+
|
251
|
+
def visit_Arel_Attributes_Attribute o
|
252
|
+
@last_column = o.column
|
253
|
+
join_name = o.relation.table_alias || o.relation.name
|
254
|
+
"#{quote_table_name join_name}.#{quote_column_name o.name}"
|
255
|
+
end
|
256
|
+
alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute
|
257
|
+
alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute
|
258
|
+
alias :visit_Arel_Attributes_Decimal :visit_Arel_Attributes_Attribute
|
259
|
+
alias :visit_Arel_Attributes_String :visit_Arel_Attributes_Attribute
|
260
|
+
alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
|
261
|
+
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
|
262
|
+
|
263
|
+
def visit_Fixnum o; o end
|
264
|
+
alias :visit_Arel_Nodes_SqlLiteral :visit_Fixnum
|
265
|
+
alias :visit_Arel_SqlLiteral :visit_Fixnum # This is deprecated
|
266
|
+
|
267
|
+
def visit_String o; quote(o, @last_column) end
|
268
|
+
|
269
|
+
alias :visit_ActiveSupport_Multibyte_Chars :visit_String
|
270
|
+
alias :visit_BigDecimal :visit_String
|
271
|
+
alias :visit_Date :visit_String
|
272
|
+
alias :visit_DateTime :visit_String
|
273
|
+
alias :visit_FalseClass :visit_String
|
274
|
+
alias :visit_Float :visit_String
|
275
|
+
alias :visit_Hash :visit_String
|
276
|
+
alias :visit_Symbol :visit_String
|
277
|
+
alias :visit_Time :visit_String
|
278
|
+
alias :visit_TrueClass :visit_String
|
279
|
+
|
280
|
+
DISPATCH = Hash.new do |hash, klass|
|
281
|
+
hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
|
282
|
+
end
|
283
|
+
|
284
|
+
def visit object
|
285
|
+
send DISPATCH[object.class], object
|
286
|
+
end
|
287
|
+
|
288
|
+
def quote value, column = nil
|
289
|
+
@connection.quote value, column
|
290
|
+
end
|
291
|
+
|
292
|
+
def quote_table_name name
|
293
|
+
@quoted_tables[name] ||= @connection.quote_table_name(name)
|
294
|
+
end
|
295
|
+
|
296
|
+
def quote_column_name name
|
297
|
+
@quoted_columns[name] ||= @connection.quote_column_name(name)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|