arel 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/README.markdown +0 -2
- data/Rakefile +2 -2
- data/arel.gemspec +13 -3
- data/lib/arel.rb +2 -2
- data/lib/arel/algebra/relations/relation.rb +3 -2
- data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +62 -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/engine.rb +17 -3
- data/lib/arel/engines/sql/formatters.rb +3 -3
- data/lib/arel/engines/sql/relations.rb +1 -0
- data/lib/arel/engines/sql/relations/compiler.rb +118 -0
- data/lib/arel/engines/sql/relations/relation.rb +38 -63
- data/lib/arel/engines/sql/relations/table.rb +23 -3
- data/lib/arel/engines/sql/relations/utilities/externalization.rb +1 -1
- data/lib/arel/engines/sql/relations/writes.rb +4 -71
- data/spec/arel/algebra/unit/relations/relation_spec.rb +1 -2
- data/spec/arel/algebra/unit/relations/table_spec.rb +0 -1
- data/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb +9 -4
- data/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb +68 -19
- data/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb +74 -20
- data/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb +33 -3
- data/spec/arel/engines/sql/unit/predicates/binary_spec.rb +22 -2
- data/spec/arel/engines/sql/unit/predicates/equality_spec.rb +15 -3
- data/spec/arel/engines/sql/unit/predicates/in_spec.rb +59 -5
- data/spec/arel/engines/sql/unit/predicates/predicates_spec.rb +12 -0
- data/spec/arel/engines/sql/unit/primitives/attribute_spec.rb +24 -1
- data/spec/arel/engines/sql/unit/primitives/expression_spec.rb +5 -1
- data/spec/arel/engines/sql/unit/primitives/literal_spec.rb +10 -2
- data/spec/arel/engines/sql/unit/relations/alias_spec.rb +11 -1
- data/spec/arel/engines/sql/unit/relations/delete_spec.rb +23 -3
- data/spec/arel/engines/sql/unit/relations/from_spec.rb +16 -2
- data/spec/arel/engines/sql/unit/relations/group_spec.rb +18 -2
- data/spec/arel/engines/sql/unit/relations/having_spec.rb +12 -3
- data/spec/arel/engines/sql/unit/relations/insert_spec.rb +37 -1
- data/spec/arel/engines/sql/unit/relations/join_spec.rb +53 -11
- data/spec/arel/engines/sql/unit/relations/lock_spec.rb +25 -0
- data/spec/arel/engines/sql/unit/relations/order_spec.rb +52 -4
- data/spec/arel/engines/sql/unit/relations/project_spec.rb +38 -5
- data/spec/arel/engines/sql/unit/relations/skip_spec.rb +10 -1
- data/spec/arel/engines/sql/unit/relations/table_spec.rb +26 -5
- data/spec/arel/engines/sql/unit/relations/take_spec.rb +18 -1
- data/spec/arel/engines/sql/unit/relations/update_spec.rb +47 -1
- data/spec/arel/engines/sql/unit/relations/where_spec.rb +18 -2
- data/spec/connections/oracle_connection.rb +19 -0
- data/spec/schemas/mysql_schema.rb +2 -1
- data/spec/schemas/oracle_schema.rb +20 -0
- data/spec/schemas/postgresql_schema.rb +2 -1
- data/spec/schemas/sqlite3_schema.rb +2 -1
- data/spec/spec_helper.rb +16 -7
- metadata +31 -9
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 0.3.0 / 2010-02-05
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
|
5
|
+
* Introduced "SQL compilers" for query generation.
|
6
|
+
* Added support for Oracle (Raimonds Simanovskis) and IBM/DB (Praveen Devarao).
|
7
|
+
* Improvements to give better support to ActiveRecord.
|
8
|
+
|
1
9
|
== 0.2.1 / 2010-02-05
|
2
10
|
|
3
11
|
* Enhancements
|
data/README.markdown
CHANGED
@@ -4,8 +4,6 @@ Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex o
|
|
4
4
|
|
5
5
|
## Status ##
|
6
6
|
|
7
|
-
Arel is alpha software, BEWARE. Nevertheless, at this point, many (most?) SELECT queries can be composed, including very very complicated ones. Writes are only experimental for now.
|
8
|
-
|
9
7
|
For the moment, Arel uses ActiveRecord's connection adapters to connect to the various engines, connection pooling, perform quoting, and do type conversion. On the horizon is the use of DataObjects instead.
|
10
8
|
|
11
9
|
The long term goal, following both LINQ and DataMapper, is to have Arel adapt to engines beyond RDBMS, including XML, IMAP, YAML, etc.
|
data/Rakefile
CHANGED
@@ -20,13 +20,13 @@ else
|
|
20
20
|
end
|
21
21
|
|
22
22
|
namespace :spec do
|
23
|
-
for adapter in %w[mysql sqlite3 postgresql]
|
23
|
+
for adapter in %w[mysql sqlite3 postgresql oracle]
|
24
24
|
desc "Run specs with the #{adapter} database adapter"
|
25
25
|
Spec::Rake::SpecTask.new(adapter) do |t|
|
26
26
|
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
27
27
|
t.libs << "#{File.dirname(__FILE__)}/vendor/rails/activerecord/lib"
|
28
28
|
t.libs << "#{File.dirname(__FILE__)}/spec"
|
29
|
-
t.warning = true
|
29
|
+
# t.warning = true
|
30
30
|
t.spec_files =
|
31
31
|
["spec/connections/#{adapter}_connection.rb"] +
|
32
32
|
["spec/schemas/#{adapter}_schema.rb"] +
|
data/arel.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{arel}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.3.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Bryan Helmkamp", "Nick Kallen", "Emilio Tagua"]
|
9
|
-
s.date = %q{2010-
|
9
|
+
s.date = %q{2010-03-10}
|
10
10
|
s.description = %q{Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex
|
11
11
|
of SQL queries and it 2) adapts to various RDBMS systems. It is intended to be
|
12
12
|
a framework framework; that is, you can build your own ORM with it, focusing on
|
@@ -69,6 +69,11 @@ and query generation.}
|
|
69
69
|
"lib/arel/engines/memory/relations/writes.rb",
|
70
70
|
"lib/arel/engines/sql.rb",
|
71
71
|
"lib/arel/engines/sql/christener.rb",
|
72
|
+
"lib/arel/engines/sql/compilers/ibm_db_compiler.rb",
|
73
|
+
"lib/arel/engines/sql/compilers/mysql_compiler.rb",
|
74
|
+
"lib/arel/engines/sql/compilers/oracle_compiler.rb",
|
75
|
+
"lib/arel/engines/sql/compilers/postgresql_compiler.rb",
|
76
|
+
"lib/arel/engines/sql/compilers/sqlite_compiler.rb",
|
72
77
|
"lib/arel/engines/sql/core_extensions.rb",
|
73
78
|
"lib/arel/engines/sql/core_extensions/array.rb",
|
74
79
|
"lib/arel/engines/sql/core_extensions/nil_class.rb",
|
@@ -79,6 +84,7 @@ and query generation.}
|
|
79
84
|
"lib/arel/engines/sql/predicates.rb",
|
80
85
|
"lib/arel/engines/sql/primitives.rb",
|
81
86
|
"lib/arel/engines/sql/relations.rb",
|
87
|
+
"lib/arel/engines/sql/relations/compiler.rb",
|
82
88
|
"lib/arel/engines/sql/relations/operations/alias.rb",
|
83
89
|
"lib/arel/engines/sql/relations/operations/join.rb",
|
84
90
|
"lib/arel/engines/sql/relations/relation.rb",
|
@@ -146,6 +152,7 @@ and query generation.}
|
|
146
152
|
"spec/arel/engines/sql/unit/relations/update_spec.rb",
|
147
153
|
"spec/arel/engines/sql/unit/relations/where_spec.rb",
|
148
154
|
"spec/connections/mysql_connection.rb",
|
155
|
+
"spec/connections/oracle_connection.rb",
|
149
156
|
"spec/connections/postgresql_connection.rb",
|
150
157
|
"spec/connections/sqlite3_connection.rb",
|
151
158
|
"spec/doubles/hash.rb",
|
@@ -153,6 +160,7 @@ and query generation.}
|
|
153
160
|
"spec/matchers/disambiguate_attributes.rb",
|
154
161
|
"spec/matchers/hash_the_same_as.rb",
|
155
162
|
"spec/schemas/mysql_schema.rb",
|
163
|
+
"spec/schemas/oracle_schema.rb",
|
156
164
|
"spec/schemas/postgresql_schema.rb",
|
157
165
|
"spec/schemas/sqlite3_schema.rb",
|
158
166
|
"spec/spec.opts",
|
@@ -161,7 +169,7 @@ and query generation.}
|
|
161
169
|
s.homepage = %q{http://github.com/brynary/arel}
|
162
170
|
s.require_paths = ["lib"]
|
163
171
|
s.rubyforge_project = %q{arel}
|
164
|
-
s.rubygems_version = %q{1.3.
|
172
|
+
s.rubygems_version = %q{1.3.6}
|
165
173
|
s.summary = %q{Arel is a relational algebra engine for Ruby}
|
166
174
|
s.test_files = [
|
167
175
|
"spec/arel/algebra/unit/predicates/binary_spec.rb",
|
@@ -221,6 +229,7 @@ and query generation.}
|
|
221
229
|
"spec/arel/engines/sql/unit/relations/update_spec.rb",
|
222
230
|
"spec/arel/engines/sql/unit/relations/where_spec.rb",
|
223
231
|
"spec/connections/mysql_connection.rb",
|
232
|
+
"spec/connections/oracle_connection.rb",
|
224
233
|
"spec/connections/postgresql_connection.rb",
|
225
234
|
"spec/connections/sqlite3_connection.rb",
|
226
235
|
"spec/doubles/hash.rb",
|
@@ -228,6 +237,7 @@ and query generation.}
|
|
228
237
|
"spec/matchers/disambiguate_attributes.rb",
|
229
238
|
"spec/matchers/hash_the_same_as.rb",
|
230
239
|
"spec/schemas/mysql_schema.rb",
|
240
|
+
"spec/schemas/oracle_schema.rb",
|
231
241
|
"spec/schemas/postgresql_schema.rb",
|
232
242
|
"spec/schemas/sqlite3_schema.rb",
|
233
243
|
"spec/spec_helper.rb"
|
data/lib/arel.rb
CHANGED
@@ -84,7 +84,8 @@ module Arel
|
|
84
84
|
|
85
85
|
module AttributeAccessable
|
86
86
|
def [](index)
|
87
|
-
|
87
|
+
@cached_attributes ||= {}
|
88
|
+
@cached_attributes[index] ||= case index
|
88
89
|
when Symbol, String
|
89
90
|
find_attribute_matching_name(index)
|
90
91
|
when Attribute, Expression
|
@@ -96,7 +97,7 @@ module Arel
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def find_attribute_matching_name(name)
|
99
|
-
attributes.detect { |a| a.named?(name) }
|
100
|
+
attributes.detect { |a| a.named?(name) } || Attribute.new(self, name)
|
100
101
|
end
|
101
102
|
|
102
103
|
def find_attribute_matching_attribute(attribute)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# +-----------------------------------------------------------------------+
|
2
|
+
# | |
|
3
|
+
# | Copyright (c) 2010 IBM Corporation |
|
4
|
+
# | |
|
5
|
+
# | Permission is hereby granted, free of charge, to any person obtaining |
|
6
|
+
# | a copy of this software and associated documentation files (the |
|
7
|
+
# | "Software"), to deal in the Software without restriction, including |
|
8
|
+
# | without limitation the rights to use, copy, modify, merge, publish, |
|
9
|
+
# | distribute, sublicense, and/or sell copies of the Software, and to |
|
10
|
+
# | permit persons to whom the Software is furnished to do so, subject to |
|
11
|
+
# | the following conditions: |
|
12
|
+
# | |
|
13
|
+
# | The above copyright notice and this permission notice shall be |
|
14
|
+
# | included in all copies or substantial portions of the Software. |
|
15
|
+
# | |
|
16
|
+
# | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
17
|
+
# | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
18
|
+
# | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.|
|
19
|
+
# | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
|
20
|
+
# | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
21
|
+
# | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
22
|
+
# | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
23
|
+
# | |
|
24
|
+
# +-----------------------------------------------------------------------+
|
25
|
+
|
26
|
+
#
|
27
|
+
# Author: Praveen Devarao <praveendrl@in.ibm.com>
|
28
|
+
#
|
29
|
+
|
30
|
+
module Arel
|
31
|
+
module SqlCompiler
|
32
|
+
class IBM_DBCompiler < GenericCompiler
|
33
|
+
|
34
|
+
def select_sql
|
35
|
+
query = build_query \
|
36
|
+
"SELECT #{select_clauses.join(', ')}",
|
37
|
+
"FROM #{from_clauses}",
|
38
|
+
(joins(self) unless joins(self).blank? ),
|
39
|
+
("WHERE #{where_clauses.join(" AND ")}" unless wheres.blank? ),
|
40
|
+
("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ),
|
41
|
+
("HAVING #{having_clauses.join(', ')}" unless havings.blank? ),
|
42
|
+
("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? )
|
43
|
+
engine.add_limit_offset!(query,{:limit=>taken,:offset=>skipped}) unless taken.blank?
|
44
|
+
query << "#{locked}" unless locked.blank?
|
45
|
+
query
|
46
|
+
end
|
47
|
+
|
48
|
+
def limited_update_conditions(conditions, taken)
|
49
|
+
quoted_primary_key = engine.quote_table_name(primary_key)
|
50
|
+
update_conditions = "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions} " #Note: - ')' not added, limit segment is to be appended
|
51
|
+
engine.add_limit_offset!(update_conditions,{:limit=>taken,:offset=>nil})
|
52
|
+
update_conditions << ")" # Close the sql segment
|
53
|
+
update_conditions
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_limit_on_delete(taken)
|
57
|
+
raise "IBM_DB does not support limit on deletion" # Limiting the number of rows to be deleted is not supported by IBM_DB
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -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
|
@@ -1,16 +1,23 @@
|
|
1
1
|
module Arel
|
2
2
|
module Sql
|
3
3
|
class Engine
|
4
|
+
|
4
5
|
def initialize(ar = nil)
|
5
6
|
@ar = ar
|
6
7
|
end
|
7
8
|
|
8
9
|
def connection
|
9
|
-
@ar.connection
|
10
|
+
@ar ? @ar.connection : nil
|
10
11
|
end
|
11
12
|
|
12
13
|
def adapter_name
|
13
|
-
@adapter_name ||= connection.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
|
14
21
|
end
|
15
22
|
|
16
23
|
def method_missing(method, *args, &block)
|
@@ -19,7 +26,14 @@ module Arel
|
|
19
26
|
|
20
27
|
module CRUD
|
21
28
|
def create(relation)
|
22
|
-
|
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)
|
23
37
|
end
|
24
38
|
|
25
39
|
def read(relation)
|
@@ -93,7 +93,7 @@ module Arel
|
|
93
93
|
|
94
94
|
class TableReference < Formatter
|
95
95
|
def select(select_sql, table)
|
96
|
-
"(#{select_sql})
|
96
|
+
"(#{select_sql}) #{quote_table_name(name_for(table))}"
|
97
97
|
end
|
98
98
|
|
99
99
|
def table(table)
|
@@ -101,7 +101,7 @@ module Arel
|
|
101
101
|
table.name
|
102
102
|
else
|
103
103
|
quote_table_name(table.name) +
|
104
|
-
(table.name != name_for(table) ? "
|
104
|
+
(table.name != name_for(table) ? " #{quote_table_name(name_for(table))}" : '')
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
@@ -112,7 +112,7 @@ module Arel
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def range(left, right)
|
115
|
-
"#{left} AND #{right}"
|
115
|
+
"#{scalar(left)} AND #{scalar(right)}"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -2,6 +2,7 @@ require 'arel/engines/sql/relations/utilities/compound'
|
|
2
2
|
require 'arel/engines/sql/relations/utilities/recursion'
|
3
3
|
require 'arel/engines/sql/relations/utilities/externalization'
|
4
4
|
require 'arel/engines/sql/relations/utilities/nil'
|
5
|
+
require 'arel/engines/sql/relations/compiler'
|
5
6
|
require 'arel/engines/sql/relations/relation'
|
6
7
|
require 'arel/engines/sql/relations/table'
|
7
8
|
require 'arel/engines/sql/relations/operations/join'
|