arel 0.2.1 → 0.3.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.
Files changed (54) hide show
  1. data/History.txt +8 -0
  2. data/README.markdown +0 -2
  3. data/Rakefile +2 -2
  4. data/arel.gemspec +13 -3
  5. data/lib/arel.rb +2 -2
  6. data/lib/arel/algebra/relations/relation.rb +3 -2
  7. data/lib/arel/engines/sql/compilers/ibm_db_compiler.rb +62 -0
  8. data/lib/arel/engines/sql/compilers/mysql_compiler.rb +11 -0
  9. data/lib/arel/engines/sql/compilers/oracle_compiler.rb +95 -0
  10. data/lib/arel/engines/sql/compilers/postgresql_compiler.rb +42 -0
  11. data/lib/arel/engines/sql/compilers/sqlite_compiler.rb +9 -0
  12. data/lib/arel/engines/sql/engine.rb +17 -3
  13. data/lib/arel/engines/sql/formatters.rb +3 -3
  14. data/lib/arel/engines/sql/relations.rb +1 -0
  15. data/lib/arel/engines/sql/relations/compiler.rb +118 -0
  16. data/lib/arel/engines/sql/relations/relation.rb +38 -63
  17. data/lib/arel/engines/sql/relations/table.rb +23 -3
  18. data/lib/arel/engines/sql/relations/utilities/externalization.rb +1 -1
  19. data/lib/arel/engines/sql/relations/writes.rb +4 -71
  20. data/spec/arel/algebra/unit/relations/relation_spec.rb +1 -2
  21. data/spec/arel/algebra/unit/relations/table_spec.rb +0 -1
  22. data/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb +9 -4
  23. data/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb +68 -19
  24. data/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb +74 -20
  25. data/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb +33 -3
  26. data/spec/arel/engines/sql/unit/predicates/binary_spec.rb +22 -2
  27. data/spec/arel/engines/sql/unit/predicates/equality_spec.rb +15 -3
  28. data/spec/arel/engines/sql/unit/predicates/in_spec.rb +59 -5
  29. data/spec/arel/engines/sql/unit/predicates/predicates_spec.rb +12 -0
  30. data/spec/arel/engines/sql/unit/primitives/attribute_spec.rb +24 -1
  31. data/spec/arel/engines/sql/unit/primitives/expression_spec.rb +5 -1
  32. data/spec/arel/engines/sql/unit/primitives/literal_spec.rb +10 -2
  33. data/spec/arel/engines/sql/unit/relations/alias_spec.rb +11 -1
  34. data/spec/arel/engines/sql/unit/relations/delete_spec.rb +23 -3
  35. data/spec/arel/engines/sql/unit/relations/from_spec.rb +16 -2
  36. data/spec/arel/engines/sql/unit/relations/group_spec.rb +18 -2
  37. data/spec/arel/engines/sql/unit/relations/having_spec.rb +12 -3
  38. data/spec/arel/engines/sql/unit/relations/insert_spec.rb +37 -1
  39. data/spec/arel/engines/sql/unit/relations/join_spec.rb +53 -11
  40. data/spec/arel/engines/sql/unit/relations/lock_spec.rb +25 -0
  41. data/spec/arel/engines/sql/unit/relations/order_spec.rb +52 -4
  42. data/spec/arel/engines/sql/unit/relations/project_spec.rb +38 -5
  43. data/spec/arel/engines/sql/unit/relations/skip_spec.rb +10 -1
  44. data/spec/arel/engines/sql/unit/relations/table_spec.rb +26 -5
  45. data/spec/arel/engines/sql/unit/relations/take_spec.rb +18 -1
  46. data/spec/arel/engines/sql/unit/relations/update_spec.rb +47 -1
  47. data/spec/arel/engines/sql/unit/relations/where_spec.rb +18 -2
  48. data/spec/connections/oracle_connection.rb +19 -0
  49. data/spec/schemas/mysql_schema.rb +2 -1
  50. data/spec/schemas/oracle_schema.rb +20 -0
  51. data/spec/schemas/postgresql_schema.rb +2 -1
  52. data/spec/schemas/sqlite3_schema.rb +2 -1
  53. data/spec/spec_helper.rb +16 -7
  54. metadata +31 -9
