Skip to content
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
13 changes: 13 additions & 0 deletions go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1478,3 +1478,16 @@ func GetAllSelects(selStmt SelectStatement) []*Select {
}
panic("[BUG]: unknown type for SelectStatement")
}

// RemoveKeyspaceFromColName removes the Qualifier.Qualifier on all ColNames in the expression tree
func RemoveKeyspaceFromColName(expr Expr) Expr {
return Rewrite(expr, nil, func(cursor *Cursor) bool {
switch col := cursor.Node().(type) {
case *ColName:
if !col.Qualifier.Qualifier.IsEmpty() {
col.Qualifier.Qualifier = NewTableIdent("")
}
}
return true
}).(Expr) // This hard cast is safe because we do not change the type the input
}
6 changes: 3 additions & 3 deletions go/vt/vtgate/planbuilder/abstract/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func getOperatorFromTableExpr(tableExpr sqlparser.TableExpr, semTable *semantics
}
op := createJoin(lhs, rhs)
if tableExpr.Condition.On != nil {
err = op.PushPredicate(tableExpr.Condition.On, semTable)
err = op.PushPredicate(sqlparser.RemoveKeyspaceFromColName(tableExpr.Condition.On), semTable)
if err != nil {
return nil, err
}
Expand All @@ -117,7 +117,7 @@ func getOperatorFromTableExpr(tableExpr sqlparser.TableExpr, semTable *semantics
if tableExpr.Join == sqlparser.RightJoinType {
lhs, rhs = rhs, lhs
}
return &Join{LHS: lhs, RHS: rhs, LeftJoin: true, Predicate: tableExpr.Condition.On}, nil
return &Join{LHS: lhs, RHS: rhs, LeftJoin: true, Predicate: sqlparser.RemoveKeyspaceFromColName(tableExpr.Condition.On)}, nil
case sqlparser.StraightJoinType:
return nil, semantics.Gen4NotSupportedF(tableExpr.Join.ToString())
default:
Expand Down Expand Up @@ -227,7 +227,7 @@ func createOperatorFromSelect(sel *sqlparser.Select, semTable *semantics.SemTabl
if sel.Where != nil {
exprs := sqlparser.SplitAndExpression(nil, sel.Where.Expr)
for _, expr := range exprs {
err := op.PushPredicate(expr, semTable)
err := op.PushPredicate(sqlparser.RemoveKeyspaceFromColName(expr), semTable)
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions go/vt/vtgate/planbuilder/abstract/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (lcr *lineCountingReader) nextLine() (string, error) {
func readTestCase(lcr *lineCountingReader) (testCase, error) {
query := ""
var err error
for query == "" || query == "\n" {
for query == "" || query == "\n" || strings.HasPrefix(query, "#") {
query, err = lcr.nextLine()
if err != nil {
return testCase{}, err
Expand All @@ -61,9 +61,9 @@ func readTestCase(lcr *lineCountingReader) (testCase, error) {
jsonPart, err := lcr.nextLine()
if err != nil {
if err == io.EOF {
return testCase{}, fmt.Errorf("test data is bad. expectation not finished")
return tc, fmt.Errorf("test data is bad. expectation not finished")
}
return testCase{}, err
return tc, err
}
if jsonPart == "}\n" {
tc.expected += "}"
Expand Down Expand Up @@ -93,6 +93,7 @@ func TestOperator(t *testing.T) {
break
}
t.Run(fmt.Sprintf("%d:%s", tc.line, tc.query), func(t *testing.T) {
require.NoError(t, err)
tree, err := sqlparser.Parse(tc.query)
require.NoError(t, err)
stmt := tree.(sqlparser.SelectStatement)
Expand Down
48 changes: 48 additions & 0 deletions go/vt/vtgate/planbuilder/abstract/operator_test_data.txt
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,51 @@ Concatenate(distinct) {
},
order by id asc
}

select id from user where exists(select user_id from user_extra where user_id = 3 and user_id < user.id)
SubQuery: {
SubQueries: [
{
Type: PulloutExists
Query: QueryGraph: {
Tables:
TableSet{1}:user_extra where user_id = 3
JoinPredicates:
TableSet{0,1} - user_id < `user`.id
}
}]
Outer: QueryGraph: {
Tables:
TableSet{0}:`user`
JoinPredicates:
TableSet{0,1} - exists (select user_id from user_extra where user_id = 3 and user_id < `user`.id)
}
}
# we should remove the keyspace from predicates
select ks.tbl.col from ks.tbl where ks.tbl.id = 1
QueryGraph: {
Tables:
TableSet{0}:ks.tbl where tbl.id = 1
}

select 1 from ks.t join ks.y on ks.t.id = ks.y.t_id
QueryGraph: {
Tables:
TableSet{0}:ks.t
TableSet{1}:ks.y
JoinPredicates:
TableSet{0,1} - t.id = y.t_id
}

select 1 from ks.t left join ks.y on ks.t.id = ks.y.t_id
OuterJoin: {
Inner: QueryGraph: {
Tables:
TableSet{0}:ks.t
}
Outer: QueryGraph: {
Tables:
TableSet{1}:ks.y
}
Predicate: t.id = y.t_id
}
11 changes: 1 addition & 10 deletions go/vt/vtgate/planbuilder/horizon_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *sem
return i, false, nil
}
}
expr = removeKeyspaceFromColName(expr)
expr.Expr = sqlparser.RemoveKeyspaceFromColName(expr.Expr)
sel, isSel := node.Select.(*sqlparser.Select)
if !isSel {
return 0, false, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadFieldError, "Unknown column '%s' in 'order clause'", sqlparser.String(expr))
Expand Down Expand Up @@ -265,15 +265,6 @@ func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *sem
}
}

func removeKeyspaceFromColName(expr *sqlparser.AliasedExpr) *sqlparser.AliasedExpr {
if _, ok := expr.Expr.(*sqlparser.ColName); ok {
expr = sqlparser.CloneRefOfAliasedExpr(expr)
col := expr.Expr.(*sqlparser.ColName)
col.Qualifier.Qualifier = sqlparser.NewTableIdent("")
}
return expr
}

func checkIfAlreadyExists(expr *sqlparser.AliasedExpr, node sqlparser.SelectStatement, semTable *semantics.SemTable) int {
exprDep := semTable.RecursiveDeps(expr.Expr)
// Here to find if the expr already exists in the SelectStatement, we have 3 cases
Expand Down
12 changes: 6 additions & 6 deletions go/vt/vtgate/planbuilder/route_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,18 +333,18 @@ func planSingleShardRoutePlan(sel sqlparser.SelectStatement, rb *route) error {
return err
}
sqlparser.Rewrite(rb.Select, func(cursor *sqlparser.Cursor) bool {
if aliasedExpr, ok := cursor.Node().(*sqlparser.AliasedExpr); ok {
cursor.Replace(removeKeyspaceFromColName(aliasedExpr))
if aliasedExpr, ok := cursor.Node().(sqlparser.SelectExpr); ok {
removeKeyspaceFromSelectExpr(aliasedExpr)
}
return true
}, nil)
return nil
}

func removeKeyspaceFromSelectExpr(expr sqlparser.SelectExpr, ast *sqlparser.Select, i int) {
func removeKeyspaceFromSelectExpr(expr sqlparser.SelectExpr) {
switch expr := expr.(type) {
case *sqlparser.AliasedExpr:
ast.SelectExprs[i] = removeKeyspaceFromColName(expr)
expr.Expr = sqlparser.RemoveKeyspaceFromColName(expr.Expr)
case *sqlparser.StarExpr:
expr.TableName.Qualifier = sqlparser.NewTableIdent("")
}
Expand All @@ -365,8 +365,8 @@ func stripDownQuery(from, to sqlparser.SelectStatement) error {
toNode.OrderBy = node.OrderBy
toNode.Comments = node.Comments
toNode.SelectExprs = node.SelectExprs
for i, expr := range toNode.SelectExprs {
removeKeyspaceFromSelectExpr(expr, toNode, i)
for _, expr := range toNode.SelectExprs {
removeKeyspaceFromSelectExpr(expr)
}
case *sqlparser.Union:
toNode, ok := to.(*sqlparser.Union)
Expand Down
117 changes: 117 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/from_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,123 @@ Gen4 plan same as above
"table disabled has been disabled"
Gen4 plan same as above

"select second_user.foo.col from second_user.foo join user on second_user.foo.id = user.id where second_user.foo.col = 42"
{
"QueryType": "SELECT",
"Original": "select second_user.foo.col from second_user.foo join user on second_user.foo.id = user.id where second_user.foo.col = 42",
"Instructions": {
"OperatorType": "Route",
"Variant": "SelectScatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select foo.col from `user` as foo join `user` on foo.id = `user`.id where 1 != 1",
"Query": "select foo.col from `user` as foo join `user` on foo.id = `user`.id where foo.col = 42",
"Table": "`user`"
}
}
{
"QueryType": "SELECT",
"Original": "select second_user.foo.col from second_user.foo join user on second_user.foo.id = user.id where second_user.foo.col = 42",
"Instructions": {
"OperatorType": "Route",
"Variant": "SelectScatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select foo.col from `user` as foo, `user` where 1 != 1",
"Query": "select foo.col from `user` as foo, `user` where foo.col = 42 and foo.id = `user`.id",
"Table": "`user`"
}
}

"select user.music.foo from user.music join user on user.music.id = user.id where user.music.col = 42"
{
"QueryType": "SELECT",
"Original": "select user.music.foo from user.music join user on user.music.id = user.id where user.music.col = 42",
"Instructions": {
"OperatorType": "Join",
"Variant": "Join",
"JoinColumnIndexes": "-1",
"JoinVars": {
"music_id": 1
},
"TableName": "music_`user`",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "SelectScatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select music.foo, music.id from music where 1 != 1",
"Query": "select music.foo, music.id from music where music.col = 42",
"Table": "music"
},
{
"OperatorType": "Route",
"Variant": "SelectEqualUnique",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select 1 from `user` where 1 != 1",
"Query": "select 1 from `user` where `user`.id = :music_id",
"Table": "`user`",
"Values": [
":music_id"
],
"Vindex": "user_index"
}
]
}
}
{
"QueryType": "SELECT",
"Original": "select user.music.foo from user.music join user on user.music.id = user.id where user.music.col = 42",
"Instructions": {
"OperatorType": "Join",
"Variant": "Join",
"JoinColumnIndexes": "-2",
"JoinVars": {
"music_id": 0
},
"TableName": "music_`user`",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "SelectScatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select music.id, music.foo from music where 1 != 1",
"Query": "select music.id, music.foo from music where music.col = 42",
"Table": "music"
},
{
"OperatorType": "Route",
"Variant": "SelectEqualUnique",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select 1 from `user` where 1 != 1",
"Query": "select 1 from `user` where `user`.id = :music_id",
"Table": "`user`",
"Values": [
":music_id"
],
"Vindex": "user_index"
}
]
}
}


# ',' join
"select music.col from user, music"
{
Expand Down
3 changes: 3 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/schema_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
}, {
"from_table": "second_user.user",
"to_tables": ["user.user"]
}, {
"from_table": "second_user.foo",
"to_tables": ["user.user"]
}, {
"from_table": "primary_redirect@primary",
"to_tables": ["user.user"]
Expand Down
16 changes: 15 additions & 1 deletion go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,21 @@ Gen4 plan same as above
"Table": "information_schema.a"
}
}
Gen4 plan same as above
{
"QueryType": "SELECT",
"Original": "select * from information_schema.a where information_schema.a.b=10",
"Instructions": {
"OperatorType": "Route",
"Variant": "SelectDBA",
"Keyspace": {
"Name": "main",
"Sharded": false
},
"FieldQuery": "select * from information_schema.a where 1 != 1",
"Query": "select * from information_schema.a where a.b = 10",
"Table": "information_schema.a"
}
}

# union of information_schema
"select * from information_schema.a union select * from information_schema.b"
Expand Down