From 4eb6ee2d28dc6a8ff4043979f2a0dbf2c126fcef Mon Sep 17 00:00:00 2001 From: Manan Gupta <35839558+GuptaManan100@users.noreply.github.com> Date: Fri, 24 Nov 2023 22:57:44 +0530 Subject: [PATCH] Type Cast all update expressions in verify queries (#14555) Signed-off-by: Manan Gupta --- go/test/endtoend/vtgate/foreignkey/fk_test.go | 9 ++ go/vt/vtgate/engine/cached_size.go | 4 +- go/vt/vtgate/engine/fk_cascade.go | 23 +-- go/vt/vtgate/planbuilder/operators/update.go | 84 ++++++++--- .../planbuilder/operators/update_test.go | 140 ++++++++++++++++++ .../testdata/foreignkey_cases.json | 63 ++++---- .../testdata/foreignkey_checks_on_cases.json | 49 +++--- .../planbuilder/testdata/vschemas/schema.json | 84 ++++++++++- 8 files changed, 344 insertions(+), 112 deletions(-) create mode 100644 go/vt/vtgate/planbuilder/operators/update_test.go diff --git a/go/test/endtoend/vtgate/foreignkey/fk_test.go b/go/test/endtoend/vtgate/foreignkey/fk_test.go index 785310b6ade..101cd313e21 100644 --- a/go/test/endtoend/vtgate/foreignkey/fk_test.go +++ b/go/test/endtoend/vtgate/foreignkey/fk_test.go @@ -905,6 +905,15 @@ func TestFkQueries(t *testing.T) { "update fk_t11 set col = id where id in (1, 5)", }, }, + { + name: "Update on child to 0 when parent has -0", + queries: []string{ + "insert into fk_t15 (id, col) values (2, '-0')", + "insert /*+ SET_VAR(foreign_key_checks=0) */ into fk_t16 (id, col) values (3, '5'), (4, '-5')", + "update fk_t16 set col = col * (col - (col)) where id = 3", + "update fk_t16 set col = col * (col - (col)) where id = 4", + }, + }, } for _, testcase := range testcases { diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index 6024c66457a..657e5323f05 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -290,7 +290,7 @@ func (cached *FkChild) CachedSize(alloc bool) int64 { } // field NonLiteralInfo []vitess.io/vitess/go/vt/vtgate/engine.NonLiteralUpdateInfo { - size += hack.RuntimeAllocSize(int64(cap(cached.NonLiteralInfo)) * int64(40)) + size += hack.RuntimeAllocSize(int64(cap(cached.NonLiteralInfo)) * int64(32)) for _, elem := range cached.NonLiteralInfo { size += elem.CachedSize(false) } @@ -625,7 +625,7 @@ func (cached *NonLiteralUpdateInfo) CachedSize(alloc bool) int64 { } size := int64(0) if alloc { - size += int64(48) + size += int64(32) } // field UpdateExprBvName string size += hack.RuntimeAllocSize(int64(len(cached.UpdateExprBvName))) diff --git a/go/vt/vtgate/engine/fk_cascade.go b/go/vt/vtgate/engine/fk_cascade.go index 94732ae161b..3046217ce94 100644 --- a/go/vt/vtgate/engine/fk_cascade.go +++ b/go/vt/vtgate/engine/fk_cascade.go @@ -25,7 +25,6 @@ import ( querypb "vitess.io/vitess/go/vt/proto/query" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vtgate/evalengine" ) // FkChild contains the Child Primitive to be executed collecting the values from the Selection Primitive using the column indexes. @@ -42,12 +41,10 @@ type FkChild struct { // NonLiteralUpdateInfo stores the information required to process non-literal update queries. // It stores 4 information- -// 1. ExprCol- The index of the column being updated in the select query. -// 2. CompExprCol- The index of the comparison expression in the select query to know if the row value is actually being changed or not. -// 3. UpdateExprCol- The index of the updated expression in the select query. -// 4. UpdateExprBvName- The bind variable name to store the updated expression into. +// 1. CompExprCol- The index of the comparison expression in the select query to know if the row value is actually being changed or not. +// 2. UpdateExprCol- The index of the updated expression in the select query. +// 3. UpdateExprBvName- The bind variable name to store the updated expression into. type NonLiteralUpdateInfo struct { - ExprCol int CompExprCol int UpdateExprCol int UpdateExprBvName string @@ -188,19 +185,7 @@ func (fkc *FkCascade) executeNonLiteralExprFkChild(ctx context.Context, vcursor // Next, we need to copy the updated expressions value into the bind variables map. for _, info := range child.NonLiteralInfo { - // Type case the value to that of the column that we are updating. - // This is required for example when we receive an updated float value of -0, but - // the column being updated is a varchar column, then if we don't coerce the value of -0 to - // varchar, MySQL ends up setting it to '0' instead of '-0'. - finalVal := row[info.UpdateExprCol] - if !finalVal.IsNull() { - var err error - finalVal, err = evalengine.CoerceTo(finalVal, selectionRes.Fields[info.ExprCol].Type) - if err != nil { - return err - } - } - bindVars[info.UpdateExprBvName] = sqltypes.ValueBindVariable(finalVal) + bindVars[info.UpdateExprBvName] = sqltypes.ValueBindVariable(row[info.UpdateExprCol]) } _, err := vcursor.ExecutePrimitive(ctx, child.Exec, bindVars, wantfields) if err != nil { diff --git a/go/vt/vtgate/planbuilder/operators/update.go b/go/vt/vtgate/planbuilder/operators/update.go index 71d82c64216..8868e83c247 100644 --- a/go/vt/vtgate/planbuilder/operators/update.go +++ b/go/vt/vtgate/planbuilder/operators/update.go @@ -22,6 +22,8 @@ import ( "slices" "strings" + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/sysvars" "vitess.io/vitess/go/vt/vterrors" @@ -217,7 +219,7 @@ func buildFkOperator(ctx *plancontext.PlanningContext, updOp ops.Operator, updCl return nil, err } - return createFKVerifyOp(ctx, op, updClone, parentFks, restrictChildFks) + return createFKVerifyOp(ctx, op, updClone, parentFks, restrictChildFks, updatedTable) } // splitChildFks splits the child foreign keys into restrict and cascade list as restrict is handled through Verify operator and cascade is handled through Cascade operator. @@ -268,7 +270,7 @@ func createFKCascadeOp(ctx *plancontext.PlanningContext, parentOp ops.Operator, for _, updExpr := range ue { // We add the expression and a comparison expression to the SELECT exprssion while storing their offsets. var info engine.NonLiteralUpdateInfo - info, selectExprs = addNonLiteralUpdExprToSelect(ctx, updExpr, selectExprs) + info, selectExprs = addNonLiteralUpdExprToSelect(ctx, updatedTable, updExpr, selectExprs) nonLiteralUpdateInfo = append(nonLiteralUpdateInfo, info) } } @@ -329,25 +331,22 @@ func addColumns(ctx *plancontext.PlanningContext, columns sqlparser.Columns, exp // For an update query having non-literal updates, we add the updated expression and a comparison expression to the select query. // For example, for a query like `update fk_table set col = id * 100 + 1` // We would add the expression `id * 100 + 1` and the comparison expression `col <=> id * 100 + 1` to the select query. -func addNonLiteralUpdExprToSelect(ctx *plancontext.PlanningContext, updExpr *sqlparser.UpdateExpr, exprs []sqlparser.SelectExpr) (engine.NonLiteralUpdateInfo, []sqlparser.SelectExpr) { +func addNonLiteralUpdExprToSelect(ctx *plancontext.PlanningContext, updatedTable *vindexes.Table, updExpr *sqlparser.UpdateExpr, exprs []sqlparser.SelectExpr) (engine.NonLiteralUpdateInfo, []sqlparser.SelectExpr) { // Create the comparison expression. - compExpr := sqlparser.NewComparisonExpr(sqlparser.NullSafeEqualOp, updExpr.Name, updExpr.Expr, nil) + castedExpr := getCastedUpdateExpression(updatedTable, updExpr) + compExpr := sqlparser.NewComparisonExpr(sqlparser.NullSafeEqualOp, updExpr.Name, castedExpr, nil) info := engine.NonLiteralUpdateInfo{ CompExprCol: -1, UpdateExprCol: -1, - ExprCol: -1, } // Add the expressions to the select expressions. We make sure to reuse the offset if it has already been added once. for idx, selectExpr := range exprs { if ctx.SemTable.EqualsExpr(selectExpr.(*sqlparser.AliasedExpr).Expr, compExpr) { info.CompExprCol = idx } - if ctx.SemTable.EqualsExpr(selectExpr.(*sqlparser.AliasedExpr).Expr, updExpr.Expr) { + if ctx.SemTable.EqualsExpr(selectExpr.(*sqlparser.AliasedExpr).Expr, castedExpr) { info.UpdateExprCol = idx } - if ctx.SemTable.EqualsExpr(selectExpr.(*sqlparser.AliasedExpr).Expr, updExpr.Name) { - info.ExprCol = idx - } } // If the expression doesn't exist, then we add the expression and store the offset. if info.CompExprCol == -1 { @@ -356,15 +355,54 @@ func addNonLiteralUpdExprToSelect(ctx *plancontext.PlanningContext, updExpr *sql } if info.UpdateExprCol == -1 { info.UpdateExprCol = len(exprs) - exprs = append(exprs, aeWrap(updExpr.Expr)) - } - if info.ExprCol == -1 { - info.ExprCol = len(exprs) - exprs = append(exprs, aeWrap(updExpr.Name)) + exprs = append(exprs, aeWrap(castedExpr)) } return info, exprs } +func getCastedUpdateExpression(updatedTable *vindexes.Table, updExpr *sqlparser.UpdateExpr) sqlparser.Expr { + castTypeStr := getCastTypeForColumn(updatedTable, updExpr) + if castTypeStr == "" { + return updExpr.Expr + } + return &sqlparser.CastExpr{ + Expr: updExpr.Expr, + Type: &sqlparser.ConvertType{ + Type: castTypeStr, + }, + } +} + +func getCastTypeForColumn(updatedTable *vindexes.Table, updExpr *sqlparser.UpdateExpr) string { + var ty querypb.Type + for _, column := range updatedTable.Columns { + if updExpr.Name.Name.Equal(column.Name) { + ty = column.Type + break + } + } + switch { + case sqltypes.IsNull(ty): + return "" + case sqltypes.IsSigned(ty): + return "SIGNED" + case sqltypes.IsUnsigned(ty): + return "UNSIGNED" + case sqltypes.IsFloat(ty): + return "FLOAT" + case sqltypes.IsDecimal(ty): + return "DECIMAL" + case sqltypes.IsDateOrTime(ty): + return "DATETIME" + case sqltypes.IsBinary(ty): + return "BINARY" + case sqltypes.IsText(ty): + return "CHAR" + default: + return "" + } +} + // createFkChildForUpdate creates the update query operator for the child table based on the foreign key constraints. func createFkChildForUpdate(ctx *plancontext.PlanningContext, fk vindexes.ChildFKInfo, selectOffsets []int, nonLiteralUpdateInfo []engine.NonLiteralUpdateInfo, updatedTable *vindexes.Table) (*FkChild, error) { // Create a ValTuple of child column names @@ -484,6 +522,7 @@ func buildChildUpdOpForSetNull( // So, if either of :v1 or :v2 is NULL, then the entire condition is true (which is the same as not having the condition when :v1 or :v2 is NULL). updateExprs := ctx.SemTable.GetUpdateExpressionsForFk(fk.String(updatedTable)) compExpr := nullSafeNotInComparison(ctx, + updatedTable, updateExprs, fk, updatedTable.GetTableName(), nonLiteralUpdateInfo, false /* appendQualifier */) if compExpr != nil { childWhereExpr = &sqlparser.AndExpr{ @@ -522,6 +561,7 @@ func createFKVerifyOp( updStmt *sqlparser.Update, parentFks []vindexes.ParentFKInfo, restrictChildFks []vindexes.ChildFKInfo, + updatedTable *vindexes.Table, ) (ops.Operator, error) { if len(parentFks) == 0 && len(restrictChildFks) == 0 { return childOp, nil @@ -530,7 +570,7 @@ func createFKVerifyOp( var Verify []*VerifyOp // This validates that new values exists on the parent table. for _, fk := range parentFks { - op, err := createFkVerifyOpForParentFKForUpdate(ctx, updStmt, fk) + op, err := createFkVerifyOpForParentFKForUpdate(ctx, updatedTable, updStmt, fk) if err != nil { return nil, err } @@ -541,7 +581,7 @@ func createFKVerifyOp( } // This validates that the old values don't exist on the child table. for _, fk := range restrictChildFks { - op, err := createFkVerifyOpForChildFKForUpdate(ctx, updStmt, fk) + op, err := createFkVerifyOpForChildFKForUpdate(ctx, updatedTable, updStmt, fk) if err != nil { return nil, err } @@ -568,7 +608,7 @@ func createFKVerifyOp( // where Parent.p1 is null and Parent.p2 is null and Child.id = 1 and Child.c2 + 1 is not null // and Child.c2 is not null and not ((Child.c1) <=> (Child.c2 + 1)) // limit 1 -func createFkVerifyOpForParentFKForUpdate(ctx *plancontext.PlanningContext, updStmt *sqlparser.Update, pFK vindexes.ParentFKInfo) (ops.Operator, error) { +func createFkVerifyOpForParentFKForUpdate(ctx *plancontext.PlanningContext, updatedTable *vindexes.Table, updStmt *sqlparser.Update, pFK vindexes.ParentFKInfo) (ops.Operator, error) { childTblExpr := updStmt.TableExprs[0].(*sqlparser.AliasedTableExpr) childTbl, err := childTblExpr.TableName() if err != nil { @@ -608,7 +648,7 @@ func createFkVerifyOpForParentFKForUpdate(ctx *plancontext.PlanningContext, updS } } else { notEqualColNames = append(notEqualColNames, prefixColNames(ctx, childTbl, matchedExpr.Name)) - prefixedMatchExpr := prefixColNames(ctx, childTbl, matchedExpr.Expr) + prefixedMatchExpr := prefixColNames(ctx, childTbl, getCastedUpdateExpression(updatedTable, matchedExpr)) notEqualExprs = append(notEqualExprs, prefixedMatchExpr) joinExpr = &sqlparser.ComparisonExpr{ Operator: sqlparser.EqualOp, @@ -668,7 +708,7 @@ func createFkVerifyOpForParentFKForUpdate(ctx *plancontext.PlanningContext, updS // verify query: // select 1 from Child join Parent on Parent.p1 = Child.c1 and Parent.p2 = Child.c2 // where Parent.id = 1 and ((Parent.col + 1) IS NULL OR (child.c1) NOT IN ((Parent.col + 1))) limit 1 -func createFkVerifyOpForChildFKForUpdate(ctx *plancontext.PlanningContext, updStmt *sqlparser.Update, cFk vindexes.ChildFKInfo) (ops.Operator, error) { +func createFkVerifyOpForChildFKForUpdate(ctx *plancontext.PlanningContext, updatedTable *vindexes.Table, updStmt *sqlparser.Update, cFk vindexes.ChildFKInfo) (ops.Operator, error) { // ON UPDATE RESTRICT foreign keys that require validation, should only be allowed in the case where we // are verifying all the FKs on vtgate level. if !ctx.VerifyAllFKs { @@ -710,7 +750,7 @@ func createFkVerifyOpForChildFKForUpdate(ctx *plancontext.PlanningContext, updSt // For example, if we are setting `update child cola = :v1 and colb = :v2`, then on the parent, the where condition would look something like this - // `:v1 IS NULL OR :v2 IS NULL OR (cola, colb) NOT IN ((:v1,:v2))` // So, if either of :v1 or :v2 is NULL, then the entire condition is true (which is the same as not having the condition when :v1 or :v2 is NULL). - compExpr := nullSafeNotInComparison(ctx, updStmt.Exprs, cFk, parentTbl, nil /* nonLiteralUpdateInfo */, true /* appendQualifier */) + compExpr := nullSafeNotInComparison(ctx, updatedTable, updStmt.Exprs, cFk, parentTbl, nil /* nonLiteralUpdateInfo */, true /* appendQualifier */) if compExpr != nil { whereCond = sqlparser.AndExpressions(whereCond, compExpr) } @@ -735,7 +775,7 @@ func createFkVerifyOpForChildFKForUpdate(ctx *plancontext.PlanningContext, updSt // `:v1 IS NULL OR :v2 IS NULL OR (cola, colb) NOT IN ((:v1,:v2))` // So, if either of :v1 or :v2 is NULL, then the entire condition is true (which is the same as not having the condition when :v1 or :v2 is NULL) // This expression is used in cascading SET NULLs and in verifying whether an update should be restricted. -func nullSafeNotInComparison(ctx *plancontext.PlanningContext, updateExprs sqlparser.UpdateExprs, cFk vindexes.ChildFKInfo, parentTbl sqlparser.TableName, nonLiteralUpdateInfo []engine.NonLiteralUpdateInfo, appendQualifier bool) sqlparser.Expr { +func nullSafeNotInComparison(ctx *plancontext.PlanningContext, updatedTable *vindexes.Table, updateExprs sqlparser.UpdateExprs, cFk vindexes.ChildFKInfo, parentTbl sqlparser.TableName, nonLiteralUpdateInfo []engine.NonLiteralUpdateInfo, appendQualifier bool) sqlparser.Expr { var valTuple sqlparser.ValTuple var updateValues sqlparser.ValTuple for idx, updateExpr := range updateExprs { @@ -744,7 +784,7 @@ func nullSafeNotInComparison(ctx *plancontext.PlanningContext, updateExprs sqlpa if sqlparser.IsNull(updateExpr.Expr) { return nil } - childUpdateExpr := prefixColNames(ctx, parentTbl, updateExpr.Expr) + childUpdateExpr := prefixColNames(ctx, parentTbl, getCastedUpdateExpression(updatedTable, updateExpr)) if len(nonLiteralUpdateInfo) > 0 && nonLiteralUpdateInfo[idx].UpdateExprBvName != "" { childUpdateExpr = sqlparser.NewArgument(nonLiteralUpdateInfo[idx].UpdateExprBvName) } diff --git a/go/vt/vtgate/planbuilder/operators/update_test.go b/go/vt/vtgate/planbuilder/operators/update_test.go new file mode 100644 index 00000000000..6cdf7be3f7d --- /dev/null +++ b/go/vt/vtgate/planbuilder/operators/update_test.go @@ -0,0 +1,140 @@ +/* +Copyright 2023 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package operators + +import ( + "testing" + + "github.com/stretchr/testify/require" + + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vtgate/vindexes" +) + +// TestGetCastTypeForColumn tests that we get the correct string value to use in a CAST function based on the type of the column. +func TestGetCastTypeForColumn(t *testing.T) { + tests := []struct { + name string + typ querypb.Type + want string + }{ + { + name: "VARCHAR column", + typ: querypb.Type_VARCHAR, + want: "CHAR", + }, + { + name: "CHAR column", + typ: querypb.Type_CHAR, + want: "CHAR", + }, + { + name: "VARBINARY column", + typ: querypb.Type_VARBINARY, + want: "BINARY", + }, + { + name: "BINARY column", + typ: querypb.Type_BINARY, + want: "BINARY", + }, + { + name: "UINT16 column", + typ: querypb.Type_UINT16, + want: "UNSIGNED", + }, + { + name: "UINT24 column", + typ: querypb.Type_UINT24, + want: "UNSIGNED", + }, + { + name: "UINT32 column", + typ: querypb.Type_UINT32, + want: "UNSIGNED", + }, + { + name: "UINT64 column", + typ: querypb.Type_UINT64, + want: "UNSIGNED", + }, + { + name: "INT16 column", + typ: querypb.Type_INT16, + want: "SIGNED", + }, + { + name: "INT24 column", + typ: querypb.Type_INT24, + want: "SIGNED", + }, + { + name: "INT32 column", + typ: querypb.Type_INT32, + want: "SIGNED", + }, + { + name: "INT64 column", + typ: querypb.Type_INT64, + want: "SIGNED", + }, + { + name: "FLOAT32 column", + typ: querypb.Type_FLOAT32, + want: "FLOAT", + }, + { + name: "FLOAT64 column", + typ: querypb.Type_FLOAT64, + want: "FLOAT", + }, + { + name: "DECIMAL column", + typ: querypb.Type_DECIMAL, + want: "DECIMAL", + }, + { + name: "DATETIME column", + typ: querypb.Type_DATETIME, + want: "DATETIME", + }, + { + name: "NULL column", + typ: querypb.Type_NULL_TYPE, + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + updExpr := &sqlparser.UpdateExpr{ + Name: sqlparser.NewColName("col"), + } + updatedTable := &vindexes.Table{ + Columns: []vindexes.Column{ + { + Name: sqlparser.NewIdentifierCI("col"), + Type: tt.typ, + }, + }, + } + tyStr := getCastTypeForColumn(updatedTable, updExpr) + require.EqualValues(t, tt.want, tyStr) + }) + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/foreignkey_cases.json b/go/vt/vtgate/planbuilder/testdata/foreignkey_cases.json index 6757f7688e1..deba02e2009 100644 --- a/go/vt/vtgate/planbuilder/testdata/foreignkey_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/foreignkey_cases.json @@ -328,7 +328,7 @@ "Cols": [ 0 ], - "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in (('bar'))", + "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((cast('bar' as CHAR)))", "Table": "u_tbl3" }, { @@ -693,7 +693,7 @@ "Cols": [ 0 ], - "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in (('foo'))", + "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((cast('foo' as CHAR)))", "Table": "u_tbl3" }, { @@ -727,7 +727,7 @@ "Sharded": false }, "FieldQuery": "select col9 from u_tbl9 where 1 != 1", - "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in (('foo')) for update nowait", + "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((cast('foo' as CHAR))) for update nowait", "Table": "u_tbl9" }, { @@ -755,7 +755,7 @@ "Sharded": false }, "TargetTabletType": "PRIMARY", - "Query": "update u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in (('foo'))", + "Query": "update u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((cast('foo' as CHAR)))", "Table": "u_tbl9" } ] @@ -805,8 +805,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = u_tbl2.col1 + 'bar' where 1 != 1", - "Query": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = u_tbl2.col1 + 'bar' where u_tbl2.col1 + 'bar' is not null and not (u_tbl2.col2) <=> (u_tbl2.col1 + 'bar') and u_tbl2.id = 1 and u_tbl1.col1 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = cast(u_tbl2.col1 + 'bar' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = cast(u_tbl2.col1 + 'bar' as CHAR) where cast(u_tbl2.col1 + 'bar' as CHAR) is not null and not (u_tbl2.col2) <=> (cast(u_tbl2.col1 + 'bar' as CHAR)) and u_tbl2.id = 1 and u_tbl1.col1 is null limit 1 for share nowait", "Table": "u_tbl1, u_tbl2" }, { @@ -821,8 +821,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select col2, col2 <=> col1 + 'bar', col1 + 'bar' from u_tbl2 where 1 != 1", - "Query": "select col2, col2 <=> col1 + 'bar', col1 + 'bar' from u_tbl2 where id = 1 for update nowait", + "FieldQuery": "select col2, col2 <=> cast(col1 + 'bar' as CHAR), cast(col1 + 'bar' as CHAR) from u_tbl2 where 1 != 1", + "Query": "select col2, col2 <=> cast(col1 + 'bar' as CHAR), cast(col1 + 'bar' as CHAR) from u_tbl2 where id = 1 for update nowait", "Table": "u_tbl2" }, { @@ -840,7 +840,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd" @@ -889,8 +888,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select col1, col1 <=> x + 'bar', x + 'bar' from u_tbl1 where 1 != 1", - "Query": "select col1, col1 <=> x + 'bar', x + 'bar' from u_tbl1 where id = 1 for update nowait", + "FieldQuery": "select col1, col1 <=> cast(x + 'bar' as CHAR), cast(x + 'bar' as CHAR) from u_tbl1 where 1 != 1", + "Query": "select col1, col1 <=> cast(x + 'bar' as CHAR), cast(x + 'bar' as CHAR) from u_tbl1 where id = 1 for update nowait", "Table": "u_tbl1" }, { @@ -902,7 +901,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd" @@ -934,7 +932,7 @@ "Cols": [ 0 ], - "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (:fkc_upd is null or (col3) not in ((:fkc_upd)))", + "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (cast(:fkc_upd as CHAR) is null or (col3) not in ((cast(:fkc_upd as CHAR))))", "Table": "u_tbl3" }, { @@ -960,7 +958,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd1" @@ -1066,7 +1063,7 @@ "Cols": [ 0 ], - "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((2))", + "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((cast(2 as CHAR)))", "Table": "u_tbl3" }, { @@ -1143,7 +1140,7 @@ "Cols": [ 0 ], - "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((2))", + "Query": "update u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((cast(2 as CHAR)))", "Table": "u_tbl3" }, { @@ -1177,7 +1174,7 @@ "Sharded": false }, "FieldQuery": "select col9 from u_tbl9 where 1 != 1", - "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((2)) for update nowait", + "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((cast(2 as CHAR))) for update nowait", "Table": "u_tbl9" }, { @@ -1205,7 +1202,7 @@ "Sharded": false }, "TargetTabletType": "PRIMARY", - "Query": "update u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((2))", + "Query": "update u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((cast(2 as CHAR)))", "Table": "u_tbl9" } ] @@ -1443,8 +1440,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = 'foo' where 1 != 1", - "Query": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = 'foo' where not (u_tbl8.col8) <=> ('foo') and (u_tbl8.col8) in ::fkc_vals and u_tbl9.col9 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = cast('foo' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = cast('foo' as CHAR) where not (u_tbl8.col8) <=> (cast('foo' as CHAR)) and (u_tbl8.col8) in ::fkc_vals and u_tbl9.col9 is null limit 1 for share nowait", "Table": "u_tbl8, u_tbl9" }, { @@ -1519,8 +1516,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = 'foo' where 1 != 1", - "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = 'foo' where not (u_tbl4.col4) <=> ('foo') and (u_tbl4.col4) in ::fkc_vals and u_tbl3.col3 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast('foo' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast('foo' as CHAR) where not (u_tbl4.col4) <=> (cast('foo' as CHAR)) and (u_tbl4.col4) in ::fkc_vals and u_tbl3.col3 is null limit 1 for share nowait", "Table": "u_tbl3, u_tbl4" }, { @@ -1532,7 +1529,7 @@ "Sharded": false }, "FieldQuery": "select 1 from u_tbl4, u_tbl9 where 1 != 1", - "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (u_tbl9.col9) not in (('foo')) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", + "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (u_tbl9.col9) not in ((cast('foo' as CHAR))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", "Table": "u_tbl4, u_tbl9" }, { @@ -1608,8 +1605,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :v1 where 1 != 1", - "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :v1 where not (u_tbl4.col4) <=> (:v1) and (u_tbl4.col4) in ::fkc_vals and :v1 is not null and u_tbl3.col3 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:v1 as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:v1 as CHAR) where not (u_tbl4.col4) <=> (cast(:v1 as CHAR)) and (u_tbl4.col4) in ::fkc_vals and cast(:v1 as CHAR) is not null and u_tbl3.col3 is null limit 1 for share nowait", "Table": "u_tbl3, u_tbl4" }, { @@ -1621,7 +1618,7 @@ "Sharded": false }, "FieldQuery": "select 1 from u_tbl4, u_tbl9 where 1 != 1", - "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (:v1 is null or (u_tbl9.col9) not in ((:v1))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", + "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (cast(:v1 as CHAR) is null or (u_tbl9.col9) not in ((cast(:v1 as CHAR)))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", "Table": "u_tbl4, u_tbl9" }, { @@ -2092,8 +2089,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select col7, col7 <=> baz + 1 + col7, baz + 1 + col7 from u_tbl7 where 1 != 1", - "Query": "select col7, col7 <=> baz + 1 + col7, baz + 1 + col7 from u_tbl7 where bar = 42 for update nowait", + "FieldQuery": "select col7, col7 <=> cast(baz + 1 + col7 as CHAR), cast(baz + 1 + col7 as CHAR) from u_tbl7 where 1 != 1", + "Query": "select col7, col7 <=> cast(baz + 1 + col7 as CHAR), cast(baz + 1 + col7 as CHAR) from u_tbl7 where bar = 42 for update nowait", "Table": "u_tbl7" }, { @@ -2105,7 +2102,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd" @@ -2120,8 +2116,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :fkc_upd where 1 != 1", - "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :fkc_upd where not (u_tbl4.col4) <=> (:fkc_upd) and (u_tbl4.col4) in ::fkc_vals and :fkc_upd is not null and u_tbl3.col3 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:fkc_upd as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:fkc_upd as CHAR) where not (u_tbl4.col4) <=> (cast(:fkc_upd as CHAR)) and (u_tbl4.col4) in ::fkc_vals and cast(:fkc_upd as CHAR) is not null and u_tbl3.col3 is null limit 1 for share nowait", "Table": "u_tbl3, u_tbl4" }, { @@ -2133,7 +2129,7 @@ "Sharded": false }, "FieldQuery": "select 1 from u_tbl4, u_tbl9 where 1 != 1", - "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (:fkc_upd is null or (u_tbl9.col9) not in ((:fkc_upd))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", + "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (cast(:fkc_upd as CHAR) is null or (u_tbl9.col9) not in ((cast(:fkc_upd as CHAR)))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", "Table": "u_tbl4, u_tbl9" }, { @@ -2203,7 +2199,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 2, "UpdateExprCol": 3, "UpdateExprBvName": "fkc_upd" @@ -2332,13 +2327,11 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 2, "UpdateExprCol": 3, "UpdateExprBvName": "fkc_upd" }, { - "ExprCol": 1, "CompExprCol": 4, "UpdateExprCol": 5, "UpdateExprBvName": "fkc_upd1" diff --git a/go/vt/vtgate/planbuilder/testdata/foreignkey_checks_on_cases.json b/go/vt/vtgate/planbuilder/testdata/foreignkey_checks_on_cases.json index 1d523f3f24f..b4892a99052 100644 --- a/go/vt/vtgate/planbuilder/testdata/foreignkey_checks_on_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/foreignkey_checks_on_cases.json @@ -328,7 +328,7 @@ "Cols": [ 0 ], - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in (('bar'))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((cast('bar' as CHAR)))", "Table": "u_tbl3" }, { @@ -693,7 +693,7 @@ "Cols": [ 0 ], - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in (('foo'))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((cast('foo' as CHAR)))", "Table": "u_tbl3" }, { @@ -727,7 +727,7 @@ "Sharded": false }, "FieldQuery": "select col9 from u_tbl9 where 1 != 1", - "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in (('foo')) for update nowait", + "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((cast('foo' as CHAR))) for update nowait", "Table": "u_tbl9" }, { @@ -755,7 +755,7 @@ "Sharded": false }, "TargetTabletType": "PRIMARY", - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in (('foo'))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((cast('foo' as CHAR)))", "Table": "u_tbl9" } ] @@ -805,8 +805,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = u_tbl2.col1 + 'bar' where 1 != 1", - "Query": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = u_tbl2.col1 + 'bar' where u_tbl2.col1 + 'bar' is not null and not (u_tbl2.col2) <=> (u_tbl2.col1 + 'bar') and u_tbl2.id = 1 and u_tbl1.col1 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = cast(u_tbl2.col1 + 'bar' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl2 left join u_tbl1 on u_tbl1.col1 = cast(u_tbl2.col1 + 'bar' as CHAR) where cast(u_tbl2.col1 + 'bar' as CHAR) is not null and not (u_tbl2.col2) <=> (cast(u_tbl2.col1 + 'bar' as CHAR)) and u_tbl2.id = 1 and u_tbl1.col1 is null limit 1 for share nowait", "Table": "u_tbl1, u_tbl2" }, { @@ -821,8 +821,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select col2, col2 <=> col1 + 'bar', col1 + 'bar' from u_tbl2 where 1 != 1", - "Query": "select col2, col2 <=> col1 + 'bar', col1 + 'bar' from u_tbl2 where id = 1 for update nowait", + "FieldQuery": "select col2, col2 <=> cast(col1 + 'bar' as CHAR), cast(col1 + 'bar' as CHAR) from u_tbl2 where 1 != 1", + "Query": "select col2, col2 <=> cast(col1 + 'bar' as CHAR), cast(col1 + 'bar' as CHAR) from u_tbl2 where id = 1 for update nowait", "Table": "u_tbl2" }, { @@ -840,7 +840,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd" @@ -889,8 +888,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select col1, col1 <=> x + 'bar', x + 'bar' from u_tbl1 where 1 != 1", - "Query": "select col1, col1 <=> x + 'bar', x + 'bar' from u_tbl1 where id = 1 for update nowait", + "FieldQuery": "select col1, col1 <=> cast(x + 'bar' as CHAR), cast(x + 'bar' as CHAR) from u_tbl1 where 1 != 1", + "Query": "select col1, col1 <=> cast(x + 'bar' as CHAR), cast(x + 'bar' as CHAR) from u_tbl1 where id = 1 for update nowait", "Table": "u_tbl1" }, { @@ -902,7 +901,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd" @@ -934,7 +932,7 @@ "Cols": [ 0 ], - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (:fkc_upd is null or (col3) not in ((:fkc_upd)))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (cast(:fkc_upd as CHAR) is null or (col3) not in ((cast(:fkc_upd as CHAR))))", "Table": "u_tbl3" }, { @@ -960,7 +958,6 @@ ], "NonLiteralUpdateInfo": [ { - "ExprCol": 0, "CompExprCol": 1, "UpdateExprCol": 2, "UpdateExprBvName": "fkc_upd1" @@ -1066,7 +1063,7 @@ "Cols": [ 0 ], - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((2))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals and (col3) not in ((cast(2 as CHAR)))", "Table": "u_tbl3" }, { @@ -1143,7 +1140,7 @@ "Cols": [ 0 ], - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((2))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl3 set col3 = null where (col3) in ::fkc_vals1 and (col3) not in ((cast(2 as CHAR)))", "Table": "u_tbl3" }, { @@ -1177,7 +1174,7 @@ "Sharded": false }, "FieldQuery": "select col9 from u_tbl9 where 1 != 1", - "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((2)) for update nowait", + "Query": "select col9 from u_tbl9 where (col9) in ::fkc_vals2 and (col9) not in ((cast(2 as CHAR))) for update nowait", "Table": "u_tbl9" }, { @@ -1205,7 +1202,7 @@ "Sharded": false }, "TargetTabletType": "PRIMARY", - "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((2))", + "Query": "update /*+ SET_VAR(foreign_key_checks=ON) */ u_tbl9 set col9 = null where (col9) in ::fkc_vals2 and (col9) not in ((cast(2 as CHAR)))", "Table": "u_tbl9" } ] @@ -1443,8 +1440,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = 'foo' where 1 != 1", - "Query": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = 'foo' where not (u_tbl8.col8) <=> ('foo') and (u_tbl8.col8) in ::fkc_vals and u_tbl9.col9 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = cast('foo' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl8 left join u_tbl9 on u_tbl9.col9 = cast('foo' as CHAR) where not (u_tbl8.col8) <=> (cast('foo' as CHAR)) and (u_tbl8.col8) in ::fkc_vals and u_tbl9.col9 is null limit 1 for share nowait", "Table": "u_tbl8, u_tbl9" }, { @@ -1519,8 +1516,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = 'foo' where 1 != 1", - "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = 'foo' where not (u_tbl4.col4) <=> ('foo') and (u_tbl4.col4) in ::fkc_vals and u_tbl3.col3 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast('foo' as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast('foo' as CHAR) where not (u_tbl4.col4) <=> (cast('foo' as CHAR)) and (u_tbl4.col4) in ::fkc_vals and u_tbl3.col3 is null limit 1 for share nowait", "Table": "u_tbl3, u_tbl4" }, { @@ -1532,7 +1529,7 @@ "Sharded": false }, "FieldQuery": "select 1 from u_tbl4, u_tbl9 where 1 != 1", - "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (u_tbl9.col9) not in (('foo')) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", + "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (u_tbl9.col9) not in ((cast('foo' as CHAR))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", "Table": "u_tbl4, u_tbl9" }, { @@ -1608,8 +1605,8 @@ "Name": "unsharded_fk_allow", "Sharded": false }, - "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :v1 where 1 != 1", - "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = :v1 where not (u_tbl4.col4) <=> (:v1) and (u_tbl4.col4) in ::fkc_vals and :v1 is not null and u_tbl3.col3 is null limit 1 for share nowait", + "FieldQuery": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:v1 as CHAR) where 1 != 1", + "Query": "select 1 from u_tbl4 left join u_tbl3 on u_tbl3.col3 = cast(:v1 as CHAR) where not (u_tbl4.col4) <=> (cast(:v1 as CHAR)) and (u_tbl4.col4) in ::fkc_vals and cast(:v1 as CHAR) is not null and u_tbl3.col3 is null limit 1 for share nowait", "Table": "u_tbl3, u_tbl4" }, { @@ -1621,7 +1618,7 @@ "Sharded": false }, "FieldQuery": "select 1 from u_tbl4, u_tbl9 where 1 != 1", - "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (:v1 is null or (u_tbl9.col9) not in ((:v1))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", + "Query": "select 1 from u_tbl4, u_tbl9 where (u_tbl4.col4) in ::fkc_vals and (cast(:v1 as CHAR) is null or (u_tbl9.col9) not in ((cast(:v1 as CHAR)))) and u_tbl4.col4 = u_tbl9.col9 limit 1 for share nowait", "Table": "u_tbl4, u_tbl9" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json b/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json index d5b9ece501b..36aa30381e2 100644 --- a/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json +++ b/go/vt/vtgate/planbuilder/testdata/vschemas/schema.json @@ -752,16 +752,84 @@ "unsharded_fk_allow": { "foreignKeyMode": "managed", "tables": { - "u_tbl1": {}, - "u_tbl2": {}, - "u_tbl3": {}, - "u_tbl4": {}, - "u_tbl5": {}, - "u_tbl6": {}, - "u_tbl7": {}, - "u_tbl8": {}, + "u_tbl1": { + "columns": [ + { + "name": "col1", + "type": "VARCHAR" + }, + { + "name": "col14", + "type": "INT16" + } + ] + }, + "u_tbl2": { + "columns": [ + { + "name": "col2", + "type": "VARCHAR" + } + ] + }, + "u_tbl3": { + "columns": [ + { + "name": "col3", + "type": "VARCHAR" + } + ] + }, + "u_tbl4": { + "columns": [ + { + "name": "col41", + "type": "INT16" + }, + { + "name": "col4", + "type": "VARCHAR" + } + ] + }, + "u_tbl5": { + "columns": [ + { + "name": "col5", + "type": "VARCHAR" + } + ] + }, + "u_tbl6": { + "columns": [ + { + "name": "col6", + "type": "VARCHAR" + } + ] + }, + "u_tbl7": { + "columns": [ + { + "name": "col7", + "type": "VARCHAR" + } + ] + }, + "u_tbl8": { + "columns": [ + { + "name": "col8", + "type": "VARCHAR" + } + ] + }, "u_tbl9": { "columns": [ + { + "name": "col9", + "type": "VARCHAR" + }, {"name": "foo"}, {"name": "bar", "default": "1"} ]