arel 0.3.1 → 0.3.2
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/lib/arel.rb +4 -3
- data/lib/arel/algebra.rb +1 -1
- data/lib/arel/algebra/attributes.rb +7 -0
- data/lib/arel/algebra/{attribute.rb → attributes/attribute.rb} +32 -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/predicates.rb +1 -0
- data/lib/arel/algebra/relations/operations/join.rb +4 -2
- data/lib/arel/algebra/relations/operations/order.rb +2 -1
- data/lib/arel/algebra/relations/operations/skip.rb +2 -1
- data/lib/arel/algebra/relations/operations/take.rb +2 -1
- data/lib/arel/algebra/relations/operations/where.rb +7 -6
- data/lib/arel/algebra/relations/relation.rb +2 -1
- data/lib/arel/algebra/relations/utilities/compound.rb +22 -2
- data/lib/arel/algebra/relations/utilities/externalization.rb +1 -1
- data/lib/arel/algebra/relations/utilities/nil.rb +2 -2
- data/lib/arel/engines/memory/predicates.rb +6 -0
- data/lib/arel/engines/memory/relations/array.rb +11 -4
- data/lib/arel/engines/memory/relations/compound.rb +1 -1
- data/lib/arel/engines/memory/relations/operations.rb +2 -2
- data/lib/arel/engines/sql.rb +1 -0
- data/lib/arel/engines/sql/attributes.rb +40 -0
- data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +0 -14
- data/lib/arel/engines/sql/predicates.rb +4 -0
- data/lib/arel/engines/sql/primitives.rb +0 -4
- data/lib/arel/engines/sql/relations/compiler.rb +5 -5
- data/lib/arel/engines/sql/relations/operations/join.rb +1 -1
- data/lib/arel/engines/sql/relations/relation.rb +1 -1
- data/lib/arel/engines/sql/relations/table.rb +6 -7
- data/lib/arel/engines/sql/relations/utilities/compound.rb +1 -1
- data/lib/arel/engines/sql/relations/utilities/nil.rb +1 -1
- data/lib/arel/session.rb +2 -2
- data/lib/arel/version.rb +3 -0
- data/spec/{arel/algebra → algebra}/unit/predicates/binary_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/predicates/equality_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/predicates/in_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/primitives/attribute_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/primitives/expression_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/primitives/value_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/alias_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/delete_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/group_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/insert_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/join_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/order_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/project_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/relation_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/skip_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/table_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/take_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/update_spec.rb +0 -0
- data/spec/{arel/algebra → algebra}/unit/relations/where_spec.rb +1 -0
- data/spec/{arel/algebra → algebra}/unit/session/session_spec.rb +0 -0
- data/spec/attributes/boolean_spec.rb +57 -0
- data/spec/attributes/float_spec.rb +119 -0
- data/spec/attributes/integer_spec.rb +119 -0
- data/spec/attributes/string_spec.rb +43 -0
- data/spec/attributes/time_spec.rb +22 -0
- data/spec/{arel/engines → engines}/memory/integration/joins/cross_engine_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/array_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/insert_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/join_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/order_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/project_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/skip_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/take_spec.rb +1 -1
- data/spec/{arel/engines → engines}/memory/unit/relations/where_spec.rb +1 -1
- data/spec/{arel/engines → engines}/sql/integration/joins/with_adjacency_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/integration/joins/with_aggregations_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/integration/joins/with_compounds_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/engine_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/predicates/binary_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/predicates/equality_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/predicates/in_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/predicates/predicates_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/primitives/attribute_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/primitives/expression_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/primitives/literal_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/primitives/value_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/alias_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/delete_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/from_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/group_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/having_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/insert_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/join_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/lock_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/order_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/project_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/skip_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/table_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/take_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/update_spec.rb +0 -0
- data/spec/{arel/engines → engines}/sql/unit/relations/where_spec.rb +0 -0
- data/spec/relations/join_spec.rb +40 -0
- data/spec/relations/relation_spec.rb +31 -0
- data/spec/shared/relation_spec.rb +142 -0
- data/spec/spec_helper.rb +17 -45
- data/spec/support/check.rb +6 -0
- data/spec/{connections → support/connections}/mysql_connection.rb +2 -4
- data/spec/{connections → support/connections}/oracle_connection.rb +3 -5
- data/spec/{connections → support/connections}/postgresql_connection.rb +2 -4
- data/spec/{connections → support/connections}/sqlite3_connection.rb +2 -4
- data/spec/support/guards.rb +28 -0
- data/spec/support/matchers.rb +4 -0
- data/spec/{matchers → support/matchers}/be_like.rb +1 -1
- data/spec/{matchers → support/matchers}/disambiguate_attributes.rb +1 -1
- data/spec/{matchers → support/matchers}/hash_the_same_as.rb +1 -1
- data/spec/support/matchers/have_rows.rb +18 -0
- data/spec/support/model.rb +58 -0
- data/spec/{schemas → support/schemas}/mysql_schema.rb +0 -0
- data/spec/{schemas → support/schemas}/oracle_schema.rb +0 -0
- data/spec/{schemas → support/schemas}/postgresql_schema.rb +0 -0
- data/spec/{schemas → support/schemas}/sqlite3_schema.rb +0 -0
- metadata +107 -163
- data/.gitignore +0 -6
- data/.gitmodules +0 -3
- data/Rakefile +0 -48
- data/Thorfile +0 -124
- data/arel.gemspec +0 -258
- data/doc/CONVENTIONS +0 -17
- data/doc/TODO +0 -118
- data/spec/doubles/hash.rb +0 -27
- data/spec/spec.opts +0 -3
data/lib/arel.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'active_support/inflector'
|
2
|
-
require 'active_support/core_ext/module/delegation'
|
3
2
|
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
require 'active_support/core_ext/object/blank'
|
4
5
|
|
5
6
|
module Arel
|
6
7
|
require 'arel/algebra'
|
7
8
|
require 'arel/engines'
|
8
|
-
|
9
|
+
require 'arel/version'
|
9
10
|
|
10
|
-
|
11
|
+
autoload :Session, 'arel/session'
|
11
12
|
end
|
data/lib/arel/algebra.rb
CHANGED
@@ -0,0 +1,7 @@
|
|
1
|
+
require "arel/algebra/attributes/attribute"
|
2
|
+
require "arel/algebra/attributes/boolean"
|
3
|
+
require "arel/algebra/attributes/decimal"
|
4
|
+
require "arel/algebra/attributes/float"
|
5
|
+
require "arel/algebra/attributes/integer"
|
6
|
+
require "arel/algebra/attributes/string"
|
7
|
+
require "arel/algebra/attributes/time"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
3
|
module Arel
|
4
|
+
class TypecastError < StandardError ; end
|
4
5
|
class Attribute
|
5
6
|
attributes :relation, :name, :alias, :ancestor
|
6
7
|
deriving :==
|
@@ -85,6 +86,10 @@ module Arel
|
|
85
86
|
Predicates::Equality.new(self, other)
|
86
87
|
end
|
87
88
|
|
89
|
+
def not(other)
|
90
|
+
Predicates::Not.new(self, other)
|
91
|
+
end
|
92
|
+
|
88
93
|
def lt(other)
|
89
94
|
Predicates::LessThan.new(self, other)
|
90
95
|
end
|
@@ -146,5 +151,32 @@ module Arel
|
|
146
151
|
alias_method :to_ordering, :asc
|
147
152
|
end
|
148
153
|
include Orderings
|
154
|
+
|
155
|
+
module Types
|
156
|
+
def type_cast(value)
|
157
|
+
if root == self
|
158
|
+
raise NotImplementedError, "#type_cast should be implemented in a subclass."
|
159
|
+
else
|
160
|
+
root.type_cast(value)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def type_cast_to_numeric(value, method)
|
165
|
+
return unless value
|
166
|
+
if value.respond_to?(:to_str)
|
167
|
+
str = value.to_str.strip
|
168
|
+
return if str.empty?
|
169
|
+
return $1.send(method) if str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
|
170
|
+
elsif value.respond_to?(method)
|
171
|
+
return value.send(method)
|
172
|
+
end
|
173
|
+
raise typecast_error(value)
|
174
|
+
end
|
175
|
+
|
176
|
+
def typecast_error(value)
|
177
|
+
raise TypecastError, "could not typecast #{value.inspect} to #{self.class.name.split('::').last}"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
include Types
|
149
181
|
end
|
150
182
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Arel
|
2
|
+
module Attributes
|
3
|
+
class Boolean < Attribute
|
4
|
+
def type_cast(value)
|
5
|
+
case value
|
6
|
+
when true, false then value
|
7
|
+
# when nil then options[:allow_nil] ? nil : false
|
8
|
+
when nil then false
|
9
|
+
when 1 then true
|
10
|
+
when 0 then false
|
11
|
+
else
|
12
|
+
case value.to_s.downcase.strip
|
13
|
+
when 'true' then true
|
14
|
+
when 'false' then false
|
15
|
+
else raise typecast_error(value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Arel
|
2
|
-
class Join
|
2
|
+
class Join
|
3
|
+
include Relation
|
4
|
+
|
3
5
|
attributes :relation1, :relation2, :predicates
|
4
6
|
deriving :==
|
5
7
|
delegate :name, :to => :relation1
|
@@ -60,7 +62,7 @@ module Arel
|
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
|
65
|
+
module Relation
|
64
66
|
def join?
|
65
67
|
false
|
66
68
|
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module Arel
|
2
2
|
class Where < Compound
|
3
|
-
attributes :relation, :
|
4
|
-
deriving
|
3
|
+
attributes :relation, :predicates
|
4
|
+
deriving :==
|
5
|
+
requires :restricting
|
5
6
|
|
6
7
|
def initialize(relation, *predicates, &block)
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
8
|
+
predicates = [yield(relation)] + predicates if block_given?
|
9
|
+
@predicates = predicates.map { |p| p.bind(relation) }
|
10
|
+
@relation = relation
|
10
11
|
end
|
11
12
|
|
12
13
|
def wheres
|
13
|
-
@wheres ||=
|
14
|
+
@wheres ||= relation.wheres + predicates
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Arel
|
2
|
-
|
2
|
+
module Relation
|
3
3
|
attr_reader :count
|
4
4
|
|
5
5
|
def session
|
@@ -128,6 +128,7 @@ module Arel
|
|
128
128
|
|
129
129
|
module DefaultOperations
|
130
130
|
def attributes; [] end
|
131
|
+
def projections; [] end
|
131
132
|
def wheres; [] end
|
132
133
|
def orders; [] end
|
133
134
|
def inserts; [] end
|
@@ -1,11 +1,19 @@
|
|
1
1
|
module Arel
|
2
|
-
class Compound
|
2
|
+
class Compound
|
3
|
+
include Relation
|
4
|
+
|
3
5
|
attr_reader :relation
|
4
6
|
delegate :joins, :join?, :inserts, :taken, :skipped, :name, :externalizable?,
|
5
7
|
:column_for, :engine, :sources, :locked, :table_alias,
|
6
8
|
:to => :relation
|
7
9
|
|
8
|
-
|
10
|
+
def self.requires(feature = nil)
|
11
|
+
@requires ||= nil
|
12
|
+
@requires = feature if feature
|
13
|
+
@requires
|
14
|
+
end
|
15
|
+
|
16
|
+
[:attributes, :wheres, :groupings, :orders, :havings, :projections].each do |operation_name|
|
9
17
|
class_eval <<-OPERATION, __FILE__, __LINE__
|
10
18
|
def #{operation_name}
|
11
19
|
@#{operation_name} ||= relation.#{operation_name}.collect { |o| o.bind(self) }
|
@@ -21,6 +29,18 @@ module Arel
|
|
21
29
|
self == other
|
22
30
|
end
|
23
31
|
|
32
|
+
def engine
|
33
|
+
requires = self.class.requires
|
34
|
+
engine = relation.engine
|
35
|
+
|
36
|
+
# Temporary check of whether or not the engine supports where.
|
37
|
+
if requires && engine.respond_to?(:supports) && !engine.supports(requires)
|
38
|
+
Memory::Engine.new
|
39
|
+
else
|
40
|
+
engine
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
24
44
|
private
|
25
45
|
|
26
46
|
def arguments_from_block(relation, &block)
|
@@ -1,16 +1,23 @@
|
|
1
1
|
module Arel
|
2
|
-
class Array
|
3
|
-
|
2
|
+
class Array
|
3
|
+
include Relation
|
4
|
+
|
5
|
+
attributes :array, :attribute_names_and_types
|
4
6
|
include Recursion::BaseCase
|
5
7
|
deriving :==, :initialize
|
6
8
|
|
9
|
+
def initialize(array, attribute_names_and_types)
|
10
|
+
@array, @attribute_names_and_types = array, attribute_names_and_types
|
11
|
+
end
|
12
|
+
|
7
13
|
def engine
|
8
14
|
@engine ||= Memory::Engine.new
|
9
15
|
end
|
10
16
|
|
11
17
|
def attributes
|
12
|
-
@attributes ||= @
|
13
|
-
|
18
|
+
@attributes ||= @attribute_names_and_types.collect do |attribute, type|
|
19
|
+
attribute = type.new(self, attribute) if Symbol === attribute
|
20
|
+
attribute
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Arel
|
2
2
|
class Where < Compound
|
3
3
|
def eval
|
4
|
-
unoperated_rows.select { |row|
|
4
|
+
unoperated_rows.select { |row| predicates.all? { |p| p.eval(row) } }
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
@@ -50,7 +50,7 @@ module Arel
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
class Join
|
53
|
+
class Join
|
54
54
|
def eval
|
55
55
|
result = []
|
56
56
|
relation1.call.each do |row1|
|
data/lib/arel/engines/sql.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Arel
|
2
|
+
module Sql
|
3
|
+
module Attributes
|
4
|
+
def self.for(column)
|
5
|
+
case column.type
|
6
|
+
when :string then String
|
7
|
+
when :text then String
|
8
|
+
when :integer then Integer
|
9
|
+
when :float then Float
|
10
|
+
when :decimal then Decimal
|
11
|
+
when :date then Time
|
12
|
+
when :datetime then Time
|
13
|
+
when :timestamp then Time
|
14
|
+
when :time then Time
|
15
|
+
when :binary then String
|
16
|
+
when :boolean then Boolean
|
17
|
+
else
|
18
|
+
raise NotImplementedError, "Column type `#{column.type}` is not currently handled"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(column, *args)
|
23
|
+
@column = column
|
24
|
+
super(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def type_cast(value)
|
28
|
+
@column.type_cast(value)
|
29
|
+
end
|
30
|
+
|
31
|
+
%w(Boolean Decimal Float Integer String Time).each do |klass|
|
32
|
+
class_eval <<-R
|
33
|
+
class #{klass} < Arel::Attributes::#{klass}
|
34
|
+
include Attributes
|
35
|
+
end
|
36
|
+
R
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -31,20 +31,6 @@ module Arel
|
|
31
31
|
module SqlCompiler
|
32
32
|
class IBM_DBCompiler < GenericCompiler
|
33
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
34
|
def limited_update_conditions(conditions, taken)
|
49
35
|
quoted_primary_key = engine.quote_table_name(primary_key)
|
50
36
|
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
|