Skip to content

Commit

Permalink
Build foreign key definition in schema tracker (#13657)
Browse files Browse the repository at this point in the history
Signed-off-by: Harshit Gangal <[email protected]>
  • Loading branch information
harshit-gangal authored Jul 31, 2023
1 parent 3b0405f commit 3328588
Show file tree
Hide file tree
Showing 24 changed files with 581 additions and 448 deletions.
3 changes: 2 additions & 1 deletion go/test/endtoend/vtgate/gen4/system_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ func TestFKConstraintUsingInformationSchema(t *testing.T) {
query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on fk.constraint_schema = rc.constraint_schema and fk.constraint_name = rc.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'"
utils.AssertMatchesAny(t, conn, query,
`[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`,
`[[VARBINARY("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") BINARY("CASCADE") BINARY("SET NULL")]]`)
`[[VARBINARY("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") BINARY("CASCADE") BINARY("SET NULL")]]`,
`[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") BINARY("CASCADE") BINARY("SET NULL")]]`)
}

func TestConnectWithSystemSchema(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestMain(m *testing.M) {
VSchema: VSchema,
}
clusterInstance.VtGateExtraArgs = []string{"--schema_change_signal"}
clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-schema-change-signal", "--queryserver-config-schema-change-signal-interval", "0.1", "--queryserver-config-max-result-size", "100", "--queryserver-config-terse-errors"}
clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-schema-change-signal", "--queryserver-config-max-result-size", "100", "--queryserver-config-terse-errors"}
err = clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 0, false)
if err != nil {
return 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ func TestInformationSchemaQueryGetsRoutedToTheRightTableAndKeyspace(t *testing.T

utils.Exec(t, mcmp.VtConn, "insert into t1(id1, id2) values (1, 1), (2, 2), (3,3), (4,4)")

_ = utils.Exec(t, mcmp.VtConn, "SELECT /*vt+ PLANNER=gen4 */ * FROM t1000") // test that the routed table is available to us
result := utils.Exec(t, mcmp.VtConn, "SELECT /*vt+ PLANNER=gen4 */ * FROM information_schema.tables WHERE table_schema = database() and table_name='t1000'")
_ = utils.Exec(t, mcmp.VtConn, "SELECT * FROM t1000") // test that the routed table is available to us
result := utils.Exec(t, mcmp.VtConn, "SELECT * FROM information_schema.tables WHERE table_schema = database() and table_name='t1000'")
assert.NotEmpty(t, result.Rows)
}

Expand All @@ -111,7 +111,8 @@ func TestFKConstraintUsingInformationSchema(t *testing.T) {
query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on fk.constraint_schema = rc.constraint_schema and fk.constraint_name = rc.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'"
mcmp.AssertMatchesAny(query,
`[[VARBINARY("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") BINARY("CASCADE") BINARY("SET NULL")]]`,
`[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`)
`[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`,
`[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") BINARY("CASCADE") BINARY("SET NULL")]]`)
}

