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

fix IN_SUBQUERY projection bugs #2182

Merged
merged 8 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
31 changes: 31 additions & 0 deletions enginetest/queries/view_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,37 @@ import (
)

var ViewScripts = []ScriptTest{
{
Name: "view of join with projections",
SetUpScript: []string{
`
CREATE TABLE tab1 (
pk int NOT NULL,
col0 int,
col1 float,
col2 text,
col3 int,
col4 float,
col5 text,
PRIMARY KEY (pk),
KEY idx_tab1_0 (col0),
KEY idx_tab1_1 (col1),
KEY idx_tab1_3 (col3),
KEY idx_tab1_4 (col4)
)`,
"insert into tab1 values (6, 0, 52.14, 'jxmel', 22, 2.27, 'pzxbn')",
},
Assertions: []ScriptTestAssertion{
{
Query: "CREATE VIEW view_2_tab1_157 AS SELECT pk, col0 FROM tab1 WHERE NOT ((col0 IN (SELECT col3 FROM tab1 WHERE ((col0 IS NULL) OR col3 > 5 OR col3 <= 50 OR col1 < 83.11))) OR col0 > 75)",
Expected: []sql.Row{},
},
{
Query: "select pk, col0 from view_2_tab1_157",
Expected: []sql.Row{{6, 0}},
},
},
},
{
Name: "view with expression name",
SetUpScript: []string{
Expand Down
50 changes: 34 additions & 16 deletions sql/analyzer/indexed_joins.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,23 +377,32 @@ func convertSemiToInnerJoin(a *Analyzer, m *memo.Memo) error {
leftCols := semi.Left.RelProps.OutputCols()
var projections []sql.Expression
for colId, hasNext := leftCols.Next(1); hasNext; colId, hasNext = leftCols.Next(colId + 1) {
var table plan.TableIdNode
var srcNode plan.TableIdNode
for _, n := range semi.Left.RelProps.TableIdNodes() {
if n.Columns().Contains(colId) {
table = n
srcNode = n
break
}
}
if table == nil {
if srcNode == nil {
break
return fmt.Errorf("table for column not found: %d", colId)
}

// projection schema is not necessarily sequential. but the columns
// from a single source should be sequential
firstCol, _ := table.Columns().Next(1)
col := table.Schema()[int(colId-firstCol)]
sch := srcNode.Schema()
var table sql.Table
if tw, ok := srcNode.(sql.TableNode); ok {
table = tw.UnderlyingTable()
}
if pkt, ok := table.(sql.PrimaryKeyTable); ok {
sch = pkt.PrimaryKeySchema().Schema
}

projections = append(projections, expression.NewGetFieldWithTable(int(colId), int(table.Id()), col.Type, col.DatabaseSource, col.Source, col.Name, col.Nullable))
firstCol, _ := srcNode.Columns().Next(1)
idx := int(colId - firstCol)
col := sch[idx]

projections = append(projections, expression.NewGetFieldWithTable(int(colId), int(srcNode.Id()), col.Type, col.DatabaseSource, col.Source, col.Name, col.Nullable))

}

Expand Down Expand Up @@ -464,22 +473,31 @@ func convertAntiToLeftJoin(m *memo.Memo) error {
for colId, hasNext := leftCols.Next(1); hasNext; colId, hasNext = leftCols.Next(colId + 1) {
// we have ids and need to get the table back?
// search in tables
var table plan.TableIdNode
var srcNode plan.TableIdNode
for _, n := range anti.Left.RelProps.TableIdNodes() {
if n.Columns().Contains(colId) {
table = n
srcNode = n
break
}
}
if table == nil {
return fmt.Errorf("table for column not found: %d", colId)
if srcNode == nil {
break
}

sch := srcNode.Schema()
var table sql.Table
if tw, ok := srcNode.(sql.TableNode); ok {
table = tw.UnderlyingTable()
}
if pkt, ok := table.(sql.PrimaryKeyTable); ok {
sch = pkt.PrimaryKeySchema().Schema
}

// todo: projection schema is not necessarily sequential
firstCol, _ := table.Columns().Next(1)
col := table.Schema()[int(colId-firstCol)]
firstCol, _ := srcNode.Columns().Next(1)
idx := int(colId - firstCol)
col := sch[idx]

projections = append(projections, expression.NewGetFieldWithTable(int(colId), int(table.Id()), col.Type, col.DatabaseSource, col.Source, col.Name, col.Nullable))
projections = append(projections, expression.NewGetFieldWithTable(int(colId), int(srcNode.Id()), col.Type, col.DatabaseSource, col.Source, col.Name, col.Nullable))
}

if len(projections) == 0 {
Expand Down
35 changes: 32 additions & 3 deletions sql/memo/rel_props.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,37 @@ func newRelProps(rel RelExpr) *relProps {
switch r := rel.(type) {
case *Max1Row:
p.populateFds()
case *EmptyTable:
if r.TableIdNode().Columns().Len() > 0 {
p.outputCols = r.TableIdNode().Columns()
p.populateFds()
p.populateOutputTables()
p.populateInputTables()
return p
}
case *SetOp:
case SourceRel:
p.outputCols = r.TableIdNode().Columns()
n := r.TableIdNode()
if len(n.Schema()) == n.Columns().Len() {
p.outputCols = r.TableIdNode().Columns()
} else {
// if the table is projected, capture subset of column ids
var tw sql.TableNode
var ok bool
for tw, ok = n.(sql.TableNode); !ok; tw, ok = n.Children()[0].(sql.TableNode) {
}

tin := tw.UnderlyingTable().(sql.PrimaryKeyTable)
firstCol, _ := n.Columns().Next(1)
sch := tin.PrimaryKeySchema().Schema

var colset sql.ColSet
for _, c := range n.Schema() {
i := sch.IndexOfColName(c.Name)
colset.Add(firstCol + sql.ColumnId(i))
}
p.outputCols = colset
}
default:
}

Expand Down Expand Up @@ -90,6 +119,8 @@ func (p *relProps) populateFds() {
all := rel.Child.RelProps.FuncDeps().All()
notNull := rel.Child.RelProps.FuncDeps().NotNull()
fds = sql.NewMax1RowFDs(all, notNull)
case *EmptyTable:
fds = &sql.FuncDepSet{}
case SourceRel:
n := rel.TableIdNode()
all := n.Columns()
Expand Down Expand Up @@ -389,8 +420,6 @@ func (p *relProps) outputColsForRel(r RelExpr) sql.ColSet {
return r.outputCols()
case *Max1Row:
return r.outputCols()
case SourceRel:
return r.TableIdNode().Columns()
default:
panic("unknown type")
}
Expand Down
5 changes: 3 additions & 2 deletions sql/memo/rel_props_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ func TestPopulateFDs(t *testing.T) {
{Name: "z", Source: "t", Type: types.Int64, Nullable: false},
}).(*plan.EmptyTable).WithId(1).WithColumns(sql.NewColSet(1, 2, 3)).(*plan.EmptyTable),
},
all: sql.NewColSet(1, 2, 3),
notNull: sql.NewColSet(1, 2, 3),
// planning ignores empty tables for now
all: sql.NewColSet(),
notNull: sql.NewColSet(),
},
{
name: "max1Row",
Expand Down