@@ -30,6 +30,24 @@ module Arel
30
30
  FROM "users"
31
31
  })
32
32
  end
33
+
34
+ adapter_is :oracle do
35
+ sql.should be_like(%Q{
36
+ SELECT "USERS"."ID", "USERS"."NAME"
37
+ FROM "USERS" FOR UPDATE
38
+ })
39
+
40
+ sql_with_order_by = @relation.order(@relation[:id]).take(1).lock.to_sql
41
+ sql_with_order_by.should be_like(%Q{
42
+ SELECT "USERS"."ID", "USERS"."NAME"
43
+ FROM "USERS"
44
+ WHERE "ID" IN (select * from
45
+ (SELECT "ID" FROM "USERS" ORDER BY "USERS"."ID" ASC)
46
+ where rownum <= 1)
47
+ FOR UPDATE
48
+ })
49
+
50
+ end
33
51
  end
34
52
 
35
53
  it "manufactures a select query locking with a given lock" do
@@ -55,6 +73,13 @@ module Arel
55
73
  FROM "users"
56
74
  })
57
75
  end
76
+
77
+ adapter_is :oracle do
78
+ sql.should be_like(%Q{
79
+ SELECT "USERS"."ID", "USERS"."NAME"
80
+ FROM "USERS" LOCK IN SHARE MODE
81
+ })
82
+ end
58
83
  end
59
84
  end
60
85
  end
@@ -20,7 +20,31 @@ module Arel
20
20
  })
21
21
  end
22
22
 
23
- adapter_is_not :mysql do
23
+ adapter_is :oracle do
24
+ sql.should be_like(%Q{
25
+ SELECT "USERS"."ID", "USERS"."NAME"
26
+ FROM "USERS"
27
+ ORDER BY "USERS"."ID" ASC
28
+ })
29
+
30
+ distinct_attributes = ActiveRecord::Base.connection.distinct('"USERS"."NAME"', '"USERS"."ID"')
31
+ @relation.project(distinct_attributes).order(@relation[:id]).to_sql.should be_like(%Q{
32
+ SELECT DISTINCT "USERS"."NAME",
33
+ FIRST_VALUE("USERS"."ID") OVER (PARTITION BY "USERS"."NAME" ORDER BY "USERS"."ID") AS alias_0__
34
+ FROM "USERS"
35
+ ORDER BY alias_0__
36
+ })
37
+
38
+ distinct_attributes = ActiveRecord::Base.connection.distinct('"USERS"."NAME"', '"USERS"."ID" DESC')
39
+ @relation.project(distinct_attributes).order('"USERS"."ID" DESC').to_sql.should be_like(%Q{
40
+ SELECT DISTINCT "USERS"."NAME",
41
+ FIRST_VALUE("USERS"."ID") OVER (PARTITION BY "USERS"."NAME" ORDER BY "USERS"."ID" DESC) AS alias_0__
42
+ FROM "USERS"
43
+ ORDER BY alias_0__ DESC
44
+ })
45
+ end
46
+
47
+ adapter_is_not :mysql, :oracle do
24
48
  sql.should be_like(%Q{
25
49
  SELECT "users"."id", "users"."name"
26
50
  FROM "users"
@@ -46,7 +70,15 @@ module Arel
46
70
  })
47
71
  end
48
72
 
49
- adapter_is_not :mysql do
73
+ adapter_is :oracle do
74
+ sql.should be_like(%Q{
75
+ SELECT "USERS"."ID", "USERS"."NAME"
76
+ FROM "USERS"
77
+ ORDER BY "USERS"."ID" ASC, "USERS"."NAME" ASC
78
+ })
79
+ end
80
+
81
+ adapter_is_not :mysql, :oracle do
50
82
  sql.should be_like(%Q{
51
83
  SELECT "users"."id", "users"."name"
52
84
  FROM "users"
@@ -72,7 +104,15 @@ module Arel
72
104
  })
73
105
  end
74
106
 
