alf 0.14.0 → 0.15.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/Gemfile +6 -3
- data/Gemfile.lock +65 -19
- data/README.md +77 -183
- data/Rakefile +25 -0
- data/alf.gemspec +5 -3
- data/alf.noespec +8 -6
- data/lib/alf/loader.rb +1 -0
- data/lib/alf/version.rb +1 -1
- data/spec/facade/test_query.rb +12 -0
- data/spec/key-inference/queries.yml +10 -0
- data/spec/key-inference/test_all.rb +21 -0
- data/{test → spec}/migrations/test_folder_migration.rb +0 -0
- data/{test → spec}/migrations/test_sequel_migration.rb +1 -1
- data/spec/operators/ungroup/grouped.json +3 -0
- data/spec/operators/ungroup/test_on_json_content.rb +11 -0
- data/spec/operators/unwrap/test_on_json_content.rb +11 -0
- data/spec/operators/unwrap/wrapped.json +3 -0
- data/spec/optimizer/project/extend.yml +20 -0
- data/spec/optimizer/project/intersect.yml +10 -0
- data/spec/optimizer/project/join.yml +20 -0
- data/spec/optimizer/project/matching.yml +21 -0
- data/spec/optimizer/project/minus.yml +9 -0
- data/spec/optimizer/project/not_matching.yml +21 -0
- data/spec/optimizer/project/project.yml +88 -0
- data/spec/optimizer/project/rename.yml +30 -0
- data/spec/optimizer/project/sort.yml +45 -0
- data/spec/optimizer/project/union.yml +8 -0
- data/spec/optimizer/restrict/clip.yml +4 -0
- data/spec/optimizer/restrict/compact.yml +4 -0
- data/spec/optimizer/restrict/generator.yml +4 -0
- data/spec/optimizer/restrict/intersect.yml +4 -0
- data/spec/optimizer/restrict/leaf_operand.yml +4 -0
- data/spec/optimizer/restrict/minus.yml +4 -0
- data/spec/optimizer/restrict/page.yml +12 -0
- data/spec/optimizer/restrict/project.yml +4 -0
- data/spec/optimizer/restrict/sort.yml +4 -0
- data/spec/optimizer/restrict/union.yml +4 -0
- data/spec/optimizer/test_all.rb +34 -0
- data/spec/sql/helpers.rb +25 -0
- data/spec/sql/queries/01-leaf-operand.yml +5 -0
- data/spec/sql/queries/02-clip.yml +12 -0
- data/spec/sql/queries/03-sort.yml +58 -0
- data/spec/sql/queries/04-frame.yml +57 -0
- data/spec/sql/queries/05-intersect.yml +23 -0
- data/spec/sql/queries/06-join.yml +207 -0
- data/spec/sql/queries/07-matching.yml +76 -0
- data/spec/sql/queries/08-minus.yml +23 -0
- data/spec/sql/queries/09-not-matching.yml +57 -0
- data/spec/sql/queries/10-page.yml +31 -0
- data/spec/sql/queries/11-project.yml +48 -0
- data/spec/sql/queries/12-rename.yml +24 -0
- data/spec/sql/queries/13-restrict.yml +114 -0
- data/spec/sql/queries/15-union.yml +90 -0
- data/spec/sql/queries/16-wrap.yml +3 -0
- data/spec/sql/queries/91-reuse.yml +28 -0
- data/spec/sql/test_sequel_compiler.rb +41 -0
- data/spec/sql/test_sql_compiler.rb +52 -0
- data/{test → spec}/test_alf.rb +0 -0
- data/spec/test_helpers.rb +54 -0
- data/tasks/doc.rake +10 -0
- data/tasks/fixtures.rake +52 -0
- data/tasks/mod.rake +50 -0
- data/tasks/release.rake +34 -0
- data/tasks/test.rake +2 -2
- metadata +150 -19
- data/test/seeding/test_seeding.rb +0 -49
- data/test/test_helpers.rb +0 -24
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helpers'
|
2
|
+
|
3
|
+
Path.dir.glob('*').select{|f| f.directory? }.each do |folder|
|
4
|
+
optimizer = Alf::Optimizer.const_get(folder.basename.to_s.capitalize)
|
5
|
+
|
6
|
+
describe optimizer do
|
7
|
+
|
8
|
+
folder.glob('*.yml').each do |file|
|
9
|
+
context "On #{file.basename}" do
|
10
|
+
|
11
|
+
file.load.each do |query|
|
12
|
+
alf, optimized = query['alf'], query['optimized']
|
13
|
+
|
14
|
+
context "on #{alf}" do
|
15
|
+
let(:expr) { conn.parse(alf) }
|
16
|
+
let(:expected){ conn.parse(optimized) }
|
17
|
+
|
18
|
+
subject{ optimizer.new.call(expr) }
|
19
|
+
|
20
|
+
it 'should be optimized as expected' do
|
21
|
+
subject.should eq(expected)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should have same heading as the initial expression' do
|
25
|
+
subject.heading.should eq(expr.heading)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/spec/sql/helpers.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helpers'
|
2
|
+
|
3
|
+
module SqlTestHelpers
|
4
|
+
|
5
|
+
def each_query_file(&bl)
|
6
|
+
(Path.dir/'queries').glob("*.yml", &bl)
|
7
|
+
end
|
8
|
+
|
9
|
+
def each_query(&bl)
|
10
|
+
each_query_file do |file|
|
11
|
+
queries = file.load
|
12
|
+
queries.each(&bl)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def strip(x)
|
17
|
+
x.strip.gsub(/\s+/, " ").gsub(/\(\s+/, "(").gsub(/\s+\)/, ")")
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
RSpec.configure do |c|
|
23
|
+
c.include(SqlTestHelpers)
|
24
|
+
c.extend(SqlTestHelpers)
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# normal clip
|
2
|
+
- alf: |-
|
3
|
+
clip(suppliers, [:sid, :status])
|
4
|
+
sql: |-
|
5
|
+
SELECT t1.sid, t1.status
|
6
|
+
FROM suppliers AS t1
|
7
|
+
# clip with no attribute at all
|
8
|
+
- alf: |-
|
9
|
+
clip(suppliers, [])
|
10
|
+
sql: |-
|
11
|
+
SELECT TRUE AS is_table_dee
|
12
|
+
WHERE EXISTS(SELECT * FROM suppliers AS t1)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
- alf: |-
|
2
|
+
sort(suppliers, [[:sid, :asc]])
|
3
|
+
sql: |-
|
4
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
5
|
+
FROM suppliers AS t1
|
6
|
+
ORDER BY t1.sid ASC
|
7
|
+
#
|
8
|
+
- alf: |-
|
9
|
+
sort(suppliers, [[:sid, :desc]])
|
10
|
+
sql: |-
|
11
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
12
|
+
FROM suppliers AS t1
|
13
|
+
ORDER BY t1.sid DESC
|
14
|
+
#
|
15
|
+
- alf: |-
|
16
|
+
sort(suppliers, [[:city, :desc], [:sid, :asc]])
|
17
|
+
sql: |-
|
18
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
19
|
+
FROM suppliers AS t1
|
20
|
+
ORDER BY t1.city DESC, t1.sid ASC
|
21
|
+
#
|
22
|
+
- alf: |-
|
23
|
+
sort(sort(suppliers, [[:sid, :asc], [:city, :desc]]), [:sid, :asc])
|
24
|
+
sql: |-
|
25
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
26
|
+
FROM suppliers AS t1
|
27
|
+
ORDER BY t1.sid ASC, t1.city DESC
|
28
|
+
#
|
29
|
+
- alf: |-
|
30
|
+
sort(sort(suppliers, [:sid, :asc]), [:sid, :desc])
|
31
|
+
sql: |-
|
32
|
+
WITH t2 AS (
|
33
|
+
SELECT t1.sid,
|
34
|
+
t1.name,
|
35
|
+
t1.status,
|
36
|
+
t1.city
|
37
|
+
FROM suppliers AS t1
|
38
|
+
ORDER BY t1.sid ASC
|
39
|
+
)
|
40
|
+
SELECT t2.sid, t2.name, t2.status, t2.city
|
41
|
+
FROM t2 AS t2
|
42
|
+
ORDER BY t2.sid DESC
|
43
|
+
#
|
44
|
+
- alf: |-
|
45
|
+
sort(union(suppliers_in_paris, suppliers_in_london), [[:sid, :asc]])
|
46
|
+
sql: |-
|
47
|
+
WITH t3 AS (
|
48
|
+
(SELECT t1.sid, t1.name, t1.status, t1.city
|
49
|
+
FROM suppliers AS t1
|
50
|
+
WHERE t1.city = 'Paris')
|
51
|
+
UNION
|
52
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
53
|
+
FROM suppliers AS t2
|
54
|
+
WHERE t2.city = 'London')
|
55
|
+
)
|
56
|
+
SELECT t3.sid, t3.name, t3.status, t3.city
|
57
|
+
FROM t3 AS t3
|
58
|
+
ORDER BY t3.sid ASC
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# BASE case
|
2
|
+
- alf: |-
|
3
|
+
frame(suppliers, [[:sid, :asc]], 2, 4)
|
4
|
+
sql: |-
|
5
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
6
|
+
FROM suppliers AS t1
|
7
|
+
ORDER BY t1.sid ASC
|
8
|
+
LIMIT 4 OFFSET 2
|
9
|
+
# KEY INFERENCE for total ordering
|
10
|
+
- alf: |-
|
11
|
+
frame(suppliers, [[:city, :desc]], 2, 4)
|
12
|
+
sql: |-
|
13
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
14
|
+
FROM suppliers AS t1
|
15
|
+
ORDER BY t1.city DESC, t1.sid ASC
|
16
|
+
LIMIT 4 OFFSET 2
|
17
|
+
# ORDER BY already ok
|
18
|
+
- alf: |-
|
19
|
+
frame(sort(suppliers, [[:city, :desc], [:sid, :asc]]), [[:city, :desc]], 2, 4)
|
20
|
+
sql: |-
|
21
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
22
|
+
FROM suppliers AS t1
|
23
|
+
ORDER BY t1.city DESC, t1.sid ASC
|
24
|
+
LIMIT 4 OFFSET 2
|
25
|
+
# ORDER BY existing but incompatible
|
26
|
+
- alf: |-
|
27
|
+
frame(sort(suppliers, [[:sid, :asc], [:city, :desc]]), [[:city, :desc]], 2, 4)
|
28
|
+
sql: |-
|
29
|
+
WITH t2 AS (
|
30
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
31
|
+
FROM suppliers AS t1
|
32
|
+
ORDER BY t1.sid ASC, t1.city DESC
|
33
|
+
)
|
34
|
+
SELECT t2.sid, t2.name, t2.status, t2.city
|
35
|
+
FROM t2 AS t2
|
36
|
+
ORDER BY t2.city DESC, t2.sid ASC
|
37
|
+
LIMIT 4 OFFSET 2
|
38
|
+
# UNION and other nadics
|
39
|
+
- alf: |-
|
40
|
+
frame(union(suppliers_in_paris, suppliers_in_london), [[:sid, :asc]], 2, 4)
|
41
|
+
sql: |-
|
42
|
+
WITH t3 AS (
|
43
|
+
(SELECT t1.sid, t1.name, t1.status, t1.city
|
44
|
+
FROM suppliers AS t1
|
45
|
+
WHERE t1.city = 'Paris')
|
46
|
+
UNION
|
47
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
48
|
+
FROM suppliers AS t2
|
49
|
+
WHERE t2.city = 'London')
|
50
|
+
)
|
51
|
+
SELECT t3.sid, t3.name, t3.status, t3.city
|
52
|
+
FROM t3 AS t3
|
53
|
+
ORDER BY t3.sid ASC, t3.name ASC, t3.status ASC, t3.city ASC
|
54
|
+
LIMIT 4 OFFSET 2
|
55
|
+
comment: |-
|
56
|
+
The big ordering comes from the fact that key inference is not smart
|
57
|
+
enough to detect that sid is still a key in the resulting union.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
- alf: |-
|
2
|
+
intersect(suppliers_in_paris, suppliers_in_london)
|
3
|
+
sql: |-
|
4
|
+
(SELECT t1.sid, t1.name, t1.status, t1.city
|
5
|
+
FROM suppliers AS t1
|
6
|
+
WHERE t1.city = 'Paris')
|
7
|
+
INTERSECT
|
8
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
9
|
+
FROM suppliers AS t2
|
10
|
+
WHERE t2.city = 'London')
|
11
|
+
- alf: |-
|
12
|
+
intersect(intersect(suppliers_in_paris, suppliers_in_london), suppliers)
|
13
|
+
sql: |-
|
14
|
+
((SELECT t1.sid, t1.name, t1.status, t1.city
|
15
|
+
FROM suppliers AS t1
|
16
|
+
WHERE t1.city = 'Paris')
|
17
|
+
INTERSECT
|
18
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
19
|
+
FROM suppliers AS t2
|
20
|
+
WHERE t2.city = 'London'))
|
21
|
+
INTERSECT
|
22
|
+
(SELECT t3.sid, t3.name, t3.status, t3.city
|
23
|
+
FROM suppliers AS t3)
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# cross join
|
2
|
+
- alf: |-
|
3
|
+
join(project(suppliers, [:sid]), project(parts, [:pid]))
|
4
|
+
sql:
|
5
|
+
SELECT t1.sid, t2.pid
|
6
|
+
FROM suppliers AS t1, parts AS t2
|
7
|
+
# inner join
|
8
|
+
- alf: |-
|
9
|
+
join(suppliers, supplies)
|
10
|
+
sql:
|
11
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
12
|
+
FROM suppliers AS t1
|
13
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
14
|
+
# inner join with same operand
|
15
|
+
- alf: |-
|
16
|
+
join(suppliers, suppliers)
|
17
|
+
sql: |-
|
18
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
19
|
+
FROM suppliers AS t1
|
20
|
+
JOIN suppliers AS t2 ON t1.sid = t2.sid
|
21
|
+
AND t1.name = t2.name
|
22
|
+
AND t1.status = t2.status
|
23
|
+
AND t1.city = t2.city
|
24
|
+
# inner join requiring keeping a common distinct
|
25
|
+
- alf: |-
|
26
|
+
join(project(suppliers, [:city]), project(parts, [:city]))
|
27
|
+
sql:
|
28
|
+
SELECT DISTINCT t1.city
|
29
|
+
FROM suppliers AS t1
|
30
|
+
JOIN parts AS t2 ON t1.city = t2.city
|
31
|
+
# inner join requiring keeping the left distinct
|
32
|
+
- alf: |-
|
33
|
+
join(project(suppliers, [:city]), parts)
|
34
|
+
sql:
|
35
|
+
SELECT DISTINCT t1.city, t2.pid, t2.name, t2.color, t2.weight
|
36
|
+
FROM suppliers AS t1
|
37
|
+
JOIN parts AS t2 ON t1.city = t2.city
|
38
|
+
# inner join requiring keeping the right distinct
|
39
|
+
- alf: |-
|
40
|
+
join(suppliers, project(parts, [:city]))
|
41
|
+
sql:
|
42
|
+
SELECT DISTINCT t1.sid, t1.name, t1.status, t1.city
|
43
|
+
FROM suppliers AS t1
|
44
|
+
JOIN parts AS t2 ON t1.city = t2.city
|
45
|
+
# inner join requiring renamings
|
46
|
+
- alf: |-
|
47
|
+
join(rename(suppliers, sid: :id), rename(supplies, sid: :id))
|
48
|
+
sql:
|
49
|
+
SELECT t1.sid AS id, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
50
|
+
FROM suppliers AS t1
|
51
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
52
|
+
# triple join
|
53
|
+
- alf: |-
|
54
|
+
join(join(suppliers, supplies), project(parts, [:pid, :color]))
|
55
|
+
sql:
|
56
|
+
WITH t4 AS (
|
57
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
58
|
+
FROM suppliers AS t1
|
59
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
60
|
+
)
|
61
|
+
SELECT t4.sid, t4.name, t4.status, t4.city, t4.pid, t4.qty, t3.color
|
62
|
+
FROM t4 AS t4
|
63
|
+
JOIN parts AS t3 ON t4.pid = t3.pid
|
64
|
+
# join of two joins
|
65
|
+
- alf: |-
|
66
|
+
join(join(suppliers, cities), join(project(parts, [:pid, :color]), supplies))
|
67
|
+
sql:
|
68
|
+
WITH
|
69
|
+
t5 AS (
|
70
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.country
|
71
|
+
FROM suppliers AS t1
|
72
|
+
JOIN cities AS t2 ON t1.city = t2.city
|
73
|
+
),
|
74
|
+
t6 AS (
|
75
|
+
SELECT t3.pid, t3.color, t4.sid, t4.qty
|
76
|
+
FROM parts AS t3
|
77
|
+
JOIN supplies AS t4 ON t3.pid = t4.pid
|
78
|
+
)
|
79
|
+
SELECT t5.sid, t5.name, t5.status, t5.city, t5.country, t6.pid, t6.color, t6.qty
|
80
|
+
FROM t5 AS t5
|
81
|
+
JOIN t6 AS t6 ON t5.sid = t6.sid
|
82
|
+
# join with a where clause at left
|
83
|
+
- alf: |-
|
84
|
+
join(restrict(suppliers, sid: 'S2'), supplies)
|
85
|
+
sql:
|
86
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
87
|
+
FROM suppliers AS t1
|
88
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
89
|
+
WHERE t1.sid = 'S2'
|
90
|
+
# join with a where clause at right
|
91
|
+
- alf: |-
|
92
|
+
join(suppliers, restrict(supplies, sid: 'S2'))
|
93
|
+
sql:
|
94
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
95
|
+
FROM suppliers AS t1
|
96
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
97
|
+
WHERE t2.sid = 'S2'
|
98
|
+
# join with where clauses both sides
|
99
|
+
- alf: |-
|
100
|
+
join(restrict(suppliers, sid: 'S2'), restrict(supplies, qty: 300))
|
101
|
+
sql:
|
102
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
103
|
+
FROM suppliers AS t1
|
104
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
105
|
+
WHERE t1.sid = 'S2'
|
106
|
+
AND t2.qty = 300
|
107
|
+
# join with an order-by clause at left
|
108
|
+
- alf: |-
|
109
|
+
join(sort(suppliers, [:sid, :asc]), supplies)
|
110
|
+
sql:
|
111
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
112
|
+
FROM suppliers AS t1
|
113
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
114
|
+
ORDER BY t1.sid ASC
|
115
|
+
# join with an order-by clause at right
|
116
|
+
- alf: |-
|
117
|
+
join(suppliers, sort(supplies, [:qty, :asc]))
|
118
|
+
sql:
|
119
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
120
|
+
FROM suppliers AS t1
|
121
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
122
|
+
ORDER BY t2.qty ASC
|
123
|
+
# join with an order-by clause on both sides
|
124
|
+
- alf: |-
|
125
|
+
join(sort(suppliers, [:sid, :asc]), sort(supplies, [:qty, :asc]))
|
126
|
+
sql:
|
127
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t2.pid, t2.qty
|
128
|
+
FROM suppliers AS t1
|
129
|
+
JOIN supplies AS t2 ON t1.sid = t2.sid
|
130
|
+
ORDER BY t1.sid ASC, t2.qty ASC
|
131
|
+
# join with a limit/offset clause at left
|
132
|
+
- alf: |-
|
133
|
+
join(frame(suppliers, [:sid, :asc], 5, 10), supplies)
|
134
|
+
sql:
|
135
|
+
WITH t3 AS (
|
136
|
+
SELECT t1.sid, t1.name, t1.status, t1.city
|
137
|
+
FROM suppliers AS t1
|
138
|
+
ORDER BY t1.sid ASC
|
139
|
+
LIMIT 10 OFFSET 5
|
140
|
+
)
|
141
|
+
SELECT t3.sid, t3.name, t3.status, t3.city, t2.pid, t2.qty
|
142
|
+
FROM t3 AS t3
|
143
|
+
JOIN supplies AS t2 ON t3.sid = t2.sid
|
144
|
+
# join with a limit/offset clause at right
|
145
|
+
- alf: |-
|
146
|
+
join(suppliers, frame(supplies, [[:sid, :asc], [:pid, :asc]], 5, 10))
|
147
|
+
sql:
|
148
|
+
WITH t3 AS (
|
149
|
+
SELECT t2.sid, t2.pid, t2.qty
|
150
|
+
FROM supplies AS t2
|
151
|
+
ORDER BY t2.sid ASC, t2.pid ASC
|
152
|
+
LIMIT 10 OFFSET 5
|
153
|
+
)
|
154
|
+
SELECT t1.sid, t1.name, t1.status, t1.city, t3.pid, t3.qty
|
155
|
+
FROM suppliers AS t1
|
156
|
+
JOIN t3 AS t3 ON t1.sid = t3.sid
|
157
|
+
# join with a limit/offset clause on both sides
|
158
|
+
- alf: |-
|
159
|
+
join(frame(suppliers, [:sid, :asc], 5, 10),
|
160
|
+
frame(supplies, [[:sid, :asc], [:pid, :asc]], 5, 10))
|
161
|
+
sql:
|
162
|
+
WITH t3 AS (SELECT t1.sid, t1.name, t1.status, t1.city
|
163
|
+
FROM suppliers AS t1
|
164
|
+
ORDER BY t1.sid ASC
|
165
|
+
LIMIT 10 OFFSET 5),
|
166
|
+
t4 AS (SELECT t2.sid, t2.pid, t2.qty
|
167
|
+
FROM supplies AS t2
|
168
|
+
ORDER BY t2.sid ASC, t2.pid ASC
|
169
|
+
LIMIT 10 OFFSET 5)
|
170
|
+
SELECT t3.sid, t3.name, t3.status, t3.city, t4.pid, t4.qty
|
171
|
+
FROM t3 AS t3
|
172
|
+
JOIN t4 AS t4 ON t3.sid = t4.sid
|
173
|
+
# join on a union at left
|
174
|
+
- alf: |-
|
175
|
+
join(union(suppliers_in_london, suppliers_in_paris), supplies)
|
176
|
+
sql:
|
177
|
+
WITH t4 AS (
|
178
|
+
(SELECT t1.sid, t1.name, t1.status, t1.city
|
179
|
+
FROM suppliers AS t1
|
180
|
+
WHERE t1.city = 'London')
|
181
|
+
UNION
|
182
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
183
|
+
FROM suppliers AS t2
|
184
|
+
WHERE t2.city = 'Paris')
|
185
|
+
)
|
186
|
+
SELECT t4.sid, t4.name, t4.status, t4.city, t3.pid, t3.qty
|
187
|
+
FROM t4 AS t4
|
188
|
+
JOIN supplies AS t3 ON t4.sid = t3.sid
|
189
|
+
# join on a union at right
|
190
|
+
- alf: |-
|
191
|
+
join(supplies, union(suppliers_in_london, suppliers_in_paris))
|
192
|
+
sql:
|
193
|
+
WITH t4 AS (
|
194
|
+
(SELECT t2.sid, t2.name, t2.status, t2.city
|
195
|
+
FROM suppliers AS t2
|
196
|
+
WHERE t2.city = 'London')
|
197
|
+
UNION
|
198
|
+
(SELECT t3.sid, t3.name, t3.status, t3.city
|
199
|
+
FROM suppliers AS t3
|
200
|
+
WHERE t3.city = 'Paris')
|
201
|
+
)
|
202
|
+
SELECT t1.sid, t1.pid, t1.qty, t4.name, t4.status, t4.city
|
203
|
+
FROM supplies AS t1
|
204
|
+
JOIN t4 AS t4 ON t1.sid = t4.sid
|
205
|
+
# joining from Relation::DEE
|
206
|
+
- alf: |-
|
207
|
+
join(Relation::DEE, suppliers)
|