github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/build_dcl.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    20  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    21  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    22  )
    23  
    24  func getPreparePlan(ctx CompilerContext, stmt tree.Statement) (*Plan, error) {
    25  	if s, ok := stmt.(*tree.Insert); ok {
    26  		if _, ok := s.Rows.Select.(*tree.ValuesClause); ok {
    27  			return BuildPlan(ctx, stmt)
    28  		}
    29  	}
    30  
    31  	switch stmt := stmt.(type) {
    32  	case *tree.Select, *tree.ParenSelect,
    33  		*tree.Update, *tree.Delete, *tree.Insert,
    34  		*tree.ShowDatabases, *tree.ShowTables, *tree.ShowColumns,
    35  		*tree.ShowCreateDatabase, *tree.ShowCreateTable:
    36  		opt := NewPrepareOptimizer(ctx)
    37  		optimized, err := opt.Optimize(stmt)
    38  		if err != nil {
    39  			return nil, err
    40  		}
    41  		return &Plan{
    42  			Plan: &Plan_Query{
    43  				Query: optimized,
    44  			},
    45  		}, nil
    46  	default:
    47  		return BuildPlan(ctx, stmt)
    48  	}
    49  }
    50  
    51  func buildPrepare(stmt tree.Prepare, ctx CompilerContext) (*Plan, error) {
    52  	var preparePlan *Plan
    53  	var err error
    54  	var stmtName string
    55  
    56  	switch pstmt := stmt.(type) {
    57  	case *tree.PrepareStmt:
    58  		stmtName = string(pstmt.Name)
    59  		preparePlan, err = getPreparePlan(ctx, pstmt.Stmt)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  
    64  	case *tree.PrepareString:
    65  		stmts, err := mysql.Parse(ctx.GetContext(), pstmt.Sql)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		if len(stmts) > 1 {
    70  			return nil, moerr.NewInvalidInput(ctx.GetContext(), "cannot prepare multi statements")
    71  		}
    72  		stmtName = string(pstmt.Name)
    73  		preparePlan, err = getPreparePlan(ctx, stmts[0])
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  	}
    78  
    79  	// dcl tcl is not support
    80  	var schemas []*plan.ObjectRef
    81  	var paramTypes []int32
    82  
    83  	switch pp := preparePlan.Plan.(type) {
    84  	case *plan.Plan_Tcl, *plan.Plan_Dcl:
    85  		return nil, moerr.NewInvalidInput(ctx.GetContext(), "cannot prepare TCL and DCL statement")
    86  
    87  	case *plan.Plan_Ddl:
    88  		if pp.Ddl.Query != nil {
    89  			getParamRule := NewGetParamRule()
    90  			VisitQuery := NewVisitPlan(preparePlan, []VisitPlanRule{getParamRule})
    91  			err = VisitQuery.Visit(ctx.GetContext())
    92  			if err != nil {
    93  				return nil, err
    94  			}
    95  			// TODO : need confirm
    96  			if len(getParamRule.params) > 0 {
    97  				return nil, moerr.NewInvalidInput(ctx.GetContext(), "cannot plan DDL statement")
    98  			}
    99  		}
   100  
   101  	case *plan.Plan_Query:
   102  		// collect args
   103  		getParamRule := NewGetParamRule()
   104  		VisitQuery := NewVisitPlan(preparePlan, []VisitPlanRule{getParamRule})
   105  		err = VisitQuery.Visit(ctx.GetContext())
   106  		if err != nil {
   107  			return nil, err
   108  		}
   109  
   110  		// sort arg
   111  		getParamRule.SetParamOrder()
   112  		args := getParamRule.params
   113  		schemas = getParamRule.schemas
   114  		paramTypes = getParamRule.paramTypes
   115  
   116  		// reset arg order
   117  		resetParamRule := NewResetParamOrderRule(args)
   118  		VisitQuery = NewVisitPlan(preparePlan, []VisitPlanRule{resetParamRule})
   119  		err = VisitQuery.Visit(ctx.GetContext())
   120  		if err != nil {
   121  			return nil, err
   122  		}
   123  	}
   124  
   125  	prepare := &plan.Prepare{
   126  		Name:       stmtName,
   127  		Schemas:    schemas,
   128  		Plan:       preparePlan,
   129  		ParamTypes: paramTypes,
   130  	}
   131  
   132  	return &Plan{
   133  		Plan: &plan.Plan_Dcl{
   134  			Dcl: &plan.DataControl{
   135  				DclType: plan.DataControl_PREPARE,
   136  				Control: &plan.DataControl_Prepare{
   137  					Prepare: prepare,
   138  				},
   139  			},
   140  		},
   141  	}, nil
   142  }
   143  
   144  func buildExecute(stmt *tree.Execute, ctx CompilerContext) (*Plan, error) {
   145  	builder := NewQueryBuilder(plan.Query_SELECT, ctx)
   146  	binder := NewWhereBinder(builder, &BindContext{})
   147  
   148  	args := make([]*Expr, len(stmt.Variables))
   149  	for idx, variable := range stmt.Variables {
   150  		arg, err := binder.baseBindExpr(variable, 0, true)
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  		args[idx] = arg
   155  	}
   156  
   157  	execute := &plan.Execute{
   158  		Name: string(stmt.Name),
   159  		Args: args,
   160  	}
   161  
   162  	return &Plan{
   163  		Plan: &plan.Plan_Dcl{
   164  			Dcl: &plan.DataControl{
   165  				DclType: plan.DataControl_EXECUTE,
   166  				Control: &plan.DataControl_Execute{
   167  					Execute: execute,
   168  				},
   169  			},
   170  		},
   171  	}, nil
   172  }
   173  
   174  func buildDeallocate(stmt *tree.Deallocate, _ CompilerContext) (*Plan, error) {
   175  	deallocate := &plan.Deallocate{
   176  		Name: string(stmt.Name),
   177  	}
   178  
   179  	return &Plan{
   180  		Plan: &plan.Plan_Dcl{
   181  			Dcl: &plan.DataControl{
   182  				DclType: plan.DataControl_DEALLOCATE,
   183  				Control: &plan.DataControl_Deallocate{
   184  					Deallocate: deallocate,
   185  				},
   186  			},
   187  		},
   188  	}, nil
   189  }
   190  
   191  func buildSetVariables(stmt *tree.SetVar, ctx CompilerContext) (*Plan, error) {
   192  	var err error
   193  	items := make([]*plan.SetVariablesItem, len(stmt.Assignments))
   194  
   195  	builder := NewQueryBuilder(plan.Query_SELECT, ctx)
   196  	binder := NewWhereBinder(builder, &BindContext{})
   197  
   198  	for idx, assignment := range stmt.Assignments {
   199  		item := &plan.SetVariablesItem{
   200  			System: assignment.System,
   201  			Global: assignment.Global,
   202  			Name:   assignment.Name,
   203  		}
   204  		if assignment.Value == nil {
   205  			return nil, moerr.NewInvalidInput(ctx.GetContext(), "Set statement has no value")
   206  		}
   207  		item.Value, err = binder.baseBindExpr(assignment.Value, 0, true)
   208  		if err != nil {
   209  			return nil, err
   210  		}
   211  		if assignment.Reserved != nil {
   212  			item.Reserved, err = binder.baseBindExpr(assignment.Reserved, 0, true)
   213  			if err != nil {
   214  				return nil, err
   215  			}
   216  		}
   217  		items[idx] = item
   218  	}
   219  
   220  	setVariables := &plan.SetVariables{
   221  		Items: items,
   222  	}
   223  
   224  	return &Plan{
   225  		Plan: &plan.Plan_Dcl{
   226  			Dcl: &plan.DataControl{
   227  				DclType: plan.DataControl_SET_VARIABLES,
   228  				Control: &plan.DataControl_SetVariables{
   229  					SetVariables: setVariables,
   230  				},
   231  			},
   232  		},
   233  	}, nil
   234  }