75
- adapter_is_not :mysql do
107
+ adapter_is :oracle do
108
+ sql.should be_like(%Q{
109
+ SELECT "USERS"."ID", "USERS"."NAME"
110
+ FROM "USERS"
111
+ ORDER BY asdf
112
+ })
113
+ end
114
+
115
+ adapter_is_not :mysql, :oracle do
76
116
  sql.should be_like(%Q{
77
117
  SELECT "users"."id", "users"."name"
78
118
  FROM "users"
@@ -99,7 +139,15 @@ module Arel
99
139
  })
100
140
  end
101
141
 
102
- adapter_is_not :mysql do
142
+ adapter_is :oracle do
143
+ sql.should be_like(%Q{
144
+ SELECT "USERS"."ID", "USERS"."NAME"
145
+ FROM "USERS"
146
+ ORDER BY "USERS"."NAME" ASC, "USERS"."ID" ASC
147
+ })
148
+ end
149
+
150
+ adapter_is_not :mysql, :oracle do
103
151
  sql.should be_like(%Q{
104
152
  SELECT "users"."id", "users"."name"
105
153
  FROM "users"
@@ -19,7 +19,14 @@ module Arel
19
19
  })
20
20
  end
21
21
 
22
- adapter_is_not :mysql do
22
+ adapter_is :oracle do
23
+ sql.should be_like(%Q{
24
+ SELECT "USERS"."ID"
25
+ FROM "USERS"
26
+ })
27
+ end
28
+
29
+ adapter_is_not :mysql, :oracle do
23
30
  sql.should be_like(%Q{
24
31
  SELECT "users"."id"
25
32
  FROM "users"
@@ -42,7 +49,13 @@ module Arel
42
49
  })
43
50
  end
44
51
 
45
- adapter_is_not :mysql do
52
+ adapter_is :oracle do
53
+ sql.should be_like(%Q{
54
+ SELECT (SELECT "USERS"."NAME" FROM "USERS") AS "USERS" FROM "USERS"
55
+ })
56
+ end
57
+
58
+ adapter_is_not :mysql, :oracle do
46
59
  sql.should be_like(%Q{
47
60
  SELECT (SELECT "users"."name" FROM "users") AS "users" FROM "users"
48
61
  })
@@ -60,7 +73,13 @@ module Arel
60
73
  })
61
74
  end
62
75
 
63
- adapter_is_not :mysql do
76
+ adapter_is :oracle do
77
+ sql.should be_like(%Q{
78
+ SELECT asdf FROM "USERS"
79
+ })
80
+ end
81
+
82
+ adapter_is_not :mysql, :oracle do
64
83
  sql.should be_like(%Q{
65
84
  SELECT asdf FROM "users"
66
85
  })
@@ -79,7 +98,14 @@ module Arel
79
98
  })
80
99
  end
81
100
 
82
- adapter_is_not :mysql do
101
+ adapter_is :oracle do
102
+ sql.should be_like(%Q{
103
+ SELECT COUNT("USERS"."ID") AS count_id
104
+ FROM "USERS"
105
+ })
106
+ end
107
+
108
+ adapter_is_not :mysql, :oracle do
83
109
  sql.should be_like(%Q{
84
110
  SELECT COUNT("users"."id") AS count_id
85
111
  FROM "users"
@@ -97,7 +123,14 @@ module Arel
97
123
  })
98
124
  end
99
125
 
100
- adapter_is_not :mysql do
126
+ adapter_is :oracle do
127
+ sql.should be_like(%Q{
128
+ SELECT COUNT(DISTINCT "USERS"."ID") AS count_id
129
+ FROM "USERS"
130
+ })
131
+ end
132
+
133
+ adapter_is_not :mysql, :oracle do
101
134
  sql.should be_like(%Q{
102
135
  SELECT COUNT(DISTINCT "users"."id") AS count_id
103
136
  FROM "users"
@@ -19,7 +19,16 @@ module Arel
19
19
  })
20
20
  end
21
21
 
22
- adapter_is_not :mysql do
22
+ adapter_is :oracle do
23
+ sql.should be_like(%Q{
24
+ select * from (select raw_sql_.*, rownum raw_rnum_ from
25
+ (SELECT "USERS"."ID", "USERS"."NAME"
26
+ FROM "USERS") raw_sql_)
27
+ where raw_rnum_ > 4
28
+ })
29
+ end
30
+
31
+ adapter_is_not :mysql, :oracle do
23
32
  sql.should be_like(%Q{
24
33
  SELECT "users"."id", "users"."name"
25
34
  FROM "users"
@@ -17,7 +17,14 @@ module Arel
17
17
  })
