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

Move subqueries to use the operator model #13750

Merged
merged 110 commits into from
Sep 29, 2023
Merged
Changes from 1 commit
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
a344c3a
renamed planbuilder, operator and engine primitive
systay Aug 11, 2023
98be673
wip - handle EXISTS and push it down through an ApplyJoin
systay Aug 15, 2023
ecb83d8
wip - change subquery pushing
systay Aug 15, 2023
f359ed0
wip - semiJoin from EXISTS now planner correctly
systay Aug 16, 2023
756e935
more work on semijoin and exists
systay Aug 16, 2023
e0f00ce
handle IN queries usign SemiJoins
systay Aug 17, 2023
f7d01e7
only add the planner phases that are needed for the current query
systay Aug 17, 2023
04ddc38
remove SubQueryInner
systay Aug 17, 2023
8aebcb9
clean up UncorrelatedSubquery
systay Aug 17, 2023
9902d54
handle uncorrelated subqueries better
systay Aug 18, 2023
20e1340
better support for PulloutValue subqueries
systay Aug 18, 2023
0761a7a
move the query signature to the semantic analysis
systay Aug 19, 2023
7df2fdd
use constructor
systay Aug 19, 2023
347a36a
handle subquery filter
systay Aug 22, 2023
337ec81
handle exists well in merging
systay Aug 22, 2023
c988fad
make merging great again
systay Aug 22, 2023
71e19ad
go back to single expression AddColumn
systay Aug 22, 2023
eb06afd
feat: refactor and fix subqery merge logic
harshit-gangal Aug 23, 2023
3da93bc
feat: ignore columns for subquery merge when comparison is not equal …
harshit-gangal Aug 23, 2023
60dddd5
fix: set pullout variables on operator to set them on engine primitiv…
harshit-gangal Aug 23, 2023
7800ca9
feat: push filter on subquery filter
harshit-gangal Aug 23, 2023
f26eb69
handle pushing subqueries when the subquery depends on both sides of …
systay Aug 24, 2023
24ab078
update some plantests
systay Aug 24, 2023
876f557
push projections under subqueries
systay Aug 24, 2023
1bc2b4c
move the subquery-filter to be closer to the ApplyJoin
systay Aug 24, 2023
ca8e7c9
make it possible to push aggregation through subquery
systay Aug 24, 2023
8f2e397
lots of work on recursive subqueries
systay Aug 28, 2023
126a37f
Merge remote-tracking branch 'upstream/main' into subq-op
harshit-gangal Aug 29, 2023
8d7811f
fail for cases when correlated subquery is not an exists query
harshit-gangal Aug 29, 2023
8055ea7
calculate the join columns and outer columns needed on demand
systay Aug 29, 2023
f6b25b3
updated plantests
systay Aug 29, 2023
3856cb3
push subqueries to the side that they have connection to
systay Aug 29, 2023
c39c5ce
remove ExtractedSubquery and uses
systay Aug 30, 2023
6eb509e
make the query rewriting work again
systay Aug 30, 2023
52c5778
dont push limit under subqueries
systay Aug 30, 2023
b0c0e7b
handle subqueries on join predicates
systay Aug 30, 2023
cee43e9
refactor: extract shared code between ExistsExpr and ComparisonExpr
systay Aug 30, 2023
97868fd
handle more types of subqueries in the WHERE clause
systay Aug 30, 2023
45ef83c
Merge remote-tracking branch 'upstream/main' into subq-op
systay Aug 30, 2023
f38f5dd
refactor: remove SubQuery interface
systay Aug 30, 2023
eb1d289
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 4, 2023
9dbd7b4
change SQC to return the subquery
systay Sep 4, 2023
419dbfc
typo
systay Sep 4, 2023
b1991cb
minor refactoring
systay Sep 4, 2023
8213ea6
add support for subquery projections
systay Sep 5, 2023
b455f80
update more tests
systay Sep 6, 2023
407636e
feat: merge subqueries with more predicates after it
GuptaManan100 Sep 6, 2023
0b36163
catch the first subquery, not the last
systay Sep 6, 2023
ca7e38e
Fix not exist subqueries
frouioui Sep 6, 2023
87f9eb6
handle stars in projections when possible
systay Sep 11, 2023
d4008e8
tiny fix and update plan-tests
systay Sep 11, 2023
29cc45e
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 11, 2023
b2f5aea
improve support for correlated subqueries
frouioui Sep 11, 2023
5bcb900
add the capability of skipping plan tests
systay Sep 12, 2023
868c6ba
move subquery code to one file
systay Sep 12, 2023
c2e05c9
fail correlated projection subqueries
systay Sep 12, 2023
b21ab58
fix some projections and break others
systay Sep 12, 2023
e8cb962
make all ProjExpr implement the interface by ref
systay Sep 12, 2023
d2a4443
move selectExprs closer to the source
systay Sep 12, 2023
b823e7d
refactor: clean up projections
systay Sep 13, 2023
89c5431
refactor: small type refactoring
systay Sep 13, 2023
8de4d9a
Merge remote-tracking branch 'upstream/main' into subq-op
harshit-gangal Sep 14, 2023
860f702
handle comments and locks using an operator
systay Sep 14, 2023
58fcb33
handle UPDATE with subqueries in the SET clause
systay Sep 15, 2023
97023e8
fix subquery that is merged on the RHS of a join
frouioui Sep 15, 2023
5f90c4b
clean up argument name creation
systay Sep 16, 2023
17402f9
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 16, 2023
741649a
DRYify the project operator - add columns refactoring
systay Sep 16, 2023
df79570
small simplification
systay Sep 16, 2023
e9f2315
handle weightstrings on projected columns
systay Sep 16, 2023
16a31fc
get the tabletSet for the subquery
systay Sep 16, 2023
5a9de19
handle subquery merging better
systay Sep 17, 2023
252ee15
rewrite not expressions
systay Sep 17, 2023
5520a31
clean up subquery handling
systay Sep 17, 2023
386da80
only merge subqueries that are at the top-level
systay Sep 17, 2023
972c1c3
refactor: clean up of code
systay Sep 17, 2023
5a9de9c
minor fixups
systay Sep 19, 2023
8864385
remove precalculated field and build it as needed instead
systay Sep 20, 2023
e70c5f2
refactoring of how we handle the pushing of subqueries through joins
systay Sep 20, 2023
5b74e3e
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 20, 2023
108a624
do the join column calculation upfront
frouioui Sep 20, 2023
6d00c9a
search the ON conditions for predicates binding inner and outer subqu…
systay Sep 21, 2023
1fb146a
remove unneeded check
systay Sep 21, 2023
d3d426e
first union query inside subquery passing
systay Sep 21, 2023
49aefe5
handle predicates inside unions inside subqueries
systay Sep 21, 2023
54d6bd9
updated tpch plan tests
systay Sep 21, 2023
f0c76ee
handle EXISTS projections correctly
systay Sep 21, 2023
155dc02
create subquery planner for having clause
harshit-gangal Sep 22, 2023
6cc5a6d
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 23, 2023
792ce30
last couple of tests turned green
systay Sep 26, 2023
a89e3d5
check that subqueries used in comparisons have the correct number of …
systay Sep 26, 2023
f9705b4
remove column number check from engine primitive and remove outdated …
systay Sep 26, 2023
b756846
restore the space between exists and the parens
systay Sep 26, 2023
df4b8fa
remove invalid queries
systay Sep 26, 2023
ba8ea10
make sure the engine primitive handles the new plans correctly
systay Sep 26, 2023
9ae46d1
comments and renaming for clarification
systay Sep 26, 2023
bcb657d
refactoring & remove silly test
systay Sep 26, 2023
e66336a
Rename `pushDown` to `push` in the operator package
systay Sep 26, 2023
7ab4d8c
remove another query with subq in outer join condition
systay Sep 27, 2023
894823e
bug: check the output columns on commented queries
systay Sep 27, 2023
a104a2d
test: fix test expectation and add a comment explaining it
GuptaManan100 Sep 27, 2023
173ea54
feat: fix pushing order by underneath an aggregation
GuptaManan100 Sep 27, 2023
eb23151
bug: fix the subquery merging logic
systay Sep 27, 2023
baeeabd
address review comments
systay Sep 27, 2023
b804997
extract subquery building from subquery container
systay Sep 28, 2023
5f4b40d
allow merging but not routing if predicates are deep in expression tree
systay Sep 28, 2023
b513c99
clean up projection subquery planning
systay Sep 29, 2023
02afec8
Merge remote-tracking branch 'upstream/main' into subq-op
systay Sep 29, 2023
826a3bb
handle subquery with vindex value on update better with blocking merge
harshit-gangal Sep 29, 2023
77e4cb7
make sure to handle Exists in projections correctly
systay Sep 29, 2023
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
handle stars in projections when possible
Signed-off-by: Andres Taylor <andres@planetscale.com>
  • Loading branch information
