github.com/matrixorigin/matrixone@v1.2.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  	"math"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    22  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    23  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    24  )
    25  
    26  func getPreparePlan(ctx CompilerContext, stmt tree.Statement) (*Plan, error) {
    27  	if s, ok := stmt.(*tree.Insert); ok {
    28  		if _, ok := s.Rows.Select.(*tree.ValuesClause); ok {
    29  			return BuildPlan(ctx, stmt, true)
    30  		}
    31  	} else if s, ok := stmt.(*tree.Replace); ok {
    32  		if _, ok := s.Rows.Select.(*tree.ValuesClause); ok {
    33  			return BuildPlan(ctx, stmt, true)
    34  		}
    35  	}
    36  
    37  	switch stmt := stmt.(type) {
    38  	case *tree.Select, *tree.ParenSelect,
    39  		*tree.Update, *tree.Delete, *tree.Insert,
    40  		*tree.ShowDatabases, *tree.ShowTables, *tree.ShowSequences, *tree.ShowColumns,
    41  		*tree.ShowCreateDatabase, *tree.ShowCreateTable:
    42  		opt := NewPrepareOptimizer(ctx)
    43  		optimized, err := opt.Optimize(stmt, true)
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  		return &Plan{
    48  			Plan: &Plan_Query{
    49  				Query: optimized,
    50  			},
    51  		}, nil
    52  	default:
    53  		return BuildPlan(ctx, stmt, true)
    54  	}
    55  }
    56  
    57  func buildPrepare(stmt tree.Prepare, ctx CompilerContext) (*Plan, error) {
    58  	var preparePlan *Plan
    59  	var err error
    60  	var stmtName string
    61  
    62  	switch pstmt := stmt.(type) {
    63  	case *tree.PrepareStmt:
    64  		stmtName = string(pstmt.Name)
    65  		preparePlan, err = getPreparePlan(ctx, pstmt.Stmt)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		preparePlan.IsPrepare = true
    70  
    71  	case *tree.PrepareString:
    72  		var v interface{}
    73  		v, err = ctx.ResolveVariable("lower_case_table_names", true, true)
    74  		if err != nil {
    75  			v = int64(1)
    76  		}
    77  		stmts, err := mysql.Parse(ctx.GetContext(), pstmt.Sql, v.(int64), 0)
    78  		defer func() {
    79  			for _, s := range stmts {
    80  				s.Free()
    81  			}
    82  		}()
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		if len(stmts) > 1 {
    87  			return nil, moerr.NewInvalidInput(ctx.GetContext(), "cannot prepare multi statements")
    88  		}
    89  		stmtName = string(pstmt.Name)
    90  		preparePlan, err = getPreparePlan(ctx, stmts[0])
    91  		if err != nil {
    92  			return nil, err
    93  		}
    94  		preparePlan.IsPrepare = true
    95  	}
    96  
    97  	schemas, paramTypes, err := ResetPreparePlan(ctx, preparePlan)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	if len(paramTypes) > math.MaxUint16 {
   102  		return nil, moerr.NewErrTooManyParameter(ctx.GetContext())
   103  	}
   104  
   105  	prepare := &plan.Prepare{
   106  		Name:       stmtName,
   107  		Schemas:    schemas,
   108  		Plan:       preparePlan,
   109  		ParamTypes: paramTypes,
   110  	}
   111  
   112  	return &Plan{
   113  		Plan: &plan.Plan_Dcl{
   114  			Dcl: &plan.DataControl{
   115  				DclType: plan.DataControl_PREPARE,
   116  				Control: &plan.DataControl_Prepare{
   117  					Prepare: prepare,
   118  				},
   119  			},
   120  		},
   121  	}, nil
   122  }
   123  
   124  func buildExecute(stmt *tree.Execute, ctx CompilerContext) (*Plan, error) {
   125  	builder := NewQueryBuilder(plan.Query_SELECT, ctx, false)
   126  	binder := NewWhereBinder(builder, &BindContext{})
   127  
   128  	args := make([]*Expr, len(stmt.Variables))
   129  	for idx, variable := range stmt.Variables {
   130  		arg, err := binder.baseBindExpr(variable, 0, true)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  		args[idx] = arg
   135  	}
   136  
   137  	execute := &plan.Execute{
   138  		Name: string(stmt.Name),
   139  		Args: args,
   140  	}
   141  
   142  	return &Plan{
   143  		Plan: &plan.Plan_Dcl{
   144  			Dcl: &plan.DataControl{
   145  				DclType: plan.DataControl_EXECUTE,
   146  				Control: &plan.DataControl_Execute{
   147  					Execute: execute,
   148  				},
   149  			},
   150  		},
   151  	}, nil
   152  }
   153  
   154  func buildDeallocate(stmt *tree.Deallocate, _ CompilerContext) (*Plan, error) {
   155  	deallocate := &plan.Deallocate{
   156  		Name: string(stmt.Name),
   157  	}
   158  
   159  	return &Plan{
   160  		Plan: &plan.Plan_Dcl{
   161  			Dcl: &plan.DataControl{
   162  				DclType: plan.DataControl_DEALLOCATE,
   163  				Control: &plan.DataControl_Deallocate{
   164  					Deallocate: deallocate,
   165  				},
   166  			},
   167  		},
   168  	}, nil
   169  }
   170  
   171  func buildSetVariables(stmt *tree.SetVar, ctx CompilerContext) (*Plan, error) {
   172  	var err error
   173  	items := make([]*plan.SetVariablesItem, len(stmt.Assignments))
   174  
   175  	builder := NewQueryBuilder(plan.Query_SELECT, ctx, false)
   176  	binder := NewWhereBinder(builder, &BindContext{})
   177  
   178  	for idx, assignment := range stmt.Assignments {
   179  		item := &plan.SetVariablesItem{
   180  			System: assignment.System,
   181  			Global: assignment.Global,
   182  			Name:   assignment.Name,
   183  		}
   184  		if assignment.Value == nil {
   185  			return nil, moerr.NewInvalidInput(ctx.GetContext(), "Set statement has no value")
   186  		}
   187  		item.Value, err = binder.baseBindExpr(assignment.Value, 0, true)
   188  		if err != nil {
   189  			return nil, err
   190  		}
   191  		if assignment.Reserved != nil {
   192  			item.Reserved, err = binder.baseBindExpr(assignment.Reserved, 0, true)
   193  			if err != nil {
   194  				return nil, err
   195  			}
   196  		}
   197  		items[idx] = item
   198  	}
   199  
   200  	setVariables := &plan.SetVariables{
   201  		Items: items,
   202  	}
   203  
   204  	return &Plan{
   205  		Plan: &plan.Plan_Dcl{
   206  			Dcl: &plan.DataControl{
   207  				DclType: plan.DataControl_SET_VARIABLES,
   208  				Control: &plan.DataControl_SetVariables{
   209  					SetVariables: setVariables,
   210  				},
   211  			},
   212  		},
   213  	}, nil
   214  }
   215  
   216  func buildCreateAccount(stmt *tree.CreateAccount, ctx CompilerContext, isPrepareStmt bool) (*Plan, error) {
   217  	params := []tree.Expr{
   218  		stmt.Name,
   219  		stmt.AuthOption.AdminName,
   220  		stmt.AuthOption.IdentifiedType.Str,
   221  	}
   222  	paramTypes, err := getParamTypes(params, ctx, isPrepareStmt)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	return &Plan{
   228  		Plan: &plan.Plan_Dcl{
   229  			Dcl: &plan.DataControl{
   230  				DclType: plan.DataControl_CREATE_ACCOUNT,
   231  				Control: &plan.DataControl_Other{
   232  					Other: &plan.OtherDCL{
   233  						ParamTypes: paramTypes,
   234  					},
   235  				},
   236  			},
   237  		},
   238  	}, nil
   239  }
   240  
   241  func buildAlterAccount(stmt *tree.AlterAccount, ctx CompilerContext, isPrepareStmt bool) (*Plan, error) {
   242  	params := []tree.Expr{
   243  		stmt.Name,
   244  		stmt.AuthOption.AdminName,
   245  		stmt.AuthOption.IdentifiedType.Str,
   246  	}
   247  	paramTypes, err := getParamTypes(params, ctx, isPrepareStmt)
   248  	if err != nil {
   249  		return nil, err
   250  	}
   251  
   252  	return &Plan{
   253  		Plan: &plan.Plan_Dcl{
   254  			Dcl: &plan.DataControl{
   255  				DclType: plan.DataControl_ALTER_ACCOUNT,
   256  				Control: &plan.DataControl_Other{
   257  					Other: &plan.OtherDCL{
   258  						ParamTypes: paramTypes,
   259  					},
   260  				},
   261  			},
   262  		},
   263  	}, nil
   264  }
   265  
   266  func buildDropAccount(stmt *tree.DropAccount, ctx CompilerContext, isPrepareStmt bool) (*Plan, error) {
   267  	params := []tree.Expr{
   268  		stmt.Name,
   269  	}
   270  	paramTypes, err := getParamTypes(params, ctx, isPrepareStmt)
   271  	if err != nil {
   272  		return nil, err
   273  	}
   274  
   275  	return &Plan{
   276  		Plan: &plan.Plan_Dcl{
   277  			Dcl: &plan.DataControl{
   278  				DclType: plan.DataControl_DROP_ACCOUNT,
   279  				Control: &plan.DataControl_Other{
   280  					Other: &plan.OtherDCL{
   281  						ParamTypes: paramTypes,
   282  					},
   283  				},
   284  			},
   285  		},
   286  	}, nil
   287  }