Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error if subqueries contain more than one result #5651

Merged
merged 18 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
introduce horrible hack
  • Loading branch information
frankmcsherry committed Mar 29, 2021
commit 4af89cfc19ab01a3f68b0141349420fc3b138d24
50 changes: 49 additions & 1 deletion src/expr/src/relation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,55 @@ impl MirRelationExpr {
.unwrap();
}
}
RelationType::new(base_cols)

// Generally, union does not have any unique keys, becuase
// each input might contribute some. However, there is at
// least one idiomatic structure that does preserve keys,
// which results from SQL aggregations that must populate
// absent records with default values. In that pattern,
// the union of one GET with its negation, which has been
// subjected to a projection and map, we can remove their
// influence on the key structure and return the keys of
// the remaining input collection.
//
// If there are A, B, each with a unique `key` such that
// we are looking at
//
// A + (B - A.proj(key)).map(stuff)
//
// TODO: make unique key structure an optimization analysis
// rather than part of the type information.
let mut keys = Vec::new();
if let MirRelationExpr::Get { id: first_id, typ: first_get_type } = &**base {
if inputs.len() == 1 {
if let MirRelationExpr::Map { input, .. } = &inputs[0] {
if let MirRelationExpr::Union { base, inputs } = &** input {
if inputs.len() == 1 {
if let MirRelationExpr::Project { input, outputs } = &**base {
if let MirRelationExpr::Negate { input } = &**input {
if let MirRelationExpr::Get { id: second_id, typ: second_get_type } = &**input {
if first_id == second_id {
keys.extend(inputs[0].typ().keys);
keys.retain(|key| {
first_get_type.keys.contains(key) && second_get_type.keys.contains(key)
&& key.iter().all(|c| outputs.get(*c) == Some(c))
});
}
}
}
}
}
}
}
}
}


