Merge pull request #63 from github/arthur/backport-vindex-lock-options

Backport `read_lock` and `no_verify` VIndex options
This commit is contained in:
Eric Yan 2023-05-16 15:51:36 +02:00 коммит произвёл GitHub
Родитель 1953490aae 51f102532f
Коммит a5fb1dc1e2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 854 добавлений и 112 удалений

Просмотреть файл

@ -41,6 +41,10 @@ var (
id BIGINT NOT NULL,
field BIGINT NOT NULL,
field2 BIGINT,
field3 BIGINT,
field4 BIGINT,
field5 BIGINT,
field6 BIGINT,
PRIMARY KEY (id)
) ENGINE=Innodb;
@ -56,6 +60,30 @@ CREATE TABLE lookup2 (
UNIQUE KEY (field2)
) ENGINE=Innodb;
CREATE TABLE lookup3 (
field3 BIGINT NOT NULL,
keyspace_id binary(8),
UNIQUE KEY (field3)
) ENGINE=Innodb;
CREATE TABLE lookup4 (
field4 BIGINT NOT NULL,
keyspace_id binary(8),
UNIQUE KEY (field4)
) ENGINE=Innodb;
CREATE TABLE lookup5 (
field5 BIGINT NOT NULL,
keyspace_id binary(8),
UNIQUE KEY (field5)
) ENGINE=Innodb;
CREATE TABLE lookup6 (
field6 BIGINT NOT NULL,
keyspace_id binary(8),
UNIQUE KEY (field6)
) ENGINE=Innodb;
CREATE TABLE thex (
id VARBINARY(64) NOT NULL,
field BIGINT NOT NULL,
@ -88,7 +116,7 @@ CREATE TABLE thex (
"table": "lookup1",
"from": "field",
"to": "keyspace_id",
"ignore_nulls": "true"
"ignore_nulls": "true"
},
"owner": "t1"
},
@ -98,7 +126,47 @@ CREATE TABLE thex (
"table": "lookup2",
"from": "field2",
"to": "keyspace_id",
"ignore_nulls": "true"
"ignore_nulls": "true"
},
"owner": "t1"
},
"lookup3": {
"type": "lookup",
"params": {
"from": "field3",
"no_verify": "true",
"table": "lookup3",
"to": "keyspace_id"
},
"owner": "t1"
},
"lookup4": {
"type": "lookup",
"params": {
"from": "field4",
"read_lock": "exclusive",
"table": "lookup4",
"to": "keyspace_id"
},
"owner": "t1"
},
"lookup5": {
"type": "lookup",
"params": {
"from": "field5",
"read_lock": "shared",
"table": "lookup5",
"to": "keyspace_id"
},
"owner": "t1"
},
"lookup6": {
"type": "lookup",
"params": {
"from": "field6",
"read_lock": "none",
"table": "lookup6",
"to": "keyspace_id"
},
"owner": "t1"
}
@ -117,6 +185,22 @@ CREATE TABLE thex (
{
"column": "field2",
"name": "lookup2"
},
{
"column": "field3",
"name": "lookup3"
},
{
"column": "field4",
"name": "lookup4"
},
{
"column": "field5",
"name": "lookup5"
},
{
"column": "field6",
"name": "lookup6"
}
]
},
@ -136,6 +220,38 @@ CREATE TABLE thex (
}
]
},
"lookup3": {
"column_vindexes": [
{
"column": "field3",
"name": "binary_md5_vdx"
}
]
},
"lookup4": {
"column_vindexes": [
{
"column": "field4",
"name": "binary_md5_vdx"
}
]
},
"lookup5": {
"column_vindexes": [
{
"column": "field5",
"name": "binary_md5_vdx"
}
]
},
"lookup6": {
"column_vindexes": [
{
"column": "field6",
"name": "binary_md5_vdx"
}
]
},
"thex": {
"column_vindexes": [
{
@ -216,51 +332,51 @@ func TestVindexBindVarOverlap(t *testing.T) {
require.Nil(t, err)
defer conn.Close()
utils.Exec(t, conn, "INSERT INTO t1 (id, field, field2) VALUES "+
"(0,1,2), "+
"(1,2,3), "+
"(2,3,4), "+
"(3,4,5), "+
"(4,5,6), "+
"(5,6,7), "+
"(6,7,8), "+
"(7,8,9), "+
"(8,9,10), "+
"(9,10,11), "+
"(10,11,12), "+
"(11,12,13), "+
"(12,13,14), "+
"(13,14,15), "+
"(14,15,16), "+
"(15,16,17), "+
"(16,17,18), "+
"(17,18,19), "+
"(18,19,20), "+
"(19,20,21), "+
"(20,21,22)")
result := utils.Exec(t, conn, "select id, field, field2 from t1 order by id")
utils.Exec(t, conn, "INSERT INTO t1 (id, field, field2, field3, field4, field5, field6) VALUES "+
"(0,1,2,3,4,5,6), "+
"(1,2,3,4,5,6,7), "+
"(2,3,4,5,6,7,8), "+
"(3,4,5,6,7,8,9), "+
"(4,5,6,7,8,9,10), "+
"(5,6,7,8,9,10,11), "+
"(6,7,8,9,10,11,12), "+
"(7,8,9,10,11,12,13), "+
"(8,9,10,11,12,13,14), "+
"(9,10,11,12,13,14,15), "+
"(10,11,12,13,14,15,16), "+
"(11,12,13,14,15,16,17), "+
"(12,13,14,15,16,17,18), "+
"(13,14,15,16,17,18,19), "+
"(14,15,16,17,18,19,20), "+
"(15,16,17,18,19,20,21), "+
"(16,17,18,19,20,21,22), "+
"(17,18,19,20,21,22,23), "+
"(18,19,20,21,22,23,24), "+
"(19,20,21,22,23,24,25), "+
"(20,21,22,23,24,25,26)")
result := utils.Exec(t, conn, "select id, field, field2, field3, field4, field5, field6 from t1 order by id")
expected :=
"[[INT64(0) INT64(1) INT64(2)] " +
"[INT64(1) INT64(2) INT64(3)] " +
"[INT64(2) INT64(3) INT64(4)] " +
"[INT64(3) INT64(4) INT64(5)] " +
"[INT64(4) INT64(5) INT64(6)] " +
"[INT64(5) INT64(6) INT64(7)] " +
"[INT64(6) INT64(7) INT64(8)] " +
"[INT64(7) INT64(8) INT64(9)] " +
"[INT64(8) INT64(9) INT64(10)] " +
"[INT64(9) INT64(10) INT64(11)] " +
"[INT64(10) INT64(11) INT64(12)] " +
"[INT64(11) INT64(12) INT64(13)] " +
"[INT64(12) INT64(13) INT64(14)] " +
"[INT64(13) INT64(14) INT64(15)] " +
"[INT64(14) INT64(15) INT64(16)] " +
"[INT64(15) INT64(16) INT64(17)] " +
"[INT64(16) INT64(17) INT64(18)] " +
"[INT64(17) INT64(18) INT64(19)] " +
"[INT64(18) INT64(19) INT64(20)] " +
"[INT64(19) INT64(20) INT64(21)] " +
"[INT64(20) INT64(21) INT64(22)]]"
"[[INT64(0) INT64(1) INT64(2) INT64(3) INT64(4) INT64(5) INT64(6)] " +
"[INT64(1) INT64(2) INT64(3) INT64(4) INT64(5) INT64(6) INT64(7)] " +
"[INT64(2) INT64(3) INT64(4) INT64(5) INT64(6) INT64(7) INT64(8)] " +
"[INT64(3) INT64(4) INT64(5) INT64(6) INT64(7) INT64(8) INT64(9)] " +
"[INT64(4) INT64(5) INT64(6) INT64(7) INT64(8) INT64(9) INT64(10)] " +
"[INT64(5) INT64(6) INT64(7) INT64(8) INT64(9) INT64(10) INT64(11)] " +
"[INT64(6) INT64(7) INT64(8) INT64(9) INT64(10) INT64(11) INT64(12)] " +
"[INT64(7) INT64(8) INT64(9) INT64(10) INT64(11) INT64(12) INT64(13)] " +
"[INT64(8) INT64(9) INT64(10) INT64(11) INT64(12) INT64(13) INT64(14)] " +
"[INT64(9) INT64(10) INT64(11) INT64(12) INT64(13) INT64(14) INT64(15)] " +
"[INT64(10) INT64(11) INT64(12) INT64(13) INT64(14) INT64(15) INT64(16)] " +
"[INT64(11) INT64(12) INT64(13) INT64(14) INT64(15) INT64(16) INT64(17)] " +
"[INT64(12) INT64(13) INT64(14) INT64(15) INT64(16) INT64(17) INT64(18)] " +
"[INT64(13) INT64(14) INT64(15) INT64(16) INT64(17) INT64(18) INT64(19)] " +
"[INT64(14) INT64(15) INT64(16) INT64(17) INT64(18) INT64(19) INT64(20)] " +
"[INT64(15) INT64(16) INT64(17) INT64(18) INT64(19) INT64(20) INT64(21)] " +
"[INT64(16) INT64(17) INT64(18) INT64(19) INT64(20) INT64(21) INT64(22)] " +
"[INT64(17) INT64(18) INT64(19) INT64(20) INT64(21) INT64(22) INT64(23)] " +
"[INT64(18) INT64(19) INT64(20) INT64(21) INT64(22) INT64(23) INT64(24)] " +
"[INT64(19) INT64(20) INT64(21) INT64(22) INT64(23) INT64(24) INT64(25)] " +
"[INT64(20) INT64(21) INT64(22) INT64(23) INT64(24) INT64(25) INT64(26)]]"
assert.Equal(t, expected, fmt.Sprintf("%v", result.Rows))
}

24
go/vt/vtexplain/testdata/test-schema.sql поставляемый
Просмотреть файл

@ -105,3 +105,27 @@ CREATE TABLE orders_id_lookup (
keyspace_id varbinary(128),
primary key(id)
);
CREATE TABLE orders_id_lookup_exclusive_read_lock (
id int NOT NULL,
keyspace_id varbinary(128),
primary key(id)
);
CREATE TABLE orders_id_lookup_shared_read_lock (
id int NOT NULL,
keyspace_id varbinary(128),
primary key(id)
);
CREATE TABLE orders_id_lookup_no_read_lock (
id int NOT NULL,
keyspace_id varbinary(128),
primary key(id)
);
CREATE TABLE orders_id_lookup_no_verify (
id int NOT NULL,
keyspace_id varbinary(128),
primary key(id)
);

56
go/vt/vtexplain/testdata/test-vschema.json поставляемый
Просмотреть файл

@ -18,6 +18,46 @@
},
"owner": "orders"
},
"orders_id_vdx_exclusive_read_lock": {
"type": "lookup_unique",
"params": {
"table": "orders_id_lookup_exclusive_read_lock",
"from": "id",
"to": "keyspace_id",
"read_lock": "exclusive"
},
"owner": "orders"
},
"orders_id_vdx_shared_read_lock": {
"type": "lookup_unique",
"params": {
"table": "orders_id_lookup_shared_read_lock",
"from": "id",
"to": "keyspace_id",
"read_lock": "shared"
},
"owner": "orders"
},
"orders_id_vdx_no_read_lock": {
"type": "lookup_unique",
"params": {
"table": "orders_id_lookup_no_read_lock",
"from": "id",
"to": "keyspace_id",
"read_lock": "none"
},
"owner": "orders"
},
"orders_id_vdx_no_verify": {
"type": "lookup_unique",
"params": {
"table": "orders_id_lookup_no_verify",
"from": "id",
"to": "keyspace_id",
"no_verify": "true"
},
"owner": "orders"
},
"music_user_map": {
"type": "lookup_hash_unique",
"owner": "music",
@ -164,6 +204,22 @@
}
]
},
"orders_id_lookup_no_read_lock": {
"column_vindexes": [
{
"column": "id",
"name": "hash"
}
]
},
"orders_id_lookup_no_verify": {
"column_vindexes": [
{
"column": "id",
"name": "hash"
}
]
},
"email_customer_map": {
"column_vindexes": [
{

Просмотреть файл

@ -164,21 +164,24 @@ func TestUpdateFromSubQuery(t *testing.T) {
testQueryLog(t, logChan, "TestExecute", "UPDATE", "update user set a=(select count(*) from user where id = 3) where id = 1", 2)
}
func TestUpdateEqualWithWriteOnlyLookupUniqueVindex(t *testing.T) {
func TestUpdateEqualWithNoVerifyAndWriteOnlyLookupUniqueVindexes(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col|t2_lu_vdx", "int64|int64|int64|int64"),
"1|2|1|0",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
_, err := executorExec(executor, "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2", nil)
_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col, lu_col = 5 from t2_wo_lookup where wo_lu_col = 2 for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where wo_lu_col = 2 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2",
Sql: "update t2_lookup set lu_col = 5 where wo_lu_col = 2",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -199,7 +202,264 @@ func TestUpdateEqualWithWriteOnlyLookupUniqueVindex(t *testing.T) {
"lu_col_0": sqltypes.Int64BindVariable(5),
},
}
lookWant := []*querypb.BoundQuery{bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2}
lookWant := []*querypb.BoundQuery{
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
}
assertQueries(t, sbcLookup, lookWant)
}
func TestUpdateInTransactionLookupDefaultReadLock(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
_, err := executorExecSession(
executor,
"update t2_lookup set lu_col = 5 where nv_lu_col = 2",
nil,
safeSession.Session,
)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where nv_lu_col = 2 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_lookup set lu_col = 5 where nv_lu_col = 2",
BindVariables: map[string]*querypb.BindVariable{},
},
}
assertQueries(t, sbc1, wantQueries)
assertQueries(t, sbc2, wantQueries)
vars, _ := sqltypes.BuildBindVariable([]any{
sqltypes.NewInt64(2),
})
bq1 := &querypb.BoundQuery{
Sql: "select nv_lu_col, keyspace_id from nv_lu_idx where nv_lu_col in ::nv_lu_col for update",
BindVariables: map[string]*querypb.BindVariable{
"nv_lu_col": vars,
},
}
bq2 := &querypb.BoundQuery{
Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id_0": sqltypes.Uint64BindVariable(1),
"lu_col_0": sqltypes.Int64BindVariable(5),
},
}
lookWant := []*querypb.BoundQuery{
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
}
assertQueries(t, sbcLookup, lookWant)
}
func TestUpdateInTransactionLookupExclusiveReadLock(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
_, err := executorExecSession(
executor,
"update t2_lookup set lu_col = 5 where erl_lu_col = 2",
nil,
safeSession.Session,
)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where nv_lu_col = 2 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_lookup set lu_col = 5 where erl_lu_col = 2",
BindVariables: map[string]*querypb.BindVariable{},
},
}
assertQueries(t, sbc1, wantQueries)
assertQueries(t, sbc2, wantQueries)
vars, _ := sqltypes.BuildBindVariable([]any{
sqltypes.NewInt64(2),
})
bq1 := &querypb.BoundQuery{
Sql: "select erl_lu_col, keyspace_id from erl_lu_idx where erl_lu_col in ::erl_lu_col for update",
BindVariables: map[string]*querypb.BindVariable{
"erl_lu_col": vars,
},
}
bq2 := &querypb.BoundQuery{
Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id_0": sqltypes.Uint64BindVariable(1),
"lu_col_0": sqltypes.Int64BindVariable(5),
},
}
lookWant := []*querypb.BoundQuery{
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
}
assertQueries(t, sbcLookup, lookWant)
}
func TestUpdateInTransactionLookupSharedReadLock(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
_, err := executorExecSession(
executor,
"update t2_lookup set lu_col = 5 where srl_lu_col = 2",
nil,
safeSession.Session,
)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where nv_lu_col = 2 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_lookup set lu_col = 5 where srl_lu_col = 2",
BindVariables: map[string]*querypb.BindVariable{},
},
}
assertQueries(t, sbc1, wantQueries)
assertQueries(t, sbc2, wantQueries)
vars, _ := sqltypes.BuildBindVariable([]any{
sqltypes.NewInt64(2),
})
bq1 := &querypb.BoundQuery{
Sql: "select srl_lu_col, keyspace_id from srl_lu_idx where srl_lu_col in ::srl_lu_col lock in share mode",
BindVariables: map[string]*querypb.BindVariable{
"srl_lu_col": vars,
},
}
bq2 := &querypb.BoundQuery{
Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id_0": sqltypes.Uint64BindVariable(1),
"lu_col_0": sqltypes.Int64BindVariable(5),
},
}
lookWant := []*querypb.BoundQuery{
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
}
assertQueries(t, sbcLookup, lookWant)
}
func TestUpdateInTransactionLookupNoReadLock(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
_, err := executorExecSession(
executor,
"update t2_lookup set lu_col = 5 where nrl_lu_col = 2",
nil,
safeSession.Session,
)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where nrl_lu_col = 2 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_lookup set lu_col = 5 where nrl_lu_col = 2",
BindVariables: map[string]*querypb.BindVariable{},
},
}
assertQueries(t, sbc1, wantQueries)
assertQueries(t, sbc2, wantQueries)
vars, _ := sqltypes.BuildBindVariable([]any{
sqltypes.NewInt64(2),
})
bq1 := &querypb.BoundQuery{
Sql: "select nrl_lu_col, keyspace_id from nrl_lu_idx where nrl_lu_col in ::nrl_lu_col",
BindVariables: map[string]*querypb.BindVariable{
"nrl_lu_col": vars,
},
}
bq2 := &querypb.BoundQuery{
Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id_0": sqltypes.Uint64BindVariable(1),
"lu_col_0": sqltypes.Int64BindVariable(5),
},
}
lookWant := []*querypb.BoundQuery{
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
bq1, bq2,
}
assertQueries(t, sbcLookup, lookWant)
}
@ -513,18 +773,21 @@ func TestUpdateEqualWithMultipleLookupVindex(t *testing.T) {
)})
sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col|t2_lu_vdx", "int64|int64|int64|int64"),
"1|2|1|0",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
)})
_, err := executorExec(executor, "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1", nil)
_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col, lu_col = 5 from t2_wo_lookup where wo_lu_col = 2 and lu_col = 1 for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where wo_lu_col = 2 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1",
Sql: "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -564,19 +827,22 @@ func TestUpdateUseHigherCostVindexIfBackfilling(t *testing.T) {
)})
sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col|t2_lu_vdx", "int64|int64|int64|int64"),
"1|2|1|0",
"1|2|2|0",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
"int64|int64|int64|int64|int64|int64|int64|int64",
),
"1|2|2|2|2|2|1|0",
"1|2|2|2|2|2|2|0",
)})
_, err := executorExec(executor, "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)", nil)
_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col, lu_col = 5 from t2_wo_lookup where wo_lu_col = 2 and lu_col in (1, 2) for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col, lu_col = 5 from t2_lookup where wo_lu_col = 2 and lu_col in (1, 2) for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "update t2_wo_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)",
Sql: "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -619,21 +885,24 @@ func TestUpdateUseHigherCostVindexIfBackfilling(t *testing.T) {
assertQueries(t, sbc2, nil)
}
func TestDeleteEqualWithWriteOnlyLookupUniqueVindex(t *testing.T) {
func TestDeleteEqualWithNoVerifyAndWriteOnlyLookupUniqueVindex(t *testing.T) {
res := []*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col", "int64|int64|int64"),
"1|1|1",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
"int64|int64|int64|int64|int64|int64|int64",
),
"1|1|1|1|1|1|1",
)}
executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
_, err := executorExec(executor, "delete from t2_wo_lookup where wo_lu_col = 1", nil)
_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col from t2_wo_lookup where wo_lu_col = 1 for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col from t2_lookup where wo_lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "delete from t2_wo_lookup where wo_lu_col = 1",
Sql: "delete from t2_lookup where wo_lu_col = 1",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -645,13 +914,50 @@ func TestDeleteEqualWithWriteOnlyLookupUniqueVindex(t *testing.T) {
},
}
bq2 := &querypb.BoundQuery{
Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"erl_lu_col": sqltypes.Int64BindVariable(1),
},
}
bq3 := &querypb.BoundQuery{
Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"srl_lu_col": sqltypes.Int64BindVariable(1),
},
}
bq4 := &querypb.BoundQuery{
Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nrl_lu_col": sqltypes.Int64BindVariable(1),
},
}
bq5 := &querypb.BoundQuery{
Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nv_lu_col": sqltypes.Int64BindVariable(1),
},
}
bq6 := &querypb.BoundQuery{
Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": sqltypes.Uint64BindVariable(1),
"lu_col": sqltypes.Int64BindVariable(1),
},
}
lookWant := []*querypb.BoundQuery{bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2, bq1, bq2}
lookWant := []*querypb.BoundQuery{
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
bq1, bq2, bq3, bq4, bq5, bq6,
}
assertQueries(t, sbcLookup, lookWant)
assertQueries(t, sbc1, wantQueries)
assertQueries(t, sbc2, wantQueries)
@ -666,18 +972,21 @@ func TestDeleteEqualWithMultipleLookupVindex(t *testing.T) {
)})
sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col", "int64|int64|int64"),
"1|1|1",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
"int64|int64|int64|int64|int64|int64|int64",
),
"1|1|1|1|1|1|1",
)})
_, err := executorExec(executor, "delete from t2_wo_lookup where wo_lu_col = 1 and lu_col = 1", nil)
_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1 and lu_col = 1", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col from t2_wo_lookup where wo_lu_col = 1 and lu_col = 1 for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col from t2_lookup where wo_lu_col = 1 and lu_col = 1 for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "delete from t2_wo_lookup where wo_lu_col = 1 and lu_col = 1",
Sql: "delete from t2_lookup where wo_lu_col = 1 and lu_col = 1",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -695,6 +1004,30 @@ func TestDeleteEqualWithMultipleLookupVindex(t *testing.T) {
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"wo_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"erl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"srl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nrl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nv_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
@ -718,19 +1051,22 @@ func TestDeleteUseHigherCostVindexIfBackfilling(t *testing.T) {
)})
sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
sqltypes.MakeTestFields("id|wo_lu_col|lu_col", "int64|int64|int64"),
"1|1|1",
"1|1|2",
sqltypes.MakeTestFields(
"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
"int64|int64|int64|int64|int64|int64|int64",
),
"1|1|1|1|1|1|1",
"1|1|1|1|1|1|2",
)})
_, err := executorExec(executor, "delete from t2_wo_lookup where wo_lu_col = 1 and lu_col in (1, 2)", nil)
_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1 and lu_col in (1, 2)", nil)
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{
{
Sql: "select id, wo_lu_col, lu_col from t2_wo_lookup where wo_lu_col = 1 and lu_col in (1, 2) for update",
Sql: "select id, wo_lu_col, erl_lu_col, srl_lu_col, nrl_lu_col, nv_lu_col, lu_col from t2_lookup where wo_lu_col = 1 and lu_col in (1, 2) for update",
BindVariables: map[string]*querypb.BindVariable{},
}, {
Sql: "delete from t2_wo_lookup where wo_lu_col = 1 and lu_col in (1, 2)",
Sql: "delete from t2_lookup where wo_lu_col = 1 and lu_col in (1, 2)",
BindVariables: map[string]*querypb.BindVariable{},
}}
@ -749,6 +1085,30 @@ func TestDeleteUseHigherCostVindexIfBackfilling(t *testing.T) {
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"wo_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"erl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"srl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nrl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nv_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
@ -761,6 +1121,30 @@ func TestDeleteUseHigherCostVindexIfBackfilling(t *testing.T) {
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"wo_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"erl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"srl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nrl_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{
"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
"nv_lu_col": sqltypes.Int64BindVariable(1),
},
}, {
Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
BindVariables: map[string]*querypb.BindVariable{

Просмотреть файл

@ -119,9 +119,49 @@ var executorVSchema = `
"table": "TestUnsharded.wo_lu_idx",
"from": "wo_lu_col",
"to": "keyspace_id",
"write_only": "true"
"write_only": "true"
},
"owner": "t2_wo_lookup"
"owner": "t2_lookup"
},
"t2_erl_lu_vdx": {
"type": "lookup_unique",
"params": {
"table": "TestUnsharded.erl_lu_idx",
"from": "erl_lu_col",
"to": "keyspace_id",
"read_lock": "exclusive"
},
"owner": "t2_lookup"
},
"t2_srl_lu_vdx": {
"type": "lookup_unique",
"params": {
"table": "TestUnsharded.srl_lu_idx",
"from": "srl_lu_col",
"to": "keyspace_id",
"read_lock": "shared"
},
"owner": "t2_lookup"
},
"t2_nrl_lu_vdx": {
"type": "lookup_unique",
"params": {
"table": "TestUnsharded.nrl_lu_idx",
"from": "nrl_lu_col",
"to": "keyspace_id",
"read_lock": "none"
},
"owner": "t2_lookup"
},
"t2_nv_lu_vdx": {
"type": "lookup_unique",
"params": {
"table": "TestUnsharded.nv_lu_idx",
"from": "nv_lu_col",
"to": "keyspace_id",
"no_verify": "true"
},
"owner": "t2_lookup"
},
"t2_lu_vdx": {
"type": "lookup_hash_unique",
@ -130,7 +170,7 @@ var executorVSchema = `
"from": "lu_col",
"to": "keyspace_id"
},
"owner": "t2_wo_lookup"
"owner": "t2_lookup"
},
"regional_vdx": {
"type": "region_experimental",
@ -294,15 +334,31 @@ var executorVSchema = `
}
]
},
"t2_wo_lookup": {
"t2_lookup": {
"column_vindexes": [
{
"column": "id",
"name": "hash_index"
},
{
"column": "wo_lu_col",
"name": "t2_wo_lu_vdx"
"column": "wo_lu_col",
"name": "t2_wo_lu_vdx"
},
{
"column": "erl_lu_col",
"name": "t2_erl_lu_vdx"
},
{
"column": "srl_lu_col",
"name": "t2_srl_lu_vdx"
},
{
"column": "nrl_lu_col",
"name": "t2_nrl_lu_vdx"
},
{
"column": "nv_lu_col",
"name": "t2_nv_lu_vdx"
},
{
"column": "lu_col",
@ -350,6 +406,10 @@ var unshardedVSchema = `
}
},
"wo_lu_idx": {},
"erl_lu_idx": {},
"srl_lu_idx": {},
"nrl_lu_idx": {},
"nv_lu_idx": {},
"lu_idx": {},
"simple": {}
}

