arel-compat 0.4.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 +25 -0
- data/README.markdown +182 -0
- data/lib/arel.rb +13 -0
- data/lib/arel/algebra.rb +10 -0
- data/lib/arel/algebra/attributes.rb +7 -0
- data/lib/arel/algebra/attributes/attribute.rb +270 -0
- data/lib/arel/algebra/attributes/boolean.rb +21 -0
- data/lib/arel/algebra/attributes/decimal.rb +9 -0
- data/lib/arel/algebra/attributes/float.rb +9 -0
- data/lib/arel/algebra/attributes/integer.rb +10 -0
- data/lib/arel/algebra/attributes/string.rb +10 -0
- data/lib/arel/algebra/attributes/time.rb +6 -0
- data/lib/arel/algebra/core_extensions.rb +4 -0
- data/lib/arel/algebra/core_extensions/class.rb +32 -0
- data/lib/arel/algebra/core_extensions/hash.rb +11 -0
- data/lib/arel/algebra/core_extensions/object.rb +30 -0
- data/lib/arel/algebra/core_extensions/symbol.rb +9 -0
- data/lib/arel/algebra/expression.rb +43 -0
- data/lib/arel/algebra/header.rb +67 -0
- data/lib/arel/algebra/ordering.rb +23 -0
- data/lib/arel/algebra/predicates.rb +190 -0
- data/lib/arel/algebra/relations.rb +17 -0
- data/lib/arel/algebra/relations/operations/alias.rb +7 -0
- data/lib/arel/algebra/relations/operations/from.rb +6 -0
- data/lib/arel/algebra/relations/operations/group.rb +12 -0
- data/lib/arel/algebra/relations/operations/having.rb +17 -0
- data/lib/arel/algebra/relations/operations/join.rb +69 -0
- data/lib/arel/algebra/relations/operations/lock.rb +12 -0
- data/lib/arel/algebra/relations/operations/order.rb +19 -0
- data/lib/arel/algebra/relations/operations/project.rb +20 -0
- data/lib/arel/algebra/relations/operations/skip.rb +7 -0
- data/lib/arel/algebra/relations/operations/take.rb +11 -0
- data/lib/arel/algebra/relations/operations/where.rb +17 -0
- data/lib/arel/algebra/relations/relation.rb +136 -0
- data/lib/arel/algebra/relations/row.rb +26 -0
- data/lib/arel/algebra/relations/utilities/compound.rb +54 -0
- data/lib/arel/algebra/relations/utilities/externalization.rb +24 -0
- data/lib/arel/algebra/relations/utilities/nil.rb +7 -0
- data/lib/arel/algebra/relations/writes.rb +36 -0
- data/lib/arel/algebra/value.rb +14 -0
- data/lib/arel/engines.rb +2 -0
- data/lib/arel/engines/memory.rb +4 -0
- data/lib/arel/engines/memory/engine.rb +16 -0
- data/lib/arel/engines/memory/predicates.rb +99 -0
- data/lib/arel/engines/memory/primitives.rb +27 -0
- data/lib/arel/engines/memory/relations.rb +5 -0
- data/lib/arel/engines/memory/relations/array.rb +35 -0
- data/lib/arel/engines/memory/relations/compound.rb +9 -0
- data/lib/arel/engines/memory/relations/operations.rb +67 -0
- data/lib/arel/engines/memory/relations/writes.rb +7 -0
- data/lib/arel/engines/sql.rb +8 -0
- data/lib/arel/engines/sql/attributes.rb +40 -0
- data/lib/arel/engines/sql/christener.rb +14 -0
- data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +48 -0
- data/lib/arel/engines/sql/compilers/mysql_compiler.rb +11 -0
- data/lib/arel/engines/sql/compilers/oracle_compiler.rb +95 -0
- data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +42 -0
- data/lib/arel/engines/sql/compilers/sqlite_compiler.rb +9 -0
- data/lib/arel/engines/sql/core_extensions.rb +4 -0
- data/lib/arel/engines/sql/core_extensions/array.rb +24 -0
- data/lib/arel/engines/sql/core_extensions/nil_class.rb +15 -0
- data/lib/arel/engines/sql/core_extensions/object.rb +19 -0
- data/lib/arel/engines/sql/core_extensions/range.rb +19 -0
- data/lib/arel/engines/sql/engine.rb +55 -0
- data/lib/arel/engines/sql/formatters.rb +122 -0
- data/lib/arel/engines/sql/predicates.rb +103 -0
- data/lib/arel/engines/sql/primitives.rb +97 -0
- data/lib/arel/engines/sql/relations.rb +10 -0
- data/lib/arel/engines/sql/relations/compiler.rb +118 -0
- data/lib/arel/engines/sql/relations/operations/alias.rb +5 -0
- data/lib/arel/engines/sql/relations/operations/join.rb +33 -0
- data/lib/arel/engines/sql/relations/relation.rb +65 -0
- data/lib/arel/engines/sql/relations/table.rb +88 -0
- data/lib/arel/engines/sql/relations/utilities/compound.rb +10 -0
- data/lib/arel/engines/sql/relations/utilities/externalization.rb +14 -0
- data/lib/arel/engines/sql/relations/utilities/nil.rb +6 -0
- data/lib/arel/engines/sql/relations/utilities/recursion.rb +13 -0
- data/lib/arel/engines/sql/relations/writes.rb +19 -0
- data/lib/arel/session.rb +51 -0
- data/lib/arel/version.rb +3 -0
- data/spec/algebra/unit/predicates/binary_spec.rb +35 -0
- data/spec/algebra/unit/predicates/equality_spec.rb +29 -0
- data/spec/algebra/unit/predicates/in_spec.rb +12 -0
- data/spec/algebra/unit/primitives/attribute_spec.rb +181 -0
- data/spec/algebra/unit/primitives/expression_spec.rb +45 -0
- data/spec/algebra/unit/primitives/value_spec.rb +15 -0
- data/spec/algebra/unit/relations/alias_spec.rb +16 -0
- data/spec/algebra/unit/relations/delete_spec.rb +9 -0
- data/spec/algebra/unit/relations/group_spec.rb +10 -0
- data/spec/algebra/unit/relations/insert_spec.rb +9 -0
- data/spec/algebra/unit/relations/join_spec.rb +25 -0
- data/spec/algebra/unit/relations/order_spec.rb +21 -0
- data/spec/algebra/unit/relations/project_spec.rb +34 -0
- data/spec/algebra/unit/relations/relation_spec.rb +187 -0
- data/spec/algebra/unit/relations/skip_spec.rb +10 -0
- data/spec/algebra/unit/relations/table_spec.rb +38 -0
- data/spec/algebra/unit/relations/take_spec.rb +10 -0
- data/spec/algebra/unit/relations/update_spec.rb +9 -0
- data/spec/algebra/unit/relations/where_spec.rb +19 -0
- data/spec/algebra/unit/session/session_spec.rb +84 -0
- data/spec/attributes/boolean_spec.rb +57 -0
- data/spec/attributes/float_spec.rb +119 -0
- data/spec/attributes/header_spec.rb +42 -0
- data/spec/attributes/integer_spec.rb +119 -0
- data/spec/attributes/string_spec.rb +43 -0
- data/spec/attributes/time_spec.rb +24 -0
- data/spec/engines/memory/integration/joins/cross_engine_spec.rb +51 -0
- data/spec/engines/memory/unit/relations/array_spec.rb +32 -0
- data/spec/engines/memory/unit/relations/insert_spec.rb +28 -0
- data/spec/engines/memory/unit/relations/join_spec.rb +31 -0
- data/spec/engines/memory/unit/relations/order_spec.rb +27 -0
- data/spec/engines/memory/unit/relations/project_spec.rb +27 -0
- data/spec/engines/memory/unit/relations/skip_spec.rb +26 -0
- data/spec/engines/memory/unit/relations/take_spec.rb +26 -0
- data/spec/engines/memory/unit/relations/where_spec.rb +39 -0
- data/spec/engines/sql/integration/joins/with_adjacency_spec.rb +258 -0
- data/spec/engines/sql/integration/joins/with_aggregations_spec.rb +221 -0
- data/spec/engines/sql/integration/joins/with_compounds_spec.rb +137 -0
- data/spec/engines/sql/unit/engine_spec.rb +45 -0
- data/spec/engines/sql/unit/predicates/binary_spec.rb +140 -0
- data/spec/engines/sql/unit/predicates/equality_spec.rb +75 -0
- data/spec/engines/sql/unit/predicates/in_spec.rb +179 -0
- data/spec/engines/sql/unit/predicates/noteq_spec.rb +75 -0
- data/spec/engines/sql/unit/predicates/predicates_spec.rb +79 -0
- data/spec/engines/sql/unit/primitives/attribute_spec.rb +36 -0
- data/spec/engines/sql/unit/primitives/expression_spec.rb +28 -0
- data/spec/engines/sql/unit/primitives/literal_spec.rb +43 -0
- data/spec/engines/sql/unit/primitives/value_spec.rb +29 -0
- data/spec/engines/sql/unit/relations/alias_spec.rb +53 -0
- data/spec/engines/sql/unit/relations/delete_spec.rb +83 -0
- data/spec/engines/sql/unit/relations/from_spec.rb +64 -0
- data/spec/engines/sql/unit/relations/group_spec.rb +72 -0
- data/spec/engines/sql/unit/relations/having_spec.rb +78 -0
- data/spec/engines/sql/unit/relations/insert_spec.rb +143 -0
- data/spec/engines/sql/unit/relations/join_spec.rb +180 -0
- data/spec/engines/sql/unit/relations/lock_spec.rb +86 -0
- data/spec/engines/sql/unit/relations/order_spec.rb +161 -0
- data/spec/engines/sql/unit/relations/project_spec.rb +143 -0
- data/spec/engines/sql/unit/relations/skip_spec.rb +41 -0
- data/spec/engines/sql/unit/relations/table_spec.rb +129 -0
- data/spec/engines/sql/unit/relations/take_spec.rb +49 -0
- data/spec/engines/sql/unit/relations/update_spec.rb +203 -0
- data/spec/engines/sql/unit/relations/where_spec.rb +72 -0
- data/spec/relations/join_spec.rb +42 -0
- data/spec/relations/relation_spec.rb +31 -0
- data/spec/shared/relation_spec.rb +255 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/check.rb +6 -0
- data/spec/support/connections/mysql_connection.rb +14 -0
- data/spec/support/connections/oracle_connection.rb +17 -0
- data/spec/support/connections/postgresql_connection.rb +13 -0
- data/spec/support/connections/sqlite3_connection.rb +24 -0
- data/spec/support/guards.rb +28 -0
- data/spec/support/matchers.rb +4 -0
- data/spec/support/matchers/be_like.rb +24 -0
- data/spec/support/matchers/disambiguate_attributes.rb +28 -0
- data/spec/support/matchers/hash_the_same_as.rb +26 -0
- data/spec/support/matchers/have_rows.rb +18 -0
- data/spec/support/model.rb +62 -0
- data/spec/support/schemas/mysql_schema.rb +26 -0
- data/spec/support/schemas/oracle_schema.rb +20 -0
- data/spec/support/schemas/postgresql_schema.rb +26 -0
- data/spec/support/schemas/sqlite3_schema.rb +26 -0
- metadata +258 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
module Arel
|
2
|
+
module SqlCompiler
|
3
|
+
class OracleCompiler < GenericCompiler
|
4
|
+
|
5
|
+
def select_sql
|
6
|
+
where_clauses_array = where_clauses
|
7
|
+
if limit_or_offset = !taken.blank? || !skipped.blank?
|
8
|
+
# if need to select first records without ORDER BY and GROUP BY
|
9
|
+
# then can use simple ROWNUM in WHERE clause
|
10
|
+
if skipped.blank? && groupings.blank? && orders.blank?
|
11
|
+
where_clauses_array << "ROWNUM <= #{taken}" if !taken.blank? && skipped.blank? && groupings.blank? && orders.blank?
|
12
|
+
limit_or_offset = false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# when limit or offset subquery is used then cannot use FOR UPDATE directly
|
17
|
+
# and need to construct separate subquery for primary key
|
18
|
+
if use_subquery_for_lock = limit_or_offset && !locked.blank?
|
19
|
+
quoted_primary_key = engine.quote_column_name(primary_key)
|
20
|
+
end
|
21
|
+
select_attributes_string = use_subquery_for_lock ? quoted_primary_key : select_clauses.join(', ')
|
22
|
+
|
23
|
+
# OracleEnhanced adapter workaround when ORDER BY is used with columns not
|
24
|
+
# present in DISTINCT columns list
|
25
|
+
order_clauses_array = if select_attributes_string =~ /DISTINCT.*FIRST_VALUE/ && !orders.blank?
|
26
|
+
order = order_clauses.join(', ').split(',').map { |s| s.strip }.reject(&:blank?)
|
27
|
+
order = order.zip((0...order.size).to_a).map { |s,i| "alias_#{i}__ #{'DESC' if s =~ /\bdesc$/i}" }
|
28
|
+
else
|
29
|
+
order_clauses
|
30
|
+
end
|
31
|
+
|
32
|
+
query = build_query \
|
33
|
+
"SELECT #{select_attributes_string}",
|
34
|
+
"FROM #{from_clauses}",
|
35
|
+
(joins(self) unless joins(self).blank? ),
|
36
|
+
("WHERE #{where_clauses_array.join(" AND ")}" unless where_clauses_array.blank? ),
|
37
|
+
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
38
|
+
("HAVING #{having_clauses.join(', ')}" unless havings.blank? ),
|
39
|
+
("ORDER BY #{order_clauses_array.join(', ')}" unless order_clauses_array.blank? )
|
40
|
+
|
41
|
+
# 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
|
43
|
+
|
44
|
+
if use_subquery_for_lock
|
45
|
+
build_query \
|
46
|
+
"SELECT #{select_clauses.join(', ')}",
|
47
|
+
"FROM #{from_clauses}",
|
48
|
+
"WHERE #{quoted_primary_key} IN (#{query})",
|
49
|
+
"#{locked}"
|
50
|
+
elsif !locked.blank?
|
51
|
+
build_query query, "#{locked}"
|
52
|
+
else
|
53
|
+
query
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete_sql
|
58
|
+
where_clauses_array = wheres.collect(&:to_sql)
|
59
|
+
where_clauses_array << "ROWNUM <= #{taken}" unless taken.blank?
|
60
|
+
build_query \
|
61
|
+
"DELETE",
|
62
|
+
"FROM #{table_sql}",
|
63
|
+
("WHERE #{where_clauses_array.join(' AND ')}" unless where_clauses_array.blank? )
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def build_update_conditions_sql
|
69
|
+
conditions = ""
|
70
|
+
where_clauses_array = wheres.collect(&:to_sql)
|
71
|
+
# if need to select first records without ORDER BY
|
72
|
+
# then can use simple ROWNUM in WHERE clause
|
73
|
+
if !taken.blank? && orders.blank?
|
74
|
+
where_clauses_array << "ROWNUM <= #{taken}"
|
75
|
+
end
|
76
|
+
conditions << " WHERE #{where_clauses_array.join(' AND ')}" unless where_clauses_array.blank?
|
77
|
+
unless taken.blank?
|
78
|
+
conditions = limited_update_conditions(conditions, taken)
|
79
|
+
end
|
80
|
+
conditions
|
81
|
+
end
|
82
|
+
|
83
|
+
def limited_update_conditions(conditions, taken)
|
84
|
+
# need to add ORDER BY only if just taken ones should be updated
|
85
|
+
conditions << " ORDER BY #{order_clauses.join(', ')}" unless orders.blank?
|
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}"
|
88
|
+
# 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 orders.blank?
|
90
|
+
"WHERE #{quoted_primary_key} IN (#{subquery})"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Arel
|
2
|
+
module SqlCompiler
|
3
|
+
class PostgreSQLCompiler < GenericCompiler
|
4
|
+
|
5
|
+
def select_sql
|
6
|
+
if !orders.blank? && using_distinct_on?
|
7
|
+
subquery = build_query \
|
8
|
+
"SELECT #{select_clauses.kind_of?(::Array) ? select_clauses.join("") : select_clauses.to_s}",
|
9
|
+
"FROM #{from_clauses}",
|
10
|
+
(joins(self) unless joins(self).blank? ),
|
11
|
+
("WHERE #{where_clauses.join(" AND ")}" unless wheres.blank? ),
|
12
|
+
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
13
|
+
("HAVING #{having_clauses.join(', ')}" unless havings.blank? ),
|
14
|
+
("#{locked}" unless locked.blank? )
|
15
|
+
|
16
|
+
build_query \
|
17
|
+
"SELECT * FROM (#{subquery}) AS id_list",
|
18
|
+
"ORDER BY #{aliased_orders(order_clauses)}",
|
19
|
+
("LIMIT #{taken}" unless taken.blank? ),
|
20
|
+
("OFFSET #{skipped}" unless skipped.blank? )
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def using_distinct_on?
|
27
|
+
select_clauses.any? { |x| x =~ /DISTINCT ON/ }
|
28
|
+
end
|
29
|
+
|
30
|
+
def aliased_orders(orders)
|
31
|
+
# PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
|
32
|
+
# by wrapping the +sql+ string as a sub-select and ordering in that query.
|
33
|
+
order = orders.join(', ').split(/,/).map { |s| s.strip }.reject(&:blank?)
|
34
|
+
order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{'DESC' if s =~ /\bdesc$/i}" }.join(', ')
|
35
|
+
end
|
36
|
+
|
37
|
+
def supports_insert_with_returning?
|
38
|
+
engine.postgresql_version >= 80200
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
module ArrayExtensions
|
4
|
+
def to_sql(formatter = nil)
|
5
|
+
if any?
|
6
|
+
"(" + collect { |e| e.to_sql(formatter) }.join(', ') + ")"
|
7
|
+
else
|
8
|
+
"(NULL)"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def inclusion_predicate_sql
|
13
|
+
"IN"
|
14
|
+
end
|
15
|
+
|
16
|
+
def exclusion_predicate_sql
|
17
|
+
"NOT IN"
|
18
|
+
end
|
19
|
+
|
20
|
+
Array.send(:include, self)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
module ObjectExtensions
|
4
|
+
def to_sql(formatter)
|
5
|
+
formatter.scalar self
|
6
|
+
end
|
7
|
+
|
8
|
+
def equality_predicate_sql
|
9
|
+
'='
|
10
|
+
end
|
11
|
+
|
12
|
+
def inequality_predicate_sql
|
13
|
+
'!='
|
14
|
+
end
|
15
|
+
|
16
|
+
Object.send(:include, self)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
module RangeExtensions
|
4
|
+
def to_sql(formatter = nil)
|
5
|
+
formatter.range self.begin, self.end
|
6
|
+
end
|
7
|
+
|
8
|
+
def inclusion_predicate_sql
|
9
|
+
"BETWEEN"
|
10
|
+
end
|
11
|
+
|
12
|
+
def exclusion_predicate_sql
|
13
|
+
"NOT BETWEEN"
|
14
|
+
end
|
15
|
+
|
16
|
+
Range.send(:include, self)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
class Engine
|
4
|
+
|
5
|
+
def initialize(ar = nil)
|
6
|
+
@ar = ar
|
7
|
+
end
|
8
|
+
|
9
|
+
def connection
|
10
|
+
@ar ? @ar.connection : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def adapter_name
|
14
|
+
@adapter_name ||= case (name = connection.adapter_name)
|
15
|
+
# map OracleEnanced adapter to Oracle
|
16
|
+
when /Oracle/
|
17
|
+
'Oracle'
|
18
|
+
else
|
19
|
+
name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(method, *args, &block)
|
24
|
+
@ar.connection.send(method, *args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
module CRUD
|
28
|
+
def create(relation)
|
29
|
+
primary_key_value = if relation.primary_key.blank?
|
30
|
+
nil
|
31
|
+
elsif relation.record.is_a?(Hash)
|
32
|
+
attribute = relation.record.detect { |attr, _| attr.name.to_s == relation.primary_key.to_s }
|
33
|
+
attribute && attribute.last.value
|
34
|
+
end
|
35
|
+
|
36
|
+
connection.insert(relation.to_sql(false), nil, relation.primary_key, primary_key_value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def read(relation)
|
40
|
+
rows = connection.select_rows(relation.to_sql)
|
41
|
+
Array.new(rows, relation.attributes)
|
42
|
+
end
|
43
|
+
|
44
|
+
def update(relation)
|
45
|
+
connection.update(relation.to_sql)
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(relation)
|
49
|
+
connection.delete(relation.to_sql)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
include CRUD
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
class Formatter
|
4
|
+
attr_reader :environment
|
5
|
+
delegate :christener, :engine, :to => :environment
|
6
|
+
delegate :name_for, :to => :christener
|
7
|
+
delegate :quote_table_name, :quote_column_name, :quote, :to => :engine
|
8
|
+
|
9
|
+
def initialize(environment)
|
10
|
+
@environment = environment
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class SelectClause < Formatter
|
15
|
+
def attribute(attribute)
|
16
|
+
"#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" +
|
17
|
+
(attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "")
|
18
|
+
end
|
19
|
+
|
20
|
+
def expression(expression)
|
21
|
+
if expression.function_sql == "DISTINCT"
|
22
|
+
"#{expression.function_sql} #{expression.attribute.to_sql(self)}" +
|
23
|
+
(expression.alias ? " AS #{quote_column_name(expression.alias)}" : '')
|
24
|
+
else
|
25
|
+
"#{expression.function_sql}(#{expression.attribute.to_sql(self)})" +
|
26
|
+
(expression.alias ? " AS #{quote_column_name(expression.alias)}" : " AS #{expression.function_sql.to_s.downcase}_id")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def select(select_sql, table)
|
31
|
+
"(#{select_sql}) AS #{quote_table_name(name_for(table))}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def value(value)
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class PassThrough < Formatter
|
40
|
+
def value(value)
|
41
|
+
value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class WhereClause < PassThrough
|
46
|
+
end
|
47
|
+
|
48
|
+
class OrderClause < PassThrough
|
49
|
+
def ordering(ordering)
|
50
|
+
"#{quote_table_name(name_for(ordering.attribute.original_relation))}.#{quote_column_name(ordering.attribute.name)} #{ordering.direction_sql}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class GroupClause < PassThrough
|
55
|
+
def attribute(attribute)
|
56
|
+
"#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class HavingClause < PassThrough
|
61
|
+
def attribute(attribute)
|
62
|
+
attribute
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class WhereCondition < Formatter
|
67
|
+
def attribute(attribute)
|
68
|
+
"#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def expression(expression)
|
72
|
+
"#{expression.function_sql}(#{expression.attribute.to_sql(self)})"
|
73
|
+
end
|
74
|
+
|
75
|
+
def value(value)
|
76
|
+
value.to_sql(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
def scalar(value, column = nil)
|
80
|
+
quote(value, column)
|
81
|
+
end
|
82
|
+
|
83
|
+
def select(select_sql, table)
|
84
|
+
"(#{select_sql})"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class SelectStatement < Formatter
|
89
|
+
def select(select_sql, table)
|
90
|
+
select_sql
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class TableReference < Formatter
|
95
|
+
def select(select_sql, table)
|
96
|
+
"(#{select_sql}) #{quote_table_name(name_for(table))}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def table(table)
|
100
|
+
if table.name =~ /\s/
|
101
|
+
table.name
|
102
|
+
else
|
103
|
+
quote_table_name(table.name) +
|
104
|
+
(table.name != name_for(table) ? " #{quote_table_name(name_for(table))}" : '')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class Attribute < WhereCondition
|
110
|
+
def scalar(scalar)
|
111
|
+
quote(scalar, environment.column)
|
112
|
+
end
|
113
|
+
|
114
|
+
def range(left, right)
|
115
|
+
"#{scalar(left)} AND #{scalar(right)}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Value < WhereCondition
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Arel
|
2
|
+
module Predicates
|
3
|
+
class Binary < Predicate
|
4
|
+
def to_sql(formatter = nil)
|
5
|
+
"#{operand1.to_sql} #{predicate_sql} #{operand1.format(operand2)}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Unary < Predicate
|
10
|
+
def to_sql(formatter = nil)
|
11
|
+
"#{predicate_sql} (#{operand.to_sql(formatter)})"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Not < Unary
|
16
|
+
def predicate_sql; "NOT" end
|
17
|
+
end
|
18
|
+
|
19
|
+
class CompoundPredicate < Binary
|
20
|
+
def to_sql(formatter = nil)
|
21
|
+
"(#{operand1.to_sql(formatter)} #{predicate_sql} #{operand2.to_sql(formatter)})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Or < CompoundPredicate
|
26
|
+
def predicate_sql; "OR" end
|
27
|
+
end
|
28
|
+
|
29
|
+
class And < CompoundPredicate
|
30
|
+
def predicate_sql; "AND" end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Polyadic < Predicate
|
34
|
+
def to_sql(formatter = nil)
|
35
|
+
"(" +
|
36
|
+
predicates.map {|p| p.to_sql(formatter)}.join(" #{predicate_sql} ") +
|
37
|
+
")"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Any < Polyadic
|
42
|
+
def predicate_sql; "OR" end
|
43
|
+
end
|
44
|
+
|
45
|
+
class All < Polyadic
|
46
|
+
def predicate_sql; "AND" end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Equality < Binary
|
50
|
+
def predicate_sql
|
51
|
+
operand2.equality_predicate_sql
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Inequality < Binary
|
56
|
+
def predicate_sql
|
57
|
+
operand2.inequality_predicate_sql
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class GreaterThanOrEqualTo < Binary
|
62
|
+
def predicate_sql; '>=' end
|
63
|
+
end
|
64
|
+
|
65
|
+
class GreaterThan < Binary
|
66
|
+
def predicate_sql; '>' end
|
67
|
+
end
|
68
|
+
|
69
|
+
class LessThanOrEqualTo < Binary
|
70
|
+
def predicate_sql; '<=' end
|
71
|
+
end
|
72
|
+
|
73
|
+
class LessThan < Binary
|
74
|
+
def predicate_sql; '<' end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Match < Binary
|
78
|
+
def predicate_sql; 'LIKE' end
|
79
|
+
end
|
80
|
+
|
81
|
+
class NotMatch < Binary
|
82
|
+
def predicate_sql; 'NOT LIKE' end
|
83
|
+
end
|
84
|
+
|
85
|
+
class In < Binary
|
86
|
+
def to_sql(formatter = nil)
|
87
|
+
if operand2.is_a?(Range) && operand2.exclude_end?
|
88
|
+
GreaterThanOrEqualTo.new(operand1, operand2.begin).and(
|
89
|
+
LessThan.new(operand1, operand2.end)
|
90
|
+
).to_sql(formatter)
|
91
|
+
else
|
92
|
+
super
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def predicate_sql; operand2.inclusion_predicate_sql end
|
97
|
+
end
|
98
|
+
|
99
|
+
class NotIn < Binary
|
100
|
+
def predicate_sql; operand2.exclusion_predicate_sql end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|