arel 0.1.0 → 0.2.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/.gitmodules +3 -0
- data/History.txt +11 -0
- data/README.markdown +26 -26
- data/Rakefile +34 -46
- data/Thorfile +124 -0
- data/arel.gemspec +216 -201
- data/lib/arel/algebra/{primitives/attribute.rb → attribute.rb} +7 -7
- data/lib/arel/algebra/{extensions → core_extensions}/class.rb +2 -2
- data/lib/arel/algebra/{extensions → core_extensions}/hash.rb +1 -1
- data/lib/arel/algebra/{extensions → core_extensions}/object.rb +1 -1
- data/lib/arel/algebra/{extensions → core_extensions}/symbol.rb +1 -1
- data/lib/arel/algebra/core_extensions.rb +4 -0
- data/lib/arel/algebra/{primitives/ordering.rb → ordering.rb} +1 -1
- data/lib/arel/algebra/predicates.rb +32 -30
- data/lib/arel/algebra/relations/operations/from.rb +6 -0
- data/lib/arel/algebra/relations/operations/having.rb +13 -0
- data/lib/arel/algebra/relations/operations/join.rb +4 -0
- data/lib/arel/algebra/relations/operations/lock.rb +12 -0
- data/lib/arel/algebra/relations/operations/project.rb +1 -1
- data/lib/arel/algebra/relations/relation.rb +9 -2
- data/lib/arel/algebra/relations/utilities/compound.rb +2 -2
- data/lib/arel/algebra/relations.rb +3 -0
- data/lib/arel/algebra.rb +7 -2
- data/lib/arel/engines/memory/predicates.rb +26 -24
- data/lib/arel/engines/memory/relations/operations.rb +6 -0
- data/lib/arel/engines/sql/christener.rb +2 -1
- data/lib/arel/engines/sql/{extensions → core_extensions}/array.rb +6 -2
- data/lib/arel/engines/sql/{extensions → core_extensions}/nil_class.rb +1 -1
- data/lib/arel/engines/sql/{extensions → core_extensions}/object.rb +1 -1
- data/lib/arel/engines/sql/{extensions → core_extensions}/range.rb +1 -1
- data/lib/arel/engines/sql/core_extensions.rb +4 -0
- data/lib/arel/engines/sql/engine.rb +4 -0
- data/lib/arel/engines/sql/formatters.rb +12 -3
- data/lib/arel/engines/sql/predicates.rb +37 -35
- data/lib/arel/engines/sql/primitives.rb +10 -2
- data/lib/arel/engines/sql/relations/operations/join.rb +2 -2
- data/lib/arel/engines/sql/relations/relation.rb +46 -10
- data/lib/arel/engines/sql/relations/table.rb +18 -5
- data/lib/arel/engines/sql/relations/utilities/compound.rb +1 -1
- data/lib/arel/engines/sql/relations/writes.rb +58 -11
- data/lib/arel/engines/sql.rb +1 -1
- data/lib/arel/session.rb +9 -6
- data/lib/arel.rb +9 -8
- data/spec/arel/algebra/unit/predicates/binary_spec.rb +23 -21
- data/spec/arel/algebra/unit/predicates/equality_spec.rb +20 -18
- data/spec/arel/algebra/unit/predicates/in_spec.rb +7 -5
- data/spec/arel/algebra/unit/primitives/attribute_spec.rb +10 -12
- data/spec/arel/algebra/unit/primitives/expression_spec.rb +1 -1
- data/spec/arel/algebra/unit/primitives/value_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/alias_spec.rb +2 -2
- data/spec/arel/algebra/unit/relations/delete_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/group_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/insert_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/join_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/order_spec.rb +2 -2
- data/spec/arel/algebra/unit/relations/project_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/relation_spec.rb +9 -9
- data/spec/arel/algebra/unit/relations/skip_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/table_spec.rb +2 -2
- data/spec/arel/algebra/unit/relations/take_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/update_spec.rb +1 -1
- data/spec/arel/algebra/unit/relations/where_spec.rb +1 -1
- data/spec/arel/algebra/unit/session/session_spec.rb +6 -6
- data/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb +3 -4
- data/spec/arel/engines/memory/unit/relations/array_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/insert_spec.rb +8 -8
- data/spec/arel/engines/memory/unit/relations/join_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/order_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/project_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/skip_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/take_spec.rb +1 -1
- data/spec/arel/engines/memory/unit/relations/where_spec.rb +1 -1
- data/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb +1 -1
- data/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb +1 -1
- data/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/engine_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/predicates/binary_spec.rb +73 -70
- data/spec/arel/engines/sql/unit/predicates/equality_spec.rb +45 -28
- data/spec/arel/engines/sql/unit/predicates/in_spec.rb +75 -54
- data/spec/arel/engines/sql/unit/predicates/predicates_spec.rb +48 -46
- data/spec/arel/engines/sql/unit/primitives/attribute_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/primitives/expression_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/primitives/literal_spec.rb +13 -1
- data/spec/arel/engines/sql/unit/primitives/value_spec.rb +3 -3
- data/spec/arel/engines/sql/unit/relations/alias_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/delete_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/from_spec.rb +50 -0
- data/spec/arel/engines/sql/unit/relations/group_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/having_spec.rb +36 -0
- data/spec/arel/engines/sql/unit/relations/insert_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/join_spec.rb +85 -4
- data/spec/arel/engines/sql/unit/relations/lock_spec.rb +61 -0
- data/spec/arel/engines/sql/unit/relations/order_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/project_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/skip_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/table_spec.rb +42 -3
- data/spec/arel/engines/sql/unit/relations/take_spec.rb +1 -1
- data/spec/arel/engines/sql/unit/relations/update_spec.rb +13 -7
- data/spec/arel/engines/sql/unit/relations/where_spec.rb +1 -1
- data/spec/connections/mysql_connection.rb +3 -3
- data/spec/connections/postgresql_connection.rb +2 -2
- data/spec/connections/sqlite3_connection.rb +3 -2
- data/spec/doubles/hash.rb +4 -0
- data/spec/schemas/mysql_schema.rb +7 -0
- data/spec/schemas/postgresql_schema.rb +7 -0
- data/spec/schemas/sqlite3_schema.rb +7 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +9 -1
- metadata +50 -25
- data/VERSION +0 -1
- data/lib/arel/.DS_Store +0 -0
- data/lib/arel/algebra/extensions.rb +0 -4
- data/lib/arel/algebra/primitives.rb +0 -5
- data/lib/arel/engines/sql/extensions.rb +0 -4
- /data/lib/arel/algebra/{primitives/expression.rb → expression.rb} +0 -0
- /data/lib/arel/algebra/{primitives/value.rb → value.rb} +0 -0
|
@@ -1,41 +1,43 @@
|
|
|
1
1
|
module Arel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
module Predicates
|
|
3
|
+
class Predicate
|
|
4
|
+
def or(other_predicate)
|
|
5
|
+
Or.new(self, other_predicate)
|
|
6
|
+
end
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
def and(other_predicate)
|
|
9
|
+
And.new(self, other_predicate)
|
|
10
|
+
end
|
|
9
11
|
end
|
|
10
|
-
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
class Binary < Predicate
|
|
14
|
+
attributes :operand1, :operand2
|
|
15
|
+
deriving :initialize
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
def ==(other)
|
|
18
|
+
self.class === other and
|
|
19
|
+
@operand1 == other.operand1 and
|
|
20
|
+
@operand2 == other.operand2
|
|
21
|
+
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
def bind(relation)
|
|
24
|
+
self.class.new(operand1.find_correlate_in(relation), operand2.find_correlate_in(relation))
|
|
25
|
+
end
|
|
24
26
|
end
|
|
25
|
-
end
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
class Equality < Binary
|
|
29
|
+
def ==(other)
|
|
30
|
+
Equality === other and
|
|
31
|
+
((operand1 == other.operand1 and operand2 == other.operand2) or
|
|
32
|
+
(operand1 == other.operand2 and operand2 == other.operand1))
|
|
33
|
+
end
|
|
32
34
|
end
|
|
33
|
-
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
class GreaterThanOrEqualTo < Binary; end
|
|
37
|
+
class GreaterThan < Binary; end
|
|
38
|
+
class LessThanOrEqualTo < Binary; end
|
|
39
|
+
class LessThan < Binary; end
|
|
40
|
+
class Match < Binary; end
|
|
41
|
+
class In < Binary; end
|
|
42
|
+
end
|
|
41
43
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Arel
|
|
2
|
+
class Having < Compound
|
|
3
|
+
attributes :relation, :havings
|
|
4
|
+
deriving :==
|
|
5
|
+
|
|
6
|
+
def initialize(relation, *havings, &block)
|
|
7
|
+
@relation = relation
|
|
8
|
+
@havings = (havings + arguments_from_block(relation, &block)) \
|
|
9
|
+
.collect { |g| g.bind(relation) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
@@ -43,7 +43,7 @@ module Arel
|
|
|
43
43
|
join(other_relation, OuterJoin)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
[:where, :project, :order, :take, :skip, :group].each do |operation_name|
|
|
46
|
+
[:where, :project, :order, :take, :skip, :group, :from, :having].each do |operation_name|
|
|
47
47
|
class_eval <<-OPERATION, __FILE__, __LINE__
|
|
48
48
|
def #{operation_name}(*arguments, &block)
|
|
49
49
|
arguments.all?(&:blank?) && !block_given?? self : #{operation_name.to_s.classify}.new(self, *arguments, &block)
|
|
@@ -51,6 +51,10 @@ module Arel
|
|
|
51
51
|
OPERATION
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def lock(locking = nil)
|
|
55
|
+
Lock.new(self, locking)
|
|
56
|
+
end
|
|
57
|
+
|
|
54
58
|
def alias
|
|
55
59
|
Alias.new(self)
|
|
56
60
|
end
|
|
@@ -110,7 +114,7 @@ module Arel
|
|
|
110
114
|
private
|
|
111
115
|
def matching_attributes(attribute)
|
|
112
116
|
(@matching_attributes ||= attributes.inject({}) do |hash, a|
|
|
113
|
-
(hash[a.root] ||= []) << a
|
|
117
|
+
(hash[a.is_a?(Value) ? a.value : a.root] ||= []) << a
|
|
114
118
|
hash
|
|
115
119
|
end)[attribute.root] || []
|
|
116
120
|
end
|
|
@@ -127,9 +131,12 @@ module Arel
|
|
|
127
131
|
def orders; [] end
|
|
128
132
|
def inserts; [] end
|
|
129
133
|
def groupings; [] end
|
|
134
|
+
def havings; [] end
|
|
130
135
|
def joins(formatter = nil); nil end # FIXME
|
|
131
136
|
def taken; nil end
|
|
132
137
|
def skipped; nil end
|
|
138
|
+
def sources; [] end
|
|
139
|
+
def locked; [] end
|
|
133
140
|
end
|
|
134
141
|
include DefaultOperations
|
|
135
142
|
end
|
|
@@ -2,10 +2,10 @@ module Arel
|
|
|
2
2
|
class Compound < Relation
|
|
3
3
|
attr_reader :relation
|
|
4
4
|
delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
|
|
5
|
-
:column_for, :engine,
|
|
5
|
+
:column_for, :engine, :sources, :locked, :table_alias,
|
|
6
6
|
:to => :relation
|
|
7
7
|
|
|
8
|
-
[:attributes, :wheres, :groupings, :orders].each do |operation_name|
|
|
8
|
+
[:attributes, :wheres, :groupings, :orders, :havings].each do |operation_name|
|
|
9
9
|
class_eval <<-OPERATION, __FILE__, __LINE__
|
|
10
10
|
def #{operation_name}
|
|
11
11
|
@#{operation_name} ||= relation.#{operation_name}.collect { |o| o.bind(self) }
|
|
@@ -5,10 +5,13 @@ require 'arel/algebra/relations/utilities/externalization'
|
|
|
5
5
|
require 'arel/algebra/relations/row'
|
|
6
6
|
require 'arel/algebra/relations/writes'
|
|
7
7
|
require 'arel/algebra/relations/operations/alias'
|
|
8
|
+
require 'arel/algebra/relations/operations/from'
|
|
8
9
|
require 'arel/algebra/relations/operations/group'
|
|
10
|
+
require 'arel/algebra/relations/operations/having'
|
|
9
11
|
require 'arel/algebra/relations/operations/join'
|
|
10
12
|
require 'arel/algebra/relations/operations/order'
|
|
11
13
|
require 'arel/algebra/relations/operations/project'
|
|
12
14
|
require 'arel/algebra/relations/operations/where'
|
|
13
15
|
require 'arel/algebra/relations/operations/skip'
|
|
14
16
|
require 'arel/algebra/relations/operations/take'
|
|
17
|
+
require 'arel/algebra/relations/operations/lock'
|
data/lib/arel/algebra.rb
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
require 'arel/algebra/
|
|
1
|
+
require 'arel/algebra/core_extensions'
|
|
2
|
+
|
|
3
|
+
require 'arel/algebra/attribute'
|
|
4
|
+
require 'arel/algebra/expression'
|
|
5
|
+
require 'arel/algebra/ordering'
|
|
2
6
|
require 'arel/algebra/predicates'
|
|
3
7
|
require 'arel/algebra/relations'
|
|
4
|
-
require 'arel/algebra/
|
|
8
|
+
require 'arel/algebra/value'
|
|
9
|
+
|
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
module Arel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
module Predicates
|
|
3
|
+
class Binary < Predicate
|
|
4
|
+
def eval(row)
|
|
5
|
+
operand1.eval(row).send(operator, operand2.eval(row))
|
|
6
|
+
end
|
|
5
7
|
end
|
|
6
|
-
end
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class Equality < Binary
|
|
10
|
+
def operator; :== end
|
|
11
|
+
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
class GreaterThanOrEqualTo < Binary
|
|
14
|
+
def operator; :>= end
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
class GreaterThan < Binary
|
|
18
|
+
def operator; :> end
|
|
19
|
+
end
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
class LessThanOrEqualTo < Binary
|
|
22
|
+
def operator; :<= end
|
|
23
|
+
end
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
class LessThan < Binary
|
|
26
|
+
def operator; :< end
|
|
27
|
+
end
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
class Match < Binary
|
|
30
|
+
def operator; :=~ end
|
|
31
|
+
end
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
class In < Binary
|
|
34
|
+
def operator; :include? end
|
|
35
|
+
end
|
|
34
36
|
end
|
|
35
37
|
end
|
|
@@ -4,7 +4,8 @@ module Arel
|
|
|
4
4
|
def name_for(relation)
|
|
5
5
|
@used_names ||= Hash.new(0)
|
|
6
6
|
(@relation_names ||= Hash.new do |hash, relation|
|
|
7
|
-
|
|
7
|
+
name = relation.table_alias ? relation.table_alias : relation.name
|
|
8
|
+
@used_names[name] += 1
|
|
8
9
|
hash[relation] = name + (@used_names[name] > 1 ? "_#{@used_names[name]}" : '')
|
|
9
10
|
end)[relation.table]
|
|
10
11
|
end
|
|
@@ -2,13 +2,17 @@ module Arel
|
|
|
2
2
|
module Sql
|
|
3
3
|
module ArrayExtensions
|
|
4
4
|
def to_sql(formatter = nil)
|
|
5
|
-
|
|
5
|
+
if any?
|
|
6
|
+
"(" + collect { |e| e.to_sql(formatter) }.join(', ') + ")"
|
|
7
|
+
else
|
|
8
|
+
"(NULL)"
|
|
9
|
+
end
|
|
6
10
|
end
|
|
7
11
|
|
|
8
12
|
def inclusion_predicate_sql
|
|
9
13
|
"IN"
|
|
10
14
|
end
|
|
11
|
-
|
|
15
|
+
|
|
12
16
|
Array.send(:include, self)
|
|
13
17
|
end
|
|
14
18
|
end
|
|
@@ -13,7 +13,6 @@ module Arel
|
|
|
13
13
|
|
|
14
14
|
class SelectClause < Formatter
|
|
15
15
|
def attribute(attribute)
|
|
16
|
-
# FIXME this should check that the column exists
|
|
17
16
|
"#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" +
|
|
18
17
|
(attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "")
|
|
19
18
|
end
|
|
@@ -58,6 +57,12 @@ module Arel
|
|
|
58
57
|
end
|
|
59
58
|
end
|
|
60
59
|
|
|
60
|
+
class HavingClause < PassThrough
|
|
61
|
+
def attribute(attribute)
|
|
62
|
+
attribute
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
61
66
|
class WhereCondition < Formatter
|
|
62
67
|
def attribute(attribute)
|
|
63
68
|
"#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}"
|
|
@@ -92,8 +97,12 @@ module Arel
|
|
|
92
97
|
end
|
|
93
98
|
|
|
94
99
|
def table(table)
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
if table.name =~ /\s/
|
|
101
|
+
table.name
|
|
102
|
+
else
|
|
103
|
+
quote_table_name(table.name) +
|
|
104
|
+
(table.name != name_for(table) ? " AS " + quote_table_name(name_for(table)) : '')
|
|
105
|
+
end
|
|
97
106
|
end
|
|
98
107
|
end
|
|
99
108
|
|
|
@@ -1,51 +1,53 @@
|
|
|
1
1
|
module Arel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
module Predicates
|
|
3
|
+
class Binary < Predicate
|
|
4
|
+
def to_sql(formatter = nil)
|
|
5
|
+
"#{operand1.to_sql} #{predicate_sql} #{operand1.format(operand2)}"
|
|
6
|
+
end
|
|
5
7
|
end
|
|
6
|
-
end
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class CompoundPredicate < Binary
|
|
10
|
+
def to_sql(formatter = nil)
|
|
11
|
+
"(#{operand1.to_sql(formatter)} #{predicate_sql} #{operand2.to_sql(formatter)})"
|
|
12
|
+
end
|
|
11
13
|
end
|
|
12
|
-
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
class Or < CompoundPredicate
|
|
16
|
+
def predicate_sql; "OR" end
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
class And < CompoundPredicate
|
|
20
|
+
def predicate_sql; "AND" end
|
|
21
|
+
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
class Equality < Binary
|
|
24
|
+
def predicate_sql
|
|
25
|
+
operand2.equality_predicate_sql
|
|
26
|
+
end
|
|
25
27
|
end
|
|
26
|
-
end
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
class GreaterThanOrEqualTo < Binary
|
|
30
|
+
def predicate_sql; '>=' end
|
|
31
|
+
end
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
class GreaterThan < Binary
|
|
34
|
+
def predicate_sql; '>' end
|
|
35
|
+
end
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
class LessThanOrEqualTo < Binary
|
|
38
|
+
def predicate_sql; '<=' end
|
|
39
|
+
end
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
class LessThan < Binary
|
|
42
|
+
def predicate_sql; '<' end
|
|
43
|
+
end
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
class Match < Binary
|
|
46
|
+
def predicate_sql; 'LIKE' end
|
|
47
|
+
end
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
class In < Binary
|
|
50
|
+
def predicate_sql; operand2.inclusion_predicate_sql end
|
|
51
|
+
end
|
|
50
52
|
end
|
|
51
53
|
end
|
|
@@ -3,10 +3,12 @@ module Arel
|
|
|
3
3
|
def relation
|
|
4
4
|
nil
|
|
5
5
|
end
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def to_sql(formatter = nil)
|
|
8
8
|
self
|
|
9
9
|
end
|
|
10
|
+
|
|
11
|
+
include Attribute::Expressions
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
class Attribute
|
|
@@ -28,7 +30,13 @@ module Arel
|
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
class Value
|
|
31
|
-
|
|
33
|
+
def inclusion_predicate_sql
|
|
34
|
+
value.inclusion_predicate_sql
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def equality_predicate_sql
|
|
38
|
+
value.equality_predicate_sql
|
|
39
|
+
end
|
|
32
40
|
|
|
33
41
|
def to_sql(formatter = Sql::WhereCondition.new(relation))
|
|
34
42
|
formatter.value value
|
|
@@ -5,15 +5,40 @@ module Arel
|
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def select_sql
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
(
|
|
12
|
-
("
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
if engine.adapter_name == "PostgreSQL" && !orders.blank? && using_distinct_on?
|
|
9
|
+
# PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
|
|
10
|
+
# by wrapping the +sql+ string as a sub-select and ordering in that query.
|
|
11
|
+
order = order_clauses.join(', ').split(',').map { |s| s.strip }.reject(&:blank?)
|
|
12
|
+
order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{'DESC' if s =~ /\bdesc$/i}" }.join(', ')
|
|
13
|
+
|
|
14
|
+
query = build_query \
|
|
15
|
+
"SELECT #{select_clauses.kind_of?(::Array) ? select_clauses.join("") : select_clauses.to_s}",
|
|
16
|
+
"FROM #{from_clauses}",
|
|
17
|
+
(joins(self) unless joins(self).blank? ),
|
|
18
|
+
("WHERE #{where_clauses.join(" AND ")}" unless wheres.blank? ),
|
|
19
|
+
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
|
20
|
+
("HAVING #{having_clauses.join(', ')}" unless havings.blank? ),
|
|
21
|
+
("#{locked}" unless locked.blank? )
|
|
22
|
+
|
|
23
|
+
build_query \
|
|
24
|
+
"SELECT * FROM (#{query}) AS id_list",
|
|
25
|
+
"ORDER BY #{order}",
|
|
26
|
+
("LIMIT #{taken}" unless taken.blank? ),
|
|
27
|
+
("OFFSET #{skipped}" unless skipped.blank? )
|
|
28
|
+
|
|
29
|
+
else
|
|
30
|
+
build_query \
|
|
31
|
+
"SELECT #{select_clauses.join(', ')}",
|
|
32
|
+
"FROM #{from_clauses}",
|
|
33
|
+
(joins(self) unless joins(self).blank? ),
|
|
34
|
+
("WHERE #{where_clauses.join(" AND ")}" unless wheres.blank? ),
|
|
35
|
+
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
|
36
|
+
("HAVING #{having_clauses.join(', ')}" unless havings.blank? ),
|
|
37
|
+
("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? ),
|
|
38
|
+
("LIMIT #{taken}" unless taken.blank? ),
|
|
39
|
+
("OFFSET #{skipped}" unless skipped.blank? ),
|
|
40
|
+
("#{locked}" unless engine.adapter_name =~ /SQLite/ || locked.blank?)
|
|
41
|
+
end
|
|
17
42
|
end
|
|
18
43
|
|
|
19
44
|
def inclusion_predicate_sql
|
|
@@ -27,7 +52,11 @@ module Arel
|
|
|
27
52
|
protected
|
|
28
53
|
|
|
29
54
|
def build_query(*parts)
|
|
30
|
-
parts.compact.join("
|
|
55
|
+
parts.compact.join(" ")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def from_clauses
|
|
59
|
+
sources.blank? ? table_sql(Sql::TableReference.new(self)) : sources
|
|
31
60
|
end
|
|
32
61
|
|
|
33
62
|
def select_clauses
|
|
@@ -42,9 +71,16 @@ module Arel
|
|
|
42
71
|
groupings.collect { |g| g.to_sql(Sql::GroupClause.new(self)) }
|
|
43
72
|
end
|
|
44
73
|
|
|
74
|
+
def having_clauses
|
|
75
|
+
havings.collect { |g| g.to_sql(Sql::HavingClause.new(self)) }
|
|
76
|
+
end
|
|
77
|
+
|
|
45
78
|
def order_clauses
|
|
46
79
|
orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) }
|
|
47
80
|
end
|
|
48
81
|
|
|
82
|
+
def using_distinct_on?
|
|
83
|
+
select_clauses.any? { |x| x =~ /DISTINCT ON/ }
|
|
84
|
+
end
|
|
49
85
|
end
|
|
50
86
|
end
|
|
@@ -3,10 +3,22 @@ module Arel
|
|
|
3
3
|
include Recursion::BaseCase
|
|
4
4
|
|
|
5
5
|
cattr_accessor :engine
|
|
6
|
-
attr_reader :name, :engine
|
|
6
|
+
attr_reader :name, :engine, :table_alias, :options
|
|
7
7
|
|
|
8
|
-
def initialize(name,
|
|
9
|
-
@name
|
|
8
|
+
def initialize(name, options = {})
|
|
9
|
+
@name = name.to_s
|
|
10
|
+
|
|
11
|
+
if options.is_a?(Hash)
|
|
12
|
+
@options = options
|
|
13
|
+
@engine = options[:engine] || Table.engine
|
|
14
|
+
@table_alias = options[:as].to_s if options[:as].present? && options[:as].to_s != @name
|
|
15
|
+
else
|
|
16
|
+
@engine = options # Table.new('foo', engine)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def as(table_alias)
|
|
21
|
+
Table.new(name, options.merge(:as => table_alias))
|
|
10
22
|
end
|
|
11
23
|
|
|
12
24
|
def attributes
|
|
@@ -40,8 +52,9 @@ module Arel
|
|
|
40
52
|
end
|
|
41
53
|
|
|
42
54
|
def ==(other)
|
|
43
|
-
Table
|
|
44
|
-
name
|
|
55
|
+
Table === other and
|
|
56
|
+
name == other.name and
|
|
57
|
+
table_alias == other.table_alias
|
|
45
58
|
end
|
|
46
59
|
end
|
|
47
60
|
end
|