18
18
  end
19
19
 
20
- adapter_is_not :mysql do
20
+ adapter_is :oracle do
21
+ sql.should be_like(%Q{
22
+ SELECT "USERS"."ID", "USERS"."NAME"
23
+ FROM "USERS"
24
+ })
25
+ end
26
+
27
+ adapter_is_not :mysql, :oracle do
21
28
  sql.should be_like(%Q{
22
29
  SELECT "users"."id", "users"."name"
23
30
  FROM "users"
@@ -33,14 +40,21 @@ module Arel
33
40
  adapter_is :mysql do
34
41
  sql.should be_like(%Q{
35
42
  SELECT `super_users`.`id`, `super_users`.`name`
36
- FROM `users` AS `super_users`
43
+ FROM `users` `super_users`
44
+ })
45
+ end
46
+
47
+ adapter_is :oracle do
48
+ sql.should be_like(%Q{
49
+ SELECT "SUPER_USERS"."ID", "SUPER_USERS"."NAME"
50
+ FROM "USERS" "SUPER_USERS"
37
51
  })
38
52
  end
39
53
 
40
- adapter_is_not :mysql do
54
+ adapter_is_not :mysql, :oracle do
41
55
  sql.should be_like(%Q{
42
56
  SELECT "super_users"."id", "super_users"."name"
43
- FROM "users" AS "super_users"
57
+ FROM "users" "super_users"
44
58
  })
45
59
  end
46
60
  end
@@ -55,7 +69,14 @@ module Arel
55
69
  })
56
70
  end
57
71
 
58
- adapter_is_not :mysql do
72
+ adapter_is :oracle do
73
+ sql.should be_like(%Q{
74
+ SELECT "USERS"."ID", "USERS"."NAME"
75
+ FROM "USERS"
76
+ })
77
+ end
78
+
79
+ adapter_is_not :mysql, :oracle do
59
80
  sql.should be_like(%Q{
60
81
  SELECT "users"."id", "users"."name"
61
82
  FROM "users"
@@ -19,7 +19,24 @@ module Arel
19
19
  })
20
20
  end
21
21
 
22
- adapter_is_not :mysql do
22
+ adapter_is :oracle do
23
+ sql.should be_like(%Q{
24
+ SELECT "USERS"."ID", "USERS"."NAME"
25
+ FROM "USERS"
26
+ WHERE ROWNUM <= 4
27
+ })
28
+
29
+ sql_with_order_by = Take.new(@relation.order(@relation[:id]), @taken).to_sql
30
+ sql_with_order_by.should be_like(%Q{
31
+ select * from
32
+ (SELECT "USERS"."ID", "USERS"."NAME"
33
+ FROM "USERS"
34
+ ORDER BY "USERS"."ID" ASC)
35
+ where rownum <= 4
36
+ })
37
+ end
38
+
39
+ adapter_is_not :mysql, :oracle do
23
40
  sql.should be_like(%Q{
24
41
  SELECT "users"."id", "users"."name"
25
42
  FROM "users"
@@ -36,6 +36,13 @@ module Arel
36
36
  SET "id" = 1, "name" = E'nick'
37
37
  })
38
38
  end
39
+
40
+ adapter_is :oracle do
41
+ sql.should be_like(%Q{
42
+ UPDATE "USERS"
43
+ SET "ID" = 1, "NAME" = 'nick'
44
+ })
45
+ end
39
46
  end
40
47
 
41
48
  it "manufactures sql updating attributes when given a ranged relation" do
@@ -64,6 +71,23 @@ module Arel
64
71
  WHERE "id" IN (SELECT "id" FROM "users" LIMIT 1)
65
72
  })
66
73
  end
