github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opaque.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sql
    12  
    13  import (
    14  	"context"
    15  	"reflect"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/opt/optbuilder"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    23  	"github.com/cockroachdb/errors"
    24  )
    25  
    26  type opaqueMetadata struct {
    27  	info string
    28  	plan planNode
    29  }
    30  
    31  var _ opt.OpaqueMetadata = &opaqueMetadata{}
    32  
    33  func (o *opaqueMetadata) ImplementsOpaqueMetadata() {}
    34  func (o *opaqueMetadata) String() string            { return o.info }
    35  
    36  func buildOpaque(
    37  	ctx context.Context, semaCtx *tree.SemaContext, evalCtx *tree.EvalContext, stmt tree.Statement,
    38  ) (opt.OpaqueMetadata, sqlbase.ResultColumns, error) {
    39  	p := evalCtx.Planner.(*planner)
    40  
    41  	// Opaque statements handle their own scalar arguments, with no help from the
    42  	// optimizer. As such, they cannot contain subqueries.
    43  	scalarProps := &semaCtx.Properties
    44  	defer scalarProps.Restore(*scalarProps)
    45  	scalarProps.Require(stmt.StatementTag(), tree.RejectSubqueries)
    46  
    47  	var plan planNode
    48  	var err error
    49  	switch n := stmt.(type) {
    50  	case *tree.AlterIndex:
    51  		plan, err = p.AlterIndex(ctx, n)
    52  	case *tree.AlterTable:
    53  		plan, err = p.AlterTable(ctx, n)
    54  	case *tree.AlterType:
    55  		plan, err = p.AlterType(ctx, n)
    56  	case *tree.AlterRole:
    57  		plan, err = p.AlterRole(ctx, n)
    58  	case *tree.AlterSequence:
    59  		plan, err = p.AlterSequence(ctx, n)
    60  	case *tree.CommentOnColumn:
    61  		plan, err = p.CommentOnColumn(ctx, n)
    62  	case *tree.CommentOnDatabase:
    63  		plan, err = p.CommentOnDatabase(ctx, n)
    64  	case *tree.CommentOnIndex:
    65  		plan, err = p.CommentOnIndex(ctx, n)
    66  	case *tree.CommentOnTable:
    67  		plan, err = p.CommentOnTable(ctx, n)
    68  	case *tree.CreateDatabase:
    69  		plan, err = p.CreateDatabase(ctx, n)
    70  	case *tree.CreateIndex:
    71  		plan, err = p.CreateIndex(ctx, n)
    72  	case *tree.CreateSchema:
    73  		plan, err = p.CreateSchema(ctx, n)
    74  	case *tree.CreateType:
    75  		plan, err = p.CreateType(ctx, n)
    76  	case *tree.CreateRole:
    77  		plan, err = p.CreateRole(ctx, n)
    78  	case *tree.CreateSequence:
    79  		plan, err = p.CreateSequence(ctx, n)
    80  	case *tree.CreateStats:
    81  		plan, err = p.CreateStatistics(ctx, n)
    82  	case *tree.Deallocate:
    83  		plan, err = p.Deallocate(ctx, n)
    84  	case *tree.Discard:
    85  		plan, err = p.Discard(ctx, n)
    86  	case *tree.DropDatabase:
    87  		plan, err = p.DropDatabase(ctx, n)
    88  	case *tree.DropIndex:
    89  		plan, err = p.DropIndex(ctx, n)
    90  	case *tree.DropRole:
    91  		plan, err = p.DropRole(ctx, n)
    92  	case *tree.DropTable:
    93  		plan, err = p.DropTable(ctx, n)
    94  	case *tree.DropType:
    95  		plan, err = p.DropType(ctx, n)
    96  	case *tree.DropView:
    97  		plan, err = p.DropView(ctx, n)
    98  	case *tree.DropSequence:
    99  		plan, err = p.DropSequence(ctx, n)
   100  	case *tree.Grant:
   101  		plan, err = p.Grant(ctx, n)
   102  	case *tree.GrantRole:
   103  		plan, err = p.GrantRole(ctx, n)
   104  	case *tree.RenameColumn:
   105  		plan, err = p.RenameColumn(ctx, n)
   106  	case *tree.RenameDatabase:
   107  		plan, err = p.RenameDatabase(ctx, n)
   108  	case *tree.RenameIndex:
   109  		plan, err = p.RenameIndex(ctx, n)
   110  	case *tree.RenameTable:
   111  		plan, err = p.RenameTable(ctx, n)
   112  	case *tree.Revoke:
   113  		plan, err = p.Revoke(ctx, n)
   114  	case *tree.RevokeRole:
   115  		plan, err = p.RevokeRole(ctx, n)
   116  	case *tree.Scatter:
   117  		plan, err = p.Scatter(ctx, n)
   118  	case *tree.Scrub:
   119  		plan, err = p.Scrub(ctx, n)
   120  	case *tree.SetClusterSetting:
   121  		plan, err = p.SetClusterSetting(ctx, n)
   122  	case *tree.SetZoneConfig:
   123  		plan, err = p.SetZoneConfig(ctx, n)
   124  	case *tree.SetVar:
   125  		plan, err = p.SetVar(ctx, n)
   126  	case *tree.SetTransaction:
   127  		plan, err = p.SetTransaction(ctx, n)
   128  	case *tree.SetSessionAuthorizationDefault:
   129  		plan, err = p.SetSessionAuthorizationDefault()
   130  	case *tree.SetSessionCharacteristics:
   131  		plan, err = p.SetSessionCharacteristics(n)
   132  	case *tree.ShowClusterSetting:
   133  		plan, err = p.ShowClusterSetting(ctx, n)
   134  	case *tree.ShowHistogram:
   135  		plan, err = p.ShowHistogram(ctx, n)
   136  	case *tree.ShowTableStats:
   137  		plan, err = p.ShowTableStats(ctx, n)
   138  	case *tree.ShowTraceForSession:
   139  		plan, err = p.ShowTrace(ctx, n)
   140  	case *tree.ShowZoneConfig:
   141  		plan, err = p.ShowZoneConfig(ctx, n)
   142  	case *tree.ShowFingerprints:
   143  		plan, err = p.ShowFingerprints(ctx, n)
   144  	case *tree.Truncate:
   145  		plan, err = p.Truncate(ctx, n)
   146  	case tree.CCLOnlyStatement:
   147  		plan, err = p.maybePlanHook(ctx, stmt)
   148  		if plan == nil && err == nil {
   149  			return nil, nil, pgerror.Newf(pgcode.CCLRequired,
   150  				"a CCL binary is required to use this statement type: %T", stmt)
   151  		}
   152  	default:
   153  		return nil, nil, errors.AssertionFailedf("unknown opaque statement %T", stmt)
   154  	}
   155  	if err != nil {
   156  		return nil, nil, err
   157  	}
   158  	res := &opaqueMetadata{
   159  		info: stmt.StatementTag(),
   160  		plan: plan,
   161  	}
   162  	return res, planColumns(plan), nil
   163  }
   164  
   165  func init() {
   166  	for _, stmt := range []tree.Statement{
   167  		&tree.AlterIndex{},
   168  		&tree.AlterTable{},
   169  		&tree.AlterType{},
   170  		&tree.AlterSequence{},
   171  		&tree.AlterRole{},
   172  		&tree.CommentOnColumn{},
   173  		&tree.CommentOnDatabase{},
   174  		&tree.CommentOnIndex{},
   175  		&tree.CommentOnTable{},
   176  		&tree.CreateDatabase{},
   177  		&tree.CreateIndex{},
   178  		&tree.CreateSchema{},
   179  		&tree.CreateSequence{},
   180  		&tree.CreateStats{},
   181  		&tree.CreateType{},
   182  		&tree.CreateRole{},
   183  		&tree.Deallocate{},
   184  		&tree.Discard{},
   185  		&tree.DropDatabase{},
   186  		&tree.DropIndex{},
   187  		&tree.DropTable{},
   188  		&tree.DropType{},
   189  		&tree.DropView{},
   190  		&tree.DropRole{},
   191  		&tree.DropSequence{},
   192  		&tree.Grant{},
   193  		&tree.GrantRole{},
   194  		&tree.RenameColumn{},
   195  		&tree.RenameDatabase{},
   196  		&tree.RenameIndex{},
   197  		&tree.RenameTable{},
   198  		&tree.Revoke{},
   199  		&tree.RevokeRole{},
   200  		&tree.Scatter{},
   201  		&tree.Scrub{},
   202  		&tree.SetClusterSetting{},
   203  		&tree.SetZoneConfig{},
   204  		&tree.SetVar{},
   205  		&tree.SetTransaction{},
   206  		&tree.SetSessionAuthorizationDefault{},
   207  		&tree.SetSessionCharacteristics{},
   208  		&tree.ShowClusterSetting{},
   209  		&tree.ShowHistogram{},
   210  		&tree.ShowTableStats{},
   211  		&tree.ShowTraceForSession{},
   212  		&tree.ShowZoneConfig{},
   213  		&tree.ShowFingerprints{},
   214  		&tree.Truncate{},
   215  
   216  		// CCL statements (without Export which has an optimizer operator).
   217  		&tree.Backup{},
   218  		&tree.ShowBackup{},
   219  		&tree.Restore{},
   220  		&tree.CreateChangefeed{},
   221  		&tree.Import{},
   222  	} {
   223  		typ := optbuilder.OpaqueReadOnly
   224  		if tree.CanModifySchema(stmt) {
   225  			typ = optbuilder.OpaqueDDL
   226  		} else if tree.CanWriteData(stmt) {
   227  			typ = optbuilder.OpaqueMutation
   228  		}
   229  		optbuilder.RegisterOpaque(reflect.TypeOf(stmt), typ, buildOpaque)
   230  	}
   231  }