Skip to content
Merged
49 changes: 49 additions & 0 deletions enginetest/queries/script_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -14883,6 +14883,55 @@ select * from t1 except (
},
},
},
{
// https://github.com/dolthub/dolt/issues/10600
Name: "self-referential NOT IN subquery",
SetUpScript: []string{
"CREATE TABLE bug_repro (id VARCHAR(32) PRIMARY KEY, status VARCHAR(16), name VARCHAR(32));",
"INSERT INTO bug_repro VALUES ('a', 'open', 'x'), ('b', 'open', 'y'), ('c', 'open', 'z');",
},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT * FROM bug_repro WHERE id NOT IN (SELECT id FROM bug_repro WHERE status='open' LIMIT 1);",
Expected: []sql.Row{
{"b", "open", "y"},
{"c", "open", "z"},
},
},
{
Query: "UPDATE bug_repro SET status='closed' WHERE id NOT IN (SELECT id FROM bug_repro WHERE status='open' LIMIT 1);",
Expected: []sql.Row{{NewUpdateResult(2, 2)}},
},
{
Query: "INSERT INTO bug_repro VALUES ('d', 'open', 'zz')",
Expected: []sql.Row{{types.NewOkResult(1)}},
},
{
Query: "DELETE FROM bug_repro WHERE status='open' AND id NOT IN (SELECT id FROM bug_repro WHERE status='open' LIMIT 1);",
Expected: []sql.Row{{types.NewOkResult(1)}},
},
{
Query: "select * from bug_repro",
Expected: []sql.Row{
{"a", "open", "x"},
{"b", "closed", "y"},
{"c", "closed", "z"},
},
},
{
Query: "UPDATE bug_repro SET status='delete this' WHERE id NOT IN (SELECT id FROM bug_repro WHERE status='keep this');",
Expected: []sql.Row{{NewUpdateResult(3, 3)}},
},
{
Query: "select * from bug_repro",
Expected: []sql.Row{
{"a", "delete this", "x"},
{"b", "delete this", "y"},
{"c", "delete this", "z"},
},
},
},
},
}

var SpatialScriptTests = []ScriptTest{
Expand Down
10 changes: 7 additions & 3 deletions sql/analyzer/indexed_joins.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,13 @@ func replanJoin(ctx *sql.Context, n *plan.JoinNode, a *Analyzer, scope *plan.Sco
return nil, err
}

err = convertAntiToLeftJoin(m)
if err != nil {
return nil, err
// TODO: updateJoinIter is not able to handle left joins wrapped in project nodes, which is what an antijoin gets
// converted to. https://github.com/dolthub/dolt/issues/10614
if !qFlags.IsSet(sql.QFlagUpdate) {
err = convertAntiToLeftJoin(m)
if err != nil {
return nil, err
}
}

err = addRightSemiJoins(ctx, m)
Expand Down
2 changes: 1 addition & 1 deletion sql/rowexec/join_iters.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (i *joinState) makeLeftOuterNonMatchingResult() sql.Row {
return resultRow
}

// makeLeftOuterNonMatchingResult returns a new sql.Row representing a row from an OUTER RIGHT join where no match was made with the left child.
// makeRightOuterNonMatchingResult returns a new sql.Row representing a row from an OUTER RIGHT join where no match was made with the left child.
func (i *joinState) makeRightOuterNonMatchingResult() sql.Row {
resultRow := make(sql.Row, i.resultRowSize())
copy(resultRow, i.scopeColumns())
Expand Down
20 changes: 14 additions & 6 deletions sql/rowexec/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,14 @@ func newUpdateIter(
// done once.
type updateJoinIter struct {
updateSourceIter sql.RowIter
joinNode sql.Node
updaters map[string]sql.RowUpdater
caches map[string]sql.KeyValueCache
disposals map[string]sql.DisposeFunc
accumulator *updateJoinRowHandler
joinSchema sql.Schema
// TODO: naming this joinNode is confusing. It's not always a join node because it could be wrapped inside another
// node
joinNode sql.Node
updaters map[string]sql.RowUpdater
caches map[string]sql.KeyValueCache
disposals map[string]sql.DisposeFunc
accumulator *updateJoinRowHandler
joinSchema sql.Schema
}

var _ sql.RowIter = (*updateJoinIter)(nil)
Expand Down Expand Up @@ -289,6 +291,7 @@ func (u *updateJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
}

func toJoinNode(node sql.Node) *plan.JoinNode {
// TODO: rewrite this to use Inspect
switch n := node.(type) {
case *plan.JoinNode:
return n
Expand Down Expand Up @@ -348,6 +351,11 @@ func (u *updateJoinIter) shouldUpdateDirectionalJoin(ctx *sql.Context, joinRow,
}

// If the overall row fits the join condition it is fine (i.e. middle of the venn diagram).
// TODO: We shouldn't be evaluating the join condition on "joinRow". "joinRow" is not actually the row from the
// join node but rather the row from the updateSourceIter. The join node could be wrapped in a Project node and the
// indexes in the join condition would no longer match the correct columns. We also need to consider how to handle
// updateJoins where a LeftOuterJoin is filtered by a null right side. JoinCond could also be nil.
// https://github.com/dolthub/dolt/issues/10614
val, err := jn.JoinCond().Eval(ctx, joinRow)
if err != nil {
return true, err
Expand Down