74
+
75
+ adapter_is :oracle do
76
+ sql.should be_like(%Q{
77
+ UPDATE "USERS" SET
78
+ "NAME" = 'nick'
79
+ WHERE "ID" IN (SELECT "ID" FROM "USERS" WHERE ROWNUM <= 1)
80
+ })
81
+
82
+ sql_with_order_by = Update.new(@relation.order(@relation[:id]).take(1), @relation[:name] => "nick").to_sql
83
+ sql_with_order_by.should be_like(%Q{
84
+ UPDATE "USERS" SET
85
+ "NAME" = 'nick'
86
+ WHERE "ID" IN (select * from
87
+ (SELECT "ID" FROM "USERS" ORDER BY "USERS"."ID" ASC)
88
+ where rownum <= 1)
89
+ })
90
+ end
67
91
  end
68
92
 
69
93
  describe 'when given values whose types correspond to the types of the attributes' do
@@ -92,6 +116,13 @@ module Arel
92
116
  SET "name" = E'nick'
93
117
  })
94
118
  end
119
+
120
+ adapter_is :oracle do
121
+ @update.to_sql.should be_like(%Q{
122
+ UPDATE "USERS"
123
+ SET "NAME" = 'nick'
124
+ })
125
+ end
95
126
  end
96
127
  end
97
128
 
@@ -108,7 +139,14 @@ module Arel
108
139
  })
109
140
  end
110
141
 
111
- adapter_is_not :mysql do
142
+ adapter_is :oracle do
143
+ @update.to_sql.should be_like(%Q{
144
+ UPDATE "USERS"
145
+ SET "ID" = 1
146
+ })
147
+ end
148
+
149
+ adapter_is_not :mysql, :oracle do
112
150
  @update.to_sql.should be_like(%Q{
113
151
  UPDATE "users"
114
152
  SET "id" = 1
@@ -149,6 +187,14 @@ module Arel
149
187
  WHERE "users"."id" = 1
150
188
  })
151
189
  end
190
+
191
+ adapter_is :oracle do
192
+ @update.to_sql.should be_like(%Q{
193
+ UPDATE "USERS"
194
+ SET "NAME" = 'nick'
195
+ WHERE "USERS"."ID" = 1
196
+ })
197
+ end
152
198
  end
153
199
  end
154
200
  end
@@ -20,7 +20,15 @@ module Arel
20
20
  })
21
21
  end
22
22
 
23
- adapter_is_not :mysql do
23
+ adapter_is :oracle do
24
+ sql.should be_like(%Q{
25
+ SELECT "USERS"."ID", "USERS"."NAME"
26
+ FROM "USERS"
27
+ WHERE "USERS"."ID" = 1
28
+ })
29
+ end
30
+
31
+ adapter_is_not :mysql, :oracle do
24
32
  sql.should be_like(%Q{
25
33
  SELECT "users"."id", "users"."name"
26
34
  FROM "users"
@@ -42,7 +50,15 @@ module Arel
42
50
  })
43
51
  end
44
52
 
45
- adapter_is_not :mysql do
53
+ adapter_is :oracle do
54
+ sql.should be_like(%Q{
55
+ SELECT "USERS"."ID", "USERS"."NAME"
56
+ FROM "USERS"
57
+ WHERE asdf
58
+ })
59
+ end
60
+
61
+ adapter_is_not :mysql, :oracle do
46
62
  sql.should be_like(%Q{
47
63
  SELECT "users"."id", "users"."name"
48
64
  FROM "users"
@@ -0,0 +1,19 @@
1
+ puts "Using native Oracle"
2
+ require "active_record"
3
+ require 'logger'
4
+
5
+ # Prepend oracle_enhanced local development directory in front of load path
6
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../oracle-enhanced/lib"
7
+
8
+ ActiveRecord::Base.logger = Logger.new("debug.log")
9
+
10
+ ActiveRecord::Base.configurations = {
11
+ 'unit' => {
12
+ :adapter => 'oracle_enhanced',
13
+ :username => 'arel_unit',
14
+ :password => 'arel_unit',
15
+ :database => 'orcl',
16
+ }
17
+ }
18
+
19
+ ActiveRecord::Base.establish_connection 'unit'
@@ -16,7 +16,8 @@ sql = <<-SQL
16
16
  id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
17
17
  name VARCHAR(255) NOT NULL,
18
18
  salary INTEGER NOT NULL,
19
- department VARCHAR(255) NOT NULL
19
+ department VARCHAR(255) NOT NULL,
20
+ created_at TIMESTAMP NOT NULL
20
21
  );
21
22
  SQL
22
23