diff --git a/go/vt/vtgate/engine/insert.go b/go/vt/vtgate/engine/insert.go index 6a6e2d4f014..80696fcc2d5 100644 --- a/go/vt/vtgate/engine/insert.go +++ b/go/vt/vtgate/engine/insert.go @@ -451,9 +451,6 @@ func (ins *Insert) processPrimary(vcursor VCursor, vindexKeys [][]sqltypes.Value func (ins *Insert) processOwned(vcursor VCursor, vindexColumnsKeys [][]sqltypes.Value, colVindex *vindexes.ColumnVindex, bv map[string]*querypb.BindVariable, ksids [][]byte) error { for rowNum, rowColumnKeys := range vindexColumnsKeys { for colIdx, vindexKey := range rowColumnKeys { - if vindexKey.IsNull() { - return fmt.Errorf("value must be supplied for column %v", colVindex.Columns[colIdx]) - } col := colVindex.Columns[colIdx] bv[insertVarName(col, rowNum)] = sqltypes.ValueBindVariable(vindexKey) } @@ -476,9 +473,6 @@ func (ins *Insert) processOwnedIgnore(vcursor VCursor, vindexColumnsKeys [][]sql createKsids = append(createKsids, ksids[rowNum]) for colIdx, vindexKey := range rowColumnKeys { - if vindexKey.IsNull() { - return fmt.Errorf("value must be supplied for column %v", colVindex.Columns) - } rowKeys = append(rowKeys, vindexKey) col := colVindex.Columns[colIdx] bv[insertVarName(col, rowNum)] = sqltypes.ValueBindVariable(vindexKey) diff --git a/go/vt/vtgate/engine/insert_test.go b/go/vt/vtgate/engine/insert_test.go index 2ebf3f63e3a..5353588c73d 100644 --- a/go/vt/vtgate/engine/insert_test.go +++ b/go/vt/vtgate/engine/insert_test.go @@ -560,7 +560,7 @@ func TestInsertShardedOwned(t *testing.T) { }) } -func TestInsertShardedOwnedFail(t *testing.T) { +func TestInsertShardedOwnedWithNull(t *testing.T) { invschema := &vschemapb.SrvVSchema{ Keyspaces: map[string]*vschemapb.Keyspace{ "sharded": { @@ -626,11 +626,20 @@ func TestInsertShardedOwnedFail(t *testing.T) { } vc := &loggingVCursor{ - shards: []string{"-20", "20-"}, + shards: []string{"-20", "20-"}, + shardForKsid: []string{"20-", "-20", "20-"}, } - // No reverse map available for lookup. So, it will fail. _, err = ins.Execute(vc, map[string]*querypb.BindVariable{}, false) - expectError(t, "Execute", err, "execInsertSharded: getInsertShardedRoute: value must be supplied for column c3") + if err != nil { + t.Fatal(err) + } + vc.ExpectLog(t, []string{ + `Execute insert into lkp1(from, toc) values(:from0, :toc0) from0: toc0: type:VARBINARY ` + + `value:"\026k@\264J\272K\326" true`, + `ResolveDestinations sharded [value:"0" ] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, + `ExecuteMultiShard sharded.20-: prefix mid1 suffix /* vtgate:: keyspace_id:166b40b44aba4bd6 */ ` + + `{_c30: _id0: type:INT64 value:"1" } true true`, + }) } func TestInsertShardedIgnoreOwned(t *testing.T) { @@ -824,7 +833,7 @@ func TestInsertShardedIgnoreOwned(t *testing.T) { }) } -func TestInsertShardedIgnoreOwnedFail(t *testing.T) { +func TestInsertShardedIgnoreOwnedWithNull(t *testing.T) { invschema := &vschemapb.SrvVSchema{ Keyspaces: map[string]*vschemapb.Keyspace{ "sharded": { @@ -889,11 +898,35 @@ func TestInsertShardedIgnoreOwnedFail(t *testing.T) { Suffix: " suffix", } + ksid0 := sqltypes.MakeTestResult( + sqltypes.MakeTestFields( + "to", + "varbinary", + ), + "\x00", + ) + //noresult := &sqltypes.Result{} vc := &loggingVCursor{ - shards: []string{"-20", "20-"}, + shards: []string{"-20", "20-"}, + shardForKsid: []string{"-20", "20-"}, + results: []*sqltypes.Result{ + ksid0, + ksid0, + ksid0, + }, } _, err = ins.Execute(vc, map[string]*querypb.BindVariable{}, false) - expectError(t, "Execute", err, "execInsertSharded: getInsertShardedRoute: value must be supplied for column [c3]") + if err != nil { + t.Fatal(err) + } + vc.ExpectLog(t, []string{ + `Execute insert ignore into lkp1(from, toc) values(:from0, :toc0) from0: toc0: type:VARBINARY ` + + `value:"\026k@\264J\272K\326" true`, + `Execute select from from lkp1 where from = :from and toc = :toc from: toc: type:VARBINARY value:"\026k@\264J\272K\326" true`, + `ResolveDestinations sharded [value:"0" ] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, + `ExecuteMultiShard sharded.-20: prefix mid1 suffix /* vtgate:: keyspace_id:166b40b44aba4bd6 */ ` + + `{_c30: _id0: type:INT64 value:"1" } true true`, + }) } func TestInsertShardedUnownedVerify(t *testing.T) { diff --git a/go/vt/vtgate/vindexes/lookup_hash_test.go b/go/vt/vtgate/vindexes/lookup_hash_test.go index ee8606704af..7cd9692d3e2 100644 --- a/go/vt/vtgate/vindexes/lookup_hash_test.go +++ b/go/vt/vtgate/vindexes/lookup_hash_test.go @@ -154,6 +154,39 @@ func TestLookupHashMapAbsent(t *testing.T) { } } +func TestLookupHashMapNull(t *testing.T) { + lookuphash := createLookup(t, "lookup_hash", false) + vc := &vcursor{numRows: 1} + + got, err := lookuphash.Map(vc, []sqltypes.Value{sqltypes.NULL}) + if err != nil { + t.Error(err) + } + want := []key.Destination{ + key.DestinationKeyspaceIDs([][]byte{ + []byte("\x16k@\xb4J\xbaK\xd6"), + }), + } + if !reflect.DeepEqual(got, want) { + t.Errorf("Map(): %#v, want %+v", got, want) + } + + // writeOnly true should return full keyranges. + lookuphash = createLookup(t, "lookup_hash", true) + got, err = lookuphash.Map(vc, []sqltypes.Value{sqltypes.NULL}) + if err != nil { + t.Error(err) + } + want = []key.Destination{ + key.DestinationKeyRange{ + KeyRange: &topodatapb.KeyRange{}, + }, + } + if !reflect.DeepEqual(got, want) { + t.Errorf("Map(): %#v, want %+v", got, want) + } +} + func TestLookupHashVerify(t *testing.T) { lookuphash := createLookup(t, "lookup_hash", false) vc := &vcursor{numRows: 1} @@ -216,6 +249,15 @@ func TestLookupHashCreate(t *testing.T) { t.Errorf("vc.queries length: %v, want %v", got, want) } + vc.queries = nil + err = lookuphash.(Lookup).Create(vc, [][]sqltypes.Value{{sqltypes.NULL}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false /* ignoreMode */) + if err != nil { + t.Error(err) + } + if got, want := len(vc.queries), 1; got != want { + t.Errorf("vc.queries length: %v, want %v", got, want) + } + err = lookuphash.(Lookup).Create(vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, [][]byte{[]byte("bogus")}, false /* ignoreMode */) want := "lookup.Create.vunhash: invalid keyspace id: 626f677573" if err == nil || err.Error() != want { @@ -235,6 +277,15 @@ func TestLookupHashDelete(t *testing.T) { t.Errorf("vc.queries length: %v, want %v", got, want) } + vc.queries = nil + err = lookuphash.(Lookup).Delete(vc, [][]sqltypes.Value{{sqltypes.NULL}}, []byte("\x16k@\xb4J\xbaK\xd6")) + if err != nil { + t.Error(err) + } + if got, want := len(vc.queries), 1; got != want { + t.Errorf("vc.queries length: %v, want %v", got, want) + } + err = lookuphash.(Lookup).Delete(vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, []byte("bogus")) want := "lookup.Delete.vunhash: invalid keyspace id: 626f677573" if err == nil || err.Error() != want { @@ -253,4 +304,13 @@ func TestLookupHashUpdate(t *testing.T) { if got, want := len(vc.queries), 2; got != want { t.Errorf("vc.queries length: %v, want %v", got, want) } + + vc.queries = nil + err = lookuphash.(Lookup).Update(vc, []sqltypes.Value{sqltypes.NULL}, []byte("\x16k@\xb4J\xbaK\xd6"), []sqltypes.Value{sqltypes.NewInt64(2)}) + if err != nil { + t.Error(err) + } + if got, want := len(vc.queries), 2; got != want { + t.Errorf("vc.queries length: %v, want %v", got, want) + } }