vitess.io/vitess@v0.16.2/go/vt/vtcombo/tablet_map.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 vtcombo
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"path"
    24  	"time"
    25  
    26  	"vitess.io/vitess/go/sqltypes"
    27  	"vitess.io/vitess/go/vt/dbconfigs"
    28  	"vitess.io/vitess/go/vt/grpcclient"
    29  	"vitess.io/vitess/go/vt/hook"
    30  	"vitess.io/vitess/go/vt/log"
    31  	"vitess.io/vitess/go/vt/logutil"
    32  	"vitess.io/vitess/go/vt/mysqlctl"
    33  	"vitess.io/vitess/go/vt/mysqlctl/tmutils"
    34  	"vitess.io/vitess/go/vt/topo"
    35  	"vitess.io/vitess/go/vt/topo/topoproto"
    36  	"vitess.io/vitess/go/vt/topotools"
    37  	"vitess.io/vitess/go/vt/vterrors"
    38  	"vitess.io/vitess/go/vt/vtgate/vindexes"
    39  	"vitess.io/vitess/go/vt/vttablet/queryservice"
    40  	"vitess.io/vitess/go/vt/vttablet/tabletconn"
    41  	"vitess.io/vitess/go/vt/vttablet/tabletmanager"
    42  	"vitess.io/vitess/go/vt/vttablet/tabletserver"
    43  	"vitess.io/vitess/go/vt/vttablet/tmclient"
    44  	"vitess.io/vitess/go/vt/wrangler"
    45  
    46  	binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
    47  	querypb "vitess.io/vitess/go/vt/proto/query"
    48  	replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata"
    49  	tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata"
    50  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    51  	vschemapb "vitess.io/vitess/go/vt/proto/vschema"
    52  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    53  	vttestpb "vitess.io/vitess/go/vt/proto/vttest"
    54  )
    55  
    56  // tablet contains all the data for an individual tablet.
    57  type comboTablet struct {
    58  	// configuration parameters
    59  	alias      *topodatapb.TabletAlias
    60  	keyspace   string
    61  	shard      string
    62  	tabletType topodatapb.TabletType
    63  	dbname     string
    64  	uid        uint32
    65  
    66  	// objects built at construction time
    67  	qsc tabletserver.Controller
    68  	tm  *tabletmanager.TabletManager
    69  }
    70  
    71  // tabletMap maps the tablet uid to the tablet record
    72  var tabletMap map[uint32]*comboTablet
    73  
    74  // CreateTablet creates an individual tablet, with its tm, and adds
    75  // it to the map. If it's a primary tablet, it also issues a TER.
    76  func CreateTablet(
    77  	ctx context.Context,
    78  	ts *topo.Server,
    79  	cell string,
    80  	uid uint32,
    81  	keyspace, shard, dbname string,
    82  	tabletType topodatapb.TabletType,
    83  	mysqld mysqlctl.MysqlDaemon,
    84  	dbcfgs *dbconfigs.DBConfigs,
    85  ) error {
    86  	alias := &topodatapb.TabletAlias{
    87  		Cell: cell,
    88  		Uid:  uid,
    89  	}
    90  	log.Infof("Creating %v tablet %v for %v/%v", tabletType, topoproto.TabletAliasString(alias), keyspace, shard)
    91  
    92  	controller := tabletserver.NewServer(topoproto.TabletAliasString(alias), ts, alias)
    93  	initTabletType := tabletType
    94  	if tabletType == topodatapb.TabletType_PRIMARY {
    95  		initTabletType = topodatapb.TabletType_REPLICA
    96  	}
    97  	_, kr, err := topo.ValidateShardName(shard)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	tm := &tabletmanager.TabletManager{
   102  		BatchCtx:            context.Background(),
   103  		TopoServer:          ts,
   104  		MysqlDaemon:         mysqld,
   105  		DBConfigs:           dbcfgs,
   106  		QueryServiceControl: controller,
   107  	}
   108  	tablet := &topodatapb.Tablet{
   109  		Alias: alias,
   110  		PortMap: map[string]int32{
   111  			"vt":   int32(8000 + uid),
   112  			"grpc": int32(9000 + uid),
   113  		},
   114  		Keyspace:       keyspace,
   115  		Shard:          shard,
   116  		KeyRange:       kr,
   117  		Type:           initTabletType,
   118  		DbNameOverride: dbname,
   119  	}
   120  	if err := tm.Start(tablet, 0); err != nil {
   121  		return err
   122  	}
   123  
   124  	if tabletType == topodatapb.TabletType_PRIMARY {
   125  		// Semi-sync has to be set to false, since we have 1 single backing MySQL
   126  		if err := tm.ChangeType(ctx, topodatapb.TabletType_PRIMARY /* semi-sync */, false); err != nil {
   127  			return fmt.Errorf("TabletExternallyReparented failed on primary %v: %v", topoproto.TabletAliasString(alias), err)
   128  		}
   129  	}
   130  	controller.AddStatusHeader()
   131  	controller.AddStatusPart()
   132  	tabletMap[uid] = &comboTablet{
   133  		alias:      alias,
   134  		keyspace:   keyspace,
   135  		shard:      shard,
   136  		tabletType: tabletType,
   137  		dbname:     dbname,
   138  		uid:        uid,
   139  
   140  		qsc: controller,
   141  		tm:  tm,
   142  	}
   143  	return nil
   144  }
   145  
   146  // InitRoutingRules saves the routing rules into ts and reloads the vschema.
   147  func InitRoutingRules(
   148  	ctx context.Context,
   149  	ts *topo.Server,
   150  	rr *vschemapb.RoutingRules,
   151  ) error {
   152  	if rr == nil {
   153  		return nil
   154  	}
   155  
   156  	if err := ts.SaveRoutingRules(ctx, rr); err != nil {
   157  		return err
   158  	}
   159  
   160  	return ts.RebuildSrvVSchema(ctx, nil)
   161  }
   162  
   163  // InitTabletMap creates the action tms and associated data structures
   164  // for all tablets, based on the vttest proto parameter.
   165  func InitTabletMap(
   166  	ts *topo.Server,
   167  	tpb *vttestpb.VTTestTopology,
   168  	mysqld mysqlctl.MysqlDaemon,
   169  	dbcfgs *dbconfigs.DBConfigs,
   170  	schemaDir string,
   171  	ensureDatabase bool,
   172  ) (uint32, error) {
   173  	tabletMap = make(map[uint32]*comboTablet)
   174  
   175  	ctx := context.Background()
   176  
   177  	// Register the tablet manager client factory for tablet manager
   178  	// Do this before any tablets are created so that they respect the protocol,
   179  	// otherwise it defaults to grpc.
   180  	//
   181  	// main() forces the --tablet_manager_protocol flag to this value.
   182  	tmclient.RegisterTabletManagerClientFactory("internal", func() tmclient.TabletManagerClient {
   183  		return &internalTabletManagerClient{}
   184  	})
   185  
   186  	// iterate through the keyspaces
   187  	wr := wrangler.New(logutil.NewConsoleLogger(), ts, nil)
   188  	var uid uint32 = 1
   189  	for _, kpb := range tpb.Keyspaces {
   190  		var err error
   191  		uid, err = CreateKs(ctx, ts, tpb, mysqld, dbcfgs, schemaDir, kpb, ensureDatabase, uid, wr)
   192  		if err != nil {
   193  			return 0, err
   194  		}
   195  	}
   196  
   197  	// Rebuild the SrvVSchema object
   198  	if err := ts.RebuildSrvVSchema(ctx, tpb.Cells); err != nil {
   199  		return 0, fmt.Errorf("RebuildVSchemaGraph failed: %v", err)
   200  	}
   201  
   202  	// Register the tablet dialer for tablet server. main() forces the --tablet_protocol
   203  	// flag to this value.
   204  	tabletconn.RegisterDialer("internal", dialer)
   205  
   206  	// run healthcheck on all vttablets
   207  	tmc := tmclient.NewTabletManagerClient()
   208  	for _, tablet := range tabletMap {
   209  		tabletInfo, err := ts.GetTablet(ctx, tablet.alias)
   210  		if err != nil {
   211  			return 0, fmt.Errorf("cannot find tablet: %+v", tablet.alias)
   212  		}
   213  		tmc.RunHealthCheck(ctx, tabletInfo.Tablet)
   214  	}
   215  
   216  	return uid, nil
   217  }
   218  
   219  // DeleteKs deletes keyspace, shards and tablets with mysql databases
   220  func DeleteKs(
   221  	ctx context.Context,
   222  	ts *topo.Server,
   223  	ksName string,
   224  	mysqld mysqlctl.MysqlDaemon,
   225  	tpb *vttestpb.VTTestTopology,
   226  ) error {
   227  	for key, tablet := range tabletMap {
   228  		if tablet.keyspace == ksName {
   229  			delete(tabletMap, key)
   230  			tablet.tm.Stop()
   231  			tablet.tm.Close()
   232  			tablet.qsc.SchemaEngine().Close()
   233  			err := ts.DeleteTablet(ctx, tablet.alias)
   234  			if err != nil {
   235  				return err
   236  			}
   237  		}
   238  	}
   239  
   240  	var ks *vttestpb.Keyspace
   241  	index := 0
   242  	for _, keyspace := range tpb.Keyspaces {
   243  		if keyspace.Name == ksName {
   244  			ks = keyspace
   245  			break
   246  		}
   247  		index++
   248  	}
   249  	if ks == nil {
   250  		return fmt.Errorf("database not found")
   251  	}
   252  
   253  	conn, err := mysqld.GetDbaConnection(ctx)
   254  	if err != nil {
   255  		return err
   256  	}
   257  	defer conn.Close()
   258  	for _, shard := range ks.Shards {
   259  		q := fmt.Sprintf("DROP DATABASE IF EXISTS `vt_%s_%s`", ksName, shard.GetName())
   260  		if _, err = conn.ExecuteFetch(q, 1, false); err != nil {
   261  			return err
   262  		}
   263  		if err := ts.DeleteShard(ctx, ksName, shard.GetName()); err != nil {
   264  			return err
   265  		}
   266  	}
   267  
   268  	if err = ts.DeleteKeyspace(ctx, ksName); err != nil {
   269  		return err
   270  	}
   271  
   272  	kss := tpb.Keyspaces             // to save on chars
   273  	copy(kss[index:], kss[index+1:]) // shift keyspaces to the left, overwriting the value to remove
   274  	tpb.Keyspaces = kss[:len(kss)-1] // shrink the slice by one
   275  
   276  	return nil
   277  }
   278  
   279  // CreateKs creates keyspace, shards and tablets with mysql database
   280  func CreateKs(
   281  	ctx context.Context,
   282  	ts *topo.Server,
   283  	tpb *vttestpb.VTTestTopology,
   284  	mysqld mysqlctl.MysqlDaemon,
   285  	dbcfgs *dbconfigs.DBConfigs,
   286  	schemaDir string,
   287  	kpb *vttestpb.Keyspace,
   288  	ensureDatabase bool,
   289  	uid uint32,
   290  	wr *wrangler.Wrangler,
   291  ) (uint32, error) {
   292  	keyspace := kpb.Name
   293  
   294  	if kpb.ServedFrom != "" {
   295  		// if we have a redirect, create a completely redirected
   296  		// keyspace and no tablet
   297  		if err := ts.CreateKeyspace(ctx, keyspace, &topodatapb.Keyspace{
   298  			ServedFroms: []*topodatapb.Keyspace_ServedFrom{
   299  				{
   300  					TabletType: topodatapb.TabletType_PRIMARY,
   301  					Keyspace:   kpb.ServedFrom,
   302  				},
   303  				{
   304  					TabletType: topodatapb.TabletType_REPLICA,
   305  					Keyspace:   kpb.ServedFrom,
   306  				},
   307  				{
   308  					TabletType: topodatapb.TabletType_RDONLY,
   309  					Keyspace:   kpb.ServedFrom,
   310  				},
   311  			},
   312  		}); err != nil {
   313  			return 0, fmt.Errorf("CreateKeyspace(%v) failed: %v", keyspace, err)
   314  		}
   315  	} else {
   316  		// create a regular keyspace
   317  		if err := ts.CreateKeyspace(ctx, keyspace, &topodatapb.Keyspace{}); err != nil {
   318  			return 0, fmt.Errorf("CreateKeyspace(%v) failed: %v", keyspace, err)
   319  		}
   320  
   321  		// iterate through the shards
   322  		for _, spb := range kpb.Shards {
   323  			shard := spb.Name
   324  			if err := ts.CreateShard(ctx, keyspace, shard); err != nil {
   325  				return 0, fmt.Errorf("CreateShard(%v:%v) failed: %v", keyspace, shard, err)
   326  			}
   327  
   328  			for _, cell := range tpb.Cells {
   329  				dbname := spb.DbNameOverride
   330  				if dbname == "" {
   331  					dbname = fmt.Sprintf("vt_%v_%v", keyspace, shard)
   332  				}
   333  
   334  				replicas := int(kpb.ReplicaCount)
   335  				if replicas == 0 {
   336  					// 2 replicas in order to ensure the primary cell has a primary and a replica
   337  					replicas = 2
   338  				}
   339  				rdonlys := int(kpb.RdonlyCount)
   340  				if rdonlys == 0 {
   341  					rdonlys = 1
   342  				}
   343  
   344  				if ensureDatabase {
   345  					// Create Database if not exist
   346  					conn, err := mysqld.GetDbaConnection(context.TODO())
   347  					if err != nil {
   348  						return 0, fmt.Errorf("GetConnection failed: %v", err)
   349  					}
   350  					defer conn.Close()
   351  
   352  					_, err = conn.ExecuteFetch("CREATE DATABASE IF NOT EXISTS `"+dbname+"`", 1, false)
   353  					if err != nil {
   354  						return 0, fmt.Errorf("error ensuring database exists: %v", err)
   355  					}
   356  
   357  				}
   358  				if cell == tpb.Cells[0] {
   359  					replicas--
   360  
   361  					// create the primary
   362  					if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_PRIMARY, mysqld, dbcfgs.Clone()); err != nil {
   363  						return 0, err
   364  					}
   365  					uid++
   366  				}
   367  
   368  				for i := 0; i < replicas; i++ {
   369  					// create a replica tablet
   370  					if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_REPLICA, mysqld, dbcfgs.Clone()); err != nil {
   371  						return 0, err
   372  					}
   373  					uid++
   374  				}
   375  
   376  				for i := 0; i < rdonlys; i++ {
   377  					// create a rdonly tablet
   378  					if err := CreateTablet(ctx, ts, cell, uid, keyspace, shard, dbname, topodatapb.TabletType_RDONLY, mysqld, dbcfgs.Clone()); err != nil {
   379  						return 0, err
   380  					}
   381  					uid++
   382  				}
   383  			}
   384  		}
   385  	}
   386  
   387  	// vschema for the keyspace
   388  	if schemaDir != "" {
   389  		f := path.Join(schemaDir, keyspace, "vschema.json")
   390  		if _, err := os.Stat(f); err == nil {
   391  			// load the vschema
   392  			formal, err := vindexes.LoadFormalKeyspace(f)
   393  			if err != nil {
   394  				return 0, fmt.Errorf("cannot load vschema file %v for keyspace %v: %v", f, keyspace, err)
   395  			}
   396  
   397  			if err := ts.SaveVSchema(ctx, keyspace, formal); err != nil {
   398  				return 0, fmt.Errorf("SaveVSchema(%v) failed: %v", keyspace, err)
   399  			}
   400  		} else {
   401  			log.Infof("File %v doesn't exist, skipping vschema for keyspace %v", f, keyspace)
   402  		}
   403  	}
   404  
   405  	// Rebuild the SrvKeyspace object, so we can support
   406  	// range-based sharding queries, and export the redirects.
   407  	if err := topotools.RebuildKeyspace(ctx, wr.Logger(), wr.TopoServer(), keyspace, nil, false); err != nil {
   408  		return 0, fmt.Errorf("cannot rebuild %v: %v", keyspace, err)
   409  	}
   410  	return uid, nil
   411  }
   412  
   413  //
   414  // TabletConn implementation
   415  //
   416  
   417  // dialer is our tabletconn.Dialer
   418  func dialer(tablet *topodatapb.Tablet, failFast grpcclient.FailFast) (queryservice.QueryService, error) {
   419  	t, ok := tabletMap[tablet.Alias.Uid]
   420  	if !ok {
   421  		return nil, vterrors.New(vtrpcpb.Code_UNAVAILABLE, "connection refused")
   422  	}
   423  
   424  	return &internalTabletConn{
   425  		tablet:     t,
   426  		topoTablet: tablet,
   427  	}, nil
   428  }
   429  
   430  // internalTabletConn implements queryservice.QueryService by forwarding everything
   431  // to the tablet
   432  type internalTabletConn struct {
   433  	tablet     *comboTablet
   434  	topoTablet *topodatapb.Tablet
   435  }
   436  
   437  var _ queryservice.QueryService = (*internalTabletConn)(nil)
   438  
   439  // Execute is part of queryservice.QueryService
   440  // We need to copy the bind variables as tablet server will change them.
   441  func (itc *internalTabletConn) Execute(
   442  	ctx context.Context,
   443  	target *querypb.Target,
   444  	query string,
   445  	bindVars map[string]*querypb.BindVariable,
   446  	transactionID, reservedID int64,
   447  	options *querypb.ExecuteOptions,
   448  ) (*sqltypes.Result, error) {
   449  	bindVars = sqltypes.CopyBindVariables(bindVars)
   450  	reply, err := itc.tablet.qsc.QueryService().Execute(ctx, target, query, bindVars, transactionID, reservedID, options)
   451  	if err != nil {
   452  		return nil, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   453  	}
   454  	return reply, nil
   455  }
   456  
   457  // StreamExecute is part of queryservice.QueryService
   458  // We need to copy the bind variables as tablet server will change them.
   459  func (itc *internalTabletConn) StreamExecute(
   460  	ctx context.Context,
   461  	target *querypb.Target,
   462  	query string,
   463  	bindVars map[string]*querypb.BindVariable,
   464  	transactionID int64,
   465  	reservedID int64,
   466  	options *querypb.ExecuteOptions,
   467  	callback func(*sqltypes.Result) error,
   468  ) error {
   469  	bindVars = sqltypes.CopyBindVariables(bindVars)
   470  	err := itc.tablet.qsc.QueryService().StreamExecute(ctx, target, query, bindVars, transactionID, reservedID, options, callback)
   471  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   472  }
   473  
   474  // Begin is part of queryservice.QueryService
   475  func (itc *internalTabletConn) Begin(
   476  	ctx context.Context,
   477  	target *querypb.Target,
   478  	options *querypb.ExecuteOptions,
   479  ) (queryservice.TransactionState, error) {
   480  	state, err := itc.tablet.qsc.QueryService().Begin(ctx, target, options)
   481  	return state, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   482  }
   483  
   484  // Commit is part of queryservice.QueryService
   485  func (itc *internalTabletConn) Commit(ctx context.Context, target *querypb.Target, transactionID int64) (int64, error) {
   486  	rID, err := itc.tablet.qsc.QueryService().Commit(ctx, target, transactionID)
   487  	return rID, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   488  }
   489  
   490  // Rollback is part of queryservice.QueryService
   491  func (itc *internalTabletConn) Rollback(ctx context.Context, target *querypb.Target, transactionID int64) (int64, error) {
   492  	rID, err := itc.tablet.qsc.QueryService().Rollback(ctx, target, transactionID)
   493  	return rID, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   494  }
   495  
   496  // Prepare is part of queryservice.QueryService
   497  func (itc *internalTabletConn) Prepare(ctx context.Context, target *querypb.Target, transactionID int64, dtid string) error {
   498  	err := itc.tablet.qsc.QueryService().Prepare(ctx, target, transactionID, dtid)
   499  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   500  }
   501  
   502  // CommitPrepared is part of queryservice.QueryService
   503  func (itc *internalTabletConn) CommitPrepared(ctx context.Context, target *querypb.Target, dtid string) error {
   504  	err := itc.tablet.qsc.QueryService().CommitPrepared(ctx, target, dtid)
   505  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   506  }
   507  
   508  // RollbackPrepared is part of queryservice.QueryService
   509  func (itc *internalTabletConn) RollbackPrepared(ctx context.Context, target *querypb.Target, dtid string, originalID int64) error {
   510  	err := itc.tablet.qsc.QueryService().RollbackPrepared(ctx, target, dtid, originalID)
   511  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   512  }
   513  
   514  // CreateTransaction is part of queryservice.QueryService
   515  func (itc *internalTabletConn) CreateTransaction(
   516  	ctx context.Context,
   517  	target *querypb.Target,
   518  	dtid string,
   519  	participants []*querypb.Target,
   520  ) error {
   521  	err := itc.tablet.qsc.QueryService().CreateTransaction(ctx, target, dtid, participants)
   522  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   523  }
   524  
   525  // StartCommit is part of queryservice.QueryService
   526  func (itc *internalTabletConn) StartCommit(ctx context.Context, target *querypb.Target, transactionID int64, dtid string) error {
   527  	err := itc.tablet.qsc.QueryService().StartCommit(ctx, target, transactionID, dtid)
   528  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   529  }
   530  
   531  // SetRollback is part of queryservice.QueryService
   532  func (itc *internalTabletConn) SetRollback(ctx context.Context, target *querypb.Target, dtid string, transactionID int64) error {
   533  	err := itc.tablet.qsc.QueryService().SetRollback(ctx, target, dtid, transactionID)
   534  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   535  }
   536  
   537  // ConcludeTransaction is part of queryservice.QueryService
   538  func (itc *internalTabletConn) ConcludeTransaction(ctx context.Context, target *querypb.Target, dtid string) error {
   539  	err := itc.tablet.qsc.QueryService().ConcludeTransaction(ctx, target, dtid)
   540  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   541  }
   542  
   543  // ReadTransaction is part of queryservice.QueryService
   544  func (itc *internalTabletConn) ReadTransaction(ctx context.Context, target *querypb.Target, dtid string) (metadata *querypb.TransactionMetadata, err error) {
   545  	metadata, err = itc.tablet.qsc.QueryService().ReadTransaction(ctx, target, dtid)
   546  	return metadata, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   547  }
   548  
   549  // BeginExecute is part of queryservice.QueryService
   550  func (itc *internalTabletConn) BeginExecute(
   551  	ctx context.Context,
   552  	target *querypb.Target,
   553  	preQueries []string,
   554  	query string,
   555  	bindVars map[string]*querypb.BindVariable,
   556  	reserveID int64,
   557  	options *querypb.ExecuteOptions,
   558  ) (queryservice.TransactionState, *sqltypes.Result, error) {
   559  	bindVars = sqltypes.CopyBindVariables(bindVars)
   560  	state, result, err := itc.tablet.qsc.QueryService().BeginExecute(ctx, target, preQueries, query, bindVars, reserveID, options)
   561  	return state, result, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   562  }
   563  
   564  // BeginStreamExecute is part of queryservice.QueryService
   565  func (itc *internalTabletConn) BeginStreamExecute(
   566  	ctx context.Context,
   567  	target *querypb.Target,
   568  	preQueries []string,
   569  	query string,
   570  	bindVars map[string]*querypb.BindVariable,
   571  	reservedID int64,
   572  	options *querypb.ExecuteOptions,
   573  	callback func(*sqltypes.Result) error,
   574  ) (queryservice.TransactionState, error) {
   575  	bindVars = sqltypes.CopyBindVariables(bindVars)
   576  	state, err := itc.tablet.qsc.QueryService().BeginStreamExecute(ctx, target, preQueries, query, bindVars, reservedID, options, callback)
   577  	return state, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   578  }
   579  
   580  // MessageStream is part of queryservice.QueryService
   581  func (itc *internalTabletConn) MessageStream(ctx context.Context, target *querypb.Target, name string, callback func(*sqltypes.Result) error) error {
   582  	err := itc.tablet.qsc.QueryService().MessageStream(ctx, target, name, callback)
   583  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   584  }
   585  
   586  // MessageAck is part of queryservice.QueryService
   587  func (itc *internalTabletConn) MessageAck(ctx context.Context, target *querypb.Target, name string, ids []*querypb.Value) (int64, error) {
   588  	count, err := itc.tablet.qsc.QueryService().MessageAck(ctx, target, name, ids)
   589  	return count, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   590  }
   591  
   592  // HandlePanic is part of the QueryService interface.
   593  func (itc *internalTabletConn) HandlePanic(err *error) {
   594  }
   595  
   596  // ReserveBeginExecute is part of the QueryService interface.
   597  func (itc *internalTabletConn) ReserveBeginExecute(
   598  	ctx context.Context,
   599  	target *querypb.Target,
   600  	preQueries []string,
   601  	postBeginQueries []string,
   602  	sql string,
   603  	bindVariables map[string]*querypb.BindVariable,
   604  	options *querypb.ExecuteOptions,
   605  ) (queryservice.ReservedTransactionState, *sqltypes.Result, error) {
   606  	bindVariables = sqltypes.CopyBindVariables(bindVariables)
   607  	state, result, err := itc.tablet.qsc.QueryService().ReserveBeginExecute(ctx, target, preQueries, postBeginQueries, sql, bindVariables, options)
   608  	return state, result, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   609  }
   610  
   611  // ReserveBeginStreamExecute is part of the QueryService interface.
   612  func (itc *internalTabletConn) ReserveBeginStreamExecute(
   613  	ctx context.Context,
   614  	target *querypb.Target,
   615  	preQueries []string,
   616  	postBeginQueries []string,
   617  	sql string,
   618  	bindVariables map[string]*querypb.BindVariable,
   619  	options *querypb.ExecuteOptions,
   620  	callback func(*sqltypes.Result) error,
   621  ) (queryservice.ReservedTransactionState, error) {
   622  	bindVariables = sqltypes.CopyBindVariables(bindVariables)
   623  	state, err := itc.tablet.qsc.QueryService().ReserveBeginStreamExecute(ctx, target, preQueries, postBeginQueries, sql, bindVariables, options, callback)
   624  	return state, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   625  }
   626  
   627  // ReserveExecute is part of the QueryService interface.
   628  func (itc *internalTabletConn) ReserveExecute(
   629  	ctx context.Context,
   630  	target *querypb.Target,
   631  	preQueries []string,
   632  	sql string,
   633  	bindVariables map[string]*querypb.BindVariable,
   634  	transactionID int64,
   635  	options *querypb.ExecuteOptions,
   636  ) (queryservice.ReservedState, *sqltypes.Result, error) {
   637  	bindVariables = sqltypes.CopyBindVariables(bindVariables)
   638  	state, result, err := itc.tablet.qsc.QueryService().ReserveExecute(ctx, target, preQueries, sql, bindVariables, transactionID, options)
   639  	return state, result, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   640  }
   641  
   642  // ReserveStreamExecute is part of the QueryService interface.
   643  func (itc *internalTabletConn) ReserveStreamExecute(
   644  	ctx context.Context,
   645  	target *querypb.Target,
   646  	preQueries []string,
   647  	sql string,
   648  	bindVariables map[string]*querypb.BindVariable,
   649  	transactionID int64,
   650  	options *querypb.ExecuteOptions,
   651  	callback func(*sqltypes.Result) error,
   652  ) (queryservice.ReservedState, error) {
   653  	bindVariables = sqltypes.CopyBindVariables(bindVariables)
   654  	state, err := itc.tablet.qsc.QueryService().ReserveStreamExecute(ctx, target, preQueries, sql, bindVariables, transactionID, options, callback)
   655  	return state, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   656  }
   657  
   658  // Release is part of the QueryService interface.
   659  func (itc *internalTabletConn) Release(ctx context.Context, target *querypb.Target, transactionID, reservedID int64) error {
   660  	err := itc.tablet.qsc.QueryService().Release(ctx, target, transactionID, reservedID)
   661  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   662  }
   663  
   664  // GetSchema is part of the QueryService interface.
   665  func (itc *internalTabletConn) GetSchema(ctx context.Context, target *querypb.Target, tableType querypb.SchemaTableType, tableNames []string, callback func(schemaRes *querypb.GetSchemaResponse) error) error {
   666  	err := itc.tablet.qsc.QueryService().GetSchema(ctx, target, tableType, tableNames, callback)
   667  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   668  }
   669  
   670  // Close is part of queryservice.QueryService
   671  func (itc *internalTabletConn) Close(ctx context.Context) error {
   672  	return nil
   673  }
   674  
   675  // Tablet is part of queryservice.QueryService
   676  func (itc *internalTabletConn) Tablet() *topodatapb.Tablet {
   677  	return itc.topoTablet
   678  }
   679  
   680  // StreamHealth is part of queryservice.QueryService
   681  func (itc *internalTabletConn) StreamHealth(ctx context.Context, callback func(*querypb.StreamHealthResponse) error) error {
   682  	err := itc.tablet.qsc.QueryService().StreamHealth(ctx, callback)
   683  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   684  }
   685  
   686  // VStream is part of queryservice.QueryService.
   687  func (itc *internalTabletConn) VStream(
   688  	ctx context.Context,
   689  	request *binlogdatapb.VStreamRequest,
   690  	send func([]*binlogdatapb.VEvent) error,
   691  ) error {
   692  	err := itc.tablet.qsc.QueryService().VStream(ctx, request, send)
   693  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   694  }
   695  
   696  // VStreamRows is part of the QueryService interface.
   697  func (itc *internalTabletConn) VStreamRows(
   698  	ctx context.Context,
   699  	request *binlogdatapb.VStreamRowsRequest,
   700  	send func(*binlogdatapb.VStreamRowsResponse) error,
   701  ) error {
   702  	err := itc.tablet.qsc.QueryService().VStreamRows(ctx, request, send)
   703  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   704  }
   705  
   706  // VStreamResults is part of the QueryService interface.
   707  func (itc *internalTabletConn) VStreamResults(
   708  	ctx context.Context,
   709  	target *querypb.Target,
   710  	query string,
   711  	send func(*binlogdatapb.VStreamResultsResponse) error,
   712  ) error {
   713  	err := itc.tablet.qsc.QueryService().VStreamResults(ctx, target, query, send)
   714  	return tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err))
   715  }
   716  
   717  //
   718  // TabletManagerClient implementation
   719  //
   720  
   721  // internalTabletManagerClient implements tmclient.TabletManagerClient
   722  type internalTabletManagerClient struct{}
   723  
   724  func (itmc *internalTabletManagerClient) VDiff(ctx context.Context, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.VDiffRequest) (*tabletmanagerdatapb.VDiffResponse, error) {
   725  	return nil, fmt.Errorf("VDiff not implemented in vtcombo")
   726  }
   727  
   728  func (itmc *internalTabletManagerClient) LockTables(ctx context.Context, tablet *topodatapb.Tablet) error {
   729  	return fmt.Errorf("not implemented in vtcombo")
   730  }
   731  
   732  func (itmc *internalTabletManagerClient) UnlockTables(ctx context.Context, tablet *topodatapb.Tablet) error {
   733  	return fmt.Errorf("not implemented in vtcombo")
   734  }
   735  
   736  func (itmc *internalTabletManagerClient) Ping(ctx context.Context, tablet *topodatapb.Tablet) error {
   737  	t, ok := tabletMap[tablet.Alias.Uid]
   738  	if !ok {
   739  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   740  	}
   741  	t.tm.Ping(ctx, "payload")
   742  	return nil
   743  }
   744  
   745  func (itmc *internalTabletManagerClient) GetSchema(
   746  	ctx context.Context,
   747  	tablet *topodatapb.Tablet,
   748  	request *tabletmanagerdatapb.GetSchemaRequest,
   749  ) (*tabletmanagerdatapb.SchemaDefinition, error) {
   750  	t, ok := tabletMap[tablet.Alias.Uid]
   751  	if !ok {
   752  		return nil, fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   753  	}
   754  	return t.tm.GetSchema(ctx, request)
   755  }
   756  
   757  func (itmc *internalTabletManagerClient) GetPermissions(ctx context.Context, tablet *topodatapb.Tablet) (*tabletmanagerdatapb.Permissions, error) {
   758  	t, ok := tabletMap[tablet.Alias.Uid]
   759  	if !ok {
   760  		return nil, fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   761  	}
   762  	return t.tm.GetPermissions(ctx)
   763  }
   764  
   765  func (itmc *internalTabletManagerClient) SetReadOnly(ctx context.Context, tablet *topodatapb.Tablet) error {
   766  	return fmt.Errorf("not implemented in vtcombo")
   767  }
   768  
   769  func (itmc *internalTabletManagerClient) SetReadWrite(ctx context.Context, tablet *topodatapb.Tablet) error {
   770  	return fmt.Errorf("not implemented in vtcombo")
   771  }
   772  
   773  func (itmc *internalTabletManagerClient) ChangeType(ctx context.Context, tablet *topodatapb.Tablet, dbType topodatapb.TabletType, semiSync bool) error {
   774  	t, ok := tabletMap[tablet.Alias.Uid]
   775  	if !ok {
   776  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   777  	}
   778  	t.tm.ChangeType(ctx, dbType, semiSync)
   779  	return nil
   780  }
   781  
   782  func (itmc *internalTabletManagerClient) Sleep(ctx context.Context, tablet *topodatapb.Tablet, duration time.Duration) error {
   783  	t, ok := tabletMap[tablet.Alias.Uid]
   784  	if !ok {
   785  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   786  	}
   787  	t.tm.Sleep(ctx, duration)
   788  	return nil
   789  }
   790  
   791  func (itmc *internalTabletManagerClient) ExecuteHook(ctx context.Context, tablet *topodatapb.Tablet, hk *hook.Hook) (*hook.HookResult, error) {
   792  	return nil, fmt.Errorf("not implemented in vtcombo")
   793  }
   794  
   795  func (itmc *internalTabletManagerClient) RefreshState(ctx context.Context, tablet *topodatapb.Tablet) error {
   796  	t, ok := tabletMap[tablet.Alias.Uid]
   797  	if !ok {
   798  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   799  	}
   800  	return t.tm.RefreshState(ctx)
   801  }
   802  
   803  func (itmc *internalTabletManagerClient) RunHealthCheck(ctx context.Context, tablet *topodatapb.Tablet) error {
   804  	t, ok := tabletMap[tablet.Alias.Uid]
   805  	if !ok {
   806  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   807  	}
   808  	t.tm.RunHealthCheck(ctx)
   809  	return nil
   810  }
   811  
   812  func (itmc *internalTabletManagerClient) ReloadSchema(ctx context.Context, tablet *topodatapb.Tablet, waitPosition string) error {
   813  	t, ok := tabletMap[tablet.Alias.Uid]
   814  	if !ok {
   815  		return fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   816  	}
   817  	return t.tm.ReloadSchema(ctx, waitPosition)
   818  }
   819  
   820  func (itmc *internalTabletManagerClient) PreflightSchema(ctx context.Context, tablet *topodatapb.Tablet, changes []string) ([]*tabletmanagerdatapb.SchemaChangeResult, error) {
   821  	t, ok := tabletMap[tablet.Alias.Uid]
   822  	if !ok {
   823  		return nil, fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   824  	}
   825  	return t.tm.PreflightSchema(ctx, changes)
   826  }
   827  
   828  func (itmc *internalTabletManagerClient) ApplySchema(ctx context.Context, tablet *topodatapb.Tablet, change *tmutils.SchemaChange) (*tabletmanagerdatapb.SchemaChangeResult, error) {
   829  	t, ok := tabletMap[tablet.Alias.Uid]
   830  	if !ok {
   831  		return nil, fmt.Errorf("tmclient: cannot find tablet %v", tablet.Alias.Uid)
   832  	}
   833  	return t.tm.ApplySchema(ctx, change)
   834  }
   835  
   836  func (itmc *internalTabletManagerClient) ExecuteQuery(context.Context, *topodatapb.Tablet, *tabletmanagerdatapb.ExecuteQueryRequest) (*querypb.QueryResult, error) {
   837  	return nil, fmt.Errorf("not implemented in vtcombo")
   838  }
   839  
   840  func (itmc *internalTabletManagerClient) ExecuteFetchAsDba(context.Context, *topodatapb.Tablet, bool, *tabletmanagerdatapb.ExecuteFetchAsDbaRequest) (*querypb.QueryResult, error) {
   841  	return nil, fmt.Errorf("not implemented in vtcombo")
   842  }
   843  
   844  func (itmc *internalTabletManagerClient) ExecuteFetchAsAllPrivs(context.Context, *topodatapb.Tablet, *tabletmanagerdatapb.ExecuteFetchAsAllPrivsRequest) (*querypb.QueryResult, error) {
   845  	return nil, fmt.Errorf("not implemented in vtcombo")
   846  }
   847  
   848  func (itmc *internalTabletManagerClient) ExecuteFetchAsApp(context.Context, *topodatapb.Tablet, bool, *tabletmanagerdatapb.ExecuteFetchAsAppRequest) (*querypb.QueryResult, error) {
   849  	return nil, fmt.Errorf("not implemented in vtcombo")
   850  }
   851  
   852  func (itmc *internalTabletManagerClient) PrimaryStatus(context.Context, *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) {
   853  	return nil, fmt.Errorf("not implemented in vtcombo")
   854  }
   855  
   856  func (itmc *internalTabletManagerClient) PrimaryPosition(context.Context, *topodatapb.Tablet) (string, error) {
   857  	return "", fmt.Errorf("not implemented in vtcombo")
   858  }
   859  
   860  func (itmc *internalTabletManagerClient) WaitForPosition(context.Context, *topodatapb.Tablet, string) error {
   861  	return fmt.Errorf("not implemented in vtcombo")
   862  }
   863  
   864  func (itmc *internalTabletManagerClient) VExec(context.Context, *topodatapb.Tablet, string, string, string) (*querypb.QueryResult, error) {
   865  	return nil, fmt.Errorf("not implemented in vtcombo")
   866  }
   867  
   868  func (itmc *internalTabletManagerClient) VReplicationExec(context.Context, *topodatapb.Tablet, string) (*querypb.QueryResult, error) {
   869  	return nil, fmt.Errorf("not implemented in vtcombo")
   870  }
   871  
   872  func (itmc *internalTabletManagerClient) VReplicationWaitForPos(context.Context, *topodatapb.Tablet, int, string) error {
   873  	return fmt.Errorf("not implemented in vtcombo")
   874  }
   875  
   876  func (itmc *internalTabletManagerClient) ResetReplication(context.Context, *topodatapb.Tablet) error {
   877  	return fmt.Errorf("not implemented in vtcombo")
   878  }
   879  
   880  func (itmc *internalTabletManagerClient) InitPrimary(context.Context, *topodatapb.Tablet, bool) (string, error) {
   881  	return "", fmt.Errorf("not implemented in vtcombo")
   882  }
   883  
   884  func (itmc *internalTabletManagerClient) PopulateReparentJournal(context.Context, *topodatapb.Tablet, int64, string, *topodatapb.TabletAlias, string) error {
   885  	return fmt.Errorf("not implemented in vtcombo")
   886  }
   887  
   888  func (itmc *internalTabletManagerClient) DemotePrimary(context.Context, *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) {
   889  	return nil, fmt.Errorf("not implemented in vtcombo")
   890  }
   891  
   892  func (itmc *internalTabletManagerClient) UndoDemotePrimary(context.Context, *topodatapb.Tablet, bool) error {
   893  	return fmt.Errorf("not implemented in vtcombo")
   894  }
   895  
   896  func (itmc *internalTabletManagerClient) SetReplicationSource(context.Context, *topodatapb.Tablet, *topodatapb.TabletAlias, int64, string, bool, bool) error {
   897  	return fmt.Errorf("not implemented in vtcombo")
   898  }
   899  
   900  func (itmc *internalTabletManagerClient) StopReplicationAndGetStatus(context.Context, *topodatapb.Tablet, replicationdatapb.StopReplicationMode) (*replicationdatapb.StopReplicationStatus, error) {
   901  	return nil, fmt.Errorf("not implemented in vtcombo")
   902  }
   903  
   904  func (itmc *internalTabletManagerClient) PromoteReplica(context.Context, *topodatapb.Tablet, bool) (string, error) {
   905  	return "", fmt.Errorf("not implemented in vtcombo")
   906  }
   907  
   908  func (itmc *internalTabletManagerClient) Backup(context.Context, *topodatapb.Tablet, *tabletmanagerdatapb.BackupRequest) (logutil.EventStream, error) {
   909  	return nil, fmt.Errorf("not implemented in vtcombo")
   910  }
   911  
   912  func (itmc *internalTabletManagerClient) RestoreFromBackup(context.Context, *topodatapb.Tablet, *tabletmanagerdatapb.RestoreFromBackupRequest) (logutil.EventStream, error) {
   913  	return nil, fmt.Errorf("not implemented in vtcombo")
   914  }
   915  
   916  func (itmc *internalTabletManagerClient) Close() {
   917  }
   918  
   919  func (itmc *internalTabletManagerClient) ReplicationStatus(context.Context, *topodatapb.Tablet) (*replicationdatapb.Status, error) {
   920  	return nil, fmt.Errorf("not implemented in vtcombo")
   921  }
   922  
   923  func (itmc *internalTabletManagerClient) FullStatus(context.Context, *topodatapb.Tablet) (*replicationdatapb.FullStatus, error) {
   924  	return nil, fmt.Errorf("not implemented in vtcombo")
   925  }
   926  
   927  func (itmc *internalTabletManagerClient) StopReplication(context.Context, *topodatapb.Tablet) error {
   928  	return fmt.Errorf("not implemented in vtcombo")
   929  }
   930  
   931  func (itmc *internalTabletManagerClient) StopReplicationMinimum(context.Context, *topodatapb.Tablet, string, time.Duration) (string, error) {
   932  	return "", fmt.Errorf("not implemented in vtcombo")
   933  }
   934  
   935  func (itmc *internalTabletManagerClient) StartReplication(context.Context, *topodatapb.Tablet, bool) error {
   936  	return fmt.Errorf("not implemented in vtcombo")
   937  }
   938  
   939  func (itmc *internalTabletManagerClient) StartReplicationUntilAfter(context.Context, *topodatapb.Tablet, string, time.Duration) error {
   940  	return fmt.Errorf("not implemented in vtcombo")
   941  }
   942  
   943  func (itmc *internalTabletManagerClient) GetReplicas(context.Context, *topodatapb.Tablet) ([]string, error) {
   944  	return nil, fmt.Errorf("not implemented in vtcombo")
   945  }
   946  
   947  func (itmc *internalTabletManagerClient) InitReplica(context.Context, *topodatapb.Tablet, *topodatapb.TabletAlias, string, int64, bool) error {
   948  	return fmt.Errorf("not implemented in vtcombo")
   949  }
   950  
   951  func (itmc *internalTabletManagerClient) ReplicaWasPromoted(context.Context, *topodatapb.Tablet) error {
   952  	return fmt.Errorf("not implemented in vtcombo")
   953  }
   954  
   955  func (itmc *internalTabletManagerClient) ResetReplicationParameters(context.Context, *topodatapb.Tablet) error {
   956  	return fmt.Errorf("not implemented in vtcombo")
   957  }
   958  
   959  func (itmc *internalTabletManagerClient) ReplicaWasRestarted(context.Context, *topodatapb.Tablet, *topodatapb.TabletAlias) error {
   960  	return fmt.Errorf("not implemented in vtcombo")
   961  }