systay committed Sep 11, 2023

Verified

This commit was signed with the committer’s verified signature. The key has expired.
BridgeAR Ruben Bridgewater
commit 87f9eb6aa7176d7c330715be012ca893f4120337
6 changes: 5 additions & 1 deletion go/vt/vtgate/planbuilder/operator_transformers.go
Original file line number Diff line number Diff line change
@@ -241,7 +241,11 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project
}
})
var primitive *engine.Projection
columnNames := slice.Map(op.Columns, func(from *sqlparser.AliasedExpr) string {
cols, err := op.GetColumns(ctx)
if err != nil {
return nil, err
}
columnNames := slice.Map(cols, func(from *sqlparser.AliasedExpr) string {
return from.ColumnName()
})

29 changes: 17 additions & 12 deletions go/vt/vtgate/planbuilder/operators/SQL_builder.go
Original file line number Diff line number Diff line change
@@ -124,22 +124,20 @@ func (qb *queryBuilder) addGroupBy(original sqlparser.Expr) {
sel.GroupBy = append(sel.GroupBy, original)
}

func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) error {
func (qb *queryBuilder) addProjection(projection sqlparser.SelectExpr) error {
switch stmt := qb.sel.(type) {
case *sqlparser.Select:
stmt.SelectExprs = append(stmt.SelectExprs, projection)
return nil
case *sqlparser.Union:
switch expr := projection.Expr.(type) {
case *sqlparser.ColName:
return checkUnionColumnByName(expr, qb.sel)
default:
// if there is more than just column names, we'll just push the UNION
// inside a derived table and then recurse into this method again
qb.pushUnionInsideDerived()
return qb.addProjection(projection)
if ae, ok := projection.(*sqlparser.AliasedExpr); ok {
if col, ok := ae.Expr.(*sqlparser.ColName); ok {
return checkUnionColumnByName(col, qb.sel)
}
}

qb.pushUnionInsideDerived()
return qb.addProjection(projection)
}
return vterrors.VT13001(fmt.Sprintf("unknown select statement type: %T", qb.sel))
}
@@ -476,8 +474,11 @@ func buildProjection(op *Projection, qb *queryBuilder) error {
_, isSel := qb.sel.(*sqlparser.Select)
if isSel {
qb.clearProjections()

for _, column := range op.Columns {
cols, err := op.GetSelectExprs(qb.ctx)
if err != nil {
return err
}
for _, column := range cols {
err := qb.addProjection(column)
if err != nil {
return err
@@ -496,7 +497,11 @@ func buildProjection(op *Projection, qb *queryBuilder) error {
}

if !isSel {
for _, column := range op.Columns {
cols, err := op.GetSelectExprs(qb.ctx)
if err != nil {
return err
}
for _, column := range cols {
err := qb.addProjection(column)
if err != nil {
return err
45 changes: 31 additions & 14 deletions go/vt/vtgate/planbuilder/operators/aggregation_pushing.go
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ limitations under the License.
package operators

import (
"errors"
"fmt"
"slices"

@@ -87,7 +88,10 @@ func pushDownAggregationThroughSubquery(
if idx >= 0 {
continue
}
pushedAggr.addColumnWithoutPushing(aeWrap(colName), true)
_, err := pushedAggr.addColumnWithoutPushing(aeWrap(colName), true)
if err != nil {
return nil, nil, err
}
}
}

@@ -242,7 +246,10 @@ withNextColumn:
continue withNextColumn
}
}
pushedAggr.addColumnWithoutPushing(aeWrap(col), true)
_, err := pushedAggr.addColumnWithoutPushing(aeWrap(col), true)
if err != nil {
return nil, nil, err
}
}

// Set the source of the filter to the new aggregator placed below the route.
@@ -373,7 +380,7 @@ func pushDownAggregationThroughJoin(ctx *plancontext.PlanningContext, rootAggr *
joinColumns, output, err := splitAggrColumnsToLeftAndRight(ctx, rootAggr, join, lhs, rhs)
if err != nil {
// if we get this error, we just abort the splitting and fall back on simpler ways of solving the same query
if err == errAbortAggrPushing {
if errors.Is(err, errAbortAggrPushing) {
return nil, nil, nil
}
return nil, nil, err
@@ -480,10 +487,12 @@ func splitAggrColumnsToLeftAndRight(
join *ApplyJoin,
lhs, rhs *joinPusher,
) ([]JoinColumn, ops.Operator, error) {
proj := newAliasedProjection(join)
proj.FromAggr = true
builder := &aggBuilder{
lhs: lhs,
rhs: rhs,
proj: &Projection{Source: join, FromAggr: true},
proj: proj,
outerJoin: join.LeftJoin,
}

@@ -511,7 +520,10 @@ outer:
continue outer
}
}
builder.proj.addUnexploredExpr(col, col.Expr)
_, err := builder.proj.addUnexploredExpr(col, col.Expr)
if err != nil {
return nil, nil, err
}
}
return builder.joinColumns, builder.proj, nil
}
@@ -576,8 +588,7 @@ func (p *joinPusher) countStar(ctx *plancontext.PlanningContext) (*sqlparser.Ali
func (ab *aggBuilder) handleAggr(ctx *plancontext.PlanningContext, aggr Aggr) error {
switch aggr.OpCode {
case opcode.AggregateCountStar:
ab.handleCountStar(ctx, aggr)
return nil
return ab.handleCountStar(ctx, aggr)
case opcode.AggregateCount, opcode.AggregateSum:
return ab.handleAggrWithCountStarMultiplier(ctx, aggr)
case opcode.AggregateMax, opcode.AggregateMin, opcode.AggregateAnyValue:
@@ -623,7 +634,10 @@ func (ab *aggBuilder) pushThroughRight(aggr Aggr) {
}

func (ab *aggBuilder) handlePushThroughAggregation(ctx *plancontext.PlanningContext, aggr Aggr) error {
ab.proj.addUnexploredExpr(aggr.Original, aggr.Original.Expr)
_, err := ab.proj.addUnexploredExpr(aggr.Original, aggr.Original.Expr)
if err != nil {
return err
}

deps := ctx.SemTable.RecursiveDeps(aggr.Original.Expr)
switch {
@@ -637,12 +651,12 @@ func (ab *aggBuilder) handlePushThroughAggregation(ctx *plancontext.PlanningCont
return nil
}

func (ab *aggBuilder) handleCountStar(ctx *plancontext.PlanningContext, aggr Aggr) {
func (ab *aggBuilder) handleCountStar(ctx *plancontext.PlanningContext, aggr Aggr) error {
// Add the aggregate to both sides of the join.
lhsAE := ab.leftCountStar(ctx)
rhsAE := ab.rightCountStar(ctx)

ab.buildProjectionForAggr(lhsAE, rhsAE, aggr, true)
return ab.buildProjectionForAggr(lhsAE, rhsAE, aggr, true)
}

func (ab *aggBuilder) handleAggrWithCountStarMultiplier(ctx *plancontext.PlanningContext, aggr Aggr) error {
@@ -668,11 +682,10 @@ func (ab *aggBuilder) handleAggrWithCountStarMultiplier(ctx *plancontext.Plannin
return errAbortAggrPushing
}

ab.buildProjectionForAggr(lhsAE, rhsAE, aggr, addCoalesce)
return nil
return ab.buildProjectionForAggr(lhsAE, rhsAE, aggr, addCoalesce)
}

func (ab *aggBuilder) buildProjectionForAggr(lhsAE *sqlparser.AliasedExpr, rhsAE *sqlparser.AliasedExpr, aggr Aggr, coalesce bool) {
func (ab *aggBuilder) buildProjectionForAggr(lhsAE *sqlparser.AliasedExpr, rhsAE *sqlparser.AliasedExpr, aggr Aggr, coalesce bool) error {
// We expect the expressions to be different on each side of the join, otherwise it's an error.
if lhsAE.Expr == rhsAE.Expr {
panic(fmt.Sprintf("Need the two produced expressions to be different. %T %T", lhsAE, rhsAE))
@@ -701,7 +714,11 @@ func (ab *aggBuilder) buildProjectionForAggr(lhsAE *sqlparser.AliasedExpr, rhsAE
As: sqlparser.NewIdentifierCI(aggr.Original.ColumnName()),
}

ab.proj.addUnexploredExpr(projAE, projExpr)
_, err := ab.proj.addUnexploredExpr(projAE, projExpr)
if err != nil {
return nil
}
return err
systay marked this conversation as resolved.
Show resolved Hide resolved
}

func coalesceFunc(e sqlparser.Expr) sqlparser.Expr {
16 changes: 10 additions & 6 deletions go/vt/vtgate/planbuilder/operators/aggregator.go
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ func (a *Aggregator) AddPredicate(ctx *plancontext.PlanningContext, expr sqlpars
return a, nil
}

func (a *Aggregator) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToGroupBy bool) int {
func (a *Aggregator) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) {
offset := len(a.Columns)
a.Columns = append(a.Columns, expr)

@@ -109,12 +109,16 @@ func (a *Aggregator) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToG
aggr.ColOffset = offset
a.Aggregations = append(a.Aggregations, aggr)
}
return offset
return offset, nil
}

func (a *Aggregator) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, groupby []bool, expr []*sqlparser.AliasedExpr) (offsets []int) {
for i, ae := range expr {
offsets = append(offsets, a.addColumnWithoutPushing(ae, groupby[i]))
func (a *Aggregator) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, groupby []bool, exprs []*sqlparser.AliasedExpr) (offsets []int, err error) {
for i, ae := range exprs {
offset, err := a.addColumnWithoutPushing(ae, groupby[i])
if err != nil {
return nil, err
}
offsets = append(offsets, offset)
}
return
}
@@ -336,7 +340,7 @@ func (aggr Aggr) getPushDownColumn() sqlparser.Expr {
}

func (a *Aggregator) planOffsetsNotPushed(ctx *plancontext.PlanningContext) error {
a.Source = &Projection{Source: a.Source}
a.Source = newAliasedProjection(a.Source)
// we need to keep things in the column order, so we can't iterate over the aggregations or groupings
for colIdx := range a.Columns {
idx, err := a.addIfGroupingColumn(ctx, colIdx)
17 changes: 8 additions & 9 deletions go/vt/vtgate/planbuilder/operators/ast_to_op.go
Original file line number Diff line number Diff line change
@@ -259,16 +259,15 @@ func createComparisonSubQuery(
}
original = cloneASTAndSemState(ctx, original)

var predicate sqlparser.Expr
ae, ok := subq.Select.GetColumns()[0].(*sqlparser.AliasedExpr)
if !ok {
return nil, vterrors.VT13001("can't use unexpanded projections here")
}

// this is a predicate that will only be used to check if we can merge the subquery with the outer query
predicate := &sqlparser.ComparisonExpr{
Operator: sqlparser.EqualOp,
Left: outside,
Right: ae.Expr,
if ok {
// this is a predicate that will only be used to check if we can merge the subquery with the outer query
predicate = &sqlparser.ComparisonExpr{
Operator: sqlparser.EqualOp,
Left: outside,
Right: ae.Expr,
}
}

filterType := opcode.PulloutValue
70 changes: 46 additions & 24 deletions go/vt/vtgate/planbuilder/operators/horizon_expanding.go
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import (
"fmt"
"strings"

"vitess.io/vitess/go/slice"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vterrors"
"vitess.io/vitess/go/vt/vtgate/engine/opcode"
@@ -63,11 +64,10 @@ func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, unio
}

if horizon.TableId != nil {
op = &Projection{
Source: op,
TableID: horizon.TableId,
Alias: horizon.Alias,
}
proj := newAliasedProjection(op)
proj.TableID = horizon.TableId
proj.Alias = horizon.Alias
op = proj
}

if op == horizon.Source {
@@ -201,18 +201,18 @@ outer:
}

func createProjectionForComplexAggregation(a *Aggregator, qp *QueryProjection) (ops.Operator, error) {
p := &Projection{
Source: a,
Alias: a.Alias,
TableID: a.TableID,
}

p := newAliasedProjection(a)
p.Alias = a.Alias
p.TableID = a.TableID
for _, expr := range qp.SelectExprs {
ae, err := expr.GetAliasedExpr()
if err != nil {
return nil, err
}
p.Columns = append(p.Columns, ae)
p.Columns, err = p.Columns.AddColumn(ae)
if err != nil {
return nil, err
}
p.Projections = append(p.Projections, UnexploredExpression{E: ae.Expr})
}
for i, by := range a.Grouping {
@@ -227,35 +227,57 @@ func createProjectionForComplexAggregation(a *Aggregator, qp *QueryProjection) (
}

func createProjectionWithoutAggr(ctx *plancontext.PlanningContext, qp *QueryProjection, src ops.Operator) (*Projection, error) {
proj := &Projection{}
sqc := &SubQueryContainer{}
outerID := TableID(src)

for _, e := range qp.SelectExprs {
if _, isStar := e.Col.(*sqlparser.StarExpr); isStar {
return nil, errHorizonNotPlanned()
// first we need to check if we have all columns or there are still unexpanded stars
aes, err := slice.MapWithError(qp.SelectExprs, func(from SelectExpr) (*sqlparser.AliasedExpr, error) {
ae, ok := from.Col.(*sqlparser.AliasedExpr)
if !ok {
return nil, fmt.Errorf("star found")
}
ae, err := e.GetAliasedExpr()
if err != nil {
return nil, err
return ae, nil
})

if err != nil {
// if we have unexpanded expressions, we take this shortcut and hope we don't need any offsets from this plan
cols := sqlparser.SelectExprs{}
for _, expr := range qp.SelectExprs {
cols = append(cols, expr.Col)
}
return newStarProjection(src, cols), nil
}

proj := newAliasedProjection(nil)
sqc := &SubQueryContainer{}
outerID := TableID(src)
for _, ae := range aes {
expr := ae.Expr
newExpr, subqs, err := sqc.handleSubqueries(ctx, expr, outerID)
if err != nil {
return nil, err
}
if newExpr == nil {
// there was no subquery in this expression
proj.addUnexploredExpr(ae, expr)
_, err := proj.addUnexploredExpr(ae, expr)
if err != nil {
return nil, err
}
} else {
proj.addSubqueryExpr(ae, newExpr, subqs...)
err := proj.addSubqueryExpr(ae, newExpr, subqs...)
if err != nil {
return nil, err
}
}
}
proj.Source = sqc.getRootOperator(src)
return proj, nil
}

func newStarProjection(src ops.Operator, cols sqlparser.SelectExprs) *Projection {
return &Projection{
Source: src,
Columns: StarProjections(cols),
}
}

type subqueryExtraction struct {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at this, I think we want to unify this with the builder parts of SubqueryContainer

new sqlparser.Expr
subq []*sqlparser.Subquery
Loading