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
@@ -1,17 +1,20 @@
|
|
1
1
|
module Arel
|
2
2
|
class Row
|
3
|
-
|
4
|
-
|
3
|
+
attr_reader :tuple, :relation
|
4
|
+
|
5
|
+
def initialize relation, tuple
|
6
|
+
@relation = relation
|
7
|
+
@tuple = tuple
|
8
|
+
end
|
5
9
|
|
6
10
|
def [](attribute)
|
7
11
|
attribute.type_cast(tuple[relation.position_of(attribute)])
|
8
12
|
end
|
9
13
|
|
10
14
|
def slice(*attributes)
|
11
|
-
Row.new(relation, attributes.
|
15
|
+
Row.new(relation, attributes.map do |attribute|
|
12
16
|
# FIXME TESTME method chaining
|
13
|
-
|
14
|
-
cheese
|
17
|
+
tuple[relation.relation.position_of(attribute)]
|
15
18
|
end)
|
16
19
|
end
|
17
20
|
|
@@ -2,15 +2,38 @@ module Arel
|
|
2
2
|
class Compound
|
3
3
|
include Relation
|
4
4
|
|
5
|
-
attr_reader :relation
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
5
|
+
attr_reader :relation, :engine
|
6
|
+
|
7
|
+
def initialize relation
|
8
|
+
@relation = relation
|
9
|
+
@engine = relation.engine
|
10
|
+
@attributes = nil
|
11
|
+
@wheres = nil
|
12
|
+
@groupings = nil
|
13
|
+
@orders = nil
|
14
|
+
@havings = nil
|
15
|
+
@projections = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def join?; @relation.join? end
|
19
|
+
def name; @relation.name end
|
20
|
+
def table_alias; @relation.table_alias end
|
21
|
+
def skipped; @relation.skipped end
|
22
|
+
def taken; @relation.taken end
|
23
|
+
def joins env; @relation.joins env end
|
24
|
+
def column_for attr; @relation.column_for attr end
|
25
|
+
def externalizable?; @relation.externalizable? end
|
26
|
+
|
27
|
+
def sources
|
28
|
+
@relation.sources
|
29
|
+
end
|
30
|
+
|
31
|
+
def table
|
32
|
+
@relation.table
|
33
|
+
end
|
34
|
+
|
35
|
+
def table_sql(formatter = Sql::TableReference.new(self))
|
36
|
+
@relation.table_sql formatter
|
14
37
|
end
|
15
38
|
|
16
39
|
[:wheres, :groupings, :orders, :havings, :projections].each do |operation_name|
|
@@ -25,30 +48,8 @@ module Arel
|
|
25
48
|
@attributes ||= relation.attributes.bind(self)
|
26
49
|
end
|
27
50
|
|
28
|
-
def
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def eql?(other)
|
33
|
-
self == other
|
34
|
-
end
|
35
|
-
|
36
|
-
def engine
|
37
|
-
requires = self.class.requires
|
38
|
-
engine = relation.engine
|
39
|
-
|
40
|
-
# Temporary check of whether or not the engine supports where.
|
41
|
-
if requires && engine.respond_to?(:supports) && !engine.supports(requires)
|
42
|
-
Memory::Engine.new
|
43
|
-
else
|
44
|
-
engine
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def arguments_from_block(relation, &block)
|
51
|
-
block_given?? [yield(relation)] : []
|
51
|
+
def unoperated_rows
|
52
|
+
relation.call.collect { |row| row.bind(self) }
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
class Externalization < Compound
|
3
|
-
|
4
|
-
|
3
|
+
include Recursion::BaseCase
|
4
|
+
|
5
|
+
def == other
|
6
|
+
super || Externalization === other && relation == other.relation
|
7
|
+
end
|
5
8
|
|
6
9
|
def wheres
|
7
10
|
[]
|
@@ -10,15 +13,14 @@ module Arel
|
|
10
13
|
def attributes
|
11
14
|
@attributes ||= Header.new(relation.attributes.map { |a| a.to_attribute(self) })
|
12
15
|
end
|
13
|
-
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
@externalized ||= externalizable?? Externalization.new(self) : self
|
17
|
+
def table_sql(formatter = Sql::TableReference.new(relation))
|
18
|
+
formatter.select relation.compiler.select_sql, self
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
# REMOVEME
|
22
|
+
def name
|
23
|
+
relation.name + '_external'
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,36 +1,47 @@
|
|
1
1
|
module Arel
|
2
|
-
class
|
3
|
-
|
4
|
-
deriving :initialize, :==
|
2
|
+
class Action < Compound
|
3
|
+
end
|
5
4
|
|
5
|
+
class Deletion < Action
|
6
6
|
def call
|
7
7
|
engine.delete(self)
|
8
8
|
end
|
9
|
+
|
10
|
+
def to_sql
|
11
|
+
compiler.delete_sql
|
12
|
+
end
|
9
13
|
end
|
10
14
|
|
11
|
-
class Insert <
|
12
|
-
|
13
|
-
deriving :==
|
15
|
+
class Insert < Action
|
16
|
+
attr_reader :record
|
14
17
|
|
15
18
|
def initialize(relation, record)
|
16
|
-
|
19
|
+
super(relation)
|
20
|
+
@record = record.bind(relation)
|
17
21
|
end
|
18
22
|
|
19
23
|
def call
|
20
24
|
engine.create(self)
|
21
25
|
end
|
22
|
-
end
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
def eval
|
28
|
+
unoperated_rows + [Row.new(self, record.values.collect(&:value))]
|
29
|
+
end
|
27
30
|
|
28
|
-
def
|
29
|
-
|
31
|
+
def to_sql(include_returning = true)
|
32
|
+
compiler.insert_sql(include_returning)
|
30
33
|
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Update < Insert
|
37
|
+
alias :assignments :record
|
31
38
|
|
32
39
|
def call
|
33
40
|
engine.update(self)
|
34
41
|
end
|
42
|
+
|
43
|
+
def to_sql
|
44
|
+
compiler.update_sql
|
45
|
+
end
|
35
46
|
end
|
36
47
|
end
|
data/lib/arel/algebra/value.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
module Arel
|
2
2
|
class Value
|
3
|
-
|
4
|
-
|
3
|
+
attr_reader :value, :relation
|
4
|
+
|
5
|
+
def initialize value, relation
|
6
|
+
@value = value
|
7
|
+
@relation = relation
|
8
|
+
end
|
9
|
+
|
10
|
+
def == other
|
11
|
+
super ||
|
12
|
+
Value === other &&
|
13
|
+
value == other.value &&
|
14
|
+
relation == other.relation
|
15
|
+
end
|
16
|
+
|
17
|
+
def eval(row)
|
18
|
+
value
|
19
|
+
end
|
5
20
|
|
6
21
|
def bind(relation)
|
7
22
|
Value.new(value, relation)
|
@@ -10,5 +25,29 @@ module Arel
|
|
10
25
|
def to_ordering
|
11
26
|
self
|
12
27
|
end
|
28
|
+
|
29
|
+
def inclusion_predicate_sql
|
30
|
+
value.inclusion_predicate_sql
|
31
|
+
end
|
32
|
+
|
33
|
+
def exclusion_predicate_sql
|
34
|
+
value.exclusion_predicate_sql
|
35
|
+
end
|
36
|
+
|
37
|
+
def equality_predicate_sql
|
38
|
+
value.equality_predicate_sql
|
39
|
+
end
|
40
|
+
|
41
|
+
def inequality_predicate_sql
|
42
|
+
value.inequality_predicate_sql
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_sql(formatter = Sql::WhereCondition.new(relation))
|
46
|
+
formatter.value value
|
47
|
+
end
|
48
|
+
|
49
|
+
def format(object)
|
50
|
+
object.to_sql(Sql::Value.new(relation))
|
51
|
+
end
|
13
52
|
end
|
14
53
|
end
|
data/lib/arel/engines/memory.rb
CHANGED
@@ -1,16 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
module Memory
|
3
3
|
class Engine
|
4
|
-
|
5
|
-
|
6
|
-
relation.eval
|
7
|
-
end
|
8
|
-
|
9
|
-
def create(relation)
|
10
|
-
relation.eval
|
11
|
-
end
|
4
|
+
def read(relation)
|
5
|
+
relation.eval
|
12
6
|
end
|
13
|
-
|
7
|
+
alias :create :read
|
14
8
|
end
|
15
9
|
end
|
16
10
|
end
|
@@ -2,12 +2,14 @@ module Arel
|
|
2
2
|
class Array
|
3
3
|
include Relation
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :array, :attribute_names_and_types
|
6
6
|
include Recursion::BaseCase
|
7
|
-
deriving :==, :initialize
|
8
7
|
|
9
8
|
def initialize(array, attribute_names_and_types)
|
10
|
-
@array
|
9
|
+
@array = array
|
10
|
+
@attribute_names_and_types = attribute_names_and_types
|
11
|
+
@engine = nil
|
12
|
+
@attributes = nil
|
11
13
|
end
|
12
14
|
|
13
15
|
def engine
|
@@ -1,67 +1,9 @@
|
|
1
1
|
module Arel
|
2
|
-
class Where < Compound
|
3
|
-
def eval
|
4
|
-
unoperated_rows.select { |row| predicates.all? { |p| p.eval(row) } }
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
class Order < Compound
|
9
|
-
def eval
|
10
|
-
unoperated_rows.sort do |row1, row2|
|
11
|
-
ordering = orders.detect { |o| o.eval(row1, row2) != 0 } || orders.last
|
12
|
-
ordering.eval(row1, row2)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Project < Compound
|
18
|
-
def eval
|
19
|
-
unoperated_rows.collect { |r| r.slice(*projections) }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Take < Compound
|
24
|
-
def eval
|
25
|
-
unoperated_rows[0, taken]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class Skip < Compound
|
30
|
-
def eval
|
31
|
-
unoperated_rows[skipped..-1]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class From < Compound
|
36
|
-
def eval
|
37
|
-
unoperated_rows[sources..-1]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
class Group < Compound
|
42
|
-
def eval
|
43
|
-
raise NotImplementedError
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
2
|
class Alias < Compound
|
48
|
-
|
49
|
-
unoperated_rows
|
50
|
-
end
|
51
|
-
end
|
3
|
+
include Recursion::BaseCase
|
52
4
|
|
53
|
-
class Join
|
54
5
|
def eval
|
55
|
-
|
56
|
-
relation1.call.each do |row1|
|
57
|
-
relation2.call.each do |row2|
|
58
|
-
combined_row = row1.combine(row2, self)
|
59
|
-
if predicates.all? { |p| p.eval(combined_row) }
|
60
|
-
result << combined_row
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
result
|
6
|
+
unoperated_rows
|
65
7
|
end
|
66
8
|
end
|
67
9
|
end
|
data/lib/arel/engines/sql.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'arel/engines/sql/attributes'
|
2
2
|
require 'arel/engines/sql/engine'
|
3
3
|
require 'arel/engines/sql/relations'
|
4
|
-
require 'arel/engines/sql/primitives'
|
5
|
-
require 'arel/engines/sql/predicates'
|
6
4
|
require 'arel/engines/sql/formatters'
|
7
5
|
require 'arel/engines/sql/core_extensions'
|
8
6
|
require 'arel/engines/sql/christener'
|
@@ -1,13 +1,19 @@
|
|
1
1
|
module Arel
|
2
2
|
module Sql
|
3
3
|
class Christener
|
4
|
+
def initialize
|
5
|
+
@names = {}
|
6
|
+
end
|
7
|
+
|
4
8
|
def name_for(relation)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
table = relation.table
|
10
|
+
name = table.table_alias || table.name
|
11
|
+
list = @names[name] ||= []
|
12
|
+
|
13
|
+
list << table unless list.include? table
|
14
|
+
|
15
|
+
idx = list.index table
|
16
|
+
name + (idx == 0 ? '' : "_#{idx + 1}")
|
11
17
|
end
|
12
18
|
end
|
13
19
|
end
|
@@ -3,12 +3,20 @@ module Arel
|
|
3
3
|
class OracleCompiler < GenericCompiler
|
4
4
|
|
5
5
|
def select_sql
|
6
|
-
|
6
|
+
select_clauses = relation.select_clauses
|
7
|
+
from_clauses = relation.from_clauses
|
8
|
+
joins = relation.joins(self)
|
9
|
+
where_clauses = relation.where_clauses
|
10
|
+
order_clauses = relation.order_clauses
|
11
|
+
group_clauses = relation.group_clauses
|
12
|
+
having_clauses = relation.having_clauses
|
13
|
+
taken = relation.taken
|
14
|
+
skipped = relation.skipped
|
7
15
|
if limit_or_offset = !taken.blank? || !skipped.blank?
|
8
|
-
# if need to select first records without ORDER BY and GROUP BY
|
16
|
+
# if need to select first records without ORDER BY and GROUP BY and without DISTINCT
|
9
17
|
# then can use simple ROWNUM in WHERE clause
|
10
|
-
if skipped.blank? &&
|
11
|
-
|
18
|
+
if skipped.blank? && group_clauses.blank? && order_clauses.blank? && select_clauses[0] !~ /^DISTINCT /
|
19
|
+
where_clauses << "ROWNUM <= #{taken}" if !taken.blank? && skipped.blank? && group_clauses.blank? && order_clauses.blank?
|
12
20
|
limit_or_offset = false
|
13
21
|
end
|
14
22
|
end
|
@@ -16,13 +24,13 @@ module Arel
|
|
16
24
|
# when limit or offset subquery is used then cannot use FOR UPDATE directly
|
17
25
|
# and need to construct separate subquery for primary key
|
18
26
|
if use_subquery_for_lock = limit_or_offset && !locked.blank?
|
19
|
-
quoted_primary_key = engine.quote_column_name(primary_key)
|
27
|
+
quoted_primary_key = engine.connection.quote_column_name(relation.primary_key)
|
20
28
|
end
|
21
29
|
select_attributes_string = use_subquery_for_lock ? quoted_primary_key : select_clauses.join(', ')
|
22
30
|
|
23
31
|
# OracleEnhanced adapter workaround when ORDER BY is used with columns not
|
24
32
|
# present in DISTINCT columns list
|
25
|
-
order_clauses_array = if select_attributes_string =~ /DISTINCT.*FIRST_VALUE/ && !
|
33
|
+
order_clauses_array = if select_attributes_string =~ /DISTINCT.*FIRST_VALUE/ && !order_clauses.blank?
|
26
34
|
order = order_clauses.join(', ').split(',').map { |s| s.strip }.reject(&:blank?)
|
27
35
|
order = order.zip((0...order.size).to_a).map { |s,i| "alias_#{i}__ #{'DESC' if s =~ /\bdesc$/i}" }
|
28
36
|
else
|
@@ -32,14 +40,14 @@ module Arel
|
|
32
40
|
query = build_query \
|
33
41
|
"SELECT #{select_attributes_string}",
|
34
42
|
"FROM #{from_clauses}",
|
35
|
-
(joins
|
36
|
-
("WHERE #{
|
37
|
-
("GROUP BY #{group_clauses.join(', ')}" unless
|
38
|
-
("HAVING #{having_clauses.join('
|
43
|
+
(joins unless joins.blank? ),
|
44
|
+
("WHERE #{where_clauses.join(' AND ')}" unless where_clauses.blank? ),
|
45
|
+
("GROUP BY #{group_clauses.join(', ')}" unless group_clauses.blank? ),
|
46
|
+
("HAVING #{having_clauses.join(' AND ')}" unless having_clauses.blank? ),
|
39
47
|
("ORDER BY #{order_clauses_array.join(', ')}" unless order_clauses_array.blank? )
|
40
48
|
|
41
49
|
# Use existing method from oracle_enhanced adapter to implement limit and offset using subqueries
|
42
|
-
engine.add_limit_offset!(query, :limit => taken, :offset => skipped) if limit_or_offset
|
50
|
+
engine.connection.add_limit_offset!(query, :limit => taken, :offset => skipped) if limit_or_offset
|
43
51
|
|
44
52
|
if use_subquery_for_lock
|
45
53
|
build_query \
|
@@ -55,25 +63,27 @@ module Arel
|
|
55
63
|
end
|
56
64
|
|
57
65
|
def delete_sql
|
58
|
-
|
59
|
-
|
66
|
+
where_clauses = relation.wheres.collect(&:to_sql)
|
67
|
+
taken = relation.taken
|
68
|
+
where_clauses << "ROWNUM <= #{taken}" unless taken.blank?
|
60
69
|
build_query \
|
61
70
|
"DELETE",
|
62
|
-
"FROM #{table_sql}",
|
63
|
-
("WHERE #{
|
71
|
+
"FROM #{relation.table_sql}",
|
72
|
+
("WHERE #{where_clauses.join(' AND ')}" unless where_clauses.blank? )
|
64
73
|
end
|
65
74
|
|
66
75
|
protected
|
67
76
|
|
68
77
|
def build_update_conditions_sql
|
69
78
|
conditions = ""
|
70
|
-
|
79
|
+
where_clauses = relation.wheres.collect(&:to_sql)
|
80
|
+
taken = relation.taken
|
71
81
|
# if need to select first records without ORDER BY
|
72
82
|
# then can use simple ROWNUM in WHERE clause
|
73
|
-
if !taken.blank? && orders.blank?
|
74
|
-
|
83
|
+
if !taken.blank? && relation.orders.blank?
|
84
|
+
where_clauses << "ROWNUM <= #{taken}"
|
75
85
|
end
|
76
|
-
conditions << " WHERE #{
|
86
|
+
conditions << " WHERE #{where_clauses.join(' AND ')}" unless where_clauses.blank?
|
77
87
|
unless taken.blank?
|
78
88
|
conditions = limited_update_conditions(conditions, taken)
|
79
89
|
end
|
@@ -81,12 +91,13 @@ module Arel
|
|
81
91
|
end
|
82
92
|
|
83
93
|
def limited_update_conditions(conditions, taken)
|
94
|
+
order_clauses = relation.order_clauses
|
84
95
|
# need to add ORDER BY only if just taken ones should be updated
|
85
|
-
conditions << " ORDER BY #{order_clauses.join(', ')}" unless
|
86
|
-
quoted_primary_key = engine.quote_column_name(primary_key)
|
87
|
-
subquery = "SELECT #{quoted_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions}"
|
96
|
+
conditions << " ORDER BY #{order_clauses.join(', ')}" unless order_clauses.blank?
|
97
|
+
quoted_primary_key = engine.connection.quote_column_name(relation.primary_key)
|
98
|
+
subquery = "SELECT #{quoted_primary_key} FROM #{engine.connection.quote_table_name relation.table.name} #{conditions}"
|
88
99
|
# Use existing method from oracle_enhanced adapter to get taken records when ORDER BY is used
|
89
|
-
engine.add_limit_offset!(subquery, :limit => taken) unless
|
100
|
+
engine.connection.add_limit_offset!(subquery, :limit => taken) unless order_clauses.blank?
|
90
101
|
"WHERE #{quoted_primary_key} IN (#{subquery})"
|
91
102
|
end
|
92
103
|
|