github.com/matrixorigin/matrixone@v1.2.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  	"time"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    21  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    22  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    23  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    24  )
    25  
    26  func buildDelete(stmt *tree.Delete, ctx CompilerContext, isPrepareStmt bool) (*Plan, error) {
    27  	start := time.Now()
    28  	defer func() {
    29  		v2.TxnStatementBuildDeleteHistogram.Observe(time.Since(start).Seconds())
    30  	}()
    31  	aliasMap := make(map[string][2]string)
    32  	for _, tbl := range stmt.TableRefs {
    33  		getAliasToName(ctx, tbl, "", aliasMap)
    34  	}
    35  	tblInfo, err := getDmlTableInfo(ctx, stmt.Tables, stmt.With, aliasMap, "delete")
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	builder := NewQueryBuilder(plan.Query_SELECT, ctx, isPrepareStmt)
    40  
    41  	queryBindCtx := NewBindContext(builder, nil)
    42  	lastNodeId, err := deleteToSelect(builder, queryBindCtx, stmt, true, tblInfo)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	sourceStep := builder.appendStep(lastNodeId)
    47  	query, err := builder.createQuery()
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	builder.qry.Steps = append(builder.qry.Steps[:sourceStep], builder.qry.Steps[sourceStep+1:]...)
    52  
    53  	// append sink node
    54  	lastNodeId = appendSinkNode(builder, queryBindCtx, lastNodeId)
    55  	sourceStep = builder.appendStep(lastNodeId)
    56  
    57  	allDelTableIDs := make(map[uint64]struct{})
    58  	for _, tableDef := range tblInfo.tableDefs {
    59  		allDelTableIDs[tableDef.TblId] = struct{}{}
    60  	}
    61  
    62  	allDelTables := make(map[FkReferKey]struct{})
    63  	for i, tableDef := range tblInfo.tableDefs {
    64  		allDelTables[FkReferKey{Db: tblInfo.objRef[i].SchemaName, Tbl: tableDef.Name}] = struct{}{}
    65  	}
    66  	// append delete plans
    67  	beginIdx := 0
    68  	// needLockTable := !tblInfo.isMulti && stmt.Where == nil && stmt.Limit == nil
    69  	// todo will do not lock table now.
    70  	isDeleteWithoutFilters := !tblInfo.isMulti && stmt.Where == nil && stmt.Limit == nil
    71  	needLockTable := isDeleteWithoutFilters
    72  	for i, tableDef := range tblInfo.tableDefs {
    73  		deleteBindCtx := NewBindContext(builder, nil)
    74  		delPlanCtx := getDmlPlanCtx()
    75  		delPlanCtx.objRef = tblInfo.objRef[i]
    76  		delPlanCtx.tableDef = tableDef
    77  		delPlanCtx.beginIdx = beginIdx
    78  		delPlanCtx.sourceStep = sourceStep
    79  		delPlanCtx.isMulti = tblInfo.isMulti
    80  		delPlanCtx.needAggFilter = tblInfo.needAggFilter
    81  		delPlanCtx.updateColLength = 0
    82  		delPlanCtx.rowIdPos = getRowIdPos(tableDef)
    83  		delPlanCtx.allDelTableIDs = allDelTableIDs
    84  		delPlanCtx.allDelTables = allDelTables
    85  		delPlanCtx.lockTable = needLockTable
    86  		delPlanCtx.isDeleteWithoutFilters = isDeleteWithoutFilters
    87  
    88  		if tableDef.Partition != nil {
    89  			partTableIds := make([]uint64, tableDef.Partition.PartitionNum)
    90  			partTableNames := make([]string, tableDef.Partition.PartitionNum)
    91  			for j, partition := range tableDef.Partition.Partitions {
    92  				_, partTableDef := ctx.Resolve(tblInfo.objRef[i].SchemaName, partition.PartitionTableName, Snapshot{TS: &timestamp.Timestamp{}})
    93  				partTableIds[j] = partTableDef.TblId
    94  				partTableNames[j] = partition.PartitionTableName
    95  			}
    96  			delPlanCtx.partitionInfos[tableDef.TblId] = &partSubTableInfo{
    97  				partTableIDs:   partTableIds,
    98  				partTableNames: partTableNames,
    99  			}
   100  		}
   101  
   102  		lastNodeId = appendSinkScanNode(builder, deleteBindCtx, sourceStep)
   103  		lastNodeId, err = makePreUpdateDeletePlan(ctx, builder, deleteBindCtx, delPlanCtx, lastNodeId)
   104  		if err != nil {
   105  			return nil, err
   106  		}
   107  		lastNodeId = appendSinkNode(builder, deleteBindCtx, lastNodeId)
   108  		nextSourceStep := builder.appendStep(lastNodeId)
   109  		delPlanCtx.sourceStep = nextSourceStep
   110  
   111  		err = buildDeletePlans(ctx, builder, deleteBindCtx, delPlanCtx)
   112  		if err != nil {
   113  			return nil, err
   114  		}
   115  		beginIdx = beginIdx + len(tableDef.Cols)
   116  		putDmlPlanCtx(delPlanCtx)
   117  	}
   118  
   119  	reduceSinkSinkScanNodes(query)
   120  	ReCalcQueryStats(builder, query)
   121  	reCheckifNeedLockWholeTable(builder)
   122  	query.StmtType = plan.Query_DELETE
   123  	return &Plan{
   124  		Plan: &plan.Plan_Query{
   125  			Query: query,
   126  		},
   127  	}, err
   128  }