let mut result = RelationType::new(base_cols);
for key in keys {
result = result.with_key(key);
}
result
// Important: do not inherit keys of either input, as not unique.
}
MirRelationExpr::ArrangeBy { input, .. } => input.typ(),
Expand Down
205 changes: 56 additions & 149 deletions test/sqllogictest/chbench.slt
Original file line number Diff line number Diff line change
Expand Up @@ -846,71 +846,41 @@ ORDER BY ordercount DESC
| | delta %0 %1.(#0) %2.(#0)
| | delta %1 %2.(#0) %0.(#17)
| | delta %2 %1.(#3) %0.(#17)
| | demand = (#14, #26)
| | demand = (#0, #14, #26)
| Filter (#26 = "GERMANY")
| Reduce group=()
| Reduce group=(#0)
| | agg sum(#14)

%4 =
| Get %3 (l0)
| Negate
| Project ()

%5 =
| Constant ()

%6 =
| Union %4 %5
| Map null

%7 = Let l1 =
| Union %3 %6
| Map (i64todec(#0) * 5dec)

%8 =
| Get materialize.public.stock (u26)
| ArrangeBy (#17)

%9 =
%5 =
| Get materialize.public.supplier (u34)
| ArrangeBy (#0) (#3)

%10 =
%6 =
| Get materialize.public.nation (u31)
| ArrangeBy (#0)

%7 =
| Join %4 %5 %6 (= #17 #18) (= #21 #25)
| | implementation = DeltaQuery
| | delta %8 %9.(#0) %10.(#0)
| | delta %9 %10.(#0) %8.(#17)
| | delta %10 %9.(#3) %8.(#17)
| | demand = (#0, #14, #26)
| | delta %4 %5.(#0) %6.(#0)
| | delta %5 %6.(#0) %4.(#17)
| | delta %6 %5.(#3) %4.(#17)
| | demand = (#14, #26)
| Filter (#26 = "GERMANY")
| Reduce group=(#0)
| Reduce group=()
| | agg sum(#14)
| Map (i64todec(#0) * 5dec)
| ArrangeBy ()

%12 =
| Get %7 (l1)
| Project (#1)

%13 =
| Get %7 (l1)
| Reduce group=()
| | agg count(true)
| Filter (#0 > 1)
| Map (err: more than one record produced in subquery)
| Project (#1)

%14 =
| Union %12 %13

%15 =
| Join %11 %14
| | implementation = Differential %14 %11.()
| | demand = (#0..#2)
| Filter ((i64todec(#1) * 1000dec) > #2)
%8 =
| Join %3 %7
| | implementation = Differential %3 %7.()
| | demand = (#0, #1, #3)
| Filter ((i64todec(#1) * 1000dec) > #3)
| Project (#0, #1)

Finish order_by=(#1 desc) limit=none offset=0 project=(#0, #1)
Expand Down Expand Up @@ -1093,84 +1063,55 @@ AND total_revenue = (
ORDER BY su_suppkey
----
%0 =
| Get materialize.public.supplier (u34)
| ArrangeBy (#0)

%1 =
| Get materialize.public.orderline (u19)
| ArrangeBy (#5, #4)

%1 =
%2 =
| Get materialize.public.stock (u26)
| ArrangeBy (#0, #1)

%3 =
| Join %1 %2 (= #4 #10) (= #5 #11)
| | implementation = DeltaQuery
| | delta %0 %1.(#0, #1)
| | delta %1 %0.(#5, #4)
| | delta %1 %2.(#0, #1)
| | delta %2 %1.(#5, #4)
| | demand = (#6, #8, #27)
| Filter (datetots(#6) >= 2007-01-02 00:00:00)
| Reduce group=(#27)
| | agg sum(#8)
| Reduce group=()
| | agg max(#1)

%3 =
| Get %2 (l0)
| Negate
| Project ()

%4 =
| Constant ()

%5 =
| Union %3 %4
| Map null

%6 = Let l1 =
| Union %2 %5

%7 =
| Get materialize.public.supplier (u34)
| ArrangeBy (#0)

%8 =
%4 =
| Get materialize.public.orderline (u19)
| ArrangeBy (#5, #4)

%9 =
%5 =
| Get materialize.public.stock (u26)
| ArrangeBy (#0, #1)

%6 =
| Join %4 %5 (= #4 #10) (= #5 #11)
| | implementation = DeltaQuery
| | delta %8 %9.(#0, #1)
| | delta %9 %8.(#5, #4)
| | delta %4 %5.(#0, #1)
| | delta %5 %4.(#5, #4)
| | demand = (#6, #8, #27)
| Filter (datetots(#6) >= 2007-01-02 00:00:00)
| Reduce group=(#27)
| | agg sum(#8)
| Filter !(isnull(#1))
| ArrangeBy (#1)

%11 =
| Get %6 (l1)
| Filter !(isnull(#0))

%12 =
| Get %6 (l1)
| Filter (err: more than one record produced in subquery)
| Reduce group=()
| | agg count(true)
| Filter (#0 > 1)
| Map (err: more than one record produced in subquery)
| Project (#1)

%13 =
| Union %11 %12
| | agg max(#1)
| Filter !(isnull(#0))
| ArrangeBy (#0)

%14 =
| Join %7 %10 %13 (= #0 #7) (= #8 #9)
| | implementation = Differential %13 %10.(#1) %7.(#0)
%7 =
| Join %0 %3 %6 (= #0 #7) (= #8 #9)
| | implementation = Differential %0.(#0) %3.(#0) %6.(#0)
| | demand = (#0..#2, #4, #8)
| Filter !(isnull(#8))
| Project (#0..#2, #4, #8)

Finish order_by=(#0 asc) limit=none offset=0 project=(#0..#4)
Expand Down Expand Up @@ -1620,80 +1561,46 @@ ORDER BY substr(c_state, 1, 1)
| Reduce group=()
| | agg sum(#16)
| | agg count(#16)

%1 =
| Get %0 (l0)
| Negate
| Project ()

%2 =
| Constant ()

%3 =
| Union %1 %2
| Map null, 0

%4 = Let l1 =
| Union %0 %3
| Map (((#0 * 10000000dec) / i64todec(if (#1 = 0) then {null} else {#1})) / 10dec)

%5 =
| Get materialize.public.customer (u6)
| Filter (((((((substr(#11, 1, 1) = "1") || (substr(#11, 1, 1) = "2")) || (substr(#11, 1, 1) = "3")) || (substr(#11, 1, 1) = "4")) || (substr(#11, 1, 1) = "5")) || (substr(#11, 1, 1) = "6")) || (substr(#11, 1, 1) = "7"))
| ArrangeBy ()

%6 =
| Get %4 (l1)
| Project (#2)

%7 =
| Get %4 (l1)
| Reduce group=()
| | agg count(true)
| Filter (#0 > 1)
| Map (err: more than one record produced in subquery)
| Project (#1)

%8 =
| Union %6 %7

%9 = Let l2 =
| Join %5 %8
| | implementation = Differential %8 %5.()
| | demand = (#0..#2, #9, #16, #22)
| Filter ((#16 * 1000000dec) > #22)

%10 = Let l3 =
| Get %9 (l2)
| Distinct group=(#0, #1, #2)
%2 = Let l0 =
| Join %0 %1
| | implementation = Differential %0 %1.()
| | demand = (#0..#2, #9, #16, #24)
| Filter ((#16 * 1000000dec) > #24)

%11 =
| Get %9 (l2)
%3 =
| Get %2 (l0)
| ArrangeBy (#0, #1, #2)

%12 =
| Get %10 (l3)
%4 =
| Get %2 (l0)
| ArrangeBy (#0, #1, #2)

%13 =
%5 =
| Get materialize.public.order (u16)
| ArrangeBy (#2, #1, #3)

%14 =
| Join %12 %13 (= #2 #5) (= #1 #4) (= #0 #6)
%6 =
| Join %4 %5 (= #0 #28) (= #1 #26) (= #2 #27)
| | implementation = DeltaQuery
| | delta %12 %13.(#2, #1, #3)
| | delta %13 %12.(#0, #1, #2)
| | delta %4 %5.(#2, #1, #3)
| | delta %5 %4.(#0, #1, #2)
| | demand = (#0..#2)
| Distinct group=(#0, #1, #2)
| Negate

%15 =
| Union %14 %10
%7 =
| Get %2 (l0)
| Project (#0..#2)

%16 =
| Join %11 %15 (= #0 #23) (= #1 #24) (= #2 #25)
| | implementation = Differential %15 %11.(#0, #1, #2)
%8 =
| Union %6 %7

%9 =
| Join %3 %8 (= #0 #25) (= #1 #26) (= #2 #27)
| | implementation = Differential %8 %3.(#0, #1, #2)
| | demand = (#9, #16)
| Reduce group=(substr(#9, 1, 1))
| | agg count(true)
Expand Down
10 changes: 0 additions & 10 deletions test/sqllogictest/joins.slt
Original file line number Diff line number Diff line change
Expand Up @@ -550,23 +550,13 @@ mode standard
query T multiline
EXPLAIN SELECT name, id FROM v4362 WHERE name = (SELECT name FROM v4362 WHERE id = 1)
----
<<<<<<< HEAD
%0 =
| Get materialize.public.t4362 (u10)
| ArrangeBy (#0)

%1 =
| Get materialize.public.t4362 (u10)
| Filter (#1 = 1)
=======
%0 = Let l0 =
| Get materialize.public.v4362 (u12)
| Filter (#1 = 1)

%1 =
| Get materialize.public.v4362 (u12)
| ArrangeBy (#0)
>>>>>>> 058c0031b (correct joins.slt)

%2 =
| Get %0 (l0)
Expand Down
Loading