Skip to content
Merged
10 changes: 9 additions & 1 deletion changelog/18.0/18.0.0/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
- **[Deprecations and Deletions](#deprecations-and-deletions)**
- [Deleted `k8stopo`](#deleted-k8stopo)
- [Deleted `vtgr`](#deleted-vtgr)
- **[New stats](#new-stats)**
- [VTGate Vindex unknown parameters](#vtgate-vindex-unknown-parameters)

## <a id="major-changes"/>Major Changes

Expand Down Expand Up @@ -38,4 +40,10 @@ The `k8stopo` has been deprecated in Vitess 17, also see https://github.com/vite

#### <a id="deleted-vtgr"/>Deleted `vtgr`

The `vtgr` has been deprecated in Vitess 17, also see https://github.com/vitessio/vitess/issues/13300. With Vitess 18 `vtgr` has been removed.
The `vtgr` has been deprecated in Vitess 17, also see https://github.com/vitessio/vitess/issues/13300. With Vitess 18 `vtgr` has been removed.

### <a id="new-stats"/>New stats

#### <a id="vtgate-vindex-unknown-parameters"/>VTGate Vindex unknown parameters

The VTGate stat `VindexUnknownParameters` gauges unknown Vindex parameters found in the latest VSchema pulled from the topology.
2 changes: 1 addition & 1 deletion go/vt/topo/vschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
// SaveVSchema first validates the VSchema, then saves it.
// If the VSchema is empty, just remove it.
func (ts *Server) SaveVSchema(ctx context.Context, keyspace string, vschema *vschemapb.Keyspace) error {
err := vindexes.ValidateKeyspace(vschema)
_, err := vindexes.BuildKeyspace(vschema)
if err != nil {
return err
}
Expand Down
18 changes: 18 additions & 0 deletions go/vt/vtctl/testdata/unknown-params-logged-dry-run-vschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"sharded": true,
"vindexes": {
"hash_vdx" : {
"type": "hash",
"params": {
"foo": "bar",
"hello": "world"
}
},
"binary_vdx": {
"type": "binary",
"params": {
"hello": "world"
}
}
}
}
18 changes: 18 additions & 0 deletions go/vt/vtctl/testdata/unknown-params-logged-vschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"sharded": true,
"vindexes": {
"binary_vdx": {
"type": "binary",
"params": {
"hello": "world"
}
},
"hash_vdx": {
"type": "hash",
"params": {
"foo": "bar",
"hello": "world"
}
}
}
}
22 changes: 22 additions & 0 deletions go/vt/vtctl/vtctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import (
"vitess.io/vitess/go/vt/topotools"
"vitess.io/vitess/go/vt/vtctl/workflow"
"vitess.io/vitess/go/vt/vterrors"
"vitess.io/vitess/go/vt/vtgate/vindexes"
"vitess.io/vitess/go/vt/wrangler"
)

Expand Down Expand Up @@ -3335,6 +3336,27 @@ func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *p
wr.Logger().Printf("New VSchema object:\n%s\nIf this is not what you expected, check the input data (as JSON parsing will skip unexpected fields).\n", b)
}

// Validate the VSchema.
ksVs, err := vindexes.BuildKeyspace(vs)
if err != nil {
return err
}

// Log unknown Vindex params as warnings.
var vdxNames []string
for name := range ksVs.Vindexes {
vdxNames = append(vdxNames, name)
}
sort.Strings(vdxNames)
for _, name := range vdxNames {
vdx := ksVs.Vindexes[name]
if val, ok := vdx.(vindexes.ParamValidating); ok {
for _, param := range val.UnknownParams() {
wr.Logger().Warningf("Unknown param in vindex %s: %s", name, param)
}
}
}

if *dryRun {
wr.Logger().Printf("Dry run: Skipping update of VSchema\n")
return nil
Expand Down
105 changes: 105 additions & 0 deletions go/vt/vtctl/vtctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ package vtctl

import (
"context"
_ "embed"
"fmt"
"regexp"
"strings"
"testing"
"time"
Expand All @@ -32,6 +34,109 @@ import (
"vitess.io/vitess/go/vt/wrangler"
)

var (
//go:embed testdata/unknown-params-logged-vschema.json
unknownParamsLoggedVSchema string

//go:embed testdata/unknown-params-logged-dry-run-vschema.json
unknownParamsLoggedDryRunVSchema string
)

// TestApplyVSchema tests the the MoveTables client command
// via the commandVRApplyVSchema() cmd handler.
func TestApplyVSchema(t *testing.T) {
shard := "0"
ks := "ks"
ctx := context.Background()
env := newTestVTCtlEnv()
defer env.close()
_ = env.addTablet(100, ks, shard, &topodatapb.KeyRange{}, topodatapb.TabletType_PRIMARY)

tests := []struct {
name string
args []string
expectResults func()
want string
}{
{
name: "EmptyVSchema",
args: []string{"--vschema", "{}", ks},
want: "New VSchema object:\n{}\nIf this is not what you expected, check the input data (as JSON parsing will skip unexpected fields).\n\n",
},
{
name: "UnknownParamsLogged",
args: []string{"--vschema", unknownParamsLoggedVSchema, ks},
want: `/New VSchema object:
{
"sharded": true,
"vindexes": {
"binary_vdx": {
"type": "binary",
"params": {
"hello": "world"
}
},
"hash_vdx": {
"type": "hash",
"params": {
"foo": "bar",
"hello": "world"
}
}
}
}
If this is not what you expected, check the input data \(as JSON parsing will skip unexpected fields\)\.

.*W.* .* vtctl.go:.* Unknown param in vindex binary_vdx: hello
W.* .* vtctl.go:.* Unknown param in vindex hash_vdx: foo
W.* .* vtctl.go:.* Unknown param in vindex hash_vdx: hello`,
},
{
name: "UnknownParamsLoggedWithDryRun",
args: []string{"--vschema", unknownParamsLoggedDryRunVSchema, "--dry-run", ks},
want: `/New VSchema object:
{
"sharded": true,
"vindexes": {
"binary_vdx": {
"type": "binary",
"params": {
"hello": "world"
}
},
"hash_vdx": {
"type": "hash",
"params": {
"foo": "bar",
"hello": "world"
}
}
}
}
If this is not what you expected, check the input data \(as JSON parsing will skip unexpected fields\)\.

.*W.* .* vtctl.go:.* Unknown param in vindex binary_vdx: hello
W.* .* vtctl.go:.* Unknown param in vindex hash_vdx: foo
W.* .* vtctl.go:.* Unknown param in vindex hash_vdx: hello
Dry run: Skipping update of VSchema`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
subFlags := pflag.NewFlagSet("test", pflag.ContinueOnError)
err := commandApplyVSchema(ctx, env.wr, subFlags, tt.args)
require.NoError(t, err)
if strings.HasPrefix(tt.want, "/") {
require.Regexp(t, regexp.MustCompile(tt.want[1:]), env.cmdlog.String())
} else {
require.Equal(t, tt.want, env.cmdlog.String())
}
env.cmdlog.Clear()
env.tmc.clearResults()
})
}
}

// TestMoveTables tests the the MoveTables client command
// via the commandVRWorkflow() cmd handler.
// This currently only tests the Progress action (which is
Expand Down
7 changes: 7 additions & 0 deletions go/vt/vtgate/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,13 @@ func (e *Executor) SaveVSchema(vschema *vindexes.VSchema, stats *VSchemaStats) {
vschemaCounters.Add("Reload", 1)
}

if vindexUnknownParams != nil {
var unknownParams int
for _, ks := range stats.Keyspaces {
unknownParams += ks.VindexUnknownParamsCount
}
vindexUnknownParams.Set(int64(unknownParams))
}
}

// ParseDestinationTarget parses destination target string and sets default keyspace if possible.
Expand Down
10 changes: 5 additions & 5 deletions go/vt/vtgate/vindexes/binarymd5.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ var (

// BinaryMD5 is a vindex that hashes binary bits to a keyspace id.
type BinaryMD5 struct {
name string
params map[string]string
name string
unknownParams []string
}

// newBinaryMD5 creates a new BinaryMD5.
func newBinaryMD5(name string, params map[string]string) (Vindex, error) {
return &BinaryMD5{
name: name,
params: params,
name: name,
unknownParams: FindUnknownParams(params, nil),
}, nil
}

Expand Down Expand Up @@ -101,7 +101,7 @@ func (vind *BinaryMD5) Hash(id sqltypes.Value) ([]byte, error) {

// UnknownParams implements the ParamValidating interface.
func (vind *BinaryMD5) UnknownParams() []string {
return FindUnknownParams(vind.params, nil)
return vind.unknownParams
}

func vMD5Hash(source []byte) []byte {
Expand Down
22 changes: 6 additions & 16 deletions go/vt/vtgate/vindexes/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions go/vt/vtgate/vindexes/vschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,10 @@ func BuildKeyspaceSchema(input *vschemapb.Keyspace, keyspace string) (*KeyspaceS
return vschema.Keyspaces[keyspace], err
}

// ValidateKeyspace ensures that the keyspace vschema is valid.
// BuildKeyspace ensures that the keyspace vschema is valid.
// External references (like sequence) are not validated.
func ValidateKeyspace(input *vschemapb.Keyspace) error {
_, err := BuildKeyspaceSchema(input, "")
return err
func BuildKeyspace(input *vschemapb.Keyspace) (*KeyspaceSchema, error) {
return BuildKeyspaceSchema(input, "")
}

func buildKeyspaces(source *vschemapb.SrvVSchema, vschema *VSchema) {
Expand Down
6 changes: 3 additions & 3 deletions go/vt/vtgate/vindexes/vschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func init() {
}

func TestUnshardedVSchemaValid(t *testing.T) {
err := ValidateKeyspace(&vschemapb.Keyspace{
_, err := BuildKeyspace(&vschemapb.Keyspace{
Sharded: false,
Vindexes: make(map[string]*vschemapb.Vindex),
Tables: make(map[string]*vschemapb.Table),
Expand Down Expand Up @@ -2432,7 +2432,7 @@ func TestValidate(t *testing.T) {
"t2": {},
},
}
err := ValidateKeyspace(good)
_, err := BuildKeyspace(good)
require.NoError(t, err)
bad := &vschemapb.Keyspace{
Sharded: true,
Expand All @@ -2445,7 +2445,7 @@ func TestValidate(t *testing.T) {
"t2": {},
},
}
err = ValidateKeyspace(bad)
_, err = BuildKeyspace(bad)
want := `vindexType "absent" not found`
if err == nil || !strings.HasPrefix(err.Error(), want) {
t.Errorf("Validate: %v, must start with %s", err, want)
Expand Down
18 changes: 13 additions & 5 deletions go/vt/vtgate/vschema_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ type VSchemaStats struct {
// VSchemaKeyspaceStats contains a rollup of the VSchema stats for a keyspace.
// It is used to display a table with the information in the status page.
type VSchemaKeyspaceStats struct {
Keyspace string
Sharded bool
TableCount int
VindexCount int
Error string
Keyspace string
Sharded bool
TableCount int
VindexCount int
VindexUnknownParamsCount int
Error string
}

// NewVSchemaStats returns a new VSchemaStats from a VSchema.
Expand All @@ -54,6 +55,11 @@ func NewVSchemaStats(vschema *vindexes.VSchema, errorMessage string) *VSchemaSta
for _, t := range k.Tables {
s.VindexCount += len(t.ColumnVindexes) + len(t.Ordered) + len(t.Owned)
}
for _, vdx := range k.Vindexes {
if pv, ok := vdx.(vindexes.ParamValidating); ok {
s.VindexUnknownParamsCount += len(pv.UnknownParams())
}
}
}
if k.Error != nil {
s.Error = k.Error.Error()
Expand Down Expand Up @@ -95,13 +101,15 @@ const (
<th>Sharded</th>
<th>Table Count</th>
<th>Vindex Count</th>
<th>Vindex Unknown Parameters Count</th>
<th>Error</th>
</tr>
{{range $i, $ks := .Keyspaces}} <tr>
<td>{{$ks.Keyspace}}</td>
<td>{{if $ks.Sharded}}Yes{{else}}No{{end}}</td>
<td>{{$ks.TableCount}}</td>
<td>{{$ks.VindexCount}}</td>
<td>{{$ks.VindexUnknownParamsCount}}</td>
<td style="color:red">{{$ks.Error}}</td>
</tr>{{end}}
</table>
Expand Down
Loading