func TestConnectWithSystemSchema(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func TestMain(m *testing.M) {
VSchema: vschema,
}
clusterInstance.VtGateExtraArgs = []string{"--schema_change_signal"}
clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-schema-change-signal", "--queryserver-config-schema-change-signal-interval", "0.1"}
clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-schema-change-signal"}
err = clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 0, false)
if err != nil {
return 1
Expand All @@ -88,7 +88,6 @@ func TestMain(m *testing.M) {
return 1
}

clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, "--enable_system_settings=true")
// Start vtgate
err = clusterInstance.StartVtgate()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const (
type MatchAction int

const (
// DefaultAction indicates no action was explicitly specified.
// DefaultMatch indicates no action was explicitly specified.
DefaultMatch MatchAction = iota
Full
Partial
Expand Down
21 changes: 14 additions & 7 deletions go/vt/vtgate/engine/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions go/vt/vtgate/engine/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,7 @@ func (del *Delete) deleteVindexEntries(ctx context.Context, vcursor VCursor, bin
return err
}
colnum := del.KsidLength
vindexTable, err := del.GetSingleTable()
if err != nil {
return err
}
for _, colVindex := range vindexTable.Owned {
for _, colVindex := range del.Vindexes {
// Fetch the column values. colnum must keep incrementing.
fromIds := make([]sqltypes.Value, 0, len(colVindex.Columns))
for range colVindex.Columns {
Expand Down
42 changes: 18 additions & 24 deletions go/vt/vtgate/engine/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,9 @@ func TestDeleteOwnedVindex(t *testing.T) {
Vindex: ks.Vindexes["hash"],
Values: []evalengine.Expr{evalengine.NewLiteralInt(1)},
},
Query: "dummy_delete",
Table: []*vindexes.Table{
ks.Tables["t1"],
},
Query: "dummy_delete",
TableNames: []string{ks.Tables["t1"].Name.String()},
Vindexes: ks.Tables["t1"].Owned,
OwnedVindexQuery: "dummy_subquery",
KsidVindex: ks.Vindexes["hash"],
KsidLength: 1,
Expand Down Expand Up @@ -285,10 +284,9 @@ func TestDeleteOwnedVindexMultiCol(t *testing.T) {
Vindex: ks.Vindexes["rg_vdx"],
Values: []evalengine.Expr{evalengine.NewLiteralInt(1), evalengine.NewLiteralInt(2)},
},
Query: "dummy_delete",
Table: []*vindexes.Table{
ks.Tables["rg_tbl"],
},
Query: "dummy_delete",
TableNames: []string{ks.Tables["rg_tbl"].Name.String()},
Vindexes: ks.Tables["rg_tbl"].Owned,
OwnedVindexQuery: "dummy_subquery",
KsidVindex: ks.Vindexes["rg_vdx"],
KsidLength: 2,
Expand Down Expand Up @@ -368,10 +366,9 @@ func TestDeleteSharded(t *testing.T) {
Opcode: Scatter,
Keyspace: ks.Keyspace,
},
Query: "dummy_delete",
Table: []*vindexes.Table{
ks.Tables["t2"],
},
Query: "dummy_delete",
TableNames: []string{ks.Tables["t2"].Name.String()},
Vindexes: ks.Tables["t2"].Owned,
},
}

Expand All @@ -397,10 +394,9 @@ func TestDeleteShardedStreaming(t *testing.T) {
Opcode: Scatter,
Keyspace: ks.Keyspace,
},
Query: "dummy_delete",
Table: []*vindexes.Table{
ks.Tables["t2"],
},
Query: "dummy_delete",
TableNames: []string{ks.Tables["t2"].Name.String()},
Vindexes: ks.Tables["t2"].Owned,
},
}

Expand All @@ -423,10 +419,9 @@ func TestDeleteScatterOwnedVindex(t *testing.T) {
Opcode: Scatter,
Keyspace: ks.Keyspace,
},
Query: "dummy_delete",
Table: []*vindexes.Table{
ks.Tables["t1"],
},
Query: "dummy_delete",
TableNames: []string{ks.Tables["t1"].Name.String()},
Vindexes: ks.Tables["t1"].Owned,
OwnedVindexQuery: "dummy_subquery",
KsidVindex: ks.Vindexes["hash"],
KsidLength: 1,
Expand Down Expand Up @@ -515,10 +510,9 @@ func TestDeleteInChangedVindexMultiCol(t *testing.T) {
evalengine.NewLiteralInt(3),
},
},
Query: "dummy_update",
Table: []*vindexes.Table{
ks.Tables["rg_tbl"],
},
Query: "dummy_update",
TableNames: []string{ks.Tables["rg_tbl"].Name.String()},
Vindexes: ks.Tables["rg_tbl"].Owned,
OwnedVindexQuery: "dummy_subquery",
KsidVindex: ks.Vindexes["rg_vdx"],
KsidLength: 2,
Expand Down
34 changes: 12 additions & 22 deletions go/vt/vtgate/engine/dml.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ type DML struct {
// KsidLength is number of columns that represents KsidVindex
KsidLength int

// Table specifies the table for the update.
Table []*vindexes.Table
// TableNames are the name of the tables involved in the query.
TableNames []string

// Vindexes are the column vindexes modified by this DML.
Vindexes []*vindexes.ColumnVindex

// OwnedVindexQuery is used for updating changes in lookup vindexes.
OwnedVindexQuery string
Expand Down Expand Up @@ -103,29 +106,16 @@ func (dml *DML) GetKeyspaceName() string {

// GetTableName specifies the table that this primitive routes to.
func (dml *DML) GetTableName() string {
if dml.Table != nil {
tableNameMap := map[string]any{}
for _, table := range dml.Table {
tableNameMap[table.Name.String()] = nil
}

var tableNames []string
for name := range tableNameMap {
sort.Strings(dml.TableNames)
var tableNames []string
var previousTbl string
for _, name := range dml.TableNames {
if name != previousTbl {
tableNames = append(tableNames, name)
previousTbl = name
}
sort.Strings(tableNames)

return strings.Join(tableNames, ", ")
}
return ""
}

// GetSingleTable returns single table used in dml.
func (dml *DML) GetSingleTable() (*vindexes.Table, error) {
if len(dml.Table) > 1 {
return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported dml on complex table expression")
}
return dml.Table[0], nil
return strings.Join(tableNames, ", ")
}

func allowOnlyPrimary(rss ...*srvtopo.ResolvedShard) error {
Expand Down
31 changes: 15 additions & 16 deletions go/vt/vtgate/engine/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ type (
// ColVindexes are the vindexes that will use the VindexValues
ColVindexes []*vindexes.ColumnVindex

// Table specifies the table for the insert.
Table *vindexes.Table
// TableName is the name of the table on which row will be inserted.
TableName string

// Generate is only set for inserts where a sequence must be generated.
Generate *Generate
Expand Down Expand Up @@ -135,16 +135,25 @@ func NewInsert(
mid []string,
suffix string,
) *Insert {
return &Insert{
ins := &Insert{
Opcode: opcode,
Ignore: ignore,
Keyspace: keyspace,
VindexValues: vindexValues,
Table: table,
Prefix: prefix,
Mid: mid,
Suffix: suffix,
}
if table != nil {
ins.TableName = table.Name.String()
for _, colVindex := range table.ColumnVindexes {
if colVindex.IsPartialVindex() {
continue
}
ins.ColVindexes = append(ins.ColVindexes, colVindex)
}
}
return ins
}

// Generate represents the instruction to generate
Expand Down Expand Up @@ -208,10 +217,7 @@ func (ins *Insert) GetKeyspaceName() string {

// GetTableName specifies the table that this primitive routes to.
func (ins *Insert) GetTableName() string {
if ins.Table != nil {
return ins.Table.Name.String()
}
return ""
return ins.TableName
}

// TryExecute performs a non-streaming exec.
Expand Down Expand Up @@ -384,10 +390,6 @@ func (ins *Insert) getInsertSelectQueries(
rows []sqltypes.Row,
) ([]*srvtopo.ResolvedShard, []*querypb.BoundQuery, error) {
colVindexes := ins.ColVindexes
if colVindexes == nil {
colVindexes = ins.Table.ColumnVindexes
}

if len(colVindexes) != len(ins.VindexValueOffset) {
return nil, nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "vindex value offsets and vindex info do not match")
}
Expand Down Expand Up @@ -656,9 +658,6 @@ func (ins *Insert) getInsertShardedRoute(
rowCount := 0
env := evalengine.NewExpressionEnv(ctx, bindVars, vcursor)
colVindexes := ins.ColVindexes
if colVindexes == nil {
colVindexes = ins.Table.ColumnVindexes
}
for vIdx, vColValues := range ins.VindexValues {
if len(vColValues) != len(colVindexes[vIdx].Columns) {
return nil, nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] supplied vindex column values don't match vschema: %v %v", vColValues, colVindexes[vIdx].Columns)
Expand Down Expand Up @@ -697,7 +696,7 @@ func (ins *Insert) getInsertShardedRoute(
// results in an error. For 'ignore' type inserts, the keyspace
// id is returned as nil, which is used later to drop the corresponding rows.
if len(vindexRowsValues) == 0 || len(colVindexes) == 0 {
return nil, nil, vterrors.NewErrorf(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.RequiresPrimaryKey, vterrors.PrimaryVindexNotSet, ins.Table.Name)
return nil, nil, vterrors.NewErrorf(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.RequiresPrimaryKey, vterrors.PrimaryVindexNotSet, ins.TableName)
}
keyspaceIDs, err := ins.processPrimary(ctx, vcursor, vindexRowsValues[0], colVindexes[0])
if err != nil {
Expand Down
Loading

0 comments on commit 3328588

Please sign in to comment.