vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/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  
    22  	"vitess.io/vitess/go/sqltypes"
    23  	"vitess.io/vitess/go/vt/proto/query"
    24  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    25  	"vitess.io/vitess/go/vt/schema"
    26  	"vitess.io/vitess/go/vt/sqlparser"
    27  	"vitess.io/vitess/go/vt/vterrors"
    28  	"vitess.io/vitess/go/vt/vtgate/vindexes"
    29  )
    30  
    31  var _ Primitive = (*DDL)(nil)
    32  
    33  // DDL represents a DDL statement, either normal or online DDL
    34  type DDL struct {
    35  	Keyspace *vindexes.Keyspace
    36  	SQL      string
    37  	DDL      sqlparser.DDLStatement
    38  
    39  	NormalDDL *Send
    40  	OnlineDDL *OnlineDDL
    41  
    42  	DirectDDLEnabled bool
    43  	OnlineDDLEnabled bool
    44  
    45  	CreateTempTable bool
    46  
    47  	noTxNeeded
    48  
    49  	noInputs
    50  }
    51  
    52  func (ddl *DDL) description() PrimitiveDescription {
    53  	other := map[string]any{
    54  		"Query": ddl.SQL,
    55  	}
    56  	if ddl.CreateTempTable {
    57  		other["TempTable"] = true
    58  	}
    59  	return PrimitiveDescription{
    60  		OperatorType: "DDL",
    61  		Keyspace:     ddl.Keyspace,
    62  		Other:        other,
    63  	}
    64  }
    65  
    66  // RouteType implements the Primitive interface
    67  func (ddl *DDL) RouteType() string {
    68  	return "DDL"
    69  }
    70  
    71  // GetKeyspaceName implements the Primitive interface
    72  func (ddl *DDL) GetKeyspaceName() string {
    73  	return ddl.Keyspace.Name
    74  }
    75  
    76  // GetTableName implements the Primitive interface
    77  func (ddl *DDL) GetTableName() string {
    78  	return ddl.DDL.GetTable().Name.String()
    79  }
    80  
    81  // IsOnlineSchemaDDL returns true if the query is an online schema change DDL
    82  func (ddl *DDL) isOnlineSchemaDDL() bool {
    83  	switch ddl.DDL.GetAction() {
    84  	case sqlparser.CreateDDLAction, sqlparser.DropDDLAction, sqlparser.AlterDDLAction:
    85  		return !ddl.OnlineDDL.DDLStrategySetting.Strategy.IsDirect()
    86  	}
    87  	return false
    88  }
    89  
    90  // TryExecute implements the Primitive interface
    91  func (ddl *DDL) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool) (result *sqltypes.Result, err error) {
    92  	if ddl.CreateTempTable {
    93  		vcursor.Session().HasCreatedTempTable()
    94  		vcursor.Session().NeedsReservedConn()
    95  		return vcursor.ExecutePrimitive(ctx, ddl.NormalDDL, bindVars, wantfields)
    96  	}
    97  
    98  	ddlStrategySetting, err := schema.ParseDDLStrategy(vcursor.Session().GetDDLStrategy())
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	ddl.OnlineDDL.DDLStrategySetting = ddlStrategySetting
   103  
   104  	switch {
   105  	case ddl.isOnlineSchemaDDL():
   106  		if !ddl.OnlineDDLEnabled {
   107  			return nil, schema.ErrOnlineDDLDisabled
   108  		}
   109  		return vcursor.ExecutePrimitive(ctx, ddl.OnlineDDL, bindVars, wantfields)
   110  	default: // non online-ddl
   111  		if !ddl.DirectDDLEnabled {
   112  			return nil, schema.ErrDirectDDLDisabled
   113  		}
   114  		return vcursor.ExecutePrimitive(ctx, ddl.NormalDDL, bindVars, wantfields)
   115  	}
   116  }
   117  
   118  // TryStreamExecute implements the Primitive interface
   119  func (ddl *DDL) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error {
   120  	results, err := ddl.TryExecute(ctx, vcursor, bindVars, wantfields)
   121  	if err != nil {
   122  		return err
   123  	}
   124  	return callback(results)
   125  }
   126  
   127  // GetFields implements the Primitive interface
   128  func (ddl *DDL) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*query.BindVariable) (*sqltypes.Result, error) {
   129  	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] GetFields in not reachable")
   130  }