Просмотреть файл

@ -865,8 +865,12 @@ func TestExecutorShow(t *testing.T) {
buildVarCharRow("TestExecutor", "name_user_map", "lookup_hash", "from=name; table=name_user_map; to=user_id", "user"),
buildVarCharRow("TestExecutor", "regional_vdx", "region_experimental", "region_bytes=1", ""),
buildVarCharRow("TestExecutor", "t1_lkp_vdx", "consistent_lookup_unique", "from=unq_col; table=t1_lkp_idx; to=keyspace_id", "t1"),
buildVarCharRow("TestExecutor", "t2_lu_vdx", "lookup_hash_unique", "from=lu_col; table=TestUnsharded.lu_idx; to=keyspace_id", "t2_wo_lookup"),
buildVarCharRow("TestExecutor", "t2_wo_lu_vdx", "lookup_unique", "from=wo_lu_col; table=TestUnsharded.wo_lu_idx; to=keyspace_id; write_only=true", "t2_wo_lookup"),
buildVarCharRow("TestExecutor", "t2_erl_lu_vdx", "lookup_unique", "from=erl_lu_col; read_lock=exclusive; table=TestUnsharded.erl_lu_idx; to=keyspace_id", "t2_lookup"),
buildVarCharRow("TestExecutor", "t2_lu_vdx", "lookup_hash_unique", "from=lu_col; table=TestUnsharded.lu_idx; to=keyspace_id", "t2_lookup"),
buildVarCharRow("TestExecutor", "t2_nrl_lu_vdx", "lookup_unique", "from=nrl_lu_col; read_lock=none; table=TestUnsharded.nrl_lu_idx; to=keyspace_id", "t2_lookup"),
buildVarCharRow("TestExecutor", "t2_nv_lu_vdx", "lookup_unique", "from=nv_lu_col; no_verify=true; table=TestUnsharded.nv_lu_idx; to=keyspace_id", "t2_lookup"),
buildVarCharRow("TestExecutor", "t2_srl_lu_vdx", "lookup_unique", "from=srl_lu_col; read_lock=shared; table=TestUnsharded.srl_lu_idx; to=keyspace_id", "t2_lookup"),
buildVarCharRow("TestExecutor", "t2_wo_lu_vdx", "lookup_unique", "from=wo_lu_col; table=TestUnsharded.wo_lu_idx; to=keyspace_id; write_only=true", "t2_lookup"),
buildVarCharRow("TestMultiCol", "multicol_vdx", "multicol", "column_bytes=1,3,4; column_count=3; column_vindex=hash,binary,unicode_loose_xxhash", ""),
},
}
@ -997,13 +1001,17 @@ func TestExecutorShow(t *testing.T) {
Fields: buildVarCharFields("Tables"),
Rows: [][]sqltypes.Value{
buildVarCharRow("dual"),
buildVarCharRow("erl_lu_idx"),
buildVarCharRow("ins_lookup"),
buildVarCharRow("lu_idx"),
buildVarCharRow("main1"),
buildVarCharRow("music_user_map"),
buildVarCharRow("name_lastname_keyspace_id_map"),
buildVarCharRow("name_user_map"),
buildVarCharRow("nrl_lu_idx"),
buildVarCharRow("nv_lu_idx"),
buildVarCharRow("simple"),
buildVarCharRow("srl_lu_idx"),
buildVarCharRow("user_msgs"),
buildVarCharRow("user_seq"),
buildVarCharRow("wo_lu_idx"),

Просмотреть файл

@ -180,7 +180,7 @@ func (cached *LookupHash) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -194,7 +194,7 @@ func (cached *LookupHashUnique) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -208,7 +208,7 @@ func (cached *LookupNonUnique) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -222,7 +222,7 @@ func (cached *LookupUnicodeLooseMD5Hash) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -236,7 +236,7 @@ func (cached *LookupUnicodeLooseMD5HashUnique) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -250,7 +250,7 @@ func (cached *LookupUnique) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(144)
size += int64(176)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -492,7 +492,7 @@ func (cached *clCommon) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(256)
size += int64(288)
}
// field name string
size += hack.RuntimeAllocSize(int64(len(cached.name)))
@ -525,7 +525,7 @@ func (cached *lookupInternal) CachedSize(alloc bool) int64 {
}
size := int64(0)
if alloc {
size += int64(112)
size += int64(144)
}
// field Table string
size += hack.RuntimeAllocSize(int64(len(cached.Table)))
@ -538,8 +538,12 @@ func (cached *lookupInternal) CachedSize(alloc bool) int64 {
}
// field To string
size += hack.RuntimeAllocSize(int64(len(cached.To)))
// field ReadLock string
size += hack.RuntimeAllocSize(int64(len(cached.ReadLock)))
// field sel string
size += hack.RuntimeAllocSize(int64(len(cached.sel)))
// field selTxDml string
size += hack.RuntimeAllocSize(int64(len(cached.selTxDml)))
// field ver string
size += hack.RuntimeAllocSize(int64(len(cached.ver)))
// field del string

Просмотреть файл

@ -46,6 +46,7 @@ func init() {
type LookupNonUnique struct {
name string
writeOnly bool
noVerify bool
lkp lookupInternal
}
@ -132,7 +133,7 @@ func (ln *LookupNonUnique) MapResult(ids []sqltypes.Value, results []*sqltypes.R
// Verify returns true if ids maps to ksids.
func (ln *LookupNonUnique) Verify(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) {
if ln.writeOnly {
if ln.writeOnly || ln.noVerify {
out := make([]bool, len(ids))
for i := range ids {
out[i] = true
@ -178,6 +179,7 @@ func (ln *LookupNonUnique) Query() (selQuery string, arguments []string) {
//
// autocommit: setting this to "true" will cause inserts to upsert and deletes to be ignored.
// write_only: in this mode, Map functions return the full keyrange causing a full scatter.
// no_verify: in this mode, Verify will always succeed.
func NewLookup(name string, m map[string]string) (Vindex, error) {
lookup := &LookupNonUnique{name: name}
@ -190,6 +192,11 @@ func NewLookup(name string, m map[string]string) (Vindex, error) {
return nil, err
}
lookup.noVerify, err = boolFromMap(m, "no_verify")
if err != nil {
return nil, err
}
// if autocommit is on for non-unique lookup, upsert should also be on.
upsert := cc.autocommit || cc.multiShardAutocommit
if err := lookup.lkp.Init(m, cc.autocommit, upsert, cc.multiShardAutocommit); err != nil {
@ -214,6 +221,7 @@ func ksidsToValues(ksids [][]byte) []sqltypes.Value {
type LookupUnique struct {
name string
writeOnly bool
noVerify bool
lkp lookupInternal
}
@ -248,6 +256,11 @@ func NewLookupUnique(name string, m map[string]string) (Vindex, error) {
return nil, err
}
lu.noVerify, err = boolFromMap(m, "no_verify")
if err != nil {
return nil, err
}
// Don't allow upserts for unique vindexes.
if err := lu.lkp.Init(m, cc.autocommit, false /* upsert */, cc.multiShardAutocommit); err != nil {
return nil, err
@ -312,7 +325,7 @@ func (lu *LookupUnique) MapResult(ids []sqltypes.Value, results []*sqltypes.Resu
// Verify returns true if ids maps to ksids.
func (lu *LookupUnique) Verify(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) {
if lu.writeOnly {
if lu.writeOnly || lu.noVerify {
out := make([]bool, len(ids))
for i := range ids {
out[i] = true

Просмотреть файл

@ -48,7 +48,7 @@ func init() {
// LookupHash defines a vindex that uses a lookup table.
// The table is expected to define the id column as unique. It's
// NonUnique and a Lookup.
// Warning: This Vindex is being depcreated in favor of Lookup
// Warning: This Vindex is being deprecated in favor of Lookup
type LookupHash struct {
name string
writeOnly bool

Просмотреть файл

@ -33,17 +33,31 @@ import (
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
)
var (
readLockExclusive = "exclusive"
readLockShared = "shared"
readLockNone = "none"
readLockDefault = readLockExclusive
readLockExprs map[string]string = map[string]string{
readLockExclusive: "for update",
readLockShared: "lock in share mode",
readLockNone: "",
}
)
// lookupInternal implements the functions for the Lookup vindexes.
type lookupInternal struct {
Table string `json:"table"`
FromColumns []string `json:"from_columns"`
To string `json:"to"`
Autocommit bool `json:"autocommit,omitempty"`
MultiShardAutocommit bool `json:"multi_shard_autocommit,omitempty"`
Upsert bool `json:"upsert,omitempty"`
IgnoreNulls bool `json:"ignore_nulls,omitempty"`
BatchLookup bool `json:"batch_lookup,omitempty"`
sel, ver, del string // sel: map query, ver: verify query, del: delete query
Table string `json:"table"`
FromColumns []string `json:"from_columns"`
To string `json:"to"`
Autocommit bool `json:"autocommit,omitempty"`
MultiShardAutocommit bool `json:"multi_shard_autocommit,omitempty"`
Upsert bool `json:"upsert,omitempty"`
IgnoreNulls bool `json:"ignore_nulls,omitempty"`
BatchLookup bool `json:"batch_lookup,omitempty"`
ReadLock string `json:"read_lock,omitempty"`
sel, selTxDml, ver, del string // sel: map query, ver: verify query, del: delete query
}
func (lkp *lookupInternal) Init(lookupQueryParams map[string]string, autocommit, upsert, multiShardAutocommit bool) error {
@ -64,6 +78,12 @@ func (lkp *lookupInternal) Init(lookupQueryParams map[string]string, autocommit,
if err != nil {
return err
}
if readLock, ok := lookupQueryParams["read_lock"]; ok {
if _, valid := readLockExprs[readLock]; !valid {
return fmt.Errorf("invalid read_lock value: %s", readLock)
}
lkp.ReadLock = readLock
}
lkp.Autocommit = autocommit
lkp.Upsert = upsert
@ -76,6 +96,15 @@ func (lkp *lookupInternal) Init(lookupQueryParams map[string]string, autocommit,
// as part of face 2 of https://github.com/vitessio/vitess/issues/3481
// For now multi column behaves as a single column for Map and Verify operations
lkp.sel = fmt.Sprintf("select %s, %s from %s where %s in ::%s", lkp.FromColumns[0], lkp.To, lkp.Table, lkp.FromColumns[0], lkp.FromColumns[0])
if lkp.ReadLock != readLockNone {
lockExpr, ok := readLockExprs[lkp.ReadLock]
if !ok {
lockExpr = readLockExprs[readLockDefault]
}
lkp.selTxDml = fmt.Sprintf("%s %s", lkp.sel, lockExpr)
} else {
lkp.selTxDml = lkp.sel
}
lkp.ver = fmt.Sprintf("select %s from %s where %s = :%s and %s = :%s", lkp.FromColumns[0], lkp.Table, lkp.FromColumns[0], lkp.FromColumns[0], lkp.To, lkp.To)
lkp.del = lkp.initDelStmt()
return nil
@ -90,9 +119,11 @@ func (lkp *lookupInternal) Lookup(ctx context.Context, vcursor VCursor, ids []sq
if lkp.Autocommit {
co = vtgatepb.CommitOrder_AUTOCOMMIT
}
sel := lkp.sel
var sel string
if vcursor.InTransactionAndIsDML() {
sel = sel + " for update"
sel = lkp.selTxDml
} else {
sel = lkp.sel
}
if ids[0].IsIntegral() || lkp.BatchLookup {
// for integral types, batch query all ids and then map them back to the input order

Просмотреть файл

@ -281,6 +281,52 @@ func TestLookupNonUniqueVerify(t *testing.T) {
utils.MustMatch(t, []bool{true, true}, got)
}
func TestLookupNonUniqueNoVerify(t *testing.T) {
vindex, err := CreateVindex("lookup", "lookup", map[string]string{
"table": "t",
"from": "fromc",
"to": "toc",
"no_verify": "true",
})
require.NoError(t, err)
lookupNonUnique := vindex.(SingleColumn)
vc := &vcursor{numRows: 1}
_, err = lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}, [][]byte{[]byte("test1"), []byte("test2")})
require.NoError(t, err)
var wantqueries []*querypb.BoundQuery
utils.MustMatch(t, vc.queries, wantqueries)
// Test query fail.
vc.mustFail = true
_, err = lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
require.NoError(t, err)
}
func TestLookupUniqueNoVerify(t *testing.T) {
vindex, err := CreateVindex("lookup_unique", "lookup_unique", map[string]string{
"table": "t",
"from": "fromc",
"to": "toc",
"no_verify": "true",
})
require.NoError(t, err)
lookupUnique := vindex.(SingleColumn)
vc := &vcursor{numRows: 1}
_, err = lookupUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}, [][]byte{[]byte("test1"), []byte("test2")})
require.NoError(t, err)
var wantqueries []*querypb.BoundQuery
utils.MustMatch(t, vc.queries, wantqueries)
// Test query fail.
vc.mustFail = true
_, err = lookupUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
require.NoError(t, err)
}
func TestLookupNonUniqueVerifyAutocommit(t *testing.T) {
vindex, err := CreateVindex("lookup", "lookup", map[string]string{
"table": "t",