Skip to content

Commit

Permalink
bugfixes: collection of fixes to bugs found while fuzzing (#13332)
Browse files Browse the repository at this point in the history
* bugfix: left join predicate only depending on RHS turns into inner join

Signed-off-by: Andres Taylor <andres@planetscale.com>

* bugfix: use the incoming type fields to calculate the outgoing types

Signed-off-by: Andres Taylor <andres@planetscale.com>

* bugfix: filter was using wrong method on evalengine

Signed-off-by: Andres Taylor <andres@planetscale.com>

---------

Signed-off-by: Andres Taylor <andres@planetscale.com>
  • Loading branch information
systay authored Jun 19, 2023
1 parent 37584b4 commit a8e939f
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ func TestBuggyQueries(t *testing.T) {
"[[NULL NULL INT64(3) NULL NULL INT64(3)] "+
"[INT32(100) DECIMAL(300) INT64(3) INT32(100) DECIMAL(300) INT64(3)] "+
"[INT32(200) DECIMAL(600) INT64(3) INT32(200) DECIMAL(600) INT64(3)]]")

mcmp.Exec("select /*vt+ PLANNER=gen4 */sum(tbl1.a), min(tbl0.b) from t10 as tbl0, t10 as tbl1 left join t10 as tbl2 on tbl1.a = tbl2.a and tbl1.b = tbl2.k")
mcmp.Exec("select /*vt+ PLANNER=gen4 */count(*) from t10 left join t10 as t11 on t10.a = t11.b where t11.a")
}

func TestMinMaxAcrossJoins(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions go/test/endtoend/vtgate/queries/misc/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,13 @@ func TestPrepareStatements(t *testing.T) {
_, err = mcmp.ExecAllowAndCompareError("deallocate prepare prep_art")
assert.ErrorContains(t, err, "VT09011: Unknown prepared statement handler (prep_art) given to DEALLOCATE PREPARE")
}

func TestBuggyOuterJoin(t *testing.T) {
// We found a couple of inconsistencies around outer joins, adding these tests to stop regressions
mcmp, closer := start(t)
defer closer()

mcmp.Exec("insert into t1(id1, id2) values (1,2), (42,5), (5, 42)")

mcmp.Exec("select t1.id1, t2.id1 from t1 left join t1 as t2 on t2.id1 = t2.id2")
}
7 changes: 2 additions & 5 deletions go/vt/vtgate/engine/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ func (f *Filter) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[s
if err != nil {
return nil, err
}
intEvalResult, err := evalResult.Value().ToInt64()
if err != nil {
return nil, err
}
if intEvalResult == 1 {

if evalResult.ToBoolean() {
rows = append(rows, row)
}
}
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/engine/projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (p *Projection) GetFields(ctx context.Context, vcursor VCursor, bindVars ma
return nil, err
}
env := evalengine.NewExpressionEnv(ctx, bindVars, vcursor)
qr.Fields, err = p.evalFields(env, nil)
qr.Fields, err = p.evalFields(env, qr.Fields)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/operators/joins.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func AddPredicate(
case deps.IsSolvedBy(TableID(join.GetRHS())):
// if we are dealing with an outer join, always start by checking if this predicate can turn
// the join into an inner join
if !join.IsInner() && canConvertToInner(ctx, expr, TableID(join.GetRHS())) {
if !joinPredicates && !join.IsInner() && canConvertToInner(ctx, expr, TableID(join.GetRHS())) {
join.MakeInner()
}

Expand Down
78 changes: 78 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/from_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -6370,5 +6370,83 @@
"query": "select missing_column from unsharded, unsharded_tab",
"v3-plan": "VT03019: column missing_column not found",
"gen4-plan": "Column 'missing_column' in field list is ambiguous"
},
{
"comment": "join predicate only depending on the RHS should not turn outer join into inner join",
"query": "select t1.id1, t2.id1 from t1 left join t1 as t2 on t2.id1 = t2.id2",
"v3-plan": {
"QueryType": "SELECT",
"Original": "select t1.id1, t2.id1 from t1 left join t1 as t2 on t2.id1 = t2.id2",
"Instructions": {
"OperatorType": "Join",
"Variant": "LeftJoin",
"JoinColumnIndexes": "L:0,R:0",
"TableName": "t1_t1",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "zlookup_unique",
"Sharded": true
},
"FieldQuery": "select t1.id1 from t1 where 1 != 1",
"Query": "select t1.id1 from t1",
"Table": "t1"
},
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "zlookup_unique",
"Sharded": true
},
"FieldQuery": "select t2.id1 from t1 as t2 where 1 != 1",
"Query": "select t2.id1 from t1 as t2 where t2.id1 = t2.id2",
"Table": "t1"
}
]
},
"TablesUsed": [
"zlookup_unique.t1"
]
},
"gen4-plan": {
"QueryType": "SELECT",
"Original": "select t1.id1, t2.id1 from t1 left join t1 as t2 on t2.id1 = t2.id2",
"Instructions": {
"OperatorType": "Join",
"Variant": "LeftJoin",
"JoinColumnIndexes": "L:0,R:0",
"TableName": "t1_t1",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "zlookup_unique",
"Sharded": true
},
"FieldQuery": "select t1.id1 from t1 where 1 != 1",
"Query": "select t1.id1 from t1",
"Table": "t1"
},
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "zlookup_unique",
"Sharded": true
},
"FieldQuery": "select t2.id1 from t1 as t2 where 1 != 1",
"Query": "select t2.id1 from t1 as t2 where t2.id1 = t2.id2",
"Table": "t1"
}
]
},
"TablesUsed": [
"zlookup_unique.t1"
]
}
}
]

0 comments on commit a8e939f

Please sign in to comment.