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 }