vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/online_ddl.go (about)

     1  /*
     2  Copyright 2020 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 engine
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"vitess.io/vitess/go/sqltypes"
    24  	"vitess.io/vitess/go/vt/key"
    25  	querypb "vitess.io/vitess/go/vt/proto/query"
    26  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    27  	"vitess.io/vitess/go/vt/schema"
    28  	"vitess.io/vitess/go/vt/sqlparser"
    29  	"vitess.io/vitess/go/vt/vterrors"
    30  	"vitess.io/vitess/go/vt/vtgate/vindexes"
    31  )
    32  
    33  var _ Primitive = (*OnlineDDL)(nil)
    34  
    35  // OnlineDDL represents the instructions to perform an online schema change via vtctld
    36  type OnlineDDL struct {
    37  	Keyspace           *vindexes.Keyspace
    38  	DDL                sqlparser.DDLStatement
    39  	SQL                string
    40  	DDLStrategySetting *schema.DDLStrategySetting
    41  	// TargetDestination specifies an explicit target destination to send the query to.
    42  	TargetDestination key.Destination
    43  
    44  	noTxNeeded
    45  
    46  	noInputs
    47  }
    48  
    49  func (v *OnlineDDL) description() PrimitiveDescription {
    50  	return PrimitiveDescription{
    51  		OperatorType: "OnlineDDL",
    52  		Keyspace:     v.Keyspace,
    53  		Other: map[string]any{
    54  			"query": v.SQL,
    55  		},
    56  	}
    57  }
    58  
    59  // RouteType implements the Primitive interface
    60  func (v *OnlineDDL) RouteType() string {
    61  	return "OnlineDDL"
    62  }
    63  
    64  // GetKeyspaceName implements the Primitive interface
    65  func (v *OnlineDDL) GetKeyspaceName() string {
    66  	return v.Keyspace.Name
    67  }
    68  
    69  // GetTableName implements the Primitive interface
    70  func (v *OnlineDDL) GetTableName() string {
    71  	return v.DDL.GetTable().Name.String()
    72  }
    73  
    74  // TryExecute implements the Primitive interface
    75  func (v *OnlineDDL) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (result *sqltypes.Result, err error) {
    76  	result = &sqltypes.Result{
    77  		Fields: []*querypb.Field{
    78  			{
    79  				Name: "uuid",
    80  				Type: sqltypes.VarChar,
    81  			},
    82  		},
    83  		Rows: [][]sqltypes.Value{},
    84  	}
    85  	onlineDDLs, err := schema.NewOnlineDDLs(v.GetKeyspaceName(), v.SQL, v.DDL,
    86  		v.DDLStrategySetting, fmt.Sprintf("vtgate:%s", vcursor.Session().GetSessionUUID()), "",
    87  	)
    88  	if err != nil {
    89  		return result, err
    90  	}
    91  	for _, onlineDDL := range onlineDDLs {
    92  		// Go directly to tablets, much like Send primitive does
    93  		s := Send{
    94  			Keyspace:          v.Keyspace,
    95  			TargetDestination: v.TargetDestination,
    96  			Query:             onlineDDL.SQL,
    97  			IsDML:             false,
    98  			SingleShardOnly:   false,
    99  		}
   100  		if _, err := vcursor.ExecutePrimitive(ctx, &s, bindVars, wantfields); err != nil {
   101  			return result, err
   102  		}
   103  		result.Rows = append(result.Rows, []sqltypes.Value{
   104  			sqltypes.NewVarChar(onlineDDL.UUID),
   105  		})
   106  	}
   107  	return result, err
   108  }
   109  
   110  // TryStreamExecute implements the Primitive interface
   111  func (v *OnlineDDL) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error {
   112  	results, err := v.TryExecute(ctx, vcursor, bindVars, wantfields)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	return callback(results)
   117  }
   118  
   119  // GetFields implements the Primitive interface
   120  func (v *OnlineDDL) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) {
   121  	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] GetFields is not reachable")
   122  }