diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go index d3eaf8479e0..4d529da5d17 100644 --- a/go/test/endtoend/vtgate/misc_test.go +++ b/go/test/endtoend/vtgate/misc_test.go @@ -23,12 +23,13 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/sqlerror" + "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/utils" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestInsertOnDuplicateKey(t *testing.T) { @@ -790,8 +791,15 @@ func TestJoinWithMergedRouteWithPredicate(t *testing.T) { } func TestRowCountExceed(t *testing.T) { - conn, closer := start(t) - defer closer() + conn, _ := start(t) + defer func() { + cluster.PanicHandler(t) + // needs special delete logic as it exceeds row count. + for i := 50; i <= 300; i += 50 { + utils.Exec(t, conn, fmt.Sprintf("delete from t1 where id1 < %d", i)) + } + conn.Close() + }() for i := 0; i < 250; i++ { utils.Exec(t, conn, fmt.Sprintf("insert into t1 (id1, id2) values (%d, %d)", i, i+1)) @@ -799,3 +807,41 @@ func TestRowCountExceed(t *testing.T) { utils.AssertContainsError(t, conn, "select id1 from t1 where id1 < 1000", `Row count exceeded 100`) } + +func TestLookupErrorMetric(t *testing.T) { + conn, closer := start(t) + defer closer() + + oldErrCount := getVtgateApiErrorCounts(t) + + utils.Exec(t, conn, `insert into t1 values (1,1)`) + _, err := utils.ExecAllowError(t, conn, `insert into t1 values (2,1)`) + require.ErrorContains(t, err, `(errno 1062) (sqlstate 23000)`) + + newErrCount := getVtgateApiErrorCounts(t) + require.EqualValues(t, oldErrCount+1, newErrCount) +} + +func getVtgateApiErrorCounts(t *testing.T) float64 { + apiErr := getVar(t, "VtgateApiErrorCounts") + if apiErr == nil { + return 0 + } + mapErrors := apiErr.(map[string]interface{}) + val, exists := mapErrors["Execute.ks.primary.ALREADY_EXISTS"] + if exists { + return val.(float64) + } + return 0 +} + +func getVar(t *testing.T, key string) interface{} { + vars, err := clusterInstance.VtgateProcess.GetVars() + require.NoError(t, err) + + val, exists := vars[key] + if !exists { + return nil + } + return val +} diff --git a/go/test/endtoend/vtgate/queries/dml/insert_test.go b/go/test/endtoend/vtgate/queries/dml/insert_test.go index 867b3b46fc8..aa34761ee2b 100644 --- a/go/test/endtoend/vtgate/queries/dml/insert_test.go +++ b/go/test/endtoend/vtgate/queries/dml/insert_test.go @@ -68,11 +68,11 @@ func TestFailureInsertSelect(t *testing.T) { // primary key same mcmp.AssertContainsError("insert into s_tbl(id, num) select id, num*20 from s_tbl where id = 1", `AlreadyExists desc = Duplicate entry '1' for key`) - // lookup key same (does not fail on MySQL as there is no lookup, and we have not put unique contrains on num column) - utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `lookup.Create: Code: ALREADY_EXISTS`) + // lookup key same (does not fail on MySQL as there is no lookup, and we have not put unique constraint on num column) + utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `(errno 1062) (sqlstate 23000)`) // mismatch column count - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count at row 1`) - mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count at row 1`) + mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count with the row`) + mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count with the row`) }) } } @@ -298,7 +298,7 @@ func TestIgnoreInsertSelect(t *testing.T) { mcmp.Exec("insert into order_tbl(region_id, oid, cust_no) values (1,1,100),(1,2,200),(1,3,300)") // inserting same rows, throws error. - mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `lookup.Create: Code: ALREADY_EXISTS`) + mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `(errno 1062) (sqlstate 23000)`) // inserting same rows with ignore qr := mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl") assert.EqualValues(t, 0, qr.RowsAffected) @@ -336,7 +336,7 @@ func TestIgnoreInsertSelectOlapMode(t *testing.T) { mcmp.Exec("insert into order_tbl(region_id, oid, cust_no) values (1,1,100),(1,2,200),(1,3,300)") // inserting same rows, throws error. - mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `lookup.Create: Code: ALREADY_EXISTS`) + mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `(errno 1062) (sqlstate 23000)`) // inserting same rows with ignore qr := mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl") assert.EqualValues(t, 0, qr.RowsAffected) diff --git a/go/vt/vterrors/code.go b/go/vt/vterrors/code.go index e6cd1ca9ba0..5e13e23b54e 100644 --- a/go/vt/vterrors/code.go +++ b/go/vt/vterrors/code.go @@ -31,7 +31,7 @@ var ( VT03003 = errorWithState("VT03003", vtrpcpb.Code_INVALID_ARGUMENT, UnknownTable, "unknown table '%s' in MULTI DELETE", "The specified table in this DELETE statement is unknown.") VT03004 = errorWithState("VT03004", vtrpcpb.Code_INVALID_ARGUMENT, NonUpdateableTable, "the target table %s of the DELETE is not updatable", "You cannot delete something that is not a real MySQL table.") VT03005 = errorWithState("VT03005", vtrpcpb.Code_INVALID_ARGUMENT, WrongGroupField, "cannot group on '%s'", "The planner does not allow grouping on certain field. For instance, aggregation function.") - VT03006 = errorWithState("VT03006", vtrpcpb.Code_INVALID_ARGUMENT, WrongValueCountOnRow, "column count does not match value count at row 1", "The number of columns you want to insert do not match the number of columns of your SELECT query.") + VT03006 = errorWithState("VT03006", vtrpcpb.Code_INVALID_ARGUMENT, WrongValueCountOnRow, "column count does not match value count with the row", "The number of columns you want to insert do not match the number of columns of your SELECT query.") VT03007 = errorWithoutState("VT03007", vtrpcpb.Code_INVALID_ARGUMENT, "keyspace not specified", "You need to add a keyspace qualifier.") VT03008 = errorWithState("VT03008", vtrpcpb.Code_INVALID_ARGUMENT, CantUseOptionHere, "incorrect usage/placement of '%s'", "The given token is not usable in this situation. Please refer to the MySQL documentation to learn more about your token's syntax.") VT03009 = errorWithState("VT03009", vtrpcpb.Code_INVALID_ARGUMENT, WrongValueForVar, "unexpected value type for '%s': %v", "You cannot assign this type to the given variable.") @@ -53,6 +53,9 @@ var ( VT03025 = errorWithState("VT03025", vtrpcpb.Code_INVALID_ARGUMENT, WrongArguments, "Incorrect arguments to %s", "The execute statement have wrong number of arguments") VT03026 = errorWithoutState("VT03024", vtrpcpb.Code_INVALID_ARGUMENT, "'%s' bind variable does not exists", "The query cannot be executed as missing the bind variable.") VT03027 = errorWithState("VT03027", vtrpcpb.Code_INVALID_ARGUMENT, BadNullError, "Column '%s' cannot be null", "The column cannot have null value.") + VT03028 = errorWithState("VT03028", vtrpcpb.Code_INVALID_ARGUMENT, BadNullError, "Column '%s' cannot be null on row %d, col %d", "The column cannot have null value.") + VT03029 = errorWithState("VT03029", vtrpcpb.Code_INVALID_ARGUMENT, WrongValueCountOnRow, "column count does not match value count with the row for vindex '%s'", "The number of columns you want to insert do not match the number of columns of your SELECT query.") + VT03030 = errorWithState("VT03030", vtrpcpb.Code_INVALID_ARGUMENT, WrongValueCountOnRow, "lookup column count does not match value count with the row (columns, count): (%v, %d)", "The number of columns you want to insert do not match the number of columns of your SELECT query.") VT05001 = errorWithState("VT05001", vtrpcpb.Code_NOT_FOUND, DbDropExists, "cannot drop database '%s'; database does not exists", "The given database does not exist; Vitess cannot drop it.") VT05002 = errorWithState("VT05002", vtrpcpb.Code_NOT_FOUND, BadDb, "cannot alter database '%s'; unknown database", "The given database does not exist; Vitess cannot alter it.") @@ -132,6 +135,9 @@ var ( VT03025, VT03026, VT03027, + VT03028, + VT03029, + VT03030, VT05001, VT05002, VT05003, diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.json b/go/vt/vtgate/planbuilder/testdata/dml_cases.json index 511ce9fb954..eb257064afd 100644 --- a/go/vt/vtgate/planbuilder/testdata/dml_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.json @@ -1207,7 +1207,7 @@ { "comment": "insert with mimatched column list", "query": "insert into user(id) values (1, 2)", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert no column list for sharded authoritative table", @@ -3759,17 +3759,17 @@ { "comment": "insert using select with more columns in insert", "query": "insert into music(id, user_id) select 1", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert using select with more columns in select", "query": "insert into music(id, user_id) select id, count(user_id), sum(user_id) from user group by id", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert using select with more columns in select after accounting for star column", "query": "insert into music(id, user_id) select id, *, 2 from user", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert using select with auto-inc column using vitess sequence, sequence column not present", @@ -4893,12 +4893,12 @@ { "comment": "insert row values smaller than number of columns", "query": "insert into user(one, two, three, four) values (1, 2, 3)", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert row values greater than number of columns", "query": "insert into user(one, two, three) values (1, 2, 3, 4)", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "insert on duplicate key update with database qualifier", diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index ba69f459e2d..58e19b0b5c1 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -102,7 +102,7 @@ { "comment": "unsharded insert, col list does not match values", "query": "insert into unsharded_auto(id, val) values(1)", - "plan": "VT03006: column count does not match value count at row 1" + "plan": "VT03006: column count does not match value count with the row" }, { "comment": "sharded upsert can't change vindex", diff --git a/go/vt/vtgate/vindexes/consistent_lookup.go b/go/vt/vtgate/vindexes/consistent_lookup.go index fb5eb5dfb0a..9173ded96e6 100644 --- a/go/vt/vtgate/vindexes/consistent_lookup.go +++ b/go/vt/vtgate/vindexes/consistent_lookup.go @@ -27,6 +27,7 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/evalengine" querypb "vitess.io/vitess/go/vt/proto/query" @@ -171,7 +172,7 @@ func (lu *ConsistentLookup) UnknownParams() []string { return lu.unknownParams } -//==================================================================== +// ==================================================================== // ConsistentLookupUnique defines a vindex that uses a lookup table. // The table is expected to define the id column as unique. It's @@ -271,7 +272,7 @@ func (lu *ConsistentLookupUnique) AutoCommitEnabled() bool { return lu.lkp.Autocommit } -//==================================================================== +// ==================================================================== // clCommon defines a vindex that uses a lookup table. // The table is expected to define the id column as unique. It's @@ -309,7 +310,7 @@ func (lu *clCommon) SetOwnerInfo(keyspace, table string, cols []sqlparser.Identi lu.keyspace = keyspace lu.ownerTable = sqlparser.String(sqlparser.NewIdentifierCS(table)) if len(cols) != len(lu.lkp.FromColumns) { - return fmt.Errorf("owner table column count does not match vindex %s", lu.name) + return vterrors.VT03029(lu.name) } lu.ownerColumns = make([]string, len(cols)) for i, col := range cols { diff --git a/go/vt/vtgate/vindexes/lookup_hash.go b/go/vt/vtgate/vindexes/lookup_hash.go index 4a4c6f7a6b5..28f38942afa 100644 --- a/go/vt/vtgate/vindexes/lookup_hash.go +++ b/go/vt/vtgate/vindexes/lookup_hash.go @@ -25,6 +25,7 @@ import ( "vitess.io/vitess/go/vt/key" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" + "vitess.io/vitess/go/vt/vterrors" ) const ( @@ -52,7 +53,7 @@ func init() { Register("lookup_hash_unique", newLookupHashUnique) } -//==================================================================== +// ==================================================================== // LookupHash defines a vindex that uses a lookup table. // The table is expected to define the id column as unique. It's @@ -205,7 +206,7 @@ func (lh *LookupHash) Verify(ctx context.Context, vcursor VCursor, ids []sqltype values, err := unhashList(ksids) if err != nil { - return nil, fmt.Errorf("lookup.Verify.vunhash: %v", err) + return nil, vterrors.Wrap(err, "lookup.Verify.vunhash") } return lh.lkp.Verify(ctx, vcursor, ids, values) } @@ -214,7 +215,7 @@ func (lh *LookupHash) Verify(ctx context.Context, vcursor VCursor, ids []sqltype func (lh *LookupHash) Create(ctx context.Context, vcursor VCursor, rowsColValues [][]sqltypes.Value, ksids [][]byte, ignoreMode bool) error { values, err := unhashList(ksids) if err != nil { - return fmt.Errorf("lookup.Create.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Create.vunhash") } return lh.lkp.Create(ctx, vcursor, rowsColValues, values, ignoreMode) } @@ -223,7 +224,7 @@ func (lh *LookupHash) Create(ctx context.Context, vcursor VCursor, rowsColValues func (lh *LookupHash) Update(ctx context.Context, vcursor VCursor, oldValues []sqltypes.Value, ksid []byte, newValues []sqltypes.Value) error { v, err := vunhash(ksid) if err != nil { - return fmt.Errorf("lookup.Update.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Update.vunhash") } return lh.lkp.Update(ctx, vcursor, oldValues, ksid, sqltypes.NewUint64(v), newValues) } @@ -232,7 +233,7 @@ func (lh *LookupHash) Update(ctx context.Context, vcursor VCursor, oldValues []s func (lh *LookupHash) Delete(ctx context.Context, vcursor VCursor, rowsColValues [][]sqltypes.Value, ksid []byte) error { v, err := vunhash(ksid) if err != nil { - return fmt.Errorf("lookup.Delete.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Delete.vunhash") } return lh.lkp.Delete(ctx, vcursor, rowsColValues, sqltypes.NewUint64(v), vtgatepb.CommitOrder_NORMAL) } @@ -260,7 +261,7 @@ func unhashList(ksids [][]byte) ([]sqltypes.Value, error) { return values, nil } -//==================================================================== +// ==================================================================== // LookupHashUnique defines a vindex that uses a lookup table. // The table is expected to define the id column as unique. It's @@ -383,7 +384,7 @@ func (lhu *LookupHashUnique) Verify(ctx context.Context, vcursor VCursor, ids [] values, err := unhashList(ksids) if err != nil { - return nil, fmt.Errorf("lookup.Verify.vunhash: %v", err) + return nil, vterrors.Wrap(err, "lookup.Verify.vunhash") } return lhu.lkp.Verify(ctx, vcursor, ids, values) } @@ -392,7 +393,7 @@ func (lhu *LookupHashUnique) Verify(ctx context.Context, vcursor VCursor, ids [] func (lhu *LookupHashUnique) Create(ctx context.Context, vcursor VCursor, rowsColValues [][]sqltypes.Value, ksids [][]byte, ignoreMode bool) error { values, err := unhashList(ksids) if err != nil { - return fmt.Errorf("lookup.Create.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Create.vunhash") } return lhu.lkp.Create(ctx, vcursor, rowsColValues, values, ignoreMode) } @@ -401,7 +402,7 @@ func (lhu *LookupHashUnique) Create(ctx context.Context, vcursor VCursor, rowsCo func (lhu *LookupHashUnique) Delete(ctx context.Context, vcursor VCursor, rowsColValues [][]sqltypes.Value, ksid []byte) error { v, err := vunhash(ksid) if err != nil { - return fmt.Errorf("lookup.Delete.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Delete.vunhash") } return lhu.lkp.Delete(ctx, vcursor, rowsColValues, sqltypes.NewUint64(v), vtgatepb.CommitOrder_NORMAL) } @@ -410,7 +411,7 @@ func (lhu *LookupHashUnique) Delete(ctx context.Context, vcursor VCursor, rowsCo func (lhu *LookupHashUnique) Update(ctx context.Context, vcursor VCursor, oldValues []sqltypes.Value, ksid []byte, newValues []sqltypes.Value) error { v, err := vunhash(ksid) if err != nil { - return fmt.Errorf("lookup.Update.vunhash: %v", err) + return vterrors.Wrap(err, "lookup.Update.vunhash") } return lhu.lkp.Update(ctx, vcursor, oldValues, ksid, sqltypes.NewUint64(v), newValues) } diff --git a/go/vt/vtgate/vindexes/lookup_hash_test.go b/go/vt/vtgate/vindexes/lookup_hash_test.go index 69bff9f6f34..fd07f6ab7d8 100644 --- a/go/vt/vtgate/vindexes/lookup_hash_test.go +++ b/go/vt/vtgate/vindexes/lookup_hash_test.go @@ -236,10 +236,7 @@ func TestLookupHashCreate(t *testing.T) { } err = lookuphash.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NULL}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false /* ignoreMode */) - want := "lookup.Create: input has null values: row: 0, col: 0" - if err == nil || err.Error() != want { - t.Errorf("lookuphash.Create(NULL) err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "VT03028: Column 'fromc' cannot be null on row 0, col 0") vc.queries = nil lookuphash.(*LookupHash).lkp.IgnoreNulls = true @@ -250,10 +247,7 @@ func TestLookupHashCreate(t *testing.T) { } err = lookuphash.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, [][]byte{[]byte("bogus")}, false /* ignoreMode */) - want = "lookup.Create.vunhash: invalid keyspace id: 626f677573" - if err == nil || err.Error() != want { - t.Errorf("lookuphash.Create(bogus) err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "lookup.Create.vunhash: invalid keyspace id: 626f677573") } func TestLookupHashDelete(t *testing.T) { diff --git a/go/vt/vtgate/vindexes/lookup_internal.go b/go/vt/vtgate/vindexes/lookup_internal.go index b793d57c3c8..5e224259d1d 100644 --- a/go/vt/vtgate/vindexes/lookup_internal.go +++ b/go/vt/vtgate/vindexes/lookup_internal.go @@ -24,13 +24,11 @@ import ( "strconv" "strings" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/sqltypes" - querypb "vitess.io/vitess/go/vt/proto/query" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" ) const ( @@ -143,7 +141,7 @@ func (lkp *lookupInternal) Init(lookupQueryParams map[string]string, autocommit, // Lookup performs a lookup for the ids. func (lkp *lookupInternal) Lookup(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, co vtgatepb.CommitOrder) ([]*sqltypes.Result, error) { if vcursor == nil { - return nil, fmt.Errorf("cannot perform lookup: no vcursor provided") + return nil, vterrors.VT13001("cannot perform lookup: no vcursor provided") } results := make([]*sqltypes.Result, 0, len(ids)) if lkp.Autocommit { @@ -159,14 +157,14 @@ func (lkp *lookupInternal) Lookup(ctx context.Context, vcursor VCursor, ids []sq // for integral types, batch query all ids and then map them back to the input order vars, err := sqltypes.BuildBindVariable(ids) if err != nil { - return nil, fmt.Errorf("lookup.Map: %v", err) + return nil, err } bindVars := map[string]*querypb.BindVariable{ lkp.FromColumns[0]: vars, } result, err := vcursor.Execute(ctx, "VindexLookup", sel, bindVars, false /* rollbackOnError */, co) if err != nil { - return nil, fmt.Errorf("lookup.Map: %v", err) + return nil, vterrors.Wrap(err, "lookup.Map") } resultMap := make(map[string][][]sqltypes.Value) for _, row := range result.Rows { @@ -183,7 +181,7 @@ func (lkp *lookupInternal) Lookup(ctx context.Context, vcursor VCursor, ids []sq for _, id := range ids { vars, err := sqltypes.BuildBindVariable([]any{id}) if err != nil { - return nil, fmt.Errorf("lookup.Map: %v", err) + return nil, err } bindVars := map[string]*querypb.BindVariable{ lkp.FromColumns[0]: vars, @@ -191,7 +189,7 @@ func (lkp *lookupInternal) Lookup(ctx context.Context, vcursor VCursor, ids []sq var result *sqltypes.Result result, err = vcursor.Execute(ctx, "VindexLookup", sel, bindVars, false /* rollbackOnError */, co) if err != nil { - return nil, fmt.Errorf("lookup.Map: %v", err) + return nil, vterrors.Wrap(err, "lookup.Map") } rows := make([][]sqltypes.Value, 0, len(result.Rows)) for _, row := range result.Rows { @@ -223,7 +221,7 @@ func (lkp *lookupInternal) VerifyCustom(ctx context.Context, vcursor VCursor, id } result, err := vcursor.Execute(ctx, "VindexVerify", lkp.ver, bindVars, false /* rollbackOnError */, co) if err != nil { - return nil, fmt.Errorf("lookup.Verify: %v", err) + return nil, vterrors.Wrap(err, "lookup.Verify") } out[i] = (len(result.Rows) != 0) } @@ -290,7 +288,8 @@ nextRow: for j, col := range row { if col.IsNull() { if !lkp.IgnoreNulls { - return fmt.Errorf("lookup.Create: input has null values: row: %d, col: %d", i, j) + cols := strings.Join(lkp.FromColumns, ",") + return vterrors.VT03028(cols, i, j) } continue nextRow } @@ -304,7 +303,7 @@ nextRow: // We only need to check the first row. Number of cols per row // is guaranteed by the engine to be uniform. if len(trimmedRowsCols[0]) != len(lkp.FromColumns) { - return fmt.Errorf("lookup.Create: column vindex count does not match the columns in the lookup: %d vs %v", len(trimmedRowsCols[0]), lkp.FromColumns) + return vterrors.VT03030(lkp.FromColumns, len(trimmedRowsCols[0])) } sort.Sort(&sorter{rowsColValues: trimmedRowsCols, toValues: trimmedToValues}) @@ -348,7 +347,7 @@ nextRow: } if _, err := vcursor.Execute(ctx, "VindexCreate", buf.String(), bindVars, true /* rollbackOnError */, co); err != nil { - return fmt.Errorf("lookup.Create: %v", err) + return vterrors.Wrap(err, "lookup.Create") } return nil } @@ -380,7 +379,7 @@ func (lkp *lookupInternal) Delete(ctx context.Context, vcursor VCursor, rowsColV // We only need to check the first row. Number of cols per row // is guaranteed by the engine to be uniform. if len(rowsColValues[0]) != len(lkp.FromColumns) { - return fmt.Errorf("lookup.Delete: column vindex count does not match the columns in the lookup: %d vs %v", len(rowsColValues[0]), lkp.FromColumns) + return vterrors.VT03030(lkp.FromColumns, len(rowsColValues[0])) } for _, column := range rowsColValues { bindVars := make(map[string]*querypb.BindVariable, len(rowsColValues)) @@ -390,7 +389,7 @@ func (lkp *lookupInternal) Delete(ctx context.Context, vcursor VCursor, rowsColV bindVars[lkp.To] = sqltypes.ValueBindVariable(value) _, err := vcursor.Execute(ctx, "VindexDelete", lkp.del, bindVars, true /* rollbackOnError */, co) if err != nil { - return fmt.Errorf("lookup.Delete: %v", err) + return vterrors.Wrap(err, "lookup.Delete") } } return nil diff --git a/go/vt/vtgate/vindexes/lookup_test.go b/go/vt/vtgate/vindexes/lookup_test.go index a59fcbf1da9..b82ab3d4fec 100644 --- a/go/vt/vtgate/vindexes/lookup_test.go +++ b/go/vt/vtgate/vindexes/lookup_test.go @@ -369,7 +369,7 @@ func TestLookupNonUniqueNew(t *testing.T) { func TestLookupNilVCursor(t *testing.T) { lnu := createLookup(t, "lookup", false /* writeOnly */) _, err := lnu.Map(context.Background(), nil, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}) - require.EqualError(t, err, "cannot perform lookup: no vcursor provided") + require.EqualError(t, err, "VT13001: [BUG] cannot perform lookup: no vcursor provided") } func TestLookupNonUniqueMap(t *testing.T) { @@ -620,7 +620,7 @@ func TestLookupNonUniqueCreate(t *testing.T) { // With ignore_nulls off err = lnu.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(2)}, {sqltypes.NULL}}, [][]byte{[]byte("test2"), []byte("test1")}, true /* ignoreMode */) - assert.EqualError(t, err, "lookup.Create: input has null values: row: 1, col: 0") + assert.EqualError(t, err, "VT03028: Column 'fromc' cannot be null on row 1, col 0") // With ignore_nulls on vc.queries = nil @@ -644,7 +644,7 @@ func TestLookupNonUniqueCreate(t *testing.T) { // Test column mismatch. err = lnu.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false /* ignoreMode */) - assert.EqualError(t, err, "lookup.Create: column vindex count does not match the columns in the lookup: 2 vs [fromc]") + assert.EqualError(t, err, "VT03030: lookup column count does not match value count with the row (columns, count): ([fromc], 2)") } func TestLookupNonUniqueCreateAutocommit(t *testing.T) { @@ -710,7 +710,7 @@ func TestLookupNonUniqueDelete(t *testing.T) { // Test column count fail. err = lnu.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}}, []byte("\x16k@\xb4J\xbaK\xd6")) - assert.EqualError(t, err, "lookup.Delete: column vindex count does not match the columns in the lookup: 2 vs [fromc]") + assert.EqualError(t, err, "VT03030: lookup column count does not match value count with the row (columns, count): ([fromc], 2)") } func TestLookupNonUniqueDeleteAutocommit(t *testing.T) { diff --git a/go/vt/vtgate/vindexes/lookup_unicodeloosemd5_hash_test.go b/go/vt/vtgate/vindexes/lookup_unicodeloosemd5_hash_test.go index 989458ccc13..c0e4611d684 100644 --- a/go/vt/vtgate/vindexes/lookup_unicodeloosemd5_hash_test.go +++ b/go/vt/vtgate/vindexes/lookup_unicodeloosemd5_hash_test.go @@ -320,10 +320,7 @@ func TestLookupUnicodeLooseMD5HashCreate(t *testing.T) { // Test column mismatch. err = lnu.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10), sqltypes.NewInt64(20)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false) - want = "lookup.Create: column vindex count does not match the columns in the lookup: 2 vs [fromc]" - if err == nil || err.Error() != want { - t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "VT03030: lookup column count does not match value count with the row (columns, count): ([fromc], 2)") } func TestLookupUnicodeLooseMD5HashCreateAutocommit(t *testing.T) { @@ -443,10 +440,7 @@ func TestLookupUnicodeLooseMD5HashDelete(t *testing.T) { // Test column count fail. err = lnu.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}}, []byte("\x16k@\xb4J\xbaK\xd6")) - want = "lookup.Delete: column vindex count does not match the columns in the lookup: 2 vs [fromc]" - if err == nil || err.Error() != want { - t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want) - } + require.ErrorContains(t, err, "VT03030: lookup column count does not match value count with the row (columns, count): ([fromc], 2)") } func TestLookupUnicodeLooseMD5HashDeleteAutocommit(t *testing.T) {