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  // }