vitess.io/vitess@v0.16.2/go/vt/vtgate/vindexes/lookup_unicodeloosemd5_hash_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package vindexes
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/require"
    25  
    26  	"vitess.io/vitess/go/sqltypes"
    27  
    28  	"vitess.io/vitess/go/vt/key"
    29  	querypb "vitess.io/vitess/go/vt/proto/query"
    30  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    31  )
    32  
    33  const (
    34  	hashed10 uint64 = 17563797831108199066
    35  	hashed20 uint64 = 8729390916138266389
    36  	hashed30 uint64 = 1472608112194674795
    37  	hashed40 uint64 = 16576388050845489136
    38  )
    39  
    40  func TestLookupUnicodeLooseMD5HashMap(t *testing.T) {
    41  	lookup := createLookup(t, "lookup_unicodeloosemd5_hash", false)
    42  	vc := &vcursor{numRows: 2, keys: []sqltypes.Value{sqltypes.NewUint64(hashed10), sqltypes.NewUint64(hashed20)}}
    43  
    44  	got, err := lookup.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)})
    45  	require.NoError(t, err)
    46  	want := []key.Destination{
    47  		key.DestinationKeyspaceIDs([][]byte{
    48  			[]byte("\x16k@\xb4J\xbaK\xd6"),
    49  			[]byte("\x06\xe7\xea\"Βp\x8f"),
    50  		}),
    51  		key.DestinationKeyspaceIDs([][]byte{
    52  			[]byte("\x16k@\xb4J\xbaK\xd6"),
    53  			[]byte("\x06\xe7\xea\"Βp\x8f"),
    54  		}),
    55  	}
    56  	if !reflect.DeepEqual(got, want) {
    57  		t.Errorf("Map(): %#v, want %+v", got, want)
    58  	}
    59  
    60  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewUint64(hashed10), sqltypes.NewUint64(hashed20)})
    61  	require.NoError(t, err)
    62  	wantqueries := []*querypb.BoundQuery{{
    63  		Sql: "select fromc, toc from t where fromc in ::fromc",
    64  		BindVariables: map[string]*querypb.BindVariable{
    65  			"fromc": vars,
    66  		},
    67  	}}
    68  	if !reflect.DeepEqual(vc.queries, wantqueries) {
    69  		t.Errorf("lookup.Map queries:\n%v, want\n%v", vc.queries, wantqueries)
    70  	}
    71  
    72  	// Test query fail.
    73  	vc.mustFail = true
    74  	_, err = lookup.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)})
    75  	wantErr := "lookup.Map: execute failed"
    76  	if err == nil || err.Error() != wantErr {
    77  		t.Errorf("lookup(query fail) err: %v, want %s", err, wantErr)
    78  	}
    79  	vc.mustFail = false
    80  }
    81  
    82  func TestLookupUnicodeLooseMD5HashMapAutocommit(t *testing.T) {
    83  	vindex, err := CreateVindex("lookup_unicodeloosemd5_hash", "lookup", map[string]string{
    84  		"table":      "t",
    85  		"from":       "fromc",
    86  		"to":         "toc",
    87  		"hash_from":  "true",
    88  		"autocommit": "true",
    89  	})
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  	lookupNonUnique := vindex.(SingleColumn)
    94  	vc := &vcursor{numRows: 2, keys: []sqltypes.Value{sqltypes.NewUint64(hashed10), sqltypes.NewUint64(hashed20)}}
    95  
    96  	got, err := lookupNonUnique.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)})
    97  	require.NoError(t, err)
    98  	want := []key.Destination{
    99  		key.DestinationKeyspaceIDs([][]byte{
   100  			[]byte("\x16k@\xb4J\xbaK\xd6"),
   101  			[]byte("\x06\xe7\xea\"Βp\x8f"),
   102  		}),
   103  		key.DestinationKeyspaceIDs([][]byte{
   104  			[]byte("\x16k@\xb4J\xbaK\xd6"),
   105  			[]byte("\x06\xe7\xea\"Βp\x8f"),
   106  		}),
   107  	}
   108  	if !reflect.DeepEqual(got, want) {
   109  		t.Errorf("Map(): %#v, want %+v", got, want)
   110  	}
   111  
   112  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewUint64(hashed10), sqltypes.NewUint64(hashed20)})
   113  	require.NoError(t, err)
   114  	wantqueries := []*querypb.BoundQuery{{
   115  		Sql: "select fromc, toc from t where fromc in ::fromc",
   116  		BindVariables: map[string]*querypb.BindVariable{
   117  			"fromc": vars,
   118  		},
   119  	}}
   120  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   121  		t.Errorf("lookup.Map queries:\n%v, want\n%v", vc.queries, wantqueries)
   122  	}
   123  
   124  	if got, want := vc.autocommits, 1; got != want {
   125  		t.Errorf("Create(autocommit) count: %d, want %d", got, want)
   126  	}
   127  }
   128  
   129  func TestLookupUnicodeLooseMD5HashMapWriteOnly(t *testing.T) {
   130  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", true)
   131  	vc := &vcursor{numRows: 0}
   132  
   133  	got, err := lookupNonUnique.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)})
   134  	require.NoError(t, err)
   135  	want := []key.Destination{
   136  		key.DestinationKeyRange{
   137  			KeyRange: &topodatapb.KeyRange{},
   138  		},
   139  		key.DestinationKeyRange{
   140  			KeyRange: &topodatapb.KeyRange{},
   141  		},
   142  	}
   143  	if !reflect.DeepEqual(got, want) {
   144  		t.Errorf("Map(): %#v, want %+v", got, want)
   145  	}
   146  }
   147  
   148  func TestLookupUnicodeLooseMD5HashMapAbsent(t *testing.T) {
   149  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", false)
   150  	vc := &vcursor{numRows: 0}
   151  
   152  	got, err := lookupNonUnique.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)})
   153  	require.NoError(t, err)
   154  	want := []key.Destination{
   155  		key.DestinationNone{},
   156  		key.DestinationNone{},
   157  	}
   158  	if !reflect.DeepEqual(got, want) {
   159  		t.Errorf("Map(): %#v, want %+v", got, want)
   160  	}
   161  }
   162  
   163  func TestLookupUnicodeLooseMD5HashVerify(t *testing.T) {
   164  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", false)
   165  	vc := &vcursor{numRows: 1}
   166  
   167  	got, err := lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")})
   168  	require.NoError(t, err)
   169  	wantResult := []bool{true, true}
   170  	if !reflect.DeepEqual(got, wantResult) {
   171  		t.Errorf("lookuphash.Verify(match): %v, want %v", got, wantResult)
   172  	}
   173  
   174  	wantqueries := []*querypb.BoundQuery{{
   175  		Sql: "select fromc from t where fromc = :fromc and toc = :toc",
   176  		BindVariables: map[string]*querypb.BindVariable{
   177  			"fromc": sqltypes.Uint64BindVariable(hashed10),
   178  			"toc":   sqltypes.Uint64BindVariable(1),
   179  		},
   180  	}, {
   181  		Sql: "select fromc from t where fromc = :fromc and toc = :toc",
   182  		BindVariables: map[string]*querypb.BindVariable{
   183  			"fromc": sqltypes.Uint64BindVariable(hashed20),
   184  			"toc":   sqltypes.Uint64BindVariable(2),
   185  		},
   186  	}}
   187  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   188  		t.Errorf("lookup.Verify queries:\n%v, want\n%v", vc.queries, wantqueries)
   189  	}
   190  
   191  	// Test query fail.
   192  	vc.mustFail = true
   193  	_, err = lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
   194  	want := "lookup.Verify: execute failed"
   195  	if err == nil || err.Error() != want {
   196  		t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want)
   197  	}
   198  	vc.mustFail = false
   199  
   200  	// writeOnly true should always yield true.
   201  	lookupNonUnique = createLookup(t, "lookup_unicodeloosemd5_hash", true)
   202  	vc.queries = nil
   203  
   204  	got, err = lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)}, [][]byte{[]byte(""), []byte("")})
   205  	require.NoError(t, err)
   206  	if vc.queries != nil {
   207  		t.Errorf("lookup.Verify(writeOnly), queries: %v, want nil", vc.queries)
   208  	}
   209  	wantBools := []bool{true, true}
   210  	if !reflect.DeepEqual(got, wantBools) {
   211  		t.Errorf("lookup.Verify(writeOnly): %v, want %v", got, wantBools)
   212  	}
   213  }
   214  
   215  func TestLookupUnicodeLooseMD5HashVerifyAutocommit(t *testing.T) {
   216  	vindex, err := CreateVindex("lookup_unicodeloosemd5_hash", "lookup", map[string]string{
   217  		"table":      "t",
   218  		"from":       "fromc",
   219  		"to":         "toc",
   220  		"autocommit": "true",
   221  	})
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  	lookupNonUnique := vindex.(SingleColumn)
   226  	vc := &vcursor{numRows: 1}
   227  
   228  	_, err = lookupNonUnique.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10), sqltypes.NewInt64(20)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")})
   229  	require.NoError(t, err)
   230  
   231  	wantqueries := []*querypb.BoundQuery{{
   232  		Sql: "select fromc from t where fromc = :fromc and toc = :toc",
   233  		BindVariables: map[string]*querypb.BindVariable{
   234  			"fromc": sqltypes.Uint64BindVariable(hashed10),
   235  			"toc":   sqltypes.Uint64BindVariable(1),
   236  		},
   237  	}, {
   238  		Sql: "select fromc from t where fromc = :fromc and toc = :toc",
   239  		BindVariables: map[string]*querypb.BindVariable{
   240  			"fromc": sqltypes.Uint64BindVariable(hashed20),
   241  			"toc":   sqltypes.Uint64BindVariable(2),
   242  		},
   243  	}}
   244  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   245  		t.Errorf("lookup.Verify queries:\n%v, want\n%v", vc.queries, wantqueries)
   246  	}
   247  
   248  	if got, want := vc.autocommits, 2; got != want {
   249  		t.Errorf("Create(autocommit) count: %d, want %d", got, want)
   250  	}
   251  }
   252  
   253  func TestLookupUnicodeLooseMD5HashCreate(t *testing.T) {
   254  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", false)
   255  	vc := &vcursor{}
   256  
   257  	err := lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10)}, {sqltypes.NewInt64(20)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")}, false)
   258  	require.NoError(t, err)
   259  
   260  	wantqueries := []*querypb.BoundQuery{{
   261  		Sql: "insert into t(fromc, toc) values(:fromc_0, :toc_0), (:fromc_1, :toc_1)",
   262  		BindVariables: map[string]*querypb.BindVariable{
   263  			"fromc_0": sqltypes.Uint64BindVariable(hashed10),
   264  			"toc_0":   sqltypes.Uint64BindVariable(1),
   265  			"fromc_1": sqltypes.Uint64BindVariable(hashed20),
   266  			"toc_1":   sqltypes.Uint64BindVariable(2),
   267  		},
   268  	}}
   269  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   270  		t.Errorf("lookup.Create queries:\n%v, want\n%v", vc.queries, wantqueries)
   271  	}
   272  
   273  	// With ignore.
   274  	vc.queries = nil
   275  	err = lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10)}, {sqltypes.NewInt64(20)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")}, true)
   276  	require.NoError(t, err)
   277  
   278  	wantqueries[0].Sql = "insert ignore into t(fromc, toc) values(:fromc_0, :toc_0), (:fromc_1, :toc_1)"
   279  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   280  		t.Errorf("lookup.Create queries:\n%v, want\n%v", vc.queries, wantqueries)
   281  	}
   282  
   283  	// Test query fail.
   284  	vc.mustFail = true
   285  	err = lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false)
   286  	want := "lookup.Create: execute failed"
   287  	if err == nil || err.Error() != want {
   288  		t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want)
   289  	}
   290  	vc.mustFail = false
   291  
   292  	// Test column mismatch.
   293  	err = lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10), sqltypes.NewInt64(20)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false)
   294  	want = "lookup.Create: column vindex count does not match the columns in the lookup: 2 vs [fromc]"
   295  	if err == nil || err.Error() != want {
   296  		t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want)
   297  	}
   298  }
   299  
   300  func TestLookupUnicodeLooseMD5HashCreateAutocommit(t *testing.T) {
   301  	lookupNonUnique, err := CreateVindex("lookup_unicodeloosemd5_hash", "lookup", map[string]string{
   302  		"table":      "t",
   303  		"from":       "from1,from2",
   304  		"to":         "toc",
   305  		"autocommit": "true",
   306  	})
   307  	if err != nil {
   308  		t.Fatal(err)
   309  	}
   310  	vc := &vcursor{}
   311  
   312  	err = lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{
   313  		sqltypes.NewInt64(10), sqltypes.NewInt64(20),
   314  	}, {
   315  		sqltypes.NewInt64(30), sqltypes.NewInt64(40),
   316  	}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")}, false)
   317  	require.NoError(t, err)
   318  
   319  	wantqueries := []*querypb.BoundQuery{{
   320  		Sql: "insert into t(from1, from2, toc) values(:from1_0, :from2_0, :toc_0), (:from1_1, :from2_1, :toc_1) on duplicate key update from1=values(from1), from2=values(from2), toc=values(toc)",
   321  		BindVariables: map[string]*querypb.BindVariable{
   322  			"from1_0": sqltypes.Uint64BindVariable(hashed30),
   323  			"from2_0": sqltypes.Uint64BindVariable(hashed40),
   324  			"toc_0":   sqltypes.Uint64BindVariable(2),
   325  			"from1_1": sqltypes.Uint64BindVariable(hashed10),
   326  			"from2_1": sqltypes.Uint64BindVariable(hashed20),
   327  			"toc_1":   sqltypes.Uint64BindVariable(1),
   328  		},
   329  	}}
   330  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   331  		t.Errorf("lookup.Create queries:\n%v, want\n%v", vc.queries, wantqueries)
   332  	}
   333  
   334  	if got, want := vc.autocommits, 1; got != want {
   335  		t.Errorf("Create(autocommit) count: %d, want %d", got, want)
   336  	}
   337  }
   338  
   339  func TestLookupUnicodeLooseMD5HashCreateMultiShardAutocommit(t *testing.T) {
   340  	lookupNonUnique, err := CreateVindex("lookup_unicodeloosemd5_hash", "lookup", map[string]string{
   341  		"table":                  "t",
   342  		"from":                   "from1,from2",
   343  		"to":                     "toc",
   344  		"multi_shard_autocommit": "true",
   345  	})
   346  	if err != nil {
   347  		t.Fatal(err)
   348  	}
   349  	vc := &vcursor{}
   350  
   351  	err = lookupNonUnique.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{
   352  		sqltypes.NewInt64(10), sqltypes.NewInt64(20),
   353  	}, {
   354  		sqltypes.NewInt64(30), sqltypes.NewInt64(40),
   355  	}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")}, false)
   356  	require.NoError(t, err)
   357  
   358  	wantqueries := []*querypb.BoundQuery{{
   359  		Sql: "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into t(from1, from2, toc) values(:from1_0, :from2_0, :toc_0), (:from1_1, :from2_1, :toc_1) on duplicate key update from1=values(from1), from2=values(from2), toc=values(toc)",
   360  		BindVariables: map[string]*querypb.BindVariable{
   361  			"from1_0": sqltypes.Uint64BindVariable(hashed30),
   362  			"from2_0": sqltypes.Uint64BindVariable(hashed40),
   363  			"toc_0":   sqltypes.Uint64BindVariable(2),
   364  			"from1_1": sqltypes.Uint64BindVariable(hashed10),
   365  			"from2_1": sqltypes.Uint64BindVariable(hashed20),
   366  			"toc_1":   sqltypes.Uint64BindVariable(1),
   367  		},
   368  	}}
   369  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   370  		t.Errorf("lookup.Create queries:\n%v, want\n%v", vc.queries, wantqueries)
   371  	}
   372  
   373  	if got, want := vc.autocommits, 1; got != want {
   374  		t.Errorf("Create(autocommit) count: %d, want %d", got, want)
   375  	}
   376  }
   377  
   378  func TestLookupUnicodeLooseMD5HashDelete(t *testing.T) {
   379  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", false)
   380  	vc := &vcursor{}
   381  
   382  	err := lookupNonUnique.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10)}, {sqltypes.NewInt64(20)}}, []byte("\x16k@\xb4J\xbaK\xd6"))
   383  	require.NoError(t, err)
   384  
   385  	wantqueries := []*querypb.BoundQuery{{
   386  		Sql: "delete from t where fromc = :fromc and toc = :toc",
   387  		BindVariables: map[string]*querypb.BindVariable{
   388  			"fromc": sqltypes.Uint64BindVariable(hashed10),
   389  			"toc":   sqltypes.Uint64BindVariable(1),
   390  		},
   391  	}, {
   392  		Sql: "delete from t where fromc = :fromc and toc = :toc",
   393  		BindVariables: map[string]*querypb.BindVariable{
   394  			"fromc": sqltypes.Uint64BindVariable(hashed20),
   395  			"toc":   sqltypes.Uint64BindVariable(1),
   396  		},
   397  	}}
   398  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   399  		t.Errorf("lookup.Delete queries:\n%v, want\n%v", vc.queries, wantqueries)
   400  	}
   401  
   402  	// Test query fail.
   403  	vc.mustFail = true
   404  	err = lookupNonUnique.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, []byte("\x16k@\xb4J\xbaK\xd6"))
   405  	want := "lookup.Delete: execute failed"
   406  	if err == nil || err.Error() != want {
   407  		t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want)
   408  	}
   409  	vc.mustFail = false
   410  
   411  	// Test column count fail.
   412  	err = lookupNonUnique.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}}, []byte("\x16k@\xb4J\xbaK\xd6"))
   413  	want = "lookup.Delete: column vindex count does not match the columns in the lookup: 2 vs [fromc]"
   414  	if err == nil || err.Error() != want {
   415  		t.Errorf("lookupNonUnique(query fail) err: %v, want %s", err, want)
   416  	}
   417  }
   418  
   419  func TestLookupUnicodeLooseMD5HashDeleteAutocommit(t *testing.T) {
   420  	lookupNonUnique, _ := CreateVindex("lookup_unicodeloosemd5_hash", "lookup", map[string]string{
   421  		"table":      "t",
   422  		"from":       "fromc",
   423  		"to":         "toc",
   424  		"autocommit": "true",
   425  	})
   426  	vc := &vcursor{}
   427  
   428  	err := lookupNonUnique.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(10)}, {sqltypes.NewInt64(20)}}, []byte("\x16k@\xb4J\xbaK\xd6"))
   429  	require.NoError(t, err)
   430  
   431  	wantqueries := []*querypb.BoundQuery(nil)
   432  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   433  		t.Errorf("lookup.Delete queries:\n%v, want\n%v", vc.queries, wantqueries)
   434  	}
   435  }
   436  
   437  func TestLookupUnicodeLooseMD5HashUpdate(t *testing.T) {
   438  	lookupNonUnique := createLookup(t, "lookup_unicodeloosemd5_hash", false)
   439  	vc := &vcursor{}
   440  
   441  	err := lookupNonUnique.(Lookup).Update(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(10)}, []byte("\x16k@\xb4J\xbaK\xd6"), []sqltypes.Value{sqltypes.NewInt64(20)})
   442  	require.NoError(t, err)
   443  
   444  	wantqueries := []*querypb.BoundQuery{{
   445  		Sql: "delete from t where fromc = :fromc and toc = :toc",
   446  		BindVariables: map[string]*querypb.BindVariable{
   447  			"fromc": sqltypes.Uint64BindVariable(hashed10),
   448  			"toc":   sqltypes.Uint64BindVariable(1),
   449  		},
   450  	}, {
   451  		Sql: "insert into t(fromc, toc) values(:fromc_0, :toc_0)",
   452  		BindVariables: map[string]*querypb.BindVariable{
   453  			"fromc_0": sqltypes.Uint64BindVariable(hashed20),
   454  			"toc_0":   sqltypes.Uint64BindVariable(1),
   455  		},
   456  	}}
   457  	if !reflect.DeepEqual(vc.queries, wantqueries) {
   458  		t.Errorf("lookup.Update queries:\n%v, want\n%v", vc.queries, wantqueries)
   459  	}
   460  }