vitess.io/vitess@v0.16.2/go/vt/vtgate/executor_dml_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 vtgate
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  	"testing"
    24  
    25  	"vitess.io/vitess/go/mysql"
    26  	"vitess.io/vitess/go/sqltypes"
    27  	"vitess.io/vitess/go/test/utils"
    28  	"vitess.io/vitess/go/vt/sqlparser"
    29  	_ "vitess.io/vitess/go/vt/vtgate/vindexes"
    30  	"vitess.io/vitess/go/vt/vttablet/sandboxconn"
    31  
    32  	"github.com/stretchr/testify/assert"
    33  	"github.com/stretchr/testify/require"
    34  
    35  	querypb "vitess.io/vitess/go/vt/proto/query"
    36  	vtgatepb "vitess.io/vitess/go/vt/proto/vtgate"
    37  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    38  )
    39  
    40  func TestUpdateEqual(t *testing.T) {
    41  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
    42  
    43  	logChan := QueryLogger.Subscribe("Test")
    44  	defer QueryLogger.Unsubscribe(logChan)
    45  
    46  	// Update by primary vindex.
    47  	_, err := executorExec(executor, "update user set a=2 where id = 1", nil)
    48  	require.NoError(t, err)
    49  	wantQueries := []*querypb.BoundQuery{{
    50  		Sql:           "update `user` set a = 2 where id = 1",
    51  		BindVariables: map[string]*querypb.BindVariable{},
    52  	}}
    53  	assertQueries(t, sbc1, wantQueries)
    54  	assertQueries(t, sbc2, nil)
    55  	testQueryLog(t, logChan, "TestExecute", "UPDATE", "update user set a=2 where id = 1", 1)
    56  
    57  	sbc1.Queries = nil
    58  	_, err = executorExec(executor, "update user set a=2 where id = 3", nil)
    59  	require.NoError(t, err)
    60  	wantQueries = []*querypb.BoundQuery{{
    61  		Sql:           "update `user` set a = 2 where id = 3",
    62  		BindVariables: map[string]*querypb.BindVariable{},
    63  	}}
    64  	assertQueries(t, sbc2, wantQueries)
    65  	assertQueries(t, sbc1, nil)
    66  
    67  	// Update by secondary vindex.
    68  	sbc1.Queries = nil
    69  	sbc2.Queries = nil
    70  	sbclookup.SetResults([]*sqltypes.Result{{}})
    71  	_, err = executorExec(executor, "update music set a=2 where id = 2", nil)
    72  	require.NoError(t, err)
    73  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewInt64(2)})
    74  	require.NoError(t, err)
    75  	wantQueries = []*querypb.BoundQuery{{
    76  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
    77  		BindVariables: map[string]*querypb.BindVariable{
    78  			"music_id": vars,
    79  		},
    80  	}}
    81  	assertQueries(t, sbclookup, wantQueries)
    82  	assertQueries(t, sbc2, nil)
    83  	assertQueries(t, sbc1, nil)
    84  
    85  	// Update changes lookup vindex values.
    86  	sbc1.Queries = nil
    87  	sbc2.Queries = nil
    88  	sbclookup.Queries = nil
    89  	sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
    90  		sqltypes.MakeTestFields("id|name|lastname|name_lastname_keyspace_id_map", "int64|int32|varchar|int64"),
    91  		"1|1|foo|0",
    92  	),
    93  	})
    94  
    95  	_, err = executorExec(executor, "update user2 set `name`='myname', lastname='mylastname' where id = 1", nil)
    96  	require.NoError(t, err)
    97  	wantQueries = []*querypb.BoundQuery{
    98  		{
    99  			Sql:           "select id, `name`, lastname, `name` = 'myname' and lastname = 'mylastname' from user2 where id = 1 for update",
   100  			BindVariables: map[string]*querypb.BindVariable{},
   101  		},
   102  		{
   103  			Sql:           "update user2 set `name` = 'myname', lastname = 'mylastname' where id = 1",
   104  			BindVariables: map[string]*querypb.BindVariable{},
   105  		},
   106  	}
   107  	assertQueries(t, sbc1, wantQueries)
   108  	assertQueries(t, sbc2, nil)
   109  
   110  	wantQueries = []*querypb.BoundQuery{
   111  		{
   112  			Sql: "delete from name_lastname_keyspace_id_map where `name` = :name and lastname = :lastname and keyspace_id = :keyspace_id",
   113  			BindVariables: map[string]*querypb.BindVariable{
   114  				"lastname":    sqltypes.StringBindVariable("foo"),
   115  				"name":        sqltypes.Int32BindVariable(1),
   116  				"keyspace_id": sqltypes.BytesBindVariable([]byte("\x16k@\xb4J\xbaK\xd6")),
   117  			},
   118  		},
   119  		{
   120  			Sql: "insert into name_lastname_keyspace_id_map(`name`, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0)",
   121  			BindVariables: map[string]*querypb.BindVariable{
   122  				"name_0":        sqltypes.StringBindVariable("myname"),
   123  				"lastname_0":    sqltypes.StringBindVariable("mylastname"),
   124  				"keyspace_id_0": sqltypes.BytesBindVariable([]byte("\x16k@\xb4J\xbaK\xd6")),
   125  			},
   126  		},
   127  	}
   128  
   129  	assertQueries(t, sbclookup, wantQueries)
   130  }
   131  
   132  func TestUpdateFromSubQuery(t *testing.T) {
   133  	executor, sbc1, sbc2, _ := createExecutorEnv()
   134  	executor.pv = querypb.ExecuteOptions_Gen4
   135  	logChan := QueryLogger.Subscribe("Test")
   136  	defer QueryLogger.Unsubscribe(logChan)
   137  
   138  	fields := []*querypb.Field{
   139  		{Name: "count(*)", Type: sqltypes.Int64},
   140  	}
   141  	sbc2.SetResults([]*sqltypes.Result{{
   142  		Fields: fields,
   143  		Rows: [][]sqltypes.Value{{
   144  			sqltypes.NewInt64(4),
   145  		}},
   146  	}})
   147  
   148  	// Update by primary vindex, but first execute subquery
   149  	_, err := executorExec(executor, "update user set a=(select count(*) from user where id = 3) where id = 1", nil)
   150  	require.NoError(t, err)
   151  	wantQueriesSbc1 := []*querypb.BoundQuery{{
   152  		Sql: "update `user` set a = :__sq1 where id = 1",
   153  		BindVariables: map[string]*querypb.BindVariable{
   154  			"__sq1": sqltypes.Int64BindVariable(4),
   155  		},
   156  	}}
   157  	wantQueriesSbc2 := []*querypb.BoundQuery{{
   158  		Sql:           "select count(*) from `user` where id = 3 lock in share mode",
   159  		BindVariables: map[string]*querypb.BindVariable{},
   160  	}}
   161  	assertQueries(t, sbc1, wantQueriesSbc1)
   162  	assertQueries(t, sbc2, wantQueriesSbc2)
   163  	testQueryLog(t, logChan, "TestExecute", "UPDATE", "update user set a=(select count(*) from user where id = 3) where id = 1", 2)
   164  }
   165  
   166  func TestUpdateEqualWithNoVerifyAndWriteOnlyLookupUniqueVindexes(t *testing.T) {
   167  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   168  		sqltypes.MakeTestFields(
   169  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   170  			"int64|int64|int64|int64|int64|int64|int64|int64",
   171  		),
   172  		"1|2|2|2|2|2|1|0",
   173  	)}
   174  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   175  
   176  	_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2", nil)
   177  	require.NoError(t, err)
   178  	wantQueries := []*querypb.BoundQuery{
   179  		{
   180  			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",
   181  			BindVariables: map[string]*querypb.BindVariable{},
   182  		}, {
   183  			Sql:           "update t2_lookup set lu_col = 5 where wo_lu_col = 2",
   184  			BindVariables: map[string]*querypb.BindVariable{},
   185  		}}
   186  
   187  	assertQueries(t, sbc1, wantQueries)
   188  	assertQueries(t, sbc2, wantQueries)
   189  
   190  	bq1 := &querypb.BoundQuery{
   191  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
   192  		BindVariables: map[string]*querypb.BindVariable{
   193  			"keyspace_id": sqltypes.Uint64BindVariable(1),
   194  			"lu_col":      sqltypes.Int64BindVariable(1),
   195  		},
   196  	}
   197  	bq2 := &querypb.BoundQuery{
   198  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   199  		BindVariables: map[string]*querypb.BindVariable{
   200  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   201  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   202  		},
   203  	}
   204  	lookWant := []*querypb.BoundQuery{
   205  		bq1, bq2,
   206  		bq1, bq2,
   207  		bq1, bq2,
   208  		bq1, bq2,
   209  		bq1, bq2,
   210  		bq1, bq2,
   211  		bq1, bq2,
   212  		bq1, bq2,
   213  	}
   214  	assertQueries(t, sbcLookup, lookWant)
   215  }
   216  
   217  func TestUpdateInTransactionLookupDefaultReadLock(t *testing.T) {
   218  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   219  		sqltypes.MakeTestFields(
   220  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   221  			"int64|int64|int64|int64|int64|int64|int64|int64",
   222  		),
   223  		"1|2|2|2|2|2|1|0",
   224  	)}
   225  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   226  
   227  	safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
   228  	_, err := executorExecSession(
   229  		executor,
   230  		"update t2_lookup set lu_col = 5 where nv_lu_col = 2",
   231  		nil,
   232  		safeSession.Session,
   233  	)
   234  
   235  	require.NoError(t, err)
   236  	wantQueries := []*querypb.BoundQuery{
   237  		{
   238  			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",
   239  			BindVariables: map[string]*querypb.BindVariable{},
   240  		}, {
   241  			Sql:           "update t2_lookup set lu_col = 5 where nv_lu_col = 2",
   242  			BindVariables: map[string]*querypb.BindVariable{},
   243  		},
   244  	}
   245  
   246  	assertQueries(t, sbc1, wantQueries)
   247  	assertQueries(t, sbc2, wantQueries)
   248  
   249  	vars, _ := sqltypes.BuildBindVariable([]any{
   250  		sqltypes.NewInt64(2),
   251  	})
   252  	bq1 := &querypb.BoundQuery{
   253  		Sql: "select nv_lu_col, keyspace_id from nv_lu_idx where nv_lu_col in ::nv_lu_col for update",
   254  		BindVariables: map[string]*querypb.BindVariable{
   255  			"nv_lu_col": vars,
   256  		},
   257  	}
   258  	bq2 := &querypb.BoundQuery{
   259  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   260  		BindVariables: map[string]*querypb.BindVariable{
   261  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   262  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   263  		},
   264  	}
   265  	lookWant := []*querypb.BoundQuery{
   266  		bq1, bq2,
   267  		bq1, bq2,
   268  		bq1, bq2,
   269  		bq1, bq2,
   270  		bq1, bq2,
   271  		bq1, bq2,
   272  		bq1, bq2,
   273  		bq1, bq2,
   274  	}
   275  
   276  	assertQueries(t, sbcLookup, lookWant)
   277  }
   278  
   279  func TestUpdateInTransactionLookupExclusiveReadLock(t *testing.T) {
   280  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   281  		sqltypes.MakeTestFields(
   282  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   283  			"int64|int64|int64|int64|int64|int64|int64|int64",
   284  		),
   285  		"1|2|2|2|2|2|1|0",
   286  	)}
   287  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   288  
   289  	safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
   290  	_, err := executorExecSession(
   291  		executor,
   292  		"update t2_lookup set lu_col = 5 where erl_lu_col = 2",
   293  		nil,
   294  		safeSession.Session,
   295  	)
   296  
   297  	require.NoError(t, err)
   298  	wantQueries := []*querypb.BoundQuery{
   299  		{
   300  			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",
   301  			BindVariables: map[string]*querypb.BindVariable{},
   302  		}, {
   303  			Sql:           "update t2_lookup set lu_col = 5 where erl_lu_col = 2",
   304  			BindVariables: map[string]*querypb.BindVariable{},
   305  		},
   306  	}
   307  
   308  	assertQueries(t, sbc1, wantQueries)
   309  	assertQueries(t, sbc2, wantQueries)
   310  
   311  	vars, _ := sqltypes.BuildBindVariable([]any{
   312  		sqltypes.NewInt64(2),
   313  	})
   314  	bq1 := &querypb.BoundQuery{
   315  		Sql: "select erl_lu_col, keyspace_id from erl_lu_idx where erl_lu_col in ::erl_lu_col for update",
   316  		BindVariables: map[string]*querypb.BindVariable{
   317  			"erl_lu_col": vars,
   318  		},
   319  	}
   320  	bq2 := &querypb.BoundQuery{
   321  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   322  		BindVariables: map[string]*querypb.BindVariable{
   323  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   324  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   325  		},
   326  	}
   327  	lookWant := []*querypb.BoundQuery{
   328  		bq1, bq2,
   329  		bq1, bq2,
   330  		bq1, bq2,
   331  		bq1, bq2,
   332  		bq1, bq2,
   333  		bq1, bq2,
   334  		bq1, bq2,
   335  		bq1, bq2,
   336  	}
   337  
   338  	assertQueries(t, sbcLookup, lookWant)
   339  }
   340  
   341  func TestUpdateInTransactionLookupSharedReadLock(t *testing.T) {
   342  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   343  		sqltypes.MakeTestFields(
   344  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   345  			"int64|int64|int64|int64|int64|int64|int64|int64",
   346  		),
   347  		"1|2|2|2|2|2|1|0",
   348  	)}
   349  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   350  
   351  	safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
   352  	_, err := executorExecSession(
   353  		executor,
   354  		"update t2_lookup set lu_col = 5 where srl_lu_col = 2",
   355  		nil,
   356  		safeSession.Session,
   357  	)
   358  
   359  	require.NoError(t, err)
   360  	wantQueries := []*querypb.BoundQuery{
   361  		{
   362  			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",
   363  			BindVariables: map[string]*querypb.BindVariable{},
   364  		}, {
   365  			Sql:           "update t2_lookup set lu_col = 5 where srl_lu_col = 2",
   366  			BindVariables: map[string]*querypb.BindVariable{},
   367  		},
   368  	}
   369  
   370  	assertQueries(t, sbc1, wantQueries)
   371  	assertQueries(t, sbc2, wantQueries)
   372  
   373  	vars, _ := sqltypes.BuildBindVariable([]any{
   374  		sqltypes.NewInt64(2),
   375  	})
   376  	bq1 := &querypb.BoundQuery{
   377  		Sql: "select srl_lu_col, keyspace_id from srl_lu_idx where srl_lu_col in ::srl_lu_col lock in share mode",
   378  		BindVariables: map[string]*querypb.BindVariable{
   379  			"srl_lu_col": vars,
   380  		},
   381  	}
   382  	bq2 := &querypb.BoundQuery{
   383  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   384  		BindVariables: map[string]*querypb.BindVariable{
   385  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   386  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   387  		},
   388  	}
   389  	lookWant := []*querypb.BoundQuery{
   390  		bq1, bq2,
   391  		bq1, bq2,
   392  		bq1, bq2,
   393  		bq1, bq2,
   394  		bq1, bq2,
   395  		bq1, bq2,
   396  		bq1, bq2,
   397  		bq1, bq2,
   398  	}
   399  
   400  	assertQueries(t, sbcLookup, lookWant)
   401  }
   402  
   403  func TestUpdateInTransactionLookupNoReadLock(t *testing.T) {
   404  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   405  		sqltypes.MakeTestFields(
   406  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   407  			"int64|int64|int64|int64|int64|int64|int64|int64",
   408  		),
   409  		"1|2|2|2|2|2|1|0",
   410  	)}
   411  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   412  
   413  	safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
   414  	_, err := executorExecSession(
   415  		executor,
   416  		"update t2_lookup set lu_col = 5 where nrl_lu_col = 2",
   417  		nil,
   418  		safeSession.Session,
   419  	)
   420  
   421  	require.NoError(t, err)
   422  	wantQueries := []*querypb.BoundQuery{
   423  		{
   424  			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",
   425  			BindVariables: map[string]*querypb.BindVariable{},
   426  		}, {
   427  			Sql:           "update t2_lookup set lu_col = 5 where nrl_lu_col = 2",
   428  			BindVariables: map[string]*querypb.BindVariable{},
   429  		},
   430  	}
   431  
   432  	assertQueries(t, sbc1, wantQueries)
   433  	assertQueries(t, sbc2, wantQueries)
   434  
   435  	vars, _ := sqltypes.BuildBindVariable([]any{
   436  		sqltypes.NewInt64(2),
   437  	})
   438  	bq1 := &querypb.BoundQuery{
   439  		Sql: "select nrl_lu_col, keyspace_id from nrl_lu_idx where nrl_lu_col in ::nrl_lu_col",
   440  		BindVariables: map[string]*querypb.BindVariable{
   441  			"nrl_lu_col": vars,
   442  		},
   443  	}
   444  	bq2 := &querypb.BoundQuery{
   445  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   446  		BindVariables: map[string]*querypb.BindVariable{
   447  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   448  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   449  		},
   450  	}
   451  	lookWant := []*querypb.BoundQuery{
   452  		bq1, bq2,
   453  		bq1, bq2,
   454  		bq1, bq2,
   455  		bq1, bq2,
   456  		bq1, bq2,
   457  		bq1, bq2,
   458  		bq1, bq2,
   459  		bq1, bq2,
   460  	}
   461  
   462  	assertQueries(t, sbcLookup, lookWant)
   463  }
   464  
   465  func TestUpdateMultiOwned(t *testing.T) {
   466  	vschema := `
   467  {
   468  	"sharded": true,
   469  	"vindexes": {
   470  		"hash_index": {
   471  			"type": "hash"
   472  		},
   473  		"lookup1": {
   474  			"type": "lookup_hash_unique",
   475  			"owner": "user",
   476  			"params": {
   477  				"table": "music_user_map",
   478  				"from": "from1,from2",
   479  				"to": "user_id"
   480  			}
   481  		},
   482  		"lookup2": {
   483  			"type": "lookup_hash_unique",
   484  			"owner": "user",
   485  			"params": {
   486  				"table": "music_user_map",
   487  				"from": "from1,from2",
   488  				"to": "user_id"
   489  			}
   490  		},
   491  		"lookup3": {
   492  			"type": "lookup_hash_unique",
   493  			"owner": "user",
   494  			"params": {
   495  				"table": "music_user_map",
   496  				"from": "from1,from2",
   497  				"to": "user_id"
   498  			}
   499  		}
   500  	},
   501  	"tables": {
   502  		"user": {
   503  			"column_vindexes": [
   504  				{
   505  					"column": "id",
   506  					"name": "hash_index"
   507  				},
   508  				{
   509  					"columns": ["a", "b"],
   510  					"name": "lookup1"
   511  				},
   512  				{
   513  					"columns": ["c", "d"],
   514  					"name": "lookup2"
   515  				},
   516  				{
   517  					"columns": ["e", "f"],
   518  					"name": "lookup3"
   519  				}
   520  			]
   521  		}
   522  	}
   523  }
   524  `
   525  	executor, sbc1, sbc2, sbclookup := createCustomExecutor(vschema)
   526  
   527  	sbc1.SetResults([]*sqltypes.Result{
   528  		sqltypes.MakeTestResult(
   529  			sqltypes.MakeTestFields("id|a|b|c|d|e|f|lookup1|lookup3", "int64|int64|int64|int64|int64|int64|int64|int64|int64"),
   530  			"1|10|20|30|40|50|60|0|0",
   531  		),
   532  	})
   533  	_, err := executorExec(executor, "update user set a=1, b=2, f=4, e=3 where id=1", nil)
   534  	if err != nil {
   535  		t.Fatal(err)
   536  	}
   537  	wantQueries := []*querypb.BoundQuery{{
   538  		Sql:           "select id, a, b, c, d, e, f, a = 1 and b = 2, e = 3 and f = 4 from `user` where id = 1 for update",
   539  		BindVariables: map[string]*querypb.BindVariable{},
   540  	}, {
   541  		Sql:           "update `user` set a = 1, b = 2, f = 4, e = 3 where id = 1",
   542  		BindVariables: map[string]*querypb.BindVariable{},
   543  	}}
   544  	assertQueries(t, sbc1, wantQueries)
   545  	assertQueries(t, sbc2, nil)
   546  
   547  	wantQueries = []*querypb.BoundQuery{{
   548  		Sql: "delete from music_user_map where from1 = :from1 and from2 = :from2 and user_id = :user_id",
   549  		BindVariables: map[string]*querypb.BindVariable{
   550  			"from1":   sqltypes.Int64BindVariable(10),
   551  			"from2":   sqltypes.Int64BindVariable(20),
   552  			"user_id": sqltypes.Uint64BindVariable(1),
   553  		},
   554  	}, {
   555  		Sql: "insert into music_user_map(from1, from2, user_id) values (:from1_0, :from2_0, :user_id_0)",
   556  		BindVariables: map[string]*querypb.BindVariable{
   557  			"from1_0":   sqltypes.Int64BindVariable(1),
   558  			"from2_0":   sqltypes.Int64BindVariable(2),
   559  			"user_id_0": sqltypes.Uint64BindVariable(1),
   560  		},
   561  	}, {
   562  		Sql: "delete from music_user_map where from1 = :from1 and from2 = :from2 and user_id = :user_id",
   563  		BindVariables: map[string]*querypb.BindVariable{
   564  			"from1":   sqltypes.Int64BindVariable(50),
   565  			"from2":   sqltypes.Int64BindVariable(60),
   566  			"user_id": sqltypes.Uint64BindVariable(1),
   567  		},
   568  	}, {
   569  		Sql: "insert into music_user_map(from1, from2, user_id) values (:from1_0, :from2_0, :user_id_0)",
   570  		BindVariables: map[string]*querypb.BindVariable{
   571  			"from1_0":   sqltypes.Int64BindVariable(3),
   572  			"from2_0":   sqltypes.Int64BindVariable(4),
   573  			"user_id_0": sqltypes.Uint64BindVariable(1),
   574  		},
   575  	}}
   576  
   577  	assertQueries(t, sbclookup, wantQueries)
   578  }
   579  
   580  func TestUpdateComments(t *testing.T) {
   581  	executor, sbc1, sbc2, _ := createExecutorEnv()
   582  
   583  	_, err := executorExec(executor, "update user set a=2 where id = 1 /* trailing */", nil)
   584  	require.NoError(t, err)
   585  	wantQueries := []*querypb.BoundQuery{{
   586  		Sql:           "update `user` set a = 2 where id = 1 /* trailing */",
   587  		BindVariables: map[string]*querypb.BindVariable{},
   588  	}}
   589  	assertQueries(t, sbc1, wantQueries)
   590  	assertQueries(t, sbc2, nil)
   591  }
   592  
   593  func TestUpdateNormalize(t *testing.T) {
   594  	executor, sbc1, sbc2, _ := createExecutorEnv()
   595  
   596  	executor.normalize = true
   597  	_, err := executorExec(executor, "/* leading */ update user set a=2 where id = 1 /* trailing */", nil)
   598  	require.NoError(t, err)
   599  	wantQueries := []*querypb.BoundQuery{{
   600  		Sql: "/* leading */ update `user` set a = :a where id = :id /* trailing */",
   601  		BindVariables: map[string]*querypb.BindVariable{
   602  			"a":  sqltypes.TestBindVariable(int64(2)),
   603  			"id": sqltypes.TestBindVariable(int64(1)),
   604  		},
   605  	}}
   606  	assertQueries(t, sbc1, wantQueries)
   607  	assertQueries(t, sbc2, nil)
   608  	sbc1.Queries = nil
   609  
   610  	// Force the query to go to the "wrong" shard and ensure that normalization still happens
   611  	primarySession.TargetString = "TestExecutor/40-60"
   612  	_, err = executorExec(executor, "/* leading */ update user set a=2 where id = 1 /* trailing */", nil)
   613  	require.NoError(t, err)
   614  	wantQueries = []*querypb.BoundQuery{{
   615  		Sql: "/* leading */ update `user` set a = :a where id = :id /* trailing */",
   616  		BindVariables: map[string]*querypb.BindVariable{
   617  			"a":  sqltypes.TestBindVariable(int64(2)),
   618  			"id": sqltypes.TestBindVariable(int64(1)),
   619  		},
   620  	}}
   621  	assertQueries(t, sbc1, nil)
   622  	assertQueries(t, sbc2, wantQueries)
   623  	sbc2.Queries = nil
   624  	primarySession.TargetString = ""
   625  }
   626  
   627  func TestDeleteEqual(t *testing.T) {
   628  	executor, sbc, _, sbclookup := createExecutorEnv()
   629  
   630  	sbc.SetResults([]*sqltypes.Result{{
   631  		Fields: []*querypb.Field{
   632  			{Name: "Id", Type: sqltypes.Int64},
   633  			{Name: "name", Type: sqltypes.VarChar},
   634  		},
   635  		RowsAffected: 1,
   636  		InsertID:     0,
   637  		Rows: [][]sqltypes.Value{{
   638  			sqltypes.NewInt64(1),
   639  			sqltypes.NewVarChar("myname"),
   640  		}},
   641  	}})
   642  	_, err := executorExec(executor, "delete from user where id = 1", nil)
   643  	require.NoError(t, err)
   644  	wantQueries := []*querypb.BoundQuery{{
   645  		Sql:           "select Id, `name` from `user` where id = 1 for update",
   646  		BindVariables: map[string]*querypb.BindVariable{},
   647  	}, {
   648  		Sql:           "delete from `user` where id = 1",
   649  		BindVariables: map[string]*querypb.BindVariable{},
   650  	}}
   651  	assertQueries(t, sbc, wantQueries)
   652  
   653  	wantQueries = []*querypb.BoundQuery{{
   654  		Sql: "delete from name_user_map where `name` = :name and user_id = :user_id",
   655  		BindVariables: map[string]*querypb.BindVariable{
   656  			"user_id": sqltypes.Uint64BindVariable(1),
   657  			"name":    sqltypes.ValueBindVariable(sqltypes.NewVarChar("myname")),
   658  		},
   659  	}}
   660  	assertQueries(t, sbclookup, wantQueries)
   661  
   662  	sbc.Queries = nil
   663  	sbclookup.Queries = nil
   664  	sbc.SetResults([]*sqltypes.Result{{}})
   665  	_, err = executorExec(executor, "delete from user where id = 1", nil)
   666  	require.NoError(t, err)
   667  	wantQueries = []*querypb.BoundQuery{{
   668  		Sql:           "select Id, `name` from `user` where id = 1 for update",
   669  		BindVariables: map[string]*querypb.BindVariable{},
   670  	}, {
   671  		Sql:           "delete from `user` where id = 1",
   672  		BindVariables: map[string]*querypb.BindVariable{},
   673  	}}
   674  	assertQueries(t, sbc, wantQueries)
   675  	assertQueries(t, sbclookup, nil)
   676  
   677  	sbc.Queries = nil
   678  	sbclookup.Queries = nil
   679  	sbclookup.SetResults([]*sqltypes.Result{{}})
   680  	_, err = executorExec(executor, "delete from music where id = 1", nil)
   681  	require.NoError(t, err)
   682  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewInt64(1)})
   683  	require.NoError(t, err)
   684  	wantQueries = []*querypb.BoundQuery{{
   685  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
   686  		BindVariables: map[string]*querypb.BindVariable{
   687  			"music_id": vars,
   688  		},
   689  	}}
   690  	assertQueries(t, sbclookup, wantQueries)
   691  	assertQueries(t, sbc, nil)
   692  
   693  	sbc.Queries = nil
   694  	sbclookup.Queries = nil
   695  	sbclookup.SetResults([]*sqltypes.Result{{}})
   696  	_, err = executorExec(executor, "delete from user_extra where user_id = 1", nil)
   697  	require.NoError(t, err)
   698  	wantQueries = []*querypb.BoundQuery{{
   699  		Sql:           "delete from user_extra where user_id = 1",
   700  		BindVariables: map[string]*querypb.BindVariable{},
   701  	}}
   702  	assertQueries(t, sbc, wantQueries)
   703  	assertQueries(t, sbclookup, nil)
   704  
   705  	sbc.Queries = nil
   706  	sbclookup.Queries = nil
   707  	sbc.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   708  		sqltypes.MakeTestFields("id|name|lastname", "int64|int32|varchar"),
   709  		"1|1|foo",
   710  	),
   711  	})
   712  	_, err = executorExec(executor, "delete from user2 where id = 1", nil)
   713  	require.NoError(t, err)
   714  	wantQueries = []*querypb.BoundQuery{
   715  		{
   716  			Sql:           "select id, `name`, lastname from user2 where id = 1 for update",
   717  			BindVariables: map[string]*querypb.BindVariable{},
   718  		},
   719  		{
   720  			Sql:           "delete from user2 where id = 1",
   721  			BindVariables: map[string]*querypb.BindVariable{},
   722  		},
   723  	}
   724  	assertQueries(t, sbc, wantQueries)
   725  
   726  	wantQueries = []*querypb.BoundQuery{
   727  		{
   728  			Sql: "delete from name_lastname_keyspace_id_map where `name` = :name and lastname = :lastname and keyspace_id = :keyspace_id",
   729  			BindVariables: map[string]*querypb.BindVariable{
   730  				"lastname":    sqltypes.ValueBindVariable(sqltypes.NewVarChar("foo")),
   731  				"name":        sqltypes.Int32BindVariable(1),
   732  				"keyspace_id": sqltypes.BytesBindVariable([]byte("\x16k@\xb4J\xbaK\xd6")),
   733  			},
   734  		},
   735  	}
   736  
   737  	assertQueries(t, sbclookup, wantQueries)
   738  }
   739  
   740  func TestUpdateScatter(t *testing.T) {
   741  	executor, sbc1, sbc2, _ := createExecutorEnv()
   742  	_, err := executorExec(executor, "update user_extra set col = 2", nil)
   743  	require.NoError(t, err)
   744  	// Queries get annotatted.
   745  	wantQueries := []*querypb.BoundQuery{{
   746  		Sql:           "update user_extra set col = 2",
   747  		BindVariables: map[string]*querypb.BindVariable{},
   748  	}}
   749  	assertQueries(t, sbc1, wantQueries)
   750  	assertQueries(t, sbc2, wantQueries)
   751  }
   752  
   753  func TestDeleteScatter(t *testing.T) {
   754  	executor, sbc1, sbc2, _ := createExecutorEnv()
   755  	_, err := executorExec(executor, "delete from user_extra", nil)
   756  	require.NoError(t, err)
   757  	// Queries get annotatted.
   758  	wantQueries := []*querypb.BoundQuery{{
   759  		Sql:           "delete from user_extra",
   760  		BindVariables: map[string]*querypb.BindVariable{},
   761  	}}
   762  	assertQueries(t, sbc1, wantQueries)
   763  	assertQueries(t, sbc2, wantQueries)
   764  }
   765  
   766  func TestUpdateEqualWithMultipleLookupVindex(t *testing.T) {
   767  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, nil)
   768  
   769  	sbcLookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   770  		sqltypes.MakeTestFields("lu_col|keyspace_id", "int64|varbinary"),
   771  		"1|1",
   772  	)})
   773  
   774  	sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   775  		sqltypes.MakeTestFields(
   776  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   777  			"int64|int64|int64|int64|int64|int64|int64|int64",
   778  		),
   779  		"1|2|2|2|2|2|1|0",
   780  	)})
   781  
   782  	_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1", nil)
   783  	require.NoError(t, err)
   784  	wantQueries := []*querypb.BoundQuery{
   785  		{
   786  			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",
   787  			BindVariables: map[string]*querypb.BindVariable{},
   788  		}, {
   789  			Sql:           "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col = 1",
   790  			BindVariables: map[string]*querypb.BindVariable{},
   791  		}}
   792  
   793  	vars, _ := sqltypes.BuildBindVariable([]any{
   794  		sqltypes.NewInt64(1),
   795  	})
   796  	lookWant := []*querypb.BoundQuery{{
   797  		Sql: "select lu_col, keyspace_id from lu_idx where lu_col in ::lu_col for update",
   798  		BindVariables: map[string]*querypb.BindVariable{
   799  			"lu_col": vars,
   800  		},
   801  	}, {
   802  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
   803  		BindVariables: map[string]*querypb.BindVariable{
   804  			"keyspace_id": sqltypes.Uint64BindVariable(1),
   805  			"lu_col":      sqltypes.Int64BindVariable(1),
   806  		},
   807  	}, {
   808  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   809  		BindVariables: map[string]*querypb.BindVariable{
   810  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   811  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   812  		},
   813  	}}
   814  	assertQueries(t, sbcLookup, lookWant)
   815  	assertQueries(t, sbc1, wantQueries)
   816  	assertQueries(t, sbc2, nil)
   817  }
   818  
   819  func TestUpdateUseHigherCostVindexIfBackfilling(t *testing.T) {
   820  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, nil)
   821  
   822  	sbcLookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   823  		sqltypes.MakeTestFields("lu_col|keyspace_id", "int64|varbinary"),
   824  		"1|1",
   825  		"2|1",
   826  	)})
   827  
   828  	sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   829  		sqltypes.MakeTestFields(
   830  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col|t2_lu_vdx",
   831  			"int64|int64|int64|int64|int64|int64|int64|int64",
   832  		),
   833  		"1|2|2|2|2|2|1|0",
   834  		"1|2|2|2|2|2|2|0",
   835  	)})
   836  
   837  	_, err := executorExec(executor, "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)", nil)
   838  	require.NoError(t, err)
   839  	wantQueries := []*querypb.BoundQuery{
   840  		{
   841  			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",
   842  			BindVariables: map[string]*querypb.BindVariable{},
   843  		}, {
   844  			Sql:           "update t2_lookup set lu_col = 5 where wo_lu_col = 2 and lu_col in (1, 2)",
   845  			BindVariables: map[string]*querypb.BindVariable{},
   846  		}}
   847  
   848  	vars, _ := sqltypes.BuildBindVariable([]any{
   849  		sqltypes.NewInt64(1),
   850  		sqltypes.NewInt64(2),
   851  	})
   852  	lookWant := []*querypb.BoundQuery{{
   853  		Sql: "select lu_col, keyspace_id from lu_idx where lu_col in ::lu_col for update",
   854  		BindVariables: map[string]*querypb.BindVariable{
   855  			"lu_col": vars,
   856  		},
   857  	}, {
   858  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
   859  		BindVariables: map[string]*querypb.BindVariable{
   860  			"keyspace_id": sqltypes.Uint64BindVariable(1),
   861  			"lu_col":      sqltypes.Int64BindVariable(1),
   862  		},
   863  	}, {
   864  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   865  		BindVariables: map[string]*querypb.BindVariable{
   866  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   867  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   868  		},
   869  	}, {
   870  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
   871  		BindVariables: map[string]*querypb.BindVariable{
   872  			"keyspace_id": sqltypes.Uint64BindVariable(1),
   873  			"lu_col":      sqltypes.Int64BindVariable(2),
   874  		},
   875  	}, {
   876  		Sql: "insert into lu_idx(lu_col, keyspace_id) values (:lu_col_0, :keyspace_id_0)",
   877  		BindVariables: map[string]*querypb.BindVariable{
   878  			"keyspace_id_0": sqltypes.Uint64BindVariable(1),
   879  			"lu_col_0":      sqltypes.Int64BindVariable(5),
   880  		},
   881  	}}
   882  	assertQueries(t, sbcLookup, lookWant)
   883  	assertQueries(t, sbc1, wantQueries)
   884  	assertQueries(t, sbc2, nil)
   885  }
   886  
   887  func TestDeleteEqualWithNoVerifyAndWriteOnlyLookupUniqueVindex(t *testing.T) {
   888  	res := []*sqltypes.Result{sqltypes.MakeTestResult(
   889  		sqltypes.MakeTestFields(
   890  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
   891  			"int64|int64|int64|int64|int64|int64|int64",
   892  		),
   893  		"1|1|1|1|1|1|1",
   894  	)}
   895  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, res)
   896  
   897  	_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1", nil)
   898  	require.NoError(t, err)
   899  	wantQueries := []*querypb.BoundQuery{
   900  		{
   901  			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",
   902  			BindVariables: map[string]*querypb.BindVariable{},
   903  		}, {
   904  			Sql:           "delete from t2_lookup where wo_lu_col = 1",
   905  			BindVariables: map[string]*querypb.BindVariable{},
   906  		}}
   907  
   908  	bq1 := &querypb.BoundQuery{
   909  		Sql: "delete from wo_lu_idx where wo_lu_col = :wo_lu_col and keyspace_id = :keyspace_id",
   910  		BindVariables: map[string]*querypb.BindVariable{
   911  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
   912  			"wo_lu_col":   sqltypes.Int64BindVariable(1),
   913  		},
   914  	}
   915  	bq2 := &querypb.BoundQuery{
   916  		Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
   917  		BindVariables: map[string]*querypb.BindVariable{
   918  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
   919  			"erl_lu_col":  sqltypes.Int64BindVariable(1),
   920  		},
   921  	}
   922  	bq3 := &querypb.BoundQuery{
   923  		Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
   924  		BindVariables: map[string]*querypb.BindVariable{
   925  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
   926  			"srl_lu_col":  sqltypes.Int64BindVariable(1),
   927  		},
   928  	}
   929  	bq4 := &querypb.BoundQuery{
   930  		Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
   931  		BindVariables: map[string]*querypb.BindVariable{
   932  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
   933  			"nrl_lu_col":  sqltypes.Int64BindVariable(1),
   934  		},
   935  	}
   936  	bq5 := &querypb.BoundQuery{
   937  		Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
   938  		BindVariables: map[string]*querypb.BindVariable{
   939  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
   940  			"nv_lu_col":   sqltypes.Int64BindVariable(1),
   941  		},
   942  	}
   943  	bq6 := &querypb.BoundQuery{
   944  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
   945  		BindVariables: map[string]*querypb.BindVariable{
   946  			"keyspace_id": sqltypes.Uint64BindVariable(1),
   947  			"lu_col":      sqltypes.Int64BindVariable(1),
   948  		},
   949  	}
   950  	lookWant := []*querypb.BoundQuery{
   951  		bq1, bq2, bq3, bq4, bq5, bq6,
   952  		bq1, bq2, bq3, bq4, bq5, bq6,
   953  		bq1, bq2, bq3, bq4, bq5, bq6,
   954  		bq1, bq2, bq3, bq4, bq5, bq6,
   955  		bq1, bq2, bq3, bq4, bq5, bq6,
   956  		bq1, bq2, bq3, bq4, bq5, bq6,
   957  		bq1, bq2, bq3, bq4, bq5, bq6,
   958  		bq1, bq2, bq3, bq4, bq5, bq6,
   959  	}
   960  	assertQueries(t, sbcLookup, lookWant)
   961  	assertQueries(t, sbc1, wantQueries)
   962  	assertQueries(t, sbc2, wantQueries)
   963  }
   964  
   965  func TestDeleteEqualWithMultipleLookupVindex(t *testing.T) {
   966  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, nil)
   967  
   968  	sbcLookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   969  		sqltypes.MakeTestFields("lu_col|keyspace_id", "int64|varbinary"),
   970  		"1|1",
   971  	)})
   972  
   973  	sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
   974  		sqltypes.MakeTestFields(
   975  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
   976  			"int64|int64|int64|int64|int64|int64|int64",
   977  		),
   978  		"1|1|1|1|1|1|1",
   979  	)})
   980  
   981  	_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1 and lu_col = 1", nil)
   982  	require.NoError(t, err)
   983  	wantQueries := []*querypb.BoundQuery{
   984  		{
   985  			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",
   986  			BindVariables: map[string]*querypb.BindVariable{},
   987  		}, {
   988  			Sql:           "delete from t2_lookup where wo_lu_col = 1 and lu_col = 1",
   989  			BindVariables: map[string]*querypb.BindVariable{},
   990  		}}
   991  
   992  	vars, _ := sqltypes.BuildBindVariable([]any{
   993  		sqltypes.NewInt64(1),
   994  	})
   995  	lookWant := []*querypb.BoundQuery{{
   996  		Sql: "select lu_col, keyspace_id from lu_idx where lu_col in ::lu_col for update",
   997  		BindVariables: map[string]*querypb.BindVariable{
   998  			"lu_col": vars,
   999  		},
  1000  	}, {
  1001  		Sql: "delete from wo_lu_idx where wo_lu_col = :wo_lu_col and keyspace_id = :keyspace_id",
  1002  		BindVariables: map[string]*querypb.BindVariable{
  1003  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1004  			"wo_lu_col":   sqltypes.Int64BindVariable(1),
  1005  		},
  1006  	}, {
  1007  		Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
  1008  		BindVariables: map[string]*querypb.BindVariable{
  1009  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1010  			"erl_lu_col":  sqltypes.Int64BindVariable(1),
  1011  		},
  1012  	}, {
  1013  		Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
  1014  		BindVariables: map[string]*querypb.BindVariable{
  1015  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1016  			"srl_lu_col":  sqltypes.Int64BindVariable(1),
  1017  		},
  1018  	}, {
  1019  		Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
  1020  		BindVariables: map[string]*querypb.BindVariable{
  1021  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1022  			"nrl_lu_col":  sqltypes.Int64BindVariable(1),
  1023  		},
  1024  	}, {
  1025  		Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
  1026  		BindVariables: map[string]*querypb.BindVariable{
  1027  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1028  			"nv_lu_col":   sqltypes.Int64BindVariable(1),
  1029  		},
  1030  	}, {
  1031  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
  1032  		BindVariables: map[string]*querypb.BindVariable{
  1033  			"keyspace_id": sqltypes.Uint64BindVariable(1),
  1034  			"lu_col":      {Type: querypb.Type_INT64, Value: []byte("1")},
  1035  		},
  1036  	}}
  1037  	assertQueries(t, sbcLookup, lookWant)
  1038  
  1039  	assertQueries(t, sbc1, wantQueries)
  1040  	assertQueries(t, sbc2, nil)
  1041  }
  1042  
  1043  func TestDeleteUseHigherCostVindexIfBackfilling(t *testing.T) {
  1044  	executor, sbc1, sbc2, sbcLookup := createCustomExecutorSetValues(executorVSchema, nil)
  1045  
  1046  	sbcLookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
  1047  		sqltypes.MakeTestFields("lu_col|keyspace_id", "int64|varbinary"),
  1048  		"1|1",
  1049  		"2|1",
  1050  	)})
  1051  
  1052  	sbc1.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
  1053  		sqltypes.MakeTestFields(
  1054  			"id|wo_lu_col|erl_lu_col|srl_lu_col|nrl_lu_col|nv_lu_col|lu_col",
  1055  			"int64|int64|int64|int64|int64|int64|int64",
  1056  		),
  1057  		"1|1|1|1|1|1|1",
  1058  		"1|1|1|1|1|1|2",
  1059  	)})
  1060  
  1061  	_, err := executorExec(executor, "delete from t2_lookup where wo_lu_col = 1 and lu_col in (1, 2)", nil)
  1062  	require.NoError(t, err)
  1063  	wantQueries := []*querypb.BoundQuery{
  1064  		{
  1065  			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",
  1066  			BindVariables: map[string]*querypb.BindVariable{},
  1067  		}, {
  1068  			Sql:           "delete from t2_lookup where wo_lu_col = 1 and lu_col in (1, 2)",
  1069  			BindVariables: map[string]*querypb.BindVariable{},
  1070  		}}
  1071  
  1072  	vars, _ := sqltypes.BuildBindVariable([]any{
  1073  		sqltypes.NewInt64(1),
  1074  		sqltypes.NewInt64(2),
  1075  	})
  1076  	lookWant := []*querypb.BoundQuery{{
  1077  		Sql: "select lu_col, keyspace_id from lu_idx where lu_col in ::lu_col for update",
  1078  		BindVariables: map[string]*querypb.BindVariable{
  1079  			"lu_col": vars,
  1080  		},
  1081  	}, {
  1082  		Sql: "delete from wo_lu_idx where wo_lu_col = :wo_lu_col and keyspace_id = :keyspace_id",
  1083  		BindVariables: map[string]*querypb.BindVariable{
  1084  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1085  			"wo_lu_col":   sqltypes.Int64BindVariable(1),
  1086  		},
  1087  	}, {
  1088  		Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
  1089  		BindVariables: map[string]*querypb.BindVariable{
  1090  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1091  			"erl_lu_col":  sqltypes.Int64BindVariable(1),
  1092  		},
  1093  	}, {
  1094  		Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
  1095  		BindVariables: map[string]*querypb.BindVariable{
  1096  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1097  			"srl_lu_col":  sqltypes.Int64BindVariable(1),
  1098  		},
  1099  	}, {
  1100  		Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
  1101  		BindVariables: map[string]*querypb.BindVariable{
  1102  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1103  			"nrl_lu_col":  sqltypes.Int64BindVariable(1),
  1104  		},
  1105  	}, {
  1106  		Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
  1107  		BindVariables: map[string]*querypb.BindVariable{
  1108  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1109  			"nv_lu_col":   sqltypes.Int64BindVariable(1),
  1110  		},
  1111  	}, {
  1112  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
  1113  		BindVariables: map[string]*querypb.BindVariable{
  1114  			"keyspace_id": sqltypes.Uint64BindVariable(1),
  1115  			"lu_col":      sqltypes.Int64BindVariable(1),
  1116  		},
  1117  	}, {
  1118  		Sql: "delete from wo_lu_idx where wo_lu_col = :wo_lu_col and keyspace_id = :keyspace_id",
  1119  		BindVariables: map[string]*querypb.BindVariable{
  1120  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1121  			"wo_lu_col":   sqltypes.Int64BindVariable(1),
  1122  		},
  1123  	}, {
  1124  		Sql: "delete from erl_lu_idx where erl_lu_col = :erl_lu_col and keyspace_id = :keyspace_id",
  1125  		BindVariables: map[string]*querypb.BindVariable{
  1126  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1127  			"erl_lu_col":  sqltypes.Int64BindVariable(1),
  1128  		},
  1129  	}, {
  1130  		Sql: "delete from srl_lu_idx where srl_lu_col = :srl_lu_col and keyspace_id = :keyspace_id",
  1131  		BindVariables: map[string]*querypb.BindVariable{
  1132  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1133  			"srl_lu_col":  sqltypes.Int64BindVariable(1),
  1134  		},
  1135  	}, {
  1136  		Sql: "delete from nrl_lu_idx where nrl_lu_col = :nrl_lu_col and keyspace_id = :keyspace_id",
  1137  		BindVariables: map[string]*querypb.BindVariable{
  1138  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1139  			"nrl_lu_col":  sqltypes.Int64BindVariable(1),
  1140  		},
  1141  	}, {
  1142  		Sql: "delete from nv_lu_idx where nv_lu_col = :nv_lu_col and keyspace_id = :keyspace_id",
  1143  		BindVariables: map[string]*querypb.BindVariable{
  1144  			"keyspace_id": {Type: querypb.Type_VARBINARY, Value: []byte("\x16k@\xb4J\xbaK\xd6")},
  1145  			"nv_lu_col":   sqltypes.Int64BindVariable(1),
  1146  		},
  1147  	}, {
  1148  		Sql: "delete from lu_idx where lu_col = :lu_col and keyspace_id = :keyspace_id",
  1149  		BindVariables: map[string]*querypb.BindVariable{
  1150  			"keyspace_id": sqltypes.Uint64BindVariable(1),
  1151  			"lu_col":      sqltypes.Int64BindVariable(2),
  1152  		},
  1153  	}}
  1154  	assertQueries(t, sbcLookup, lookWant)
  1155  
  1156  	assertQueries(t, sbc1, wantQueries)
  1157  	assertQueries(t, sbc2, nil)
  1158  }
  1159  
  1160  func TestDeleteByDestination(t *testing.T) {
  1161  	executor, sbc1, sbc2, _ := createExecutorEnv()
  1162  	// This query is not supported in v3, so we know for sure is taking the DeleteByDestination route
  1163  	_, err := executorExec(executor, "delete from `TestExecutor[-]`.user_extra limit 10", nil)
  1164  	require.NoError(t, err)
  1165  	// Queries get annotatted.
  1166  	wantQueries := []*querypb.BoundQuery{{
  1167  		Sql:           "delete from user_extra limit 10",
  1168  		BindVariables: map[string]*querypb.BindVariable{},
  1169  	}}
  1170  	assertQueries(t, sbc1, wantQueries)
  1171  	assertQueries(t, sbc2, wantQueries)
  1172  }
  1173  
  1174  func TestDeleteComments(t *testing.T) {
  1175  	executor, sbc, _, sbclookup := createExecutorEnv()
  1176  
  1177  	sbc.SetResults([]*sqltypes.Result{{
  1178  		Fields: []*querypb.Field{
  1179  			{Name: "Id", Type: sqltypes.Int64},
  1180  			{Name: "name", Type: sqltypes.VarChar},
  1181  		},
  1182  		RowsAffected: 1,
  1183  		InsertID:     0,
  1184  		Rows: [][]sqltypes.Value{{
  1185  			sqltypes.NewInt64(1),
  1186  			sqltypes.NewVarChar("myname"),
  1187  		}},
  1188  	}})
  1189  	_, err := executorExec(executor, "delete from user where id = 1 /* trailing */", nil)
  1190  	require.NoError(t, err)
  1191  	wantQueries := []*querypb.BoundQuery{{
  1192  		Sql:           "select Id, `name` from `user` where id = 1 for update /* trailing */",
  1193  		BindVariables: map[string]*querypb.BindVariable{},
  1194  	}, {
  1195  		Sql:           "delete from `user` where id = 1 /* trailing */",
  1196  		BindVariables: map[string]*querypb.BindVariable{},
  1197  	}}
  1198  	assertQueries(t, sbc, wantQueries)
  1199  
  1200  	wantQueries = []*querypb.BoundQuery{{
  1201  		Sql: "delete from name_user_map where `name` = :name and user_id = :user_id /* trailing */",
  1202  		BindVariables: map[string]*querypb.BindVariable{
  1203  			"user_id": sqltypes.Uint64BindVariable(1),
  1204  			"name":    sqltypes.ValueBindVariable(sqltypes.NewVarChar("myname")),
  1205  		},
  1206  	}}
  1207  	assertQueries(t, sbclookup, wantQueries)
  1208  }
  1209  
  1210  func TestInsertSharded(t *testing.T) {
  1211  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  1212  
  1213  	logChan := QueryLogger.Subscribe("Test")
  1214  	defer QueryLogger.Unsubscribe(logChan)
  1215  
  1216  	_, err := executorExec(executor, "insert into user(id, v, name) values (1, 2, 'myname')", nil)
  1217  	require.NoError(t, err)
  1218  	wantQueries := []*querypb.BoundQuery{{
  1219  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 2, :_name_0)",
  1220  		BindVariables: map[string]*querypb.BindVariable{
  1221  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1222  			"_name_0": sqltypes.StringBindVariable("myname"),
  1223  			"__seq0":  sqltypes.Int64BindVariable(1),
  1224  		},
  1225  	}}
  1226  	assertQueries(t, sbc1, wantQueries)
  1227  	assertQueries(t, sbc2, nil)
  1228  	wantQueries = []*querypb.BoundQuery{{
  1229  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)",
  1230  		BindVariables: map[string]*querypb.BindVariable{
  1231  			"name_0":    sqltypes.StringBindVariable("myname"),
  1232  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1233  		},
  1234  	}}
  1235  	assertQueries(t, sbclookup, wantQueries)
  1236  
  1237  	testQueryLog(t, logChan, "MarkSavepoint", "SAVEPOINT", "savepoint x", 0)
  1238  	testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_user_map(name, user_id) values(:name_0, :user_id_0)", 1)
  1239  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into user(id, v, name) values (1, 2, 'myname')", 1)
  1240  
  1241  	sbc1.Queries = nil
  1242  	sbclookup.Queries = nil
  1243  	_, err = executorExec(executor, "insert into user(id, v, name) values (3, 2, 'myname2')", nil)
  1244  	require.NoError(t, err)
  1245  	wantQueries = []*querypb.BoundQuery{{
  1246  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 2, :_name_0)",
  1247  		BindVariables: map[string]*querypb.BindVariable{
  1248  			"_Id_0":   sqltypes.Int64BindVariable(3),
  1249  			"__seq0":  sqltypes.Int64BindVariable(3),
  1250  			"_name_0": sqltypes.StringBindVariable("myname2"),
  1251  		},
  1252  	}}
  1253  	assertQueries(t, sbc2, wantQueries)
  1254  	assertQueries(t, sbc1, nil)
  1255  	wantQueries = []*querypb.BoundQuery{{
  1256  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)",
  1257  		BindVariables: map[string]*querypb.BindVariable{
  1258  			"name_0":    sqltypes.StringBindVariable("myname2"),
  1259  			"user_id_0": sqltypes.Uint64BindVariable(3),
  1260  		},
  1261  	}}
  1262  	assertQueries(t, sbclookup, wantQueries)
  1263  	testQueryLog(t, logChan, "MarkSavepoint", "SAVEPOINT", "savepoint x", 2)
  1264  	testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_user_map(name, user_id) values(:name_0, :user_id_0)", 1)
  1265  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into user(id, v, name) values (3, 2, 'myname2')", 1)
  1266  
  1267  	sbc1.Queries = nil
  1268  	_, err = executorExec(executor, "insert into user2(id, name, lastname) values (2, 'myname', 'mylastname')", nil)
  1269  	require.NoError(t, err)
  1270  	wantQueries = []*querypb.BoundQuery{{
  1271  		Sql: "insert into user2(id, `name`, lastname) values (:_id_0, :_name_0, :_lastname_0)",
  1272  		BindVariables: map[string]*querypb.BindVariable{
  1273  			"_id_0":       sqltypes.Int64BindVariable(2),
  1274  			"_name_0":     sqltypes.StringBindVariable("myname"),
  1275  			"_lastname_0": sqltypes.StringBindVariable("mylastname"),
  1276  		},
  1277  	}}
  1278  	assertQueries(t, sbc1, wantQueries)
  1279  	testQueryLog(t, logChan, "MarkSavepoint", "SAVEPOINT", "savepoint x", 3)
  1280  	testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_lastname_keyspace_id_map(name, lastname, keyspace_id) values(:name_0, :lastname_0, :keyspace_id_0)", 1)
  1281  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into user2(id, name, lastname) values (2, 'myname', 'mylastname')", 1)
  1282  
  1283  	// insert with binary values
  1284  	executor.normalize = true
  1285  	sbc1.Queries = nil
  1286  	sbc2.Queries = nil
  1287  	sbclookup.Queries = nil
  1288  	_, err = executorExec(executor, "insert into user(id, v, name) values (1, 2, _binary 'myname')", nil)
  1289  	require.NoError(t, err)
  1290  	wantQueries = []*querypb.BoundQuery{{
  1291  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, :vtg2, :_name_0)",
  1292  		BindVariables: map[string]*querypb.BindVariable{
  1293  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1294  			"_name_0": sqltypes.BytesBindVariable([]byte("myname")),
  1295  			"__seq0":  sqltypes.Int64BindVariable(1),
  1296  			"vtg1":    sqltypes.Int64BindVariable(1),
  1297  			"vtg2":    sqltypes.Int64BindVariable(2),
  1298  			"vtg3":    sqltypes.StringBindVariable("myname"),
  1299  		},
  1300  	}}
  1301  	assertQueries(t, sbc1, wantQueries)
  1302  	assertQueries(t, sbc2, nil)
  1303  	wantQueries = []*querypb.BoundQuery{{
  1304  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)",
  1305  		BindVariables: map[string]*querypb.BindVariable{
  1306  			"name_0":    sqltypes.BytesBindVariable([]byte("myname")),
  1307  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1308  		},
  1309  	}}
  1310  	assertQueries(t, sbclookup, wantQueries)
  1311  
  1312  	testQueryLog(t, logChan, "MarkSavepoint", "SAVEPOINT", "savepoint x", 3)
  1313  	testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)", 1)
  1314  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into `user`(id, v, `name`) values (:vtg1, :vtg2, _binary :vtg3)", 1)
  1315  }
  1316  
  1317  func TestInsertShardedKeyrange(t *testing.T) {
  1318  	executor, _, _, _ := createExecutorEnv()
  1319  
  1320  	// If a unique vindex returns a keyrange, we fail the insert
  1321  	_, err := executorExec(executor, "insert into keyrange_table(krcol_unique, krcol) values(1, 1)", nil)
  1322  	require.EqualError(t, err, "could not map [INT64(1)] to a unique keyspace id: DestinationKeyRange(-10)")
  1323  }
  1324  
  1325  func TestInsertShardedAutocommitLookup(t *testing.T) {
  1326  
  1327  	vschema := `
  1328  {
  1329  	"sharded": true,
  1330  	"vindexes": {
  1331  		"hash_index": {
  1332  			"type": "hash"
  1333  		},
  1334  		"name_user_map": {
  1335  			"type": "lookup_hash",
  1336  			"owner": "user",
  1337  			"params": {
  1338  				"table": "name_user_map",
  1339  				"from": "name",
  1340  				"to": "user_id",
  1341  				"autocommit": "true"
  1342  			}
  1343  		},
  1344  		"music_user_map": {
  1345  			"type": "lookup_hash",
  1346  			"owner": "user",
  1347  			"params": {
  1348  				"table": "music_user_map",
  1349  				"from": "music",
  1350  				"to": "user_id",
  1351  				"multi_shard_autocommit": "true"
  1352  			}
  1353  		}
  1354  	},
  1355  	"tables": {
  1356  		"user": {
  1357  			"column_vindexes": [
  1358  				{
  1359  					"column": "Id",
  1360  					"name": "hash_index"
  1361  				},
  1362  				{
  1363  					"column": "name",
  1364  					"name": "name_user_map"
  1365  				},
  1366  				{
  1367  					"column": "music",
  1368  					"name": "music_user_map"
  1369  				}
  1370  			],
  1371  			"auto_increment": {
  1372  				"column": "id",
  1373  				"sequence": "user_seq"
  1374  			},
  1375  			"columns": [
  1376  				{
  1377  					"name": "textcol",
  1378  					"type": "VARCHAR"
  1379  				}
  1380  			]
  1381  		}
  1382  	}
  1383  }
  1384  `
  1385  	executor, sbc1, sbc2, sbclookup := createCustomExecutor(vschema)
  1386  
  1387  	_, err := executorExecSession(executor, "insert into user(id, v, name, music) values (1, 2, 'myname', 'star')", nil, &vtgatepb.Session{})
  1388  	require.NoError(t, err)
  1389  	wantQueries := []*querypb.BoundQuery{{
  1390  		Sql: "insert into `user`(id, v, `name`, music) values (:_Id_0, 2, :_name_0, :_music_0)",
  1391  		BindVariables: map[string]*querypb.BindVariable{
  1392  			"_Id_0":    sqltypes.Int64BindVariable(1),
  1393  			"_music_0": sqltypes.StringBindVariable("star"),
  1394  			"_name_0":  sqltypes.StringBindVariable("myname"),
  1395  			"__seq0":   sqltypes.Int64BindVariable(1),
  1396  		},
  1397  	}}
  1398  	assertQueries(t, sbc1, wantQueries)
  1399  	assertQueries(t, sbc2, nil)
  1400  	wantQueries = []*querypb.BoundQuery{{
  1401  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0) on duplicate key update `name` = values(`name`), user_id = values(user_id)",
  1402  		BindVariables: map[string]*querypb.BindVariable{
  1403  			"name_0":    sqltypes.StringBindVariable("myname"),
  1404  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1405  		},
  1406  	}, {
  1407  		Sql: "insert /*vt+ MULTI_SHARD_AUTOCOMMIT=1 */ into music_user_map(music, user_id) values (:music_0, :user_id_0) on duplicate key update music = values(music), user_id = values(user_id)",
  1408  		BindVariables: map[string]*querypb.BindVariable{
  1409  			"music_0":   sqltypes.StringBindVariable("star"),
  1410  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1411  		},
  1412  	}}
  1413  	// autocommit should go as ExecuteBatch
  1414  	assertQueries(t, sbclookup, wantQueries)
  1415  }
  1416  
  1417  func TestInsertShardedIgnore(t *testing.T) {
  1418  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  1419  
  1420  	// Build the sequence of responses for sbclookup. This should
  1421  	// match the sequence of queries we validate below.
  1422  	fields := sqltypes.MakeTestFields("b|a", "int64|int64")
  1423  	field := sqltypes.MakeTestFields("a", "int64")
  1424  	sbclookup.SetResults([]*sqltypes.Result{
  1425  		// select music_id
  1426  		sqltypes.MakeTestResult(fields, "1|1", "3|1", "4|1", "5|1", "6|3"),
  1427  		// insert ins_lookup
  1428  		{},
  1429  		// select ins_lookup 1
  1430  		sqltypes.MakeTestResult(field, "1"),
  1431  		// select ins_lookup 3
  1432  		{},
  1433  		// select ins_lookup 4
  1434  		sqltypes.MakeTestResult(field, "4"),
  1435  		// select ins_lookup 5
  1436  		sqltypes.MakeTestResult(field, "5"),
  1437  		// select ins_lookup 6
  1438  		sqltypes.MakeTestResult(field, "6"),
  1439  	})
  1440  	// First row: first shard.
  1441  	// Second row: will fail because primary vindex will fail to map.
  1442  	// Third row: will fail because verification will fail on owned vindex after Create.
  1443  	// Fourth row: will fail because verification will fail on unowned hash vindex.
  1444  	// Fifth row: first shard.
  1445  	// Sixth row: second shard (because 3 hash maps to 40-60).
  1446  	query := "insert ignore into insert_ignore_test(pv, owned, verify) values (1, 1, 1), (2, 2, 2), (3, 3, 1), (4, 4, 4), (5, 5, 1), (6, 6, 3)"
  1447  	_, err := executorExec(executor, query, nil)
  1448  	require.NoError(t, err)
  1449  	wantQueries := []*querypb.BoundQuery{{
  1450  		Sql: "insert ignore into insert_ignore_test(pv, owned, verify) values (:_pv_0, :_owned_0, :_verify_0),(:_pv_4, :_owned_4, :_verify_4)",
  1451  		BindVariables: map[string]*querypb.BindVariable{
  1452  			"_pv_0":     sqltypes.Int64BindVariable(1),
  1453  			"_pv_4":     sqltypes.Int64BindVariable(5),
  1454  			"_pv_5":     sqltypes.Int64BindVariable(6),
  1455  			"_owned_0":  sqltypes.Int64BindVariable(1),
  1456  			"_owned_4":  sqltypes.Int64BindVariable(5),
  1457  			"_owned_5":  sqltypes.Int64BindVariable(6),
  1458  			"_verify_0": sqltypes.Int64BindVariable(1),
  1459  			"_verify_4": sqltypes.Int64BindVariable(1),
  1460  			"_verify_5": sqltypes.Int64BindVariable(3),
  1461  		},
  1462  	}}
  1463  	assertQueries(t, sbc1, wantQueries)
  1464  	wantQueries = []*querypb.BoundQuery{{
  1465  		Sql: "insert ignore into insert_ignore_test(pv, owned, verify) values (:_pv_5, :_owned_5, :_verify_5)",
  1466  		BindVariables: map[string]*querypb.BindVariable{
  1467  			"_pv_0":     sqltypes.Int64BindVariable(1),
  1468  			"_pv_4":     sqltypes.Int64BindVariable(5),
  1469  			"_pv_5":     sqltypes.Int64BindVariable(6),
  1470  			"_owned_0":  sqltypes.Int64BindVariable(1),
  1471  			"_owned_4":  sqltypes.Int64BindVariable(5),
  1472  			"_owned_5":  sqltypes.Int64BindVariable(6),
  1473  			"_verify_0": sqltypes.Int64BindVariable(1),
  1474  			"_verify_4": sqltypes.Int64BindVariable(1),
  1475  			"_verify_5": sqltypes.Int64BindVariable(3),
  1476  		},
  1477  	}}
  1478  	assertQueries(t, sbc2, wantQueries)
  1479  
  1480  	vars, err := sqltypes.BuildBindVariable([]any{
  1481  		sqltypes.NewInt64(1),
  1482  		sqltypes.NewInt64(2),
  1483  		sqltypes.NewInt64(3),
  1484  		sqltypes.NewInt64(4),
  1485  		sqltypes.NewInt64(5),
  1486  		sqltypes.NewInt64(6),
  1487  	})
  1488  	require.NoError(t, err)
  1489  	wantQueries = []*querypb.BoundQuery{{
  1490  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
  1491  		BindVariables: map[string]*querypb.BindVariable{
  1492  			"music_id": vars,
  1493  		},
  1494  	}, {
  1495  		Sql: "insert ignore into ins_lookup(fromcol, tocol) values (:fromcol_0, :tocol_0), (:fromcol_1, :tocol_1), (:fromcol_2, :tocol_2), (:fromcol_3, :tocol_3), (:fromcol_4, :tocol_4)",
  1496  		BindVariables: map[string]*querypb.BindVariable{
  1497  			"fromcol_0": sqltypes.Int64BindVariable(1),
  1498  			"tocol_0":   sqltypes.Uint64BindVariable(1),
  1499  			"fromcol_1": sqltypes.Int64BindVariable(3),
  1500  			"tocol_1":   sqltypes.Uint64BindVariable(1),
  1501  			"fromcol_2": sqltypes.Int64BindVariable(4),
  1502  			"tocol_2":   sqltypes.Uint64BindVariable(1),
  1503  			"fromcol_3": sqltypes.Int64BindVariable(5),
  1504  			"tocol_3":   sqltypes.Uint64BindVariable(1),
  1505  			"fromcol_4": sqltypes.Int64BindVariable(6),
  1506  			"tocol_4":   sqltypes.Uint64BindVariable(3),
  1507  		},
  1508  	}, {
  1509  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1510  		BindVariables: map[string]*querypb.BindVariable{
  1511  			"fromcol": sqltypes.Int64BindVariable(1),
  1512  			"tocol":   sqltypes.Uint64BindVariable(1),
  1513  		},
  1514  	}, {
  1515  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1516  		BindVariables: map[string]*querypb.BindVariable{
  1517  			"fromcol": sqltypes.Int64BindVariable(3),
  1518  			"tocol":   sqltypes.Uint64BindVariable(1),
  1519  		},
  1520  	}, {
  1521  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1522  		BindVariables: map[string]*querypb.BindVariable{
  1523  			"fromcol": sqltypes.Int64BindVariable(4),
  1524  			"tocol":   sqltypes.Uint64BindVariable(1),
  1525  		},
  1526  	}, {
  1527  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1528  		BindVariables: map[string]*querypb.BindVariable{
  1529  			"fromcol": sqltypes.Int64BindVariable(5),
  1530  			"tocol":   sqltypes.Uint64BindVariable(1),
  1531  		},
  1532  	}, {
  1533  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1534  		BindVariables: map[string]*querypb.BindVariable{
  1535  			"fromcol": sqltypes.Int64BindVariable(6),
  1536  			"tocol":   sqltypes.Uint64BindVariable(3),
  1537  		},
  1538  	}}
  1539  	assertQueries(t, sbclookup, wantQueries)
  1540  
  1541  	// Test the 0 rows case,
  1542  	sbc1.Queries = nil
  1543  	sbc2.Queries = nil
  1544  	sbclookup.Queries = nil
  1545  	sbclookup.SetResults([]*sqltypes.Result{
  1546  		{},
  1547  	})
  1548  	query = "insert ignore into insert_ignore_test(pv, owned, verify) values (1, 1, 1)"
  1549  	qr, err := executorExec(executor, query, nil)
  1550  	require.NoError(t, err)
  1551  	if !qr.Equal(&sqltypes.Result{}) {
  1552  		t.Errorf("qr: %v, want empty result", qr)
  1553  	}
  1554  	assertQueries(t, sbc1, nil)
  1555  	assertQueries(t, sbc2, nil)
  1556  	vars, err = sqltypes.BuildBindVariable([]any{sqltypes.NewInt64(1)})
  1557  	require.NoError(t, err)
  1558  	wantQueries = []*querypb.BoundQuery{{
  1559  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
  1560  		BindVariables: map[string]*querypb.BindVariable{
  1561  			"music_id": vars,
  1562  		},
  1563  	}}
  1564  	assertQueries(t, sbclookup, wantQueries)
  1565  }
  1566  
  1567  func TestInsertOnDupKey(t *testing.T) {
  1568  	// This test just sanity checks that the statement is getting passed through
  1569  	// correctly. The full set of use cases are covered by TestInsertShardedIgnore.
  1570  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  1571  	sbclookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
  1572  		sqltypes.MakeTestFields("b|a", "int64|varbinary"),
  1573  		"1|1",
  1574  	)})
  1575  	query := "insert into insert_ignore_test(pv, owned, verify) values (1, 1, 1) on duplicate key update col = 2"
  1576  	_, err := executorExec(executor, query, nil)
  1577  	require.NoError(t, err)
  1578  	wantQueries := []*querypb.BoundQuery{{
  1579  		Sql: "insert into insert_ignore_test(pv, owned, verify) values (:_pv_0, :_owned_0, :_verify_0) on duplicate key update col = 2",
  1580  		BindVariables: map[string]*querypb.BindVariable{
  1581  			"_pv_0":     sqltypes.Int64BindVariable(1),
  1582  			"_owned_0":  sqltypes.Int64BindVariable(1),
  1583  			"_verify_0": sqltypes.Int64BindVariable(1),
  1584  		},
  1585  	}}
  1586  	assertQueries(t, sbc1, wantQueries)
  1587  	assertQueries(t, sbc2, nil)
  1588  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewInt64(1)})
  1589  	require.NoError(t, err)
  1590  	wantQueries = []*querypb.BoundQuery{{
  1591  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
  1592  		BindVariables: map[string]*querypb.BindVariable{
  1593  			"music_id": vars,
  1594  		},
  1595  	}, {
  1596  		Sql: "insert ignore into ins_lookup(fromcol, tocol) values (:fromcol_0, :tocol_0)",
  1597  		BindVariables: map[string]*querypb.BindVariable{
  1598  			"fromcol_0": sqltypes.Int64BindVariable(1),
  1599  			"tocol_0":   sqltypes.Uint64BindVariable(1),
  1600  		},
  1601  	}, {
  1602  		Sql: "select fromcol from ins_lookup where fromcol = :fromcol and tocol = :tocol",
  1603  		BindVariables: map[string]*querypb.BindVariable{
  1604  			"fromcol": sqltypes.Int64BindVariable(1),
  1605  			"tocol":   sqltypes.Uint64BindVariable(1),
  1606  		},
  1607  	}}
  1608  	assertQueries(t, sbclookup, wantQueries)
  1609  }
  1610  
  1611  func TestAutocommitFail(t *testing.T) {
  1612  	executor, sbc1, _, _ := createExecutorEnv()
  1613  
  1614  	query := "insert into user (id) values (1)"
  1615  	sbc1.MustFailCodes[vtrpcpb.Code_ALREADY_EXISTS] = 1
  1616  	primarySession.Reset()
  1617  	primarySession.Autocommit = true
  1618  	defer func() {
  1619  		primarySession.Autocommit = false
  1620  	}()
  1621  	_, err := executorExec(executor, query, nil)
  1622  	require.Error(t, err)
  1623  
  1624  	// make sure we have closed and rolled back any transactions started
  1625  	assert.False(t, primarySession.InTransaction, "left with tx open")
  1626  }
  1627  
  1628  func TestInsertComments(t *testing.T) {
  1629  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  1630  
  1631  	_, err := executorExec(executor, "insert into user(id, v, name) values (1, 2, 'myname') /* trailing */", nil)
  1632  	require.NoError(t, err)
  1633  	wantQueries := []*querypb.BoundQuery{{
  1634  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 2, :_name_0) /* trailing */",
  1635  		BindVariables: map[string]*querypb.BindVariable{
  1636  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1637  			"_name_0": sqltypes.StringBindVariable("myname"),
  1638  			"__seq0":  sqltypes.Int64BindVariable(1),
  1639  		},
  1640  	}}
  1641  	assertQueries(t, sbc1, wantQueries)
  1642  	assertQueries(t, sbc2, nil)
  1643  	wantQueries = []*querypb.BoundQuery{{
  1644  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0) /* trailing */",
  1645  		BindVariables: map[string]*querypb.BindVariable{
  1646  			"name_0":    sqltypes.StringBindVariable("myname"),
  1647  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1648  		},
  1649  	}}
  1650  	assertQueries(t, sbclookup, wantQueries)
  1651  }
  1652  
  1653  func TestInsertGeneratorSharded(t *testing.T) {
  1654  	executor, sbc, _, sbclookup := createExecutorEnv()
  1655  
  1656  	sbclookup.SetResults([]*sqltypes.Result{{
  1657  		Rows: [][]sqltypes.Value{{
  1658  			sqltypes.NewInt64(1),
  1659  		}},
  1660  		RowsAffected: 1,
  1661  		InsertID:     1,
  1662  	}})
  1663  	result, err := executorExec(executor, "insert into user(v, `name`) values (2, 'myname')", nil)
  1664  	require.NoError(t, err)
  1665  	wantQueries := []*querypb.BoundQuery{{
  1666  		Sql: "insert into `user`(v, `name`, id) values (2, :_name_0, :_Id_0)",
  1667  		BindVariables: map[string]*querypb.BindVariable{
  1668  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1669  			"__seq0":  sqltypes.Int64BindVariable(1),
  1670  			"_name_0": sqltypes.StringBindVariable("myname"),
  1671  		},
  1672  	}}
  1673  	assertQueries(t, sbc, wantQueries)
  1674  	wantQueries = []*querypb.BoundQuery{{
  1675  		Sql:           "select next :n values from user_seq",
  1676  		BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)},
  1677  	}, {
  1678  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)",
  1679  		BindVariables: map[string]*querypb.BindVariable{
  1680  			"name_0":    sqltypes.StringBindVariable("myname"),
  1681  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1682  		},
  1683  	}}
  1684  	assertQueries(t, sbclookup, wantQueries)
  1685  	wantResult := &sqltypes.Result{
  1686  		InsertID:     1,
  1687  		RowsAffected: 1,
  1688  	}
  1689  	utils.MustMatch(t, wantResult, result)
  1690  }
  1691  
  1692  func TestInsertAutoincSharded(t *testing.T) {
  1693  	router, sbc, _, _ := createExecutorEnv()
  1694  
  1695  	// Fake a mysql auto-inc response.
  1696  	wantResult := &sqltypes.Result{
  1697  		Rows: [][]sqltypes.Value{{
  1698  			sqltypes.NewInt64(1),
  1699  		}},
  1700  		RowsAffected: 1,
  1701  		InsertID:     2,
  1702  	}
  1703  	sbc.SetResults([]*sqltypes.Result{wantResult})
  1704  	result, err := executorExec(router, "insert into user_extra(user_id) values (2)", nil)
  1705  	require.NoError(t, err)
  1706  	wantQueries := []*querypb.BoundQuery{{
  1707  		Sql: "insert into user_extra(user_id) values (:_user_id_0)",
  1708  		BindVariables: map[string]*querypb.BindVariable{
  1709  			"_user_id_0": sqltypes.Int64BindVariable(2),
  1710  		},
  1711  	}}
  1712  	assertQueries(t, sbc, wantQueries)
  1713  	if !result.Equal(wantResult) {
  1714  		t.Errorf("result: %+v, want %+v", result, wantResult)
  1715  	}
  1716  	assert.EqualValues(t, 2, primarySession.LastInsertId)
  1717  }
  1718  
  1719  func TestInsertGeneratorUnsharded(t *testing.T) {
  1720  	executor, _, _, sbclookup := createExecutorEnv()
  1721  	result, err := executorExec(executor, "insert into main1(id, name) values (null, 'myname')", nil)
  1722  	require.NoError(t, err)
  1723  	wantQueries := []*querypb.BoundQuery{{
  1724  		Sql:           "select next :n values from user_seq",
  1725  		BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)},
  1726  	}, {
  1727  		Sql: "insert into main1(id, `name`) values (:__seq0, 'myname')",
  1728  		BindVariables: map[string]*querypb.BindVariable{
  1729  			"__seq0": sqltypes.Int64BindVariable(1),
  1730  		},
  1731  	}}
  1732  	assertQueries(t, sbclookup, wantQueries)
  1733  	wantResult := &sqltypes.Result{
  1734  		InsertID:     1,
  1735  		RowsAffected: 1,
  1736  	}
  1737  	utils.MustMatch(t, wantResult, result)
  1738  }
  1739  
  1740  func TestInsertAutoincUnsharded(t *testing.T) {
  1741  	router, _, _, sbclookup := createExecutorEnv()
  1742  
  1743  	logChan := QueryLogger.Subscribe("Test")
  1744  	defer QueryLogger.Unsubscribe(logChan)
  1745  
  1746  	// Fake a mysql auto-inc response.
  1747  	query := "insert into `simple`(val) values ('val')"
  1748  	wantResult := &sqltypes.Result{
  1749  		Rows: [][]sqltypes.Value{{
  1750  			sqltypes.NewInt64(1),
  1751  		}},
  1752  		RowsAffected: 1,
  1753  		InsertID:     2,
  1754  	}
  1755  	sbclookup.SetResults([]*sqltypes.Result{wantResult})
  1756  
  1757  	result, err := executorExec(router, query, nil)
  1758  	require.NoError(t, err)
  1759  	wantQueries := []*querypb.BoundQuery{{
  1760  		Sql:           query,
  1761  		BindVariables: map[string]*querypb.BindVariable{},
  1762  	}}
  1763  	assertQueries(t, sbclookup, wantQueries)
  1764  	assert.Equal(t, result, wantResult)
  1765  
  1766  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into `simple`(val) values ('val')", 1)
  1767  }
  1768  
  1769  func TestInsertLookupOwned(t *testing.T) {
  1770  	executor, sbc, _, sbclookup := createExecutorEnv()
  1771  
  1772  	_, err := executorExec(executor, "insert into music(user_id, id) values (2, 3)", nil)
  1773  	require.NoError(t, err)
  1774  	wantQueries := []*querypb.BoundQuery{{
  1775  		Sql: "insert into music(user_id, id) values (:_user_id_0, :_id_0)",
  1776  		BindVariables: map[string]*querypb.BindVariable{
  1777  			"_user_id_0": sqltypes.Int64BindVariable(2),
  1778  			"_id_0":      sqltypes.Int64BindVariable(3),
  1779  			"__seq0":     sqltypes.Int64BindVariable(3),
  1780  		},
  1781  	}}
  1782  	assertQueries(t, sbc, wantQueries)
  1783  	wantQueries = []*querypb.BoundQuery{{
  1784  		Sql: "insert into music_user_map(music_id, user_id) values (:music_id_0, :user_id_0)",
  1785  		BindVariables: map[string]*querypb.BindVariable{
  1786  			"music_id_0": sqltypes.Int64BindVariable(3),
  1787  			"user_id_0":  sqltypes.Uint64BindVariable(2),
  1788  		},
  1789  	}}
  1790  	assertQueries(t, sbclookup, wantQueries)
  1791  }
  1792  
  1793  func TestInsertLookupOwnedGenerator(t *testing.T) {
  1794  	executor, sbc, _, sbclookup := createExecutorEnv()
  1795  
  1796  	sbclookup.SetResults([]*sqltypes.Result{{
  1797  		Rows: [][]sqltypes.Value{{
  1798  			sqltypes.NewInt64(4),
  1799  		}},
  1800  		RowsAffected: 1,
  1801  		InsertID:     1,
  1802  	}})
  1803  	result, err := executorExec(executor, "insert into music(user_id) values (2)", nil)
  1804  	require.NoError(t, err)
  1805  	wantQueries := []*querypb.BoundQuery{{
  1806  		Sql: "insert into music(user_id, id) values (:_user_id_0, :_id_0)",
  1807  		BindVariables: map[string]*querypb.BindVariable{
  1808  			"_user_id_0": sqltypes.Int64BindVariable(2),
  1809  			"_id_0":      sqltypes.Int64BindVariable(4),
  1810  			"__seq0":     sqltypes.Int64BindVariable(4),
  1811  		},
  1812  	}}
  1813  	assertQueries(t, sbc, wantQueries)
  1814  	wantQueries = []*querypb.BoundQuery{{
  1815  		Sql:           "select next :n values from user_seq",
  1816  		BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)},
  1817  	}, {
  1818  		Sql: "insert into music_user_map(music_id, user_id) values (:music_id_0, :user_id_0)",
  1819  		BindVariables: map[string]*querypb.BindVariable{
  1820  			"music_id_0": sqltypes.Int64BindVariable(4),
  1821  			"user_id_0":  sqltypes.Uint64BindVariable(2),
  1822  		},
  1823  	}}
  1824  	assertQueries(t, sbclookup, wantQueries)
  1825  	wantResult := &sqltypes.Result{
  1826  		InsertID:     4,
  1827  		RowsAffected: 1,
  1828  	}
  1829  	utils.MustMatch(t, wantResult, result)
  1830  }
  1831  
  1832  func TestInsertLookupUnowned(t *testing.T) {
  1833  	executor, sbc, _, sbclookup := createExecutorEnv()
  1834  
  1835  	_, err := executorExec(executor, "insert into music_extra(user_id, music_id) values (2, 3)", nil)
  1836  	require.NoError(t, err)
  1837  	wantQueries := []*querypb.BoundQuery{{
  1838  		Sql: "insert into music_extra(user_id, music_id) values (:_user_id_0, :_music_id_0)",
  1839  		BindVariables: map[string]*querypb.BindVariable{
  1840  			"_user_id_0":  sqltypes.Int64BindVariable(2),
  1841  			"_music_id_0": sqltypes.Int64BindVariable(3),
  1842  		},
  1843  	}}
  1844  	assertQueries(t, sbc, wantQueries)
  1845  	wantQueries = []*querypb.BoundQuery{{
  1846  		Sql: "select music_id from music_user_map where music_id = :music_id and user_id = :user_id",
  1847  		BindVariables: map[string]*querypb.BindVariable{
  1848  			"music_id": sqltypes.Int64BindVariable(3),
  1849  			"user_id":  sqltypes.Uint64BindVariable(2),
  1850  		},
  1851  	}}
  1852  	assertQueries(t, sbclookup, wantQueries)
  1853  }
  1854  
  1855  func TestInsertLookupUnownedUnsupplied(t *testing.T) {
  1856  	executor, sbc, _, sbclookup := createExecutorEnv()
  1857  	sbclookup.SetResults([]*sqltypes.Result{sqltypes.MakeTestResult(
  1858  		sqltypes.MakeTestFields("b|a", "int64|varbinary"),
  1859  		"3|1",
  1860  	)})
  1861  	_, err := executorExec(executor, "insert into music_extra_reversed(music_id) values (3)", nil)
  1862  	require.NoError(t, err)
  1863  	wantQueries := []*querypb.BoundQuery{{
  1864  		Sql: "insert into music_extra_reversed(music_id, user_id) values (:_music_id_0, :_user_id_0)",
  1865  		BindVariables: map[string]*querypb.BindVariable{
  1866  			"_user_id_0":  sqltypes.Uint64BindVariable(1),
  1867  			"_music_id_0": sqltypes.Int64BindVariable(3),
  1868  		},
  1869  	}}
  1870  	assertQueries(t, sbc, wantQueries)
  1871  	vars, err := sqltypes.BuildBindVariable([]any{sqltypes.NewInt64(3)})
  1872  	require.NoError(t, err)
  1873  	wantQueries = []*querypb.BoundQuery{{
  1874  		Sql: "select music_id, user_id from music_user_map where music_id in ::music_id for update",
  1875  		BindVariables: map[string]*querypb.BindVariable{
  1876  			"music_id": vars,
  1877  		},
  1878  	}}
  1879  	assertQueries(t, sbclookup, wantQueries)
  1880  }
  1881  
  1882  // If a statement gets broken up into two, and the first one fails,
  1883  // then an error should be returned normally.
  1884  func TestInsertPartialFail1(t *testing.T) {
  1885  	executor, _, _, sbclookup := createExecutorEnv()
  1886  
  1887  	// Make the first DML fail, there should be no rollback.
  1888  	sbclookup.MustFailCodes[vtrpcpb.Code_INVALID_ARGUMENT] = 1
  1889  
  1890  	_, err := executor.Execute(
  1891  		context.Background(),
  1892  		"TestExecute",
  1893  		NewSafeSession(&vtgatepb.Session{InTransaction: true}),
  1894  		"insert into user(id, v, name) values (1, 2, 'myname')",
  1895  		nil,
  1896  	)
  1897  	require.Error(t, err)
  1898  }
  1899  
  1900  // If a statement gets broken up into two, and the second one fails
  1901  // after successful execution of the first, then the transaction must
  1902  // be rolled back due to partial execution.
  1903  func TestInsertPartialFail2(t *testing.T) {
  1904  	executor, sbc1, _, _ := createExecutorEnv()
  1905  
  1906  	// Make the second DML fail, it should result in a rollback.
  1907  	sbc1.MustFailExecute[sqlparser.StmtInsert] = 1
  1908  
  1909  	safeSession := NewSafeSession(&vtgatepb.Session{InTransaction: true})
  1910  	_, err := executor.Execute(
  1911  		context.Background(),
  1912  		"TestExecute",
  1913  		safeSession,
  1914  		"insert into user(id, v, name) values (1, 2, 'myname')",
  1915  		nil,
  1916  	)
  1917  
  1918  	want := "reverted partial DML execution failure"
  1919  	if err == nil || !strings.HasPrefix(err.Error(), want) {
  1920  		t.Errorf("insert first DML fail: %v, must start with %s", err, want)
  1921  	}
  1922  
  1923  	assert.True(t, safeSession.InTransaction())
  1924  	wantQueries := []*querypb.BoundQuery{
  1925  		{
  1926  			Sql:           "savepoint x",
  1927  			BindVariables: map[string]*querypb.BindVariable{},
  1928  		}, {
  1929  			Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 2, :_name_0)",
  1930  			BindVariables: map[string]*querypb.BindVariable{
  1931  				"_Id_0":   sqltypes.Int64BindVariable(1),
  1932  				"__seq0":  sqltypes.Int64BindVariable(1),
  1933  				"_name_0": sqltypes.StringBindVariable("myname"),
  1934  			},
  1935  		}, {
  1936  			Sql:           "rollback to x",
  1937  			BindVariables: map[string]*querypb.BindVariable{},
  1938  		}}
  1939  	assertQueriesWithSavepoint(t, sbc1, wantQueries)
  1940  }
  1941  
  1942  func TestMultiInsertSharded(t *testing.T) {
  1943  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  1944  
  1945  	_, err := executorExec(executor, "insert into user(id, v, name) values (1, 1, 'myname1'),(3, 3, 'myname3')", nil)
  1946  	require.NoError(t, err)
  1947  	wantQueries1 := []*querypb.BoundQuery{{
  1948  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 1, :_name_0)",
  1949  		BindVariables: map[string]*querypb.BindVariable{
  1950  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1951  			"_name_0": sqltypes.StringBindVariable("myname1"),
  1952  			"__seq0":  sqltypes.Int64BindVariable(1),
  1953  			"_Id_1":   sqltypes.Int64BindVariable(3),
  1954  			"_name_1": sqltypes.StringBindVariable("myname3"),
  1955  			"__seq1":  sqltypes.Int64BindVariable(3),
  1956  		},
  1957  	}}
  1958  
  1959  	wantQueries2 := []*querypb.BoundQuery{{
  1960  		Sql: "insert into `user`(id, v, `name`) values (:_Id_1, 3, :_name_1)",
  1961  		BindVariables: map[string]*querypb.BindVariable{
  1962  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1963  			"_name_0": sqltypes.StringBindVariable("myname1"),
  1964  			"__seq0":  sqltypes.Int64BindVariable(1),
  1965  			"_Id_1":   sqltypes.Int64BindVariable(3),
  1966  			"_name_1": sqltypes.StringBindVariable("myname3"),
  1967  			"__seq1":  sqltypes.Int64BindVariable(3),
  1968  		},
  1969  	}}
  1970  	assertQueries(t, sbc1, wantQueries1)
  1971  	assertQueries(t, sbc2, wantQueries2)
  1972  
  1973  	wantQueries1 = []*querypb.BoundQuery{{
  1974  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)",
  1975  		BindVariables: map[string]*querypb.BindVariable{
  1976  			"name_0":    sqltypes.StringBindVariable("myname1"),
  1977  			"user_id_0": sqltypes.Uint64BindVariable(1),
  1978  			"name_1":    sqltypes.StringBindVariable("myname3"),
  1979  			"user_id_1": sqltypes.Uint64BindVariable(3),
  1980  		},
  1981  	}}
  1982  	assertQueries(t, sbclookup, wantQueries1)
  1983  
  1984  	sbc1.Queries = nil
  1985  	sbclookup.Queries = nil
  1986  	sbc2.Queries = nil
  1987  	_, err = executorExec(executor, "insert into user(id, v, name) values (1, 1, 'myname1'),(2, 2, 'myname2')", nil)
  1988  	require.NoError(t, err)
  1989  	wantQueries := []*querypb.BoundQuery{{
  1990  		Sql: "insert into `user`(id, v, `name`) values (:_Id_0, 1, :_name_0),(:_Id_1, 2, :_name_1)",
  1991  		BindVariables: map[string]*querypb.BindVariable{
  1992  			"_Id_0":   sqltypes.Int64BindVariable(1),
  1993  			"__seq0":  sqltypes.Int64BindVariable(1),
  1994  			"_name_0": sqltypes.StringBindVariable("myname1"),
  1995  			"_Id_1":   sqltypes.Int64BindVariable(2),
  1996  			"__seq1":  sqltypes.Int64BindVariable(2),
  1997  			"_name_1": sqltypes.StringBindVariable("myname2"),
  1998  		},
  1999  	}}
  2000  
  2001  	assertQueries(t, sbc1, wantQueries)
  2002  	assertQueries(t, sbc2, nil)
  2003  	wantQueries = []*querypb.BoundQuery{{
  2004  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1)",
  2005  		BindVariables: map[string]*querypb.BindVariable{
  2006  			"name_0":    sqltypes.StringBindVariable("myname1"),
  2007  			"user_id_0": sqltypes.Uint64BindVariable(1),
  2008  			"name_1":    sqltypes.StringBindVariable("myname2"),
  2009  			"user_id_1": sqltypes.Uint64BindVariable(2),
  2010  		},
  2011  	}}
  2012  	assertQueries(t, sbclookup, wantQueries)
  2013  
  2014  	// Insert multiple rows in a multi column vindex
  2015  	sbc1.Queries = nil
  2016  	sbclookup.Queries = nil
  2017  	sbc2.Queries = nil
  2018  	_, err = executorExec(executor, "insert into user2(id, `name`, lastname) values (2, 'myname', 'mylastname'), (3, 'myname2', 'mylastname2')", nil)
  2019  	require.NoError(t, err)
  2020  	wantQueries = []*querypb.BoundQuery{{
  2021  		Sql: "insert into user2(id, `name`, lastname) values (:_id_0, :_name_0, :_lastname_0)",
  2022  		BindVariables: map[string]*querypb.BindVariable{
  2023  			"_id_0":       sqltypes.Int64BindVariable(2),
  2024  			"_name_0":     sqltypes.StringBindVariable("myname"),
  2025  			"_lastname_0": sqltypes.StringBindVariable("mylastname"),
  2026  			"_id_1":       sqltypes.Int64BindVariable(3),
  2027  			"_name_1":     sqltypes.StringBindVariable("myname2"),
  2028  			"_lastname_1": sqltypes.StringBindVariable("mylastname2"),
  2029  		},
  2030  	}}
  2031  	assertQueries(t, sbc1, wantQueries)
  2032  	wantQueries = []*querypb.BoundQuery{{
  2033  		Sql: "insert into name_lastname_keyspace_id_map(`name`, lastname, keyspace_id) values (:name_0, :lastname_0, :keyspace_id_0), (:name_1, :lastname_1, :keyspace_id_1)",
  2034  		BindVariables: map[string]*querypb.BindVariable{
  2035  			"name_0":        sqltypes.StringBindVariable("myname"),
  2036  			"lastname_0":    sqltypes.StringBindVariable("mylastname"),
  2037  			"keyspace_id_0": sqltypes.BytesBindVariable([]byte("\x06\xe7\xea\"Βp\x8f")),
  2038  			"name_1":        sqltypes.StringBindVariable("myname2"),
  2039  			"lastname_1":    sqltypes.StringBindVariable("mylastname2"),
  2040  			"keyspace_id_1": sqltypes.BytesBindVariable([]byte("N\xb1\x90ɢ\xfa\x16\x9c")),
  2041  		},
  2042  	}}
  2043  	assertQueries(t, sbclookup, wantQueries)
  2044  }
  2045  
  2046  func TestMultiInsertGenerator(t *testing.T) {
  2047  	executor, sbc, _, sbclookup := createExecutorEnv()
  2048  
  2049  	sbclookup.SetResults([]*sqltypes.Result{{
  2050  		Rows: [][]sqltypes.Value{{
  2051  			sqltypes.NewInt64(1),
  2052  		}},
  2053  		RowsAffected: 1,
  2054  		InsertID:     1,
  2055  	}})
  2056  	result, err := executorExec(executor, "insert into music(user_id, `name`) values (:u, 'myname1'),(:u, 'myname2')", map[string]*querypb.BindVariable{"u": sqltypes.Int64BindVariable(2)})
  2057  	require.NoError(t, err)
  2058  	wantQueries := []*querypb.BoundQuery{{
  2059  		Sql: "insert into music(user_id, `name`, id) values (:_user_id_0, 'myname1', :_id_0),(:_user_id_1, 'myname2', :_id_1)",
  2060  		BindVariables: map[string]*querypb.BindVariable{
  2061  			"u":          sqltypes.Int64BindVariable(2),
  2062  			"_id_0":      sqltypes.Int64BindVariable(1),
  2063  			"__seq0":     sqltypes.Int64BindVariable(1),
  2064  			"_user_id_0": sqltypes.Int64BindVariable(2),
  2065  			"_id_1":      sqltypes.Int64BindVariable(2),
  2066  			"__seq1":     sqltypes.Int64BindVariable(2),
  2067  			"_user_id_1": sqltypes.Int64BindVariable(2),
  2068  		},
  2069  	}}
  2070  	assertQueries(t, sbc, wantQueries)
  2071  	wantQueries = []*querypb.BoundQuery{{
  2072  		Sql:           "select next :n values from user_seq",
  2073  		BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(2)},
  2074  	}, {
  2075  		Sql: "insert into music_user_map(music_id, user_id) values (:music_id_0, :user_id_0), (:music_id_1, :user_id_1)",
  2076  		BindVariables: map[string]*querypb.BindVariable{
  2077  			"user_id_0":  sqltypes.Uint64BindVariable(2),
  2078  			"music_id_0": sqltypes.Int64BindVariable(1),
  2079  			"user_id_1":  sqltypes.Uint64BindVariable(2),
  2080  			"music_id_1": sqltypes.Int64BindVariable(2),
  2081  		},
  2082  	}}
  2083  	assertQueries(t, sbclookup, wantQueries)
  2084  	wantResult := &sqltypes.Result{
  2085  		InsertID:     1,
  2086  		RowsAffected: 1,
  2087  	}
  2088  	utils.MustMatch(t, wantResult, result)
  2089  }
  2090  
  2091  func TestMultiInsertGeneratorSparse(t *testing.T) {
  2092  	executor, sbc, _, sbclookup := createExecutorEnv()
  2093  
  2094  	sbclookup.SetResults([]*sqltypes.Result{{
  2095  		Rows: [][]sqltypes.Value{{
  2096  			sqltypes.NewInt64(1),
  2097  		}},
  2098  		RowsAffected: 1,
  2099  		InsertID:     1,
  2100  	}})
  2101  	result, err := executorExec(executor, "insert into music(id, user_id, name) values (NULL, :u, 'myname1'),(2, :u, 'myname2'), (NULL, :u, 'myname3')", map[string]*querypb.BindVariable{"u": sqltypes.Int64BindVariable(2)})
  2102  	require.NoError(t, err)
  2103  	wantQueries := []*querypb.BoundQuery{{
  2104  		Sql: "insert into music(id, user_id, `name`) values (:_id_0, :_user_id_0, 'myname1'),(:_id_1, :_user_id_1, 'myname2'),(:_id_2, :_user_id_2, 'myname3')",
  2105  		BindVariables: map[string]*querypb.BindVariable{
  2106  			"u":          sqltypes.Int64BindVariable(2),
  2107  			"_id_0":      sqltypes.Int64BindVariable(1),
  2108  			"__seq0":     sqltypes.Int64BindVariable(1),
  2109  			"_user_id_0": sqltypes.Int64BindVariable(2),
  2110  			"_id_1":      sqltypes.Int64BindVariable(2),
  2111  			"__seq1":     sqltypes.Int64BindVariable(2),
  2112  			"_user_id_1": sqltypes.Int64BindVariable(2),
  2113  			"_id_2":      sqltypes.Int64BindVariable(2),
  2114  			"__seq2":     sqltypes.Int64BindVariable(2),
  2115  			"_user_id_2": sqltypes.Int64BindVariable(2),
  2116  		},
  2117  	}}
  2118  	assertQueries(t, sbc, wantQueries)
  2119  	wantQueries = []*querypb.BoundQuery{{
  2120  		Sql:           "select next :n values from user_seq",
  2121  		BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(2)},
  2122  	}, {
  2123  		Sql: "insert into music_user_map(music_id, user_id) values (:music_id_0, :user_id_0), (:music_id_1, :user_id_1), (:music_id_2, :user_id_2)",
  2124  		BindVariables: map[string]*querypb.BindVariable{
  2125  			"user_id_0":  sqltypes.Uint64BindVariable(2),
  2126  			"music_id_0": sqltypes.Int64BindVariable(1),
  2127  			"user_id_1":  sqltypes.Uint64BindVariable(2),
  2128  			"music_id_1": sqltypes.Int64BindVariable(2),
  2129  			"user_id_2":  sqltypes.Uint64BindVariable(2),
  2130  			"music_id_2": sqltypes.Int64BindVariable(2),
  2131  		},
  2132  	}}
  2133  	assertQueries(t, sbclookup, wantQueries)
  2134  	wantResult := &sqltypes.Result{
  2135  		InsertID:     1,
  2136  		RowsAffected: 1,
  2137  	}
  2138  	utils.MustMatch(t, wantResult, result)
  2139  }
  2140  
  2141  func TestInsertBadAutoInc(t *testing.T) {
  2142  	vschema := `
  2143  {
  2144  	"sharded": true,
  2145  	"vindexes": {
  2146  		"hash_index": {
  2147  			"type": "hash"
  2148  		}
  2149  	},
  2150  	"tables": {
  2151  		"bad_auto": {
  2152  			"column_vindexes": [
  2153  				{
  2154  					"column": "id",
  2155  					"name": "hash_index"
  2156  				}
  2157  			],
  2158  			"auto_increment": {
  2159  				"column": "id",
  2160  				"sequence": "absent"
  2161  			}
  2162  		}
  2163  	}
  2164  }
  2165  `
  2166  	executor, _, _, _ := createCustomExecutor(vschema)
  2167  
  2168  	// If auto inc table cannot be found, the table should not be added to vschema.
  2169  	_, err := executorExec(executor, "insert into bad_auto(v, name) values (1, 'myname')", nil)
  2170  	want := "table bad_auto not found"
  2171  	if err == nil || err.Error() != want {
  2172  		t.Errorf("bad auto inc err: %v, want %v", err, want)
  2173  	}
  2174  }
  2175  
  2176  func TestKeyDestRangeQuery(t *testing.T) {
  2177  
  2178  	type testCase struct {
  2179  		inputQuery, targetString string
  2180  		expectedSbc1Query        string
  2181  		expectedSbc2Query        string
  2182  	}
  2183  	deleteInput := "DELETE FROM sharded_user_msgs LIMIT 1000"
  2184  	deleteOutput := "delete from sharded_user_msgs limit 1000"
  2185  
  2186  	selectInput := "SELECT * FROM sharded_user_msgs LIMIT 1"
  2187  	selectOutput := "select * from sharded_user_msgs limit 1"
  2188  	updateInput := "UPDATE sharded_user_msgs set message='test' LIMIT 1"
  2189  	updateOutput := "update sharded_user_msgs set message = 'test' limit 1"
  2190  	insertInput := "INSERT INTO sharded_user_msgs(message) VALUES('test')"
  2191  	insertOutput := "insert into sharded_user_msgs(message) values ('test')"
  2192  	tests := []testCase{
  2193  		{
  2194  			inputQuery:        deleteInput,
  2195  			targetString:      "TestExecutor[-60]",
  2196  			expectedSbc1Query: deleteOutput,
  2197  			expectedSbc2Query: deleteOutput,
  2198  		},
  2199  		{
  2200  			inputQuery:        deleteInput,
  2201  			targetString:      "TestExecutor[40-60]",
  2202  			expectedSbc2Query: deleteOutput,
  2203  		},
  2204  		{
  2205  			inputQuery:        deleteInput,
  2206  			targetString:      "TestExecutor[-]",
  2207  			expectedSbc1Query: deleteOutput,
  2208  			expectedSbc2Query: deleteOutput,
  2209  		},
  2210  		{
  2211  			inputQuery:        selectInput,
  2212  			targetString:      "TestExecutor[-]",
  2213  			expectedSbc1Query: selectOutput,
  2214  			expectedSbc2Query: selectOutput,
  2215  		},
  2216  		{
  2217  			inputQuery:        updateInput,
  2218  			targetString:      "TestExecutor[-]",
  2219  			expectedSbc1Query: updateOutput,
  2220  			expectedSbc2Query: updateOutput,
  2221  		},
  2222  		{
  2223  			inputQuery:        insertInput,
  2224  			targetString:      "TestExecutor:40-60",
  2225  			expectedSbc2Query: insertOutput,
  2226  		},
  2227  		{
  2228  			inputQuery:        insertInput,
  2229  			targetString:      "TestExecutor:-20",
  2230  			expectedSbc1Query: insertOutput,
  2231  		},
  2232  	}
  2233  
  2234  	for _, tc := range tests {
  2235  		t.Run(tc.targetString+" - "+tc.inputQuery, func(t *testing.T) {
  2236  			executor, sbc1, sbc2, _ := createExecutorEnv()
  2237  
  2238  			primarySession.TargetString = tc.targetString
  2239  			_, err := executorExec(executor, tc.inputQuery, nil)
  2240  			require.NoError(t, err)
  2241  
  2242  			if tc.expectedSbc1Query == "" {
  2243  				require.Empty(t, sbc1.BatchQueries, "sbc1")
  2244  			} else {
  2245  				assertQueriesContain(t, tc.expectedSbc1Query, "sbc1", sbc1)
  2246  			}
  2247  
  2248  			if tc.expectedSbc2Query == "" {
  2249  				require.Empty(t, sbc2.BatchQueries)
  2250  			} else {
  2251  				assertQueriesContain(t, tc.expectedSbc2Query, "sbc2", sbc2)
  2252  			}
  2253  		})
  2254  	}
  2255  
  2256  	// it does not work for inserts
  2257  	executor, _, _, _ := createExecutorEnv()
  2258  	primarySession.TargetString = "TestExecutor[-]"
  2259  	_, err := executorExec(executor, insertInput, nil)
  2260  
  2261  	require.EqualError(t, err, "VT03023: INSERT not supported when targeting a key range: TestExecutor[-]")
  2262  
  2263  	primarySession.TargetString = ""
  2264  }
  2265  
  2266  func assertQueriesContain(t *testing.T, sql, sbcName string, sbc *sandboxconn.SandboxConn) {
  2267  	t.Helper()
  2268  	expectedQuery := []*querypb.BoundQuery{{
  2269  		Sql:           sql,
  2270  		BindVariables: map[string]*querypb.BindVariable{},
  2271  	}}
  2272  	assertQueries(t, sbc, expectedQuery)
  2273  }
  2274  
  2275  // Prepared statement tests
  2276  func TestUpdateEqualWithPrepare(t *testing.T) {
  2277  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2278  
  2279  	logChan := QueryLogger.Subscribe("Test")
  2280  	defer QueryLogger.Unsubscribe(logChan)
  2281  
  2282  	_, err := executorPrepare(executor, "update music set a = :a0 where id = :id0", map[string]*querypb.BindVariable{
  2283  		"a0":  sqltypes.Int64BindVariable(3),
  2284  		"id0": sqltypes.Int64BindVariable(2),
  2285  	})
  2286  	require.NoError(t, err)
  2287  
  2288  	var wantQueries []*querypb.BoundQuery
  2289  
  2290  	assertQueries(t, sbclookup, wantQueries)
  2291  	assertQueries(t, sbc2, nil)
  2292  	assertQueries(t, sbc1, nil)
  2293  }
  2294  func TestInsertShardedWithPrepare(t *testing.T) {
  2295  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2296  
  2297  	logChan := QueryLogger.Subscribe("Test")
  2298  	defer QueryLogger.Unsubscribe(logChan)
  2299  
  2300  	_, err := executorPrepare(executor, "insert into user(id, v, name) values (:_Id0, 2, ':_name_0')", map[string]*querypb.BindVariable{
  2301  		"_Id0":    sqltypes.Int64BindVariable(1),
  2302  		"_name_0": sqltypes.BytesBindVariable([]byte("myname")),
  2303  		"__seq0":  sqltypes.Int64BindVariable(1),
  2304  	})
  2305  	require.NoError(t, err)
  2306  
  2307  	var wantQueries []*querypb.BoundQuery
  2308  
  2309  	assertQueries(t, sbc1, wantQueries)
  2310  	assertQueries(t, sbc2, nil)
  2311  
  2312  	assertQueries(t, sbclookup, wantQueries)
  2313  }
  2314  
  2315  func TestDeleteEqualWithPrepare(t *testing.T) {
  2316  	executor, sbc, _, sbclookup := createExecutorEnv()
  2317  	_, err := executorPrepare(executor, "delete from user where id = :id0", map[string]*querypb.BindVariable{
  2318  		"id0": sqltypes.Int64BindVariable(1),
  2319  	})
  2320  	require.NoError(t, err)
  2321  
  2322  	var wantQueries []*querypb.BoundQuery
  2323  
  2324  	assertQueries(t, sbc, wantQueries)
  2325  
  2326  	assertQueries(t, sbclookup, wantQueries)
  2327  }
  2328  
  2329  func TestUpdateLastInsertID(t *testing.T) {
  2330  	executor, sbc1, _, _ := createExecutorEnv()
  2331  	executor.normalize = true
  2332  
  2333  	sql := "update user set a = last_insert_id() where id = 1"
  2334  	primarySession.LastInsertId = 43
  2335  	_, err := executorExec(executor, sql, map[string]*querypb.BindVariable{})
  2336  	require.NoError(t, err)
  2337  	wantQueries := []*querypb.BoundQuery{{
  2338  		Sql: "update `user` set a = :__lastInsertId where id = :id",
  2339  		BindVariables: map[string]*querypb.BindVariable{
  2340  			"__lastInsertId": sqltypes.Uint64BindVariable(43),
  2341  			"id":             sqltypes.Int64BindVariable(1)},
  2342  	}}
  2343  
  2344  	assertQueries(t, sbc1, wantQueries)
  2345  }
  2346  
  2347  func TestUpdateReference(t *testing.T) {
  2348  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2349  
  2350  	logChan := QueryLogger.Subscribe("Test")
  2351  	defer QueryLogger.Unsubscribe(logChan)
  2352  
  2353  	_, err := executorExec(executor, "update zip_detail set status = 'CLOSED' where id = 1", nil)
  2354  	require.NoError(t, err)
  2355  	wantQueries := []*querypb.BoundQuery{{
  2356  		Sql:           "update zip_detail set `status` = 'CLOSED' where id = 1",
  2357  		BindVariables: map[string]*querypb.BindVariable{},
  2358  	}}
  2359  	assertQueries(t, sbc1, nil)
  2360  	assertQueries(t, sbc2, nil)
  2361  	assertQueries(t, sbclookup, wantQueries)
  2362  
  2363  	testQueryLog(t, logChan, "TestExecute", "UPDATE", "update zip_detail set status = 'CLOSED' where id = 1", 1)
  2364  
  2365  	sbclookup.Queries = nil
  2366  
  2367  	_, err = executorExec(executor, "update TestUnsharded.zip_detail set status = 'CLOSED' where id = 1", nil)
  2368  	require.NoError(t, err)
  2369  	wantQueries = []*querypb.BoundQuery{{
  2370  		Sql:           "update zip_detail set `status` = 'CLOSED' where id = 1",
  2371  		BindVariables: map[string]*querypb.BindVariable{},
  2372  	}}
  2373  	assertQueries(t, sbc1, nil)
  2374  	assertQueries(t, sbc2, nil)
  2375  	assertQueries(t, sbclookup, wantQueries)
  2376  
  2377  	testQueryLog(t, logChan, "TestExecute", "UPDATE",
  2378  		"update TestUnsharded.zip_detail set status = 'CLOSED' where id = 1", 1)
  2379  
  2380  	sbclookup.Queries = nil
  2381  
  2382  	_, err = executorExec(executor, "update TestExecutor.zip_detail set status = 'CLOSED' where id = 1", nil)
  2383  	require.Error(t, err)
  2384  }
  2385  
  2386  func TestDeleteLookupOwnedEqual(t *testing.T) {
  2387  	executor, sbc1, sbc2, _ := createExecutorEnv()
  2388  
  2389  	sbc1.SetResults([]*sqltypes.Result{
  2390  		sqltypes.MakeTestResult(sqltypes.MakeTestFields("uniq_col|keyspace_id", "int64|varbinary"), "1|N±\u0090ɢú\u0016\u009C"),
  2391  	})
  2392  	_, err := executorExec(executor, "delete from t1 where unq_col = 1", nil)
  2393  	require.NoError(t, err)
  2394  	tupleBindVar, _ := sqltypes.BuildBindVariable([]int64{1})
  2395  	sbc1wantQueries := []*querypb.BoundQuery{{
  2396  		Sql: "select unq_col, keyspace_id from t1_lkp_idx where unq_col in ::__vals for update",
  2397  		BindVariables: map[string]*querypb.BindVariable{
  2398  			"__vals":  tupleBindVar,
  2399  			"unq_col": tupleBindVar,
  2400  		},
  2401  	}}
  2402  	sbc2wantQueries := []*querypb.BoundQuery{{
  2403  		Sql:           "select id, unq_col from t1 where unq_col = 1 for update",
  2404  		BindVariables: map[string]*querypb.BindVariable{},
  2405  	}, {
  2406  		Sql:           "delete from t1 where unq_col = 1",
  2407  		BindVariables: map[string]*querypb.BindVariable{},
  2408  	}}
  2409  	assertQueries(t, sbc1, sbc1wantQueries)
  2410  	assertQueries(t, sbc2, sbc2wantQueries)
  2411  }
  2412  
  2413  func TestDeleteReference(t *testing.T) {
  2414  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2415  
  2416  	logChan := QueryLogger.Subscribe("Test")
  2417  	defer QueryLogger.Unsubscribe(logChan)
  2418  
  2419  	_, err := executorExec(executor, "delete from zip_detail where id = 1", nil)
  2420  	require.NoError(t, err)
  2421  	wantQueries := []*querypb.BoundQuery{{
  2422  		Sql:           "delete from zip_detail where id = 1",
  2423  		BindVariables: map[string]*querypb.BindVariable{},
  2424  	}}
  2425  	assertQueries(t, sbc1, nil)
  2426  	assertQueries(t, sbc2, nil)
  2427  	assertQueries(t, sbclookup, wantQueries)
  2428  
  2429  	testQueryLog(t, logChan, "TestExecute", "DELETE", "delete from zip_detail where id = 1", 1)
  2430  
  2431  	sbclookup.Queries = nil
  2432  
  2433  	_, err = executorExec(executor, "delete from zip_detail where id = 1", nil)
  2434  	require.NoError(t, err)
  2435  	wantQueries = []*querypb.BoundQuery{{
  2436  		Sql:           "delete from zip_detail where id = 1",
  2437  		BindVariables: map[string]*querypb.BindVariable{},
  2438  	}}
  2439  	assertQueries(t, sbc1, nil)
  2440  	assertQueries(t, sbc2, nil)
  2441  	assertQueries(t, sbclookup, wantQueries)
  2442  
  2443  	testQueryLog(t, logChan, "TestExecute", "DELETE", "delete from zip_detail where id = 1", 1)
  2444  
  2445  	sbclookup.Queries = nil
  2446  
  2447  	_, err = executorExec(executor, "delete from TestExecutor.zip_detail where id = 1", nil)
  2448  	require.Error(t, err)
  2449  }
  2450  
  2451  func TestReservedConnDML(t *testing.T) {
  2452  	executor, _, _, sbc := createExecutorEnv()
  2453  
  2454  	logChan := QueryLogger.Subscribe("TestReservedConnDML")
  2455  	defer QueryLogger.Unsubscribe(logChan)
  2456  
  2457  	ctx := context.Background()
  2458  	session := NewAutocommitSession(&vtgatepb.Session{EnableSystemSettings: true})
  2459  
  2460  	_, err := executor.Execute(ctx, "TestReservedConnDML", session, "use "+KsTestUnsharded, nil)
  2461  	require.NoError(t, err)
  2462  
  2463  	wantQueries := []*querypb.BoundQuery{
  2464  		{Sql: "select 1 from dual where @@default_week_format != 1", BindVariables: map[string]*querypb.BindVariable{}},
  2465  	}
  2466  	sbc.SetResults([]*sqltypes.Result{
  2467  		sqltypes.MakeTestResult(sqltypes.MakeTestFields("id", "int64"), "1"),
  2468  	})
  2469  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "set default_week_format = 1", nil)
  2470  	require.NoError(t, err)
  2471  	assertQueries(t, sbc, wantQueries)
  2472  
  2473  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "begin", nil)
  2474  	require.NoError(t, err)
  2475  
  2476  	wantQueries = append(wantQueries,
  2477  		&querypb.BoundQuery{Sql: "set default_week_format = 1", BindVariables: map[string]*querypb.BindVariable{}},
  2478  		&querypb.BoundQuery{Sql: "insert into `simple`() values ()", BindVariables: map[string]*querypb.BindVariable{}})
  2479  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "insert into `simple`() values ()", nil)
  2480  	require.NoError(t, err)
  2481  	assertQueries(t, sbc, wantQueries)
  2482  
  2483  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "commit", nil)
  2484  	require.NoError(t, err)
  2485  
  2486  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "begin", nil)
  2487  	require.NoError(t, err)
  2488  
  2489  	sbc.EphemeralShardErr = mysql.NewSQLError(mysql.CRServerGone, mysql.SSNetError, "connection gone")
  2490  	// as the first time the query fails due to connection loss i.e. reserved conn lost. It will be recreated to set statement will be executed again.
  2491  	wantQueries = append(wantQueries,
  2492  		&querypb.BoundQuery{Sql: "set default_week_format = 1", BindVariables: map[string]*querypb.BindVariable{}},
  2493  		&querypb.BoundQuery{Sql: "insert into `simple`() values ()", BindVariables: map[string]*querypb.BindVariable{}})
  2494  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "insert into `simple`() values ()", nil)
  2495  	require.NoError(t, err)
  2496  	assertQueries(t, sbc, wantQueries)
  2497  
  2498  	_, err = executor.Execute(ctx, "TestReservedConnDML", session, "commit", nil)
  2499  	require.NoError(t, err)
  2500  }
  2501  
  2502  func TestStreamingDML(t *testing.T) {
  2503  	method := "TestStreamingDML"
  2504  
  2505  	executor, _, _, sbc := createExecutorEnv()
  2506  
  2507  	logChan := QueryLogger.Subscribe(method)
  2508  	defer QueryLogger.Unsubscribe(logChan)
  2509  
  2510  	ctx := context.Background()
  2511  	session := NewAutocommitSession(&vtgatepb.Session{})
  2512  
  2513  	tcases := []struct {
  2514  		query  string
  2515  		result *sqltypes.Result
  2516  
  2517  		inTx        bool
  2518  		openTx      bool
  2519  		changedRows int
  2520  		commitCount int
  2521  		expQuery    []*querypb.BoundQuery
  2522  	}{{
  2523  		query: "begin",
  2524  
  2525  		inTx:     true,
  2526  		expQuery: []*querypb.BoundQuery{},
  2527  	}, {
  2528  		query:  "insert into `simple`() values ()",
  2529  		result: &sqltypes.Result{RowsAffected: 1},
  2530  
  2531  		inTx:        true,
  2532  		openTx:      true,
  2533  		changedRows: 1,
  2534  		expQuery: []*querypb.BoundQuery{{
  2535  			Sql:           "insert into `simple`() values ()",
  2536  			BindVariables: map[string]*querypb.BindVariable{},
  2537  		}},
  2538  	}, {
  2539  		query:  "update `simple` set name = 'V' where col = 2",
  2540  		result: &sqltypes.Result{RowsAffected: 3},
  2541  
  2542  		inTx:        true,
  2543  		openTx:      true,
  2544  		changedRows: 3,
  2545  		expQuery: []*querypb.BoundQuery{{
  2546  			Sql:           "update `simple` set `name` = 'V' where col = 2",
  2547  			BindVariables: map[string]*querypb.BindVariable{},
  2548  		}},
  2549  	}, {
  2550  		query:  "delete from `simple`",
  2551  		result: &sqltypes.Result{RowsAffected: 12},
  2552  
  2553  		inTx:        true,
  2554  		openTx:      true,
  2555  		changedRows: 12,
  2556  		expQuery: []*querypb.BoundQuery{{
  2557  			Sql:           "delete from `simple`",
  2558  			BindVariables: map[string]*querypb.BindVariable{},
  2559  		}},
  2560  	}, {
  2561  		query: "commit",
  2562  
  2563  		commitCount: 1,
  2564  		expQuery:    []*querypb.BoundQuery{},
  2565  	}}
  2566  
  2567  	var qr *sqltypes.Result
  2568  	for _, tcase := range tcases {
  2569  		sbc.Queries = nil
  2570  		sbc.SetResults([]*sqltypes.Result{tcase.result})
  2571  		err := executor.StreamExecute(ctx, method, session, tcase.query, nil, func(result *sqltypes.Result) error {
  2572  			qr = result
  2573  			return nil
  2574  		})
  2575  		require.NoError(t, err)
  2576  		// should tx start
  2577  		assert.Equal(t, tcase.inTx, session.GetInTransaction())
  2578  		// open transaction
  2579  		assert.Equal(t, tcase.openTx, len(session.ShardSessions) > 0)
  2580  		// row affected as returned by result
  2581  		assert.EqualValues(t, tcase.changedRows, qr.RowsAffected)
  2582  		// match the query received on tablet
  2583  		assertQueries(t, sbc, tcase.expQuery)
  2584  
  2585  		assert.EqualValues(t, tcase.commitCount, sbc.CommitCount.Get())
  2586  	}
  2587  }
  2588  
  2589  func TestPartialVindexInsertQueryFailure(t *testing.T) {
  2590  	executor, sbc1, sbc2, _ := createExecutorEnv()
  2591  
  2592  	logChan := QueryLogger.Subscribe("Test")
  2593  	defer QueryLogger.Unsubscribe(logChan)
  2594  
  2595  	session := NewAutocommitSession(&vtgatepb.Session{})
  2596  	require.True(t, session.GetAutocommit())
  2597  	require.False(t, session.InTransaction())
  2598  
  2599  	_, err := executorExecSession(executor, "begin", nil, session.Session)
  2600  	require.NoError(t, err)
  2601  	require.True(t, session.GetAutocommit())
  2602  	require.True(t, session.InTransaction())
  2603  
  2604  	// fail the second lookup insert query i.e t1_lkp_idx(3, ksid)
  2605  	sbc2.MustFailExecute[sqlparser.StmtInsert] = 1
  2606  	wantQ := []*querypb.BoundQuery{{
  2607  		Sql:           "savepoint x",
  2608  		BindVariables: map[string]*querypb.BindVariable{},
  2609  	}, {
  2610  		Sql: "insert into t1_lkp_idx(unq_col, keyspace_id) values (:_unq_col_0, :keyspace_id_0)",
  2611  		BindVariables: map[string]*querypb.BindVariable{
  2612  			"unq_col_0":     sqltypes.Int64BindVariable(1),
  2613  			"keyspace_id_0": sqltypes.BytesBindVariable([]byte("\x16k@\xb4J\xbaK\xd6")),
  2614  			"unq_col_1":     sqltypes.Int64BindVariable(3),
  2615  			"keyspace_id_1": sqltypes.BytesBindVariable([]byte("\x06\xe7\xea\"Βp\x8f")),
  2616  			"_unq_col_0":    sqltypes.Int64BindVariable(1),
  2617  			"_unq_col_1":    sqltypes.Int64BindVariable(3),
  2618  		},
  2619  	}, {
  2620  		Sql:           "rollback to x",
  2621  		BindVariables: map[string]*querypb.BindVariable{},
  2622  	}}
  2623  
  2624  	_, err = executorExecSession(executor, "insert into t1(id, unq_col) values (1, 1), (2, 3)", nil, session.Session)
  2625  	require.Error(t, err)
  2626  	require.Contains(t, err.Error(), "reverted partial DML execution failure")
  2627  	require.True(t, session.GetAutocommit())
  2628  	require.True(t, session.InTransaction())
  2629  
  2630  	assertQueriesWithSavepoint(t, sbc1, wantQ)
  2631  
  2632  	// only parameter in expected query changes
  2633  	wantQ[1].Sql = "insert into t1_lkp_idx(unq_col, keyspace_id) values (:_unq_col_1, :keyspace_id_1)"
  2634  	assertQueriesWithSavepoint(t, sbc2, wantQ)
  2635  
  2636  	testQueryLog(t, logChan, "TestExecute", "BEGIN", "begin", 0)
  2637  	testQueryLog(t, logChan, "MarkSavepoint", "SAVEPOINT", "savepoint x", 0)
  2638  	testQueryLog(t, logChan, "VindexCreate", "SAVEPOINT_ROLLBACK", "rollback to x", 0)
  2639  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into t1(id, unq_col) values (1, 1), (2, 3)", 0)
  2640  }
  2641  
  2642  func TestPartialVindexInsertQueryFailureAutoCommit(t *testing.T) {
  2643  	executor, sbc1, sbc2, _ := createExecutorEnv()
  2644  
  2645  	logChan := QueryLogger.Subscribe("Test")
  2646  	defer QueryLogger.Unsubscribe(logChan)
  2647  
  2648  	session := NewAutocommitSession(&vtgatepb.Session{})
  2649  	require.True(t, session.GetAutocommit())
  2650  	require.False(t, session.InTransaction())
  2651  
  2652  	// fail the second lookup insert query i.e t1_lkp_idx(3, ksid)
  2653  	sbc2.MustFailExecute[sqlparser.StmtInsert] = 1
  2654  	wantQ := []*querypb.BoundQuery{{
  2655  		Sql: "insert into t1_lkp_idx(unq_col, keyspace_id) values (:_unq_col_0, :keyspace_id_0)",
  2656  		BindVariables: map[string]*querypb.BindVariable{
  2657  			"unq_col_0":     sqltypes.Int64BindVariable(1),
  2658  			"keyspace_id_0": sqltypes.BytesBindVariable([]byte("\x16k@\xb4J\xbaK\xd6")),
  2659  			"unq_col_1":     sqltypes.Int64BindVariable(3),
  2660  			"keyspace_id_1": sqltypes.BytesBindVariable([]byte("\x06\xe7\xea\"Βp\x8f")),
  2661  			"_unq_col_0":    sqltypes.Int64BindVariable(1),
  2662  			"_unq_col_1":    sqltypes.Int64BindVariable(3),
  2663  		},
  2664  	}}
  2665  
  2666  	_, err := executorExecSession(executor, "insert into t1(id, unq_col) values (1, 1), (2, 3)", nil, session.Session)
  2667  	require.Error(t, err)
  2668  	assert.Contains(t, err.Error(), "transaction rolled back to reverse changes of partial DML execution")
  2669  	assert.True(t, session.GetAutocommit())
  2670  	assert.False(t, session.InTransaction())
  2671  
  2672  	assertQueriesWithSavepoint(t, sbc1, wantQ)
  2673  
  2674  	// only parameter in expected query changes
  2675  	wantQ[0].Sql = "insert into t1_lkp_idx(unq_col, keyspace_id) values (:_unq_col_1, :keyspace_id_1)"
  2676  	assertQueriesWithSavepoint(t, sbc2, wantQ)
  2677  
  2678  	testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into t1_lkp_idx(unq_col, keyspace_id) values(:unq_col_0, :keyspace_id_0), (:unq_col_1, :keyspace_id_1)", 2)
  2679  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into t1(id, unq_col) values (1, 1), (2, 3)", 0)
  2680  }
  2681  
  2682  // TestMultiInternalSavepoint shows that the internal savepoint created for rolling back any partial dml changes on a failure is not removed from the savepoint list.
  2683  // Any new transaction opened on a different shard will apply those savepoints as well.
  2684  // The change for it cannot be done as the executor level and will be made at the VTGate entry point.
  2685  // Test TestMultiInternalSavepointVtGate shows that it fixes the behaviour.
  2686  func TestMultiInternalSavepoint(t *testing.T) {
  2687  	executor, sbc1, sbc2, _ := createExecutorEnv()
  2688  
  2689  	session := NewAutocommitSession(&vtgatepb.Session{})
  2690  	_, err := executorExecSession(executor, "begin", nil, session.Session)
  2691  	require.NoError(t, err)
  2692  
  2693  	// this query goes to multiple shards so internal savepoint will be created.
  2694  	_, err = executorExecSession(executor, "insert into user_extra(user_id) values (1), (4)", nil, session.Session)
  2695  	require.NoError(t, err)
  2696  
  2697  	wantQ := []*querypb.BoundQuery{{
  2698  		Sql:           "savepoint x",
  2699  		BindVariables: map[string]*querypb.BindVariable{},
  2700  	}, {
  2701  		Sql: "insert into user_extra(user_id) values (:_user_id_0)",
  2702  		BindVariables: map[string]*querypb.BindVariable{
  2703  			"_user_id_0": sqltypes.Int64BindVariable(1),
  2704  			"_user_id_1": sqltypes.Int64BindVariable(4),
  2705  		},
  2706  	}}
  2707  	assertQueriesWithSavepoint(t, sbc1, wantQ)
  2708  	require.Len(t, sbc2.Queries, 0)
  2709  	sbc1.Queries = nil
  2710  
  2711  	_, err = executorExecSession(executor, "insert into user_extra(user_id) values (3), (6)", nil, session.Session)
  2712  	require.NoError(t, err)
  2713  	wantQ = []*querypb.BoundQuery{{
  2714  		Sql:           "savepoint x",
  2715  		BindVariables: map[string]*querypb.BindVariable{},
  2716  	}, {
  2717  		Sql:           "savepoint y",
  2718  		BindVariables: map[string]*querypb.BindVariable{},
  2719  	}, {
  2720  		Sql: "insert into user_extra(user_id) values (:_user_id_0)",
  2721  		BindVariables: map[string]*querypb.BindVariable{
  2722  			"_user_id_0": sqltypes.Int64BindVariable(3),
  2723  			"_user_id_1": sqltypes.Int64BindVariable(6),
  2724  		},
  2725  	}}
  2726  	assertQueriesWithSavepoint(t, sbc2, wantQ)
  2727  	wantQ = []*querypb.BoundQuery{{
  2728  		Sql:           "savepoint y",
  2729  		BindVariables: map[string]*querypb.BindVariable{},
  2730  	}}
  2731  	assertQueriesWithSavepoint(t, sbc1, wantQ)
  2732  }
  2733  
  2734  func TestInsertSelectFromDual(t *testing.T) {
  2735  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2736  
  2737  	logChan := QueryLogger.Subscribe("TestInsertSelect")
  2738  	defer QueryLogger.Unsubscribe(logChan)
  2739  
  2740  	session := NewAutocommitSession(&vtgatepb.Session{})
  2741  
  2742  	query := "insert into user(id, v, name) select 1, 2, 'myname' from dual"
  2743  	wantQueries := []*querypb.BoundQuery{{
  2744  		Sql: "insert into `user`(id, v, `name`) values (:_c0_0, :_c0_1, :_c0_2)",
  2745  		BindVariables: map[string]*querypb.BindVariable{
  2746  			"_c0_0": sqltypes.Int64BindVariable(1),
  2747  			"_c0_1": sqltypes.Int64BindVariable(2),
  2748  			"_c0_2": sqltypes.StringBindVariable("myname"),
  2749  		},
  2750  	}}
  2751  
  2752  	wantlkpQueries := []*querypb.BoundQuery{{
  2753  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0)",
  2754  		BindVariables: map[string]*querypb.BindVariable{
  2755  			"name_0":    sqltypes.StringBindVariable("myname"),
  2756  			"user_id_0": sqltypes.Uint64BindVariable(1),
  2757  		},
  2758  	}}
  2759  
  2760  	for _, workload := range []string{"olap", "oltp"} {
  2761  		sbc1.Queries = nil
  2762  		sbc2.Queries = nil
  2763  		sbclookup.Queries = nil
  2764  		wQuery := fmt.Sprintf("set @@workload = %s", workload)
  2765  		_, err := executor.Execute(context.Background(), "TestInsertSelect", session, wQuery, nil)
  2766  		require.NoError(t, err)
  2767  
  2768  		_, err = executor.Execute(context.Background(), "TestInsertSelect", session, query, nil)
  2769  		require.NoError(t, err)
  2770  
  2771  		assertQueries(t, sbc1, wantQueries)
  2772  		assertQueries(t, sbc2, nil)
  2773  		assertQueries(t, sbclookup, wantlkpQueries)
  2774  
  2775  		testQueryLog(t, logChan, "TestInsertSelect", "SET", wQuery, 0)
  2776  		testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_user_map(name, user_id) values(:name_0, :user_id_0)", 1)
  2777  		testQueryLog(t, logChan, "TestInsertSelect", "INSERT", "insert into user(id, v, name) select 1, 2, 'myname' from dual", 1)
  2778  	}
  2779  }
  2780  
  2781  func TestInsertSelectFromTable(t *testing.T) {
  2782  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2783  
  2784  	logChan := QueryLogger.Subscribe("TestInsertSelect")
  2785  	defer QueryLogger.Unsubscribe(logChan)
  2786  
  2787  	session := NewAutocommitSession(&vtgatepb.Session{})
  2788  
  2789  	query := "insert into user(id, name) select c1, c2 from music"
  2790  	wantQueries := []*querypb.BoundQuery{{
  2791  		Sql:           "select c1, c2 from music for update",
  2792  		BindVariables: map[string]*querypb.BindVariable{},
  2793  	}, {
  2794  		Sql: "insert into `user`(id, `name`) values (:_c0_0, :_c0_1), (:_c1_0, :_c1_1), (:_c2_0, :_c2_1), (:_c3_0, :_c3_1), (:_c4_0, :_c4_1), (:_c5_0, :_c5_1), (:_c6_0, :_c6_1), (:_c7_0, :_c7_1)",
  2795  		BindVariables: map[string]*querypb.BindVariable{
  2796  			"_c0_0": sqltypes.Int32BindVariable(1), "_c0_1": sqltypes.StringBindVariable("foo"),
  2797  			"_c1_0": sqltypes.Int32BindVariable(1), "_c1_1": sqltypes.StringBindVariable("foo"),
  2798  			"_c2_0": sqltypes.Int32BindVariable(1), "_c2_1": sqltypes.StringBindVariable("foo"),
  2799  			"_c3_0": sqltypes.Int32BindVariable(1), "_c3_1": sqltypes.StringBindVariable("foo"),
  2800  			"_c4_0": sqltypes.Int32BindVariable(1), "_c4_1": sqltypes.StringBindVariable("foo"),
  2801  			"_c5_0": sqltypes.Int32BindVariable(1), "_c5_1": sqltypes.StringBindVariable("foo"),
  2802  			"_c6_0": sqltypes.Int32BindVariable(1), "_c6_1": sqltypes.StringBindVariable("foo"),
  2803  			"_c7_0": sqltypes.Int32BindVariable(1), "_c7_1": sqltypes.StringBindVariable("foo"),
  2804  		},
  2805  	}}
  2806  
  2807  	wantlkpQueries := []*querypb.BoundQuery{{
  2808  		Sql: "insert into name_user_map(`name`, user_id) values (:name_0, :user_id_0), (:name_1, :user_id_1), (:name_2, :user_id_2), (:name_3, :user_id_3), (:name_4, :user_id_4), (:name_5, :user_id_5), (:name_6, :user_id_6), (:name_7, :user_id_7)",
  2809  		BindVariables: map[string]*querypb.BindVariable{
  2810  			"name_0": sqltypes.StringBindVariable("foo"), "user_id_0": sqltypes.Uint64BindVariable(1),
  2811  			"name_1": sqltypes.StringBindVariable("foo"), "user_id_1": sqltypes.Uint64BindVariable(1),
  2812  			"name_2": sqltypes.StringBindVariable("foo"), "user_id_2": sqltypes.Uint64BindVariable(1),
  2813  			"name_3": sqltypes.StringBindVariable("foo"), "user_id_3": sqltypes.Uint64BindVariable(1),
  2814  			"name_4": sqltypes.StringBindVariable("foo"), "user_id_4": sqltypes.Uint64BindVariable(1),
  2815  			"name_5": sqltypes.StringBindVariable("foo"), "user_id_5": sqltypes.Uint64BindVariable(1),
  2816  			"name_6": sqltypes.StringBindVariable("foo"), "user_id_6": sqltypes.Uint64BindVariable(1),
  2817  			"name_7": sqltypes.StringBindVariable("foo"), "user_id_7": sqltypes.Uint64BindVariable(1),
  2818  		},
  2819  	}}
  2820  
  2821  	for _, workload := range []string{"olap", "oltp"} {
  2822  		sbc1.Queries = nil
  2823  		sbc2.Queries = nil
  2824  		sbclookup.Queries = nil
  2825  		wQuery := fmt.Sprintf("set @@workload = %s", workload)
  2826  		_, err := executor.Execute(context.Background(), "TestInsertSelect", session, wQuery, nil)
  2827  		require.NoError(t, err)
  2828  
  2829  		_, err = executor.Execute(context.Background(), "TestInsertSelect", session, query, nil)
  2830  		require.NoError(t, err)
  2831  
  2832  		assertQueries(t, sbc1, wantQueries)
  2833  		assertQueries(t, sbc2, wantQueries[:1]) // select scatter query went scatter.
  2834  		assertQueries(t, sbclookup, wantlkpQueries)
  2835  
  2836  		testQueryLog(t, logChan, "TestInsertSelect", "SET", wQuery, 0)
  2837  		testQueryLog(t, logChan, "VindexCreate", "INSERT", "insert into name_user_map(name, user_id) values(:name_0, :user_id_0), (:name_1, :user_id_1), (:name_2, :user_id_2), (:name_3, :user_id_3), (:name_4, :user_id_4), (:name_5, :user_id_5), (:name_6, :user_id_6), (:name_7, :user_id_7)", 1)
  2838  		testQueryLog(t, logChan, "TestInsertSelect", "INSERT", "insert into user(id, name) select c1, c2 from music", 9) // 8 from select and 1 from insert.
  2839  	}
  2840  }
  2841  
  2842  func TestInsertReference(t *testing.T) {
  2843  	executor, sbc1, sbc2, sbclookup := createExecutorEnv()
  2844  
  2845  	logChan := QueryLogger.Subscribe("Test")
  2846  	defer QueryLogger.Unsubscribe(logChan)
  2847  
  2848  	_, err := executorExec(executor, "insert into zip_detail(id, status) values (1, 'CLOSED')", nil)
  2849  	require.NoError(t, err)
  2850  	wantQueries := []*querypb.BoundQuery{{
  2851  		Sql:           "insert into zip_detail(id, `status`) values (1, 'CLOSED')",
  2852  		BindVariables: map[string]*querypb.BindVariable{},
  2853  	}}
  2854  	assertQueries(t, sbc1, nil)
  2855  	assertQueries(t, sbc2, nil)
  2856  	assertQueries(t, sbclookup, wantQueries)
  2857  
  2858  	testQueryLog(t, logChan, "TestExecute", "INSERT", "insert into zip_detail(id, status) values (1, 'CLOSED')", 1)
  2859  
  2860  	sbclookup.Queries = nil
  2861  
  2862  	_, err = executorExec(executor, "insert into TestUnsharded.zip_detail(id, status) values (1, 'CLOSED')", nil)
  2863  	require.NoError(t, err)
  2864  	wantQueries = []*querypb.BoundQuery{{
  2865  		Sql:           "insert into zip_detail(id, `status`) values (1, 'CLOSED')",
  2866  		BindVariables: map[string]*querypb.BindVariable{},
  2867  	}}
  2868  	assertQueries(t, sbc1, nil)
  2869  	assertQueries(t, sbc2, nil)
  2870  	assertQueries(t, sbclookup, wantQueries)
  2871  
  2872  	testQueryLog(t, logChan, "TestExecute", "INSERT",
  2873  		"insert into TestUnsharded.zip_detail(id, status) values (1, 'CLOSED')", 1)
  2874  
  2875  	sbclookup.Queries = nil
  2876  
  2877  	_, err = executorExec(executor, "insert into TestExecutor.zip_detail(id, status) values (1, 'CLOSED')", nil)
  2878  	require.Error(t, err)
  2879  }