arel 0.4.0 → 1.0.0.rc1
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/README.markdown +24 -0
- data/lib/arel.rb +3 -1
- data/lib/arel/algebra/attributes/attribute.rb +175 -141
- data/lib/arel/algebra/core_extensions.rb +0 -1
- data/lib/arel/algebra/core_extensions/hash.rb +5 -9
- data/lib/arel/algebra/core_extensions/object.rb +0 -4
- data/lib/arel/algebra/expression.rb +37 -24
- data/lib/arel/algebra/header.rb +5 -6
- data/lib/arel/algebra/ordering.rb +13 -5
- data/lib/arel/algebra/predicates.rb +143 -27
- data/lib/arel/algebra/relations.rb +0 -1
- data/lib/arel/algebra/relations/operations/from.rb +10 -2
- data/lib/arel/algebra/relations/operations/group.rb +8 -6
- data/lib/arel/algebra/relations/operations/having.rb +3 -6
- data/lib/arel/algebra/relations/operations/join.rb +52 -18
- data/lib/arel/algebra/relations/operations/lock.rb +4 -6
- data/lib/arel/algebra/relations/operations/order.rb +11 -7
- data/lib/arel/algebra/relations/operations/project.rb +10 -10
- data/lib/arel/algebra/relations/operations/skip.rb +10 -3
- data/lib/arel/algebra/relations/operations/take.rb +10 -3
- data/lib/arel/algebra/relations/operations/where.rb +12 -6
- data/lib/arel/algebra/relations/relation.rb +161 -92
- data/lib/arel/algebra/relations/row.rb +8 -5
- data/lib/arel/algebra/relations/utilities/compound.rb +34 -33
- data/lib/arel/algebra/relations/utilities/externalization.rb +10 -8
- data/lib/arel/algebra/relations/writes.rb +24 -13
- data/lib/arel/algebra/value.rb +41 -2
- data/lib/arel/engines/memory.rb +0 -2
- data/lib/arel/engines/memory/engine.rb +3 -9
- data/lib/arel/engines/memory/relations.rb +0 -3
- data/lib/arel/engines/memory/relations/array.rb +5 -3
- data/lib/arel/engines/memory/relations/operations.rb +2 -60
- data/lib/arel/engines/sql.rb +0 -2
- data/lib/arel/engines/sql/christener.rb +12 -6
- data/lib/arel/engines/sql/compilers/oracle_compiler.rb +34 -23
- data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +23 -15
- data/lib/arel/engines/sql/engine.rb +19 -27
- data/lib/arel/engines/sql/formatters.rb +26 -10
- data/lib/arel/engines/sql/relations.rb +0 -7
- data/lib/arel/engines/sql/relations/compiler.rb +70 -35
- data/lib/arel/engines/sql/relations/table.rb +44 -32
- data/lib/arel/{engines/sql/relations/utilities/recursion.rb → recursion/base_case.rb} +0 -0
- data/lib/arel/session.rb +24 -40
- data/lib/arel/sql_literal.rb +13 -0
- data/lib/arel/version.rb +1 -1
- data/spec/algebra/unit/predicates/inequality_spec.rb +32 -0
- data/spec/algebra/unit/predicates/predicate_spec.rb +22 -0
- data/spec/algebra/unit/primitives/attribute_spec.rb +3 -9
- data/spec/algebra/unit/primitives/expression_spec.rb +1 -7
- data/spec/algebra/unit/relations/join_spec.rb +0 -7
- data/spec/algebra/unit/relations/project_spec.rb +3 -3
- data/spec/algebra/unit/relations/relation_spec.rb +74 -25
- data/spec/algebra/unit/session/session_spec.rb +7 -7
- data/spec/engines/memory/integration/joins/cross_engine_spec.rb +20 -10
- data/spec/engines/memory/unit/relations/array_spec.rb +6 -5
- data/spec/engines/memory/unit/relations/join_spec.rb +7 -6
- data/spec/engines/memory/unit/relations/order_spec.rb +7 -6
- data/spec/engines/memory/unit/relations/project_spec.rb +6 -6
- data/spec/engines/memory/unit/relations/skip_spec.rb +10 -5
- data/spec/engines/memory/unit/relations/take_spec.rb +7 -5
- data/spec/engines/memory/unit/relations/where_spec.rb +13 -9
- data/spec/engines/sql/unit/engine_spec.rb +20 -0
- data/spec/engines/sql/unit/relations/group_spec.rb +2 -2
- data/spec/engines/sql/unit/relations/order_spec.rb +5 -5
- data/spec/engines/sql/unit/relations/project_spec.rb +4 -4
- data/spec/engines/sql/unit/relations/table_spec.rb +0 -7
- data/spec/engines/sql/unit/relations/take_spec.rb +26 -0
- data/spec/engines/sql/unit/relations/where_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -4
- data/spec/sql/christener_spec.rb +70 -0
- data/spec/support/model.rb +7 -2
- metadata +109 -23
- data/lib/arel/algebra/core_extensions/class.rb +0 -32
- data/lib/arel/algebra/relations/operations/alias.rb +0 -7
- data/lib/arel/engines/memory/predicates.rb +0 -99
- data/lib/arel/engines/memory/primitives.rb +0 -27
- data/lib/arel/engines/memory/relations/compound.rb +0 -9
- data/lib/arel/engines/memory/relations/writes.rb +0 -7
- data/lib/arel/engines/sql/predicates.rb +0 -103
- data/lib/arel/engines/sql/primitives.rb +0 -97
- data/lib/arel/engines/sql/relations/operations/alias.rb +0 -5
- data/lib/arel/engines/sql/relations/operations/join.rb +0 -33
- data/lib/arel/engines/sql/relations/relation.rb +0 -65
- data/lib/arel/engines/sql/relations/utilities/compound.rb +0 -10
- data/lib/arel/engines/sql/relations/utilities/externalization.rb +0 -14
- data/lib/arel/engines/sql/relations/writes.rb +0 -19
@@ -4,7 +4,6 @@ require 'arel/algebra/relations/utilities/nil'
|
|
4
4
|
require 'arel/algebra/relations/utilities/externalization'
|
5
5
|
require 'arel/algebra/relations/row'
|
6
6
|
require 'arel/algebra/relations/writes'
|
7
|
-
require 'arel/algebra/relations/operations/alias'
|
8
7
|
require 'arel/algebra/relations/operations/from'
|
9
8
|
require 'arel/algebra/relations/operations/group'
|
10
9
|
require 'arel/algebra/relations/operations/having'
|
@@ -1,6 +1,14 @@
|
|
1
1
|
module Arel
|
2
2
|
class From < Compound
|
3
|
-
|
4
|
-
|
3
|
+
attr_reader :sources
|
4
|
+
|
5
|
+
def initialize relation, sources
|
6
|
+
super(relation)
|
7
|
+
@sources = sources
|
8
|
+
end
|
9
|
+
|
10
|
+
def eval
|
11
|
+
unoperated_rows[sources..-1]
|
12
|
+
end
|
5
13
|
end
|
6
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module Arel
|
2
2
|
class Group < Compound
|
3
|
-
|
4
|
-
deriving :==
|
3
|
+
attr_reader :groupings
|
5
4
|
|
6
|
-
def initialize(relation,
|
7
|
-
|
8
|
-
@groupings =
|
9
|
-
|
5
|
+
def initialize(relation, groupings)
|
6
|
+
super(relation)
|
7
|
+
@groupings = groupings.collect { |g| g.bind(relation) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def eval
|
11
|
+
raise NotImplementedError
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
class Having < Compound
|
3
|
-
|
4
|
-
deriving :==
|
5
|
-
requires :restricting
|
3
|
+
attr_reader :predicates
|
6
4
|
|
7
|
-
def initialize(relation,
|
8
|
-
|
5
|
+
def initialize(relation, predicates)
|
6
|
+
super(relation)
|
9
7
|
@predicates = predicates.map { |p| p.bind(relation) }
|
10
|
-
@relation = relation
|
11
8
|
end
|
12
9
|
|
13
10
|
def havings
|
@@ -2,20 +2,17 @@ module Arel
|
|
2
2
|
class Join
|
3
3
|
include Relation
|
4
4
|
|
5
|
-
|
6
|
-
deriving :==
|
7
|
-
delegate :name, :to => :relation1
|
5
|
+
attr_reader :relation1, :relation2, :predicates
|
8
6
|
|
9
7
|
def initialize(relation1, relation2 = Nil.instance, *predicates)
|
10
|
-
@relation1
|
8
|
+
@relation1 = relation1
|
9
|
+
@relation2 = relation2
|
10
|
+
@predicates = predicates
|
11
|
+
@attributes = nil
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def eql?(other)
|
18
|
-
self == other
|
14
|
+
def name
|
15
|
+
relation1.name
|
19
16
|
end
|
20
17
|
|
21
18
|
def attributes
|
@@ -43,11 +40,54 @@ module Arel
|
|
43
40
|
def engine
|
44
41
|
relation1.engine != relation2.engine ? Memory::Engine.new : relation1.engine
|
45
42
|
end
|
43
|
+
|
44
|
+
def table_sql(formatter = Sql::TableReference.new(self))
|
45
|
+
relation1.externalize.table_sql(formatter)
|
46
|
+
end
|
47
|
+
|
48
|
+
def joins(environment, formatter = Sql::TableReference.new(environment))
|
49
|
+
@joins ||= begin
|
50
|
+
this_join = [
|
51
|
+
join_sql,
|
52
|
+
relation2.externalize.table_sql(formatter),
|
53
|
+
("ON" unless predicates.blank?),
|
54
|
+
(ons + relation2.externalize.wheres).collect { |p| p.bind(environment.relation).to_sql(Sql::WhereClause.new(environment)) }.join(' AND ')
|
55
|
+
].compact.join(" ")
|
56
|
+
[relation1.joins(environment), this_join, relation2.joins(environment)].compact.join(" ")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def eval
|
61
|
+
result = []
|
62
|
+
relation1.call.each do |row1|
|
63
|
+
relation2.call.each do |row2|
|
64
|
+
combined_row = row1.combine(row2, self)
|
65
|
+
if predicates.all? { |p| p.eval(combined_row) }
|
66
|
+
result << combined_row
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_sql(formatter = nil)
|
74
|
+
compiler.select_sql
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class InnerJoin < Join
|
79
|
+
def join_sql; "INNER JOIN" end
|
80
|
+
end
|
81
|
+
|
82
|
+
class OuterJoin < Join
|
83
|
+
def join_sql; "LEFT OUTER JOIN" end
|
46
84
|
end
|
47
85
|
|
48
|
-
class InnerJoin < Join; end
|
49
|
-
class OuterJoin < Join; end
|
50
86
|
class StringJoin < Join
|
87
|
+
def joins(environment, formatter = Sql::TableReference.new(environment))
|
88
|
+
[relation1.joins(environment), relation2].compact.join(" ")
|
89
|
+
end
|
90
|
+
|
51
91
|
def externalizable?
|
52
92
|
relation1.externalizable?
|
53
93
|
end
|
@@ -60,10 +100,4 @@ module Arel
|
|
60
100
|
relation1.engine
|
61
101
|
end
|
62
102
|
end
|
63
|
-
|
64
|
-
module Relation
|
65
|
-
def join?
|
66
|
-
false
|
67
|
-
end
|
68
|
-
end
|
69
103
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
class Lock < Compound
|
3
|
-
|
4
|
-
deriving :initialize, :==
|
3
|
+
attr_reader :locked
|
5
4
|
|
6
|
-
def initialize(relation, locked
|
7
|
-
|
8
|
-
@locked
|
5
|
+
def initialize(relation, locked)
|
6
|
+
super(relation)
|
7
|
+
@locked = true == locked ? " FOR UPDATE" : locked
|
9
8
|
end
|
10
9
|
end
|
11
10
|
end
|
12
|
-
|
@@ -1,13 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
class Order < Compound
|
3
|
-
|
4
|
-
deriving :==
|
5
|
-
requires :ordering
|
3
|
+
attr_reader :orderings
|
6
4
|
|
7
|
-
def initialize(relation,
|
8
|
-
|
9
|
-
@orderings =
|
10
|
-
.collect { |o| o.bind(relation) }
|
5
|
+
def initialize(relation, orderings)
|
6
|
+
super(relation)
|
7
|
+
@orderings = orderings.collect { |o| o.bind(relation) }
|
11
8
|
end
|
12
9
|
|
13
10
|
# TESTME
|
@@ -15,5 +12,12 @@ module Arel
|
|
15
12
|
# QUESTION - do we still need relation.orders ?
|
16
13
|
(orderings + relation.orders).collect { |o| o.bind(self) }.collect { |o| o.to_ordering }
|
17
14
|
end
|
15
|
+
|
16
|
+
def eval
|
17
|
+
unoperated_rows.sort do |row1, row2|
|
18
|
+
ordering = orders.detect { |o| o.eval(row1, row2) != 0 } || orders.last
|
19
|
+
ordering.eval(row1, row2)
|
20
|
+
end
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module Arel
|
2
2
|
class Project < Compound
|
3
|
-
|
4
|
-
deriving :==
|
3
|
+
attr_reader :projections, :attributes, :christener
|
5
4
|
|
6
|
-
def initialize(relation,
|
7
|
-
|
8
|
-
@projections =
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def attributes
|
13
|
-
@attributes ||= Header.new(projections).bind(self)
|
5
|
+
def initialize(relation, projections)
|
6
|
+
super(relation)
|
7
|
+
@projections = projections.map { |p| p.bind(relation) }
|
8
|
+
@christener = Sql::Christener.new
|
9
|
+
@attributes = Header.new(projections.map { |x| x.bind(self) })
|
14
10
|
end
|
15
11
|
|
16
12
|
def externalizable?
|
17
13
|
attributes.any? { |a| a.respond_to?(:aggregation?) && a.aggregation? } || relation.externalizable?
|
18
14
|
end
|
15
|
+
|
16
|
+
def eval
|
17
|
+
unoperated_rows.collect { |r| r.slice(*projections) }
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
@@ -1,7 +1,14 @@
|
|
1
1
|
module Arel
|
2
2
|
class Skip < Compound
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
attr_reader :relation, :skipped
|
4
|
+
|
5
|
+
def initialize relation, skipped
|
6
|
+
super(relation)
|
7
|
+
@skipped = skipped
|
8
|
+
end
|
9
|
+
|
10
|
+
def eval
|
11
|
+
unoperated_rows[skipped..-1]
|
12
|
+
end
|
6
13
|
end
|
7
14
|
end
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module Arel
|
2
2
|
class Take < Compound
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
attr_reader :taken
|
4
|
+
|
5
|
+
def initialize relation, taken
|
6
|
+
super(relation)
|
7
|
+
@taken = taken
|
8
|
+
end
|
6
9
|
|
7
10
|
def externalizable?
|
8
11
|
true
|
9
12
|
end
|
13
|
+
|
14
|
+
def eval
|
15
|
+
unoperated_rows[0, taken]
|
16
|
+
end
|
10
17
|
end
|
11
18
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
module Arel
|
2
2
|
class Where < Compound
|
3
|
-
|
4
|
-
deriving :==
|
5
|
-
requires :restricting
|
3
|
+
attr_reader :predicates
|
6
4
|
|
7
|
-
def initialize(relation,
|
8
|
-
|
5
|
+
def initialize(relation, predicates)
|
6
|
+
super(relation)
|
9
7
|
@predicates = predicates.map { |p| p.bind(relation) }
|
10
|
-
@
|
8
|
+
@wheres = nil
|
11
9
|
end
|
12
10
|
|
13
11
|
def wheres
|
14
12
|
@wheres ||= relation.wheres + predicates
|
15
13
|
end
|
14
|
+
|
15
|
+
def eval
|
16
|
+
unoperated_rows.select { |row| predicates.all? { |p| p.eval(row) } }
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_sql(formatter = nil)
|
20
|
+
compiler.select_sql
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module Arel
|
2
2
|
module Relation
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
@@connection_tables_primary_keys = {}
|
6
|
+
|
3
7
|
attr_reader :count
|
4
8
|
|
5
9
|
def session
|
6
|
-
Session.
|
10
|
+
Session.instance
|
11
|
+
end
|
12
|
+
|
13
|
+
def join?
|
14
|
+
false
|
7
15
|
end
|
8
16
|
|
9
17
|
def call
|
@@ -14,123 +22,184 @@ module Arel
|
|
14
22
|
self
|
15
23
|
end
|
16
24
|
|
17
|
-
|
18
|
-
|
25
|
+
def externalize
|
26
|
+
@externalized ||= externalizable?? Externalization.new(self) : self
|
27
|
+
end
|
28
|
+
|
29
|
+
def externalizable?
|
30
|
+
false
|
31
|
+
end
|
19
32
|
|
20
|
-
|
21
|
-
|
33
|
+
def compiler
|
34
|
+
@compiler ||= begin
|
35
|
+
Arel::SqlCompiler.const_get("#{engine.adapter_name}Compiler").new(self)
|
36
|
+
rescue
|
37
|
+
Arel::SqlCompiler::GenericCompiler.new(self)
|
22
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_sql(formatter = nil)
|
42
|
+
sql = compiler.select_sql
|
43
|
+
|
44
|
+
return sql unless formatter
|
45
|
+
formatter.select sql, self
|
46
|
+
end
|
47
|
+
|
48
|
+
def christener
|
49
|
+
@christener ||= Sql::Christener.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def inclusion_predicate_sql
|
53
|
+
"IN"
|
54
|
+
end
|
55
|
+
|
56
|
+
def exclusion_predicate_sql
|
57
|
+
"NOT IN"
|
58
|
+
end
|
23
59
|
|
24
|
-
|
25
|
-
|
60
|
+
def primary_key
|
61
|
+
connection_id = engine.connection.object_id
|
62
|
+
if @@connection_tables_primary_keys[connection_id] && @@connection_tables_primary_keys[connection_id].has_key?(table.name)
|
63
|
+
@@connection_tables_primary_keys[connection_id][table.name]
|
64
|
+
else
|
65
|
+
@@connection_tables_primary_keys[connection_id] ||= {}
|
66
|
+
@@connection_tables_primary_keys[connection_id][table.name] = engine.connection.primary_key(table.name)
|
26
67
|
end
|
27
68
|
end
|
28
|
-
include Enumerable
|
29
69
|
|
30
|
-
|
31
|
-
|
32
|
-
case
|
33
|
-
when
|
34
|
-
|
35
|
-
when Relation
|
36
|
-
JoinOperation.new(join_class, self, other_relation)
|
70
|
+
def select_clauses
|
71
|
+
attributes.map { |a|
|
72
|
+
case a
|
73
|
+
when Value
|
74
|
+
a.value
|
37
75
|
else
|
38
|
-
self
|
76
|
+
a.to_sql(Sql::SelectClause.new(self))
|
39
77
|
end
|
40
|
-
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def from_clauses
|
82
|
+
sources.empty? ? table_sql : sources
|
83
|
+
end
|
84
|
+
|
85
|
+
def where_clauses
|
86
|
+
wheres.map { |w| w.value }
|
87
|
+
end
|
88
|
+
|
89
|
+
def group_clauses
|
90
|
+
groupings.collect { |g| g.to_sql(Sql::GroupClause.new(self)) }
|
91
|
+
end
|
41
92
|
|
42
|
-
|
43
|
-
|
93
|
+
def having_clauses
|
94
|
+
havings.collect { |g| g.to_sql(Sql::HavingClause.new(self)) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def order_clauses
|
98
|
+
orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def each
|
102
|
+
session.read(self).each { |e| yield e }
|
103
|
+
end
|
104
|
+
|
105
|
+
def join(other_relation = nil, join_class = InnerJoin)
|
106
|
+
case other_relation
|
107
|
+
when String
|
108
|
+
StringJoin.new(self, other_relation)
|
109
|
+
when Relation
|
110
|
+
JoinOperation.new(join_class, self, other_relation)
|
111
|
+
else
|
112
|
+
self
|
44
113
|
end
|
114
|
+
end
|
45
115
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
116
|
+
def outer_join(other_relation = nil)
|
117
|
+
join(other_relation, OuterJoin)
|
118
|
+
end
|
119
|
+
|
120
|
+
%w{
|
121
|
+
having group order
|
122
|
+
}.each do |op|
|
123
|
+
class_eval <<-OPERATION, __FILE__, __LINE__
|
124
|
+
def #{op}(*args)
|
125
|
+
args.all? { |x| x.blank? } ? self : #{op.capitalize}.new(self, args)
|
50
126
|
end
|
51
|
-
|
52
|
-
|
127
|
+
OPERATION
|
128
|
+
end
|
53
129
|
|
54
|
-
|
55
|
-
|
56
|
-
|
130
|
+
def project *args
|
131
|
+
args.empty? ? self : Project.new(self, args)
|
132
|
+
end
|
57
133
|
|
58
|
-
|
59
|
-
|
60
|
-
|
134
|
+
def where clause = nil
|
135
|
+
clause ? Where.new(self, Array(clause)) : self
|
136
|
+
end
|
61
137
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
138
|
+
def skip thing = nil
|
139
|
+
thing ? Skip.new(self, thing) : self
|
140
|
+
end
|
66
141
|
|
67
|
-
|
68
|
-
|
69
|
-
|
142
|
+
def take count
|
143
|
+
Take.new self, count
|
144
|
+
end
|
70
145
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
include Writable
|
146
|
+
def from thing
|
147
|
+
From.new self, thing
|
148
|
+
end
|
76
149
|
|
77
|
-
|
78
|
-
|
79
|
-
join_class.new(relation1, relation2, *predicates)
|
80
|
-
end
|
81
|
-
end
|
150
|
+
def lock(locking = true)
|
151
|
+
Lock.new(self, locking)
|
82
152
|
end
|
83
|
-
include Operable
|
84
153
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
154
|
+
def alias
|
155
|
+
Alias.new(self)
|
156
|
+
end
|
89
157
|
|
90
|
-
|
91
|
-
|
92
|
-
|
158
|
+
def insert(record)
|
159
|
+
session.create Insert.new(self, record)
|
160
|
+
end
|
93
161
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
162
|
+
def update(assignments)
|
163
|
+
session.update Update.new(self, assignments)
|
164
|
+
end
|
99
165
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end)[attribute]
|
104
|
-
end
|
166
|
+
def delete
|
167
|
+
session.delete Deletion.new(self)
|
168
|
+
end
|
105
169
|
|
106
|
-
|
107
|
-
def
|
108
|
-
|
109
|
-
(hash[a.is_a?(Value) ? a.value : a.root] ||= []) << a
|
110
|
-
hash
|
111
|
-
end)[attribute.root] || []
|
170
|
+
JoinOperation = Struct.new(:join_class, :relation1, :relation2) do
|
171
|
+
def on(*predicates)
|
172
|
+
join_class.new(relation1, relation2, *predicates)
|
112
173
|
end
|
174
|
+
end
|
113
175
|
|
114
|
-
|
115
|
-
|
116
|
-
|
176
|
+
def [](index)
|
177
|
+
attributes[index]
|
178
|
+
end
|
179
|
+
|
180
|
+
def find_attribute_matching_name(name)
|
181
|
+
attributes.detect { |a| a.named?(name) } || Attribute.new(self, name)
|
182
|
+
end
|
183
|
+
|
184
|
+
def position_of(attribute)
|
185
|
+
@position_of ||= {}
|
186
|
+
|
187
|
+
return @position_of[attribute] if @position_of.key? attribute
|
188
|
+
|
189
|
+
@position_of[attribute] = attributes.index(attributes[attribute])
|
117
190
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
def sources; [] end
|
132
|
-
def locked; [] end
|
133
|
-
end
|
134
|
-
include DefaultOperations
|
191
|
+
|
192
|
+
def attributes; Header.new end
|
193
|
+
def projections; [] end
|
194
|
+
def wheres; [] end
|
195
|
+
def orders; [] end
|
196
|
+
def inserts; [] end
|
197
|
+
def groupings; [] end
|
198
|
+
def havings; [] end
|
199
|
+
def joins(formatter = nil); nil end # FIXME
|
200
|
+
def taken; nil end
|
201
|
+
def skipped; nil end
|
202
|
+
def sources; [] end
|
203
|
+
def locked; [] end
|
135
204
|
end
|
136
205
|
end
|