github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/constraint_util.go (about)

     1  // Copyright 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 colexec
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    24  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    25  	"github.com/matrixorigin/matrixone/pkg/container/types"
    26  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    29  )
    30  
    31  func FilterRowIdForDel(proc *process.Process, bat *batch.Batch,
    32  	idx int, primaryKeyIdx int) (*batch.Batch, error) {
    33  	sels := proc.Mp().GetSels()
    34  	defer proc.Mp().PutSels(sels)
    35  	retBat := batch.NewWithSize(2)
    36  	retBat.SetAttributes([]string{catalog.Row_ID, "pk"})
    37  	rowidVec := proc.GetVector(types.T_Rowid.ToType())
    38  	primaryVec := proc.GetVector(*bat.GetVector(int32(primaryKeyIdx)).GetType())
    39  	retBat.SetVector(0, rowidVec)
    40  	retBat.SetVector(1, primaryVec)
    41  	rowIdMap := make(map[types.Rowid]bool)
    42  	nulls := bat.Vecs[idx].GetNulls()
    43  	for i, r := range vector.MustFixedCol[types.Rowid](bat.Vecs[idx]) {
    44  		if !nulls.Contains(uint64(i)) {
    45  			if rowIdMap[r] {
    46  				continue
    47  			}
    48  			rowIdMap[r] = true
    49  			sels = append(sels, int64(i))
    50  		}
    51  	}
    52  	uf := vector.GetUnionOneFunction(types.T_Rowid.ToType(), proc.Mp())
    53  	for _, sel := range sels {
    54  		if err := uf(rowidVec, bat.Vecs[idx], sel); err != nil {
    55  			retBat.Clean(proc.Mp())
    56  			return nil, err
    57  		}
    58  	}
    59  	uf = vector.GetUnionOneFunction(*bat.GetVector(int32(primaryKeyIdx)).GetType(), proc.Mp())
    60  	for _, sel := range sels {
    61  		if err := uf(primaryVec, bat.Vecs[primaryKeyIdx], sel); err != nil {
    62  			retBat.Clean(proc.Mp())
    63  			return nil, err
    64  		}
    65  	}
    66  	retBat.SetRowCount(len(sels))
    67  	return retBat, nil
    68  }
    69  
    70  // GroupByPartitionForDeleteS3: Group data based on partition and return batch array with the same length as the number of partitions.
    71  // Data from the same partition is placed in the same batch
    72  func GroupByPartitionForDelete(proc *process.Process, bat *batch.Batch, rowIdIdx int, partitionIdx int, partitionNum int, pkIdx int) ([]*batch.Batch, error) {
    73  	vecList := make([]*vector.Vector, partitionNum)
    74  	pkList := make([]*vector.Vector, partitionNum)
    75  	pkTyp := bat.Vecs[pkIdx].GetType()
    76  	fun := vector.GetUnionOneFunction(*pkTyp, proc.Mp())
    77  	for i := 0; i < partitionNum; i++ {
    78  		//retVec := vector.NewVec(types.T_Rowid.ToType())
    79  		retVec := proc.GetVector(types.T_Rowid.ToType())
    80  		pkVec := proc.GetVector(*pkTyp)
    81  		vecList[i] = retVec
    82  		pkList[i] = pkVec
    83  	}
    84  
    85  	// Fill the data into the corresponding batch based on the different partitions to which the current `row_id` data
    86  	var err error
    87  	for i, rowid := range vector.MustFixedCol[types.Rowid](bat.Vecs[rowIdIdx]) {
    88  		if !bat.Vecs[rowIdIdx].GetNulls().Contains(uint64(i)) {
    89  			partition := vector.MustFixedCol[int32](bat.Vecs[partitionIdx])[i]
    90  			if partition == -1 {
    91  				err = moerr.NewInvalidInput(proc.Ctx, "Table has no partition for value from column_list")
    92  				break
    93  			} else {
    94  				err = vector.AppendFixed(vecList[partition], rowid, false, proc.Mp())
    95  				if err != nil {
    96  					break
    97  				}
    98  				err = fun(pkList[partition], bat.Vecs[pkIdx], int64(i))
    99  				if err != nil {
   100  					break
   101  				}
   102  			}
   103  		}
   104  	}
   105  	if err != nil {
   106  		for _, vecElem := range vecList {
   107  			vecElem.Free(proc.Mp())
   108  		}
   109  		for _, vecElem := range pkList {
   110  			vecElem.Free(proc.Mp())
   111  		}
   112  		return nil, err
   113  	}
   114  
   115  	// create a batch array equal to the number of partitions
   116  	batches := make([]*batch.Batch, partitionNum)
   117  	for i := range vecList {
   118  		// initialize the vectors in each batch, the batch only contains a `row_id` column
   119  		retBatch := batch.New(true, []string{catalog.Row_ID, "pk"})
   120  		retBatch.SetRowCount(vecList[i].Length())
   121  		retBatch.SetVector(0, vecList[i])
   122  		retBatch.SetVector(1, pkList[i])
   123  		batches[i] = retBatch
   124  	}
   125  	return batches, nil
   126  }
   127  
   128  // GroupByPartitionForInsert: Group data based on partition and return batch array with the same length as the number of partitions.
   129  // Data from the same partition is placed in the same batch
   130  func GroupByPartitionForInsert(proc *process.Process, bat *batch.Batch, attrs []string, pIdx int, partitionNum int) ([]*batch.Batch, error) {
   131  	// create a batch array equal to the number of partitions
   132  	batches := make([]*batch.Batch, partitionNum)
   133  	for partIdx := 0; partIdx < partitionNum; partIdx++ {
   134  		// initialize the vectors in each batch, corresponding to the original batch
   135  		partitionBatch := batch.NewWithSize(len(attrs))
   136  		partitionBatch.Attrs = attrs
   137  		for i := range partitionBatch.Attrs {
   138  			vecType := bat.GetVector(int32(i)).GetType()
   139  			//retVec := vector.NewVec(*vecType)
   140  			retVec := proc.GetVector(*vecType)
   141  			partitionBatch.SetVector(int32(i), retVec)
   142  		}
   143  		batches[partIdx] = partitionBatch
   144  	}
   145  
   146  	// fill the data into the corresponding batch based on the different partitions to which the current row data belongs
   147  	var err error
   148  	for i, partition := range vector.MustFixedCol[int32](bat.Vecs[pIdx]) {
   149  		if !bat.Vecs[pIdx].GetNulls().Contains(uint64(i)) {
   150  			if partition == -1 {
   151  				err = moerr.NewInvalidInput(proc.Ctx, "Table has no partition for value from column_list")
   152  				break
   153  			} else {
   154  				//  `i` corresponds to the row number of the batch data,
   155  				//  `j` corresponds to the column number of the batch data
   156  				for j := range attrs {
   157  					err = batches[partition].GetVector(int32(j)).UnionOne(bat.Vecs[j], int64(i), proc.Mp())
   158  					if err != nil {
   159  						break
   160  					}
   161  				}
   162  				if err != nil {
   163  					break
   164  				}
   165  			}
   166  		}
   167  	}
   168  	if err != nil {
   169  		for _, batchElem := range batches {
   170  			proc.PutBatch(batchElem)
   171  		}
   172  		return nil, err
   173  	}
   174  
   175  	for partIdx := range batches {
   176  		length := batches[partIdx].GetVector(0).Length()
   177  		batches[partIdx].SetRowCount(length)
   178  	}
   179  	return batches, nil
   180  }
   181  
   182  func BatchDataNotNullCheck(tmpBat *batch.Batch, tableDef *plan.TableDef, ctx context.Context) error {
   183  	for j := range tmpBat.Vecs {
   184  		if tmpBat.Vecs[j] == nil {
   185  			continue
   186  		}
   187  		nsp := tmpBat.Vecs[j].GetNulls()
   188  		if tableDef.Cols[j].Default != nil && !tableDef.Cols[j].Default.NullAbility && nulls.Any(nsp) {
   189  			return moerr.NewConstraintViolation(ctx, fmt.Sprintf("Column '%s' cannot be null", tmpBat.Attrs[j]))
   190  		}
   191  	}
   192  	return nil
   193  }