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 }