github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/build_delete.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/pb/plan" 19 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 20 ) 21 22 func buildDelete(stmt *tree.Delete, ctx CompilerContext) (*Plan, error) { 23 aliasMap := make(map[string][2]string) 24 for _, tbl := range stmt.TableRefs { 25 getAliasToName(ctx, tbl, "", aliasMap) 26 } 27 tblInfo, err := getDmlTableInfo(ctx, stmt.Tables, stmt.With, aliasMap) 28 if err != nil { 29 return nil, err 30 } 31 builder := NewQueryBuilder(plan.Query_SELECT, ctx) 32 bindCtx := NewBindContext(builder, nil) 33 34 rewriteInfo := &dmlSelectInfo{ 35 typ: "delete", 36 rootId: -1, 37 tblInfo: tblInfo, 38 } 39 40 canTruncate := false 41 if tblInfo.haveConstraint { 42 bindCtx.groupTag = builder.genNewTag() 43 bindCtx.aggregateTag = builder.genNewTag() 44 bindCtx.projectTag = builder.genNewTag() 45 46 // if delete table have constraint 47 err = initDeleteStmt(builder, bindCtx, rewriteInfo, stmt) 48 if err != nil { 49 return nil, err 50 } 51 52 for i, tableDef := range tblInfo.tableDefs { 53 err = rewriteDmlSelectInfo(builder, bindCtx, rewriteInfo, tableDef, rewriteInfo.derivedTableId, i) 54 if err != nil { 55 return nil, err 56 } 57 } 58 59 // append ProjectNode 60 rewriteInfo.rootId = builder.appendNode(&plan.Node{ 61 NodeType: plan.Node_PROJECT, 62 ProjectList: rewriteInfo.projectList, 63 Children: []int32{rewriteInfo.rootId}, 64 BindingTags: []int32{bindCtx.projectTag}, 65 }, bindCtx) 66 bindCtx.results = rewriteInfo.projectList 67 } else { 68 // if delete table have no constraint 69 if stmt.Where == nil && stmt.Limit == nil { 70 // we need to fix #7779 first, don't use truncate 71 // I will improve this after cn-write-s3 delete 72 canTruncate = false 73 } 74 rewriteInfo.rootId, err = deleteToSelect(builder, bindCtx, stmt, false) 75 if err != nil { 76 return nil, err 77 } 78 } 79 80 builder.qry.Steps = append(builder.qry.Steps, rewriteInfo.rootId) 81 query, err := builder.createQuery() 82 if err != nil { 83 return nil, err 84 } 85 86 // append delete node 87 deleteCtx := &plan.DeleteCtx{ 88 CanTruncate: canTruncate, 89 Ref: rewriteInfo.tblInfo.objRef, 90 91 IdxRef: rewriteInfo.onIdxTbl, 92 IdxIdx: rewriteInfo.onIdx, 93 94 OnRestrictRef: rewriteInfo.onRestrictTbl, 95 OnRestrictIdx: rewriteInfo.onRestrict, 96 OnCascadeRef: rewriteInfo.onCascadeRef, 97 OnCascadeIdx: make([]int32, len(rewriteInfo.onCascade)), 98 99 OnSetRef: rewriteInfo.onSetRef, 100 OnSetIdx: make([]*plan.IdList, len(rewriteInfo.onSet)), 101 OnSetDef: rewriteInfo.onSetTableDef, 102 OnSetUpdateCol: make([]*plan.ColPosMap, len(rewriteInfo.onSetUpdateCol)), 103 } 104 for i, idxList := range rewriteInfo.onCascade { 105 deleteCtx.OnCascadeIdx[i] = int32(idxList[0]) 106 } 107 for i, setList := range rewriteInfo.onSet { 108 deleteCtx.OnSetIdx[i] = &plan.IdList{ 109 List: setList, 110 } 111 } 112 for i, idxMap := range rewriteInfo.onSetUpdateCol { 113 deleteCtx.OnSetUpdateCol[i] = &plan.ColPosMap{ 114 Map: idxMap, 115 } 116 } 117 118 node := &Node{ 119 NodeType: plan.Node_DELETE, 120 ObjRef: nil, 121 TableDef: nil, 122 Children: []int32{query.Steps[len(query.Steps)-1]}, 123 NodeId: int32(len(query.Nodes)), 124 DeleteCtx: deleteCtx, 125 } 126 query.Nodes = append(query.Nodes, node) 127 query.Steps[len(query.Steps)-1] = node.NodeId 128 query.StmtType = plan.Query_DELETE 129 130 return &Plan{ 131 Plan: &plan.Plan_Query{ 132 Query: query, 133 }, 134 }, err 135 } 136 137 // // build rowid column abstract syntax tree expression of the table to be deleted 138 // func buildRowIdAstExpr(ctx CompilerContext, tbinfo *tableInfo, schemaName string, tableName string) (tree.SelectExpr, error) { 139 // hideKey := ctx.GetHideKeyDef(schemaName, tableName) 140 // if hideKey == nil { 141 // return tree.SelectExpr{}, moerr.NewInvalidState(ctx.GetContext(), "cannot find hide key") 142 // } 143 // tblAliasName := tableName 144 // if tbinfo != nil { 145 // tblAliasName = tbinfo.baseName2AliasMap[tableName] 146 // } 147 // expr := tree.SetUnresolvedName(tblAliasName, hideKey.Name) 148 // return tree.SelectExpr{Expr: expr}, nil 149 // } 150 151 // // build Index table ast expr 152 // func buildIndexTableExpr(indexTableName string) tree.TableExpr { 153 // prefix := tree.ObjectNamePrefix{ 154 // CatalogName: "", 155 // SchemaName: "", 156 // ExplicitCatalog: false, 157 // ExplicitSchema: false, 158 // } 159 160 // tableExpr := tree.NewTableName(tree.Identifier(indexTableName), prefix) 161 162 // aliasClause := tree.AliasClause{ 163 // Alias: "", 164 // } 165 // return tree.NewAliasedTableExpr(tableExpr, aliasClause) 166 // } 167 168 // // construct equivalent connection conditions between original table and index table 169 // func buildJoinOnCond(tbinfo *tableInfo, originTableName string, indexTableName string, indexField *plan.Field) *tree.OnJoinCond { 170 // originTableAlias := tbinfo.baseName2AliasMap[originTableName] 171 // // If it is a single column index 172 // if len(indexField.Parts) == 1 { 173 // uniqueColName := indexField.Parts[0] 174 // leftExpr := tree.SetUnresolvedName(originTableAlias, uniqueColName) 175 // rightExpr := tree.SetUnresolvedName(indexTableName, strings.ToLower(catalog.IndexTableIndexColName)) 176 177 // onCondExpr := tree.NewComparisonExprWithSubop(tree.EQUAL, tree.EQUAL, leftExpr, rightExpr) 178 // return tree.NewOnJoinCond(onCondExpr) 179 // } else { // If it is a composite index 180 // funcName := tree.SetUnresolvedName(strings.ToLower("serial")) 181 // // build function parameters 182 // exprs := make(tree.Exprs, len(indexField.Parts)) 183 // for i, part := range indexField.Parts { 184 // exprs[i] = tree.SetUnresolvedName(originTableAlias, part) 185 // } 186 187 // // build composite index serialize function expression 188 // leftExpr := &tree.FuncExpr{ 189 // Func: tree.FuncName2ResolvableFunctionReference(funcName), 190 // Exprs: exprs, 191 // } 192 193 // rightExpr := tree.SetUnresolvedName(indexTableName, strings.ToLower(catalog.IndexTableIndexColName)) 194 // onCondExpr := tree.NewComparisonExprWithSubop(tree.EQUAL, tree.EQUAL, leftExpr, rightExpr) 195 // return tree.NewOnJoinCond(onCondExpr) 196 // } 197 // }