github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/compile/operator.go (about) 1 // Copyright 2021 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 compile 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 22 "github.com/google/uuid" 23 "github.com/matrixorigin/matrixone/pkg/catalog" 24 "github.com/matrixorigin/matrixone/pkg/common/moerr" 25 "github.com/matrixorigin/matrixone/pkg/container/batch" 26 "github.com/matrixorigin/matrixone/pkg/container/types" 27 "github.com/matrixorigin/matrixone/pkg/defines" 28 "github.com/matrixorigin/matrixone/pkg/pb/plan" 29 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 30 "github.com/matrixorigin/matrixone/pkg/sql/colexec/agg" 31 "github.com/matrixorigin/matrixone/pkg/sql/colexec/anti" 32 "github.com/matrixorigin/matrixone/pkg/sql/colexec/connector" 33 "github.com/matrixorigin/matrixone/pkg/sql/colexec/deletion" 34 "github.com/matrixorigin/matrixone/pkg/sql/colexec/dispatch" 35 "github.com/matrixorigin/matrixone/pkg/sql/colexec/external" 36 "github.com/matrixorigin/matrixone/pkg/sql/colexec/group" 37 "github.com/matrixorigin/matrixone/pkg/sql/colexec/hashbuild" 38 "github.com/matrixorigin/matrixone/pkg/sql/colexec/insert" 39 "github.com/matrixorigin/matrixone/pkg/sql/colexec/intersect" 40 "github.com/matrixorigin/matrixone/pkg/sql/colexec/intersectall" 41 "github.com/matrixorigin/matrixone/pkg/sql/colexec/join" 42 "github.com/matrixorigin/matrixone/pkg/sql/colexec/left" 43 "github.com/matrixorigin/matrixone/pkg/sql/colexec/limit" 44 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopanti" 45 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopjoin" 46 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopleft" 47 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopmark" 48 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopsemi" 49 "github.com/matrixorigin/matrixone/pkg/sql/colexec/loopsingle" 50 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mark" 51 "github.com/matrixorigin/matrixone/pkg/sql/colexec/merge" 52 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mergegroup" 53 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mergelimit" 54 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mergeoffset" 55 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mergeorder" 56 "github.com/matrixorigin/matrixone/pkg/sql/colexec/mergetop" 57 "github.com/matrixorigin/matrixone/pkg/sql/colexec/minus" 58 "github.com/matrixorigin/matrixone/pkg/sql/colexec/multi_col/group_concat" 59 "github.com/matrixorigin/matrixone/pkg/sql/colexec/offset" 60 "github.com/matrixorigin/matrixone/pkg/sql/colexec/order" 61 "github.com/matrixorigin/matrixone/pkg/sql/colexec/product" 62 "github.com/matrixorigin/matrixone/pkg/sql/colexec/projection" 63 "github.com/matrixorigin/matrixone/pkg/sql/colexec/restrict" 64 "github.com/matrixorigin/matrixone/pkg/sql/colexec/semi" 65 "github.com/matrixorigin/matrixone/pkg/sql/colexec/single" 66 "github.com/matrixorigin/matrixone/pkg/sql/colexec/table_function" 67 "github.com/matrixorigin/matrixone/pkg/sql/colexec/top" 68 "github.com/matrixorigin/matrixone/pkg/sql/colexec/update" 69 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 70 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 71 "github.com/matrixorigin/matrixone/pkg/vm" 72 "github.com/matrixorigin/matrixone/pkg/vm/engine" 73 "github.com/matrixorigin/matrixone/pkg/vm/process" 74 ) 75 76 var constBat *batch.Batch 77 78 func init() { 79 constBat = batch.NewWithSize(0) 80 constBat.Zs = []int64{1} 81 } 82 83 func dupInstruction(sourceIns *vm.Instruction, regMap map[*process.WaitRegister]*process.WaitRegister) vm.Instruction { 84 res := vm.Instruction{Op: sourceIns.Op, Idx: sourceIns.Idx, IsFirst: sourceIns.IsFirst, IsLast: sourceIns.IsLast} 85 switch sourceIns.Op { 86 case vm.Anti: 87 t := sourceIns.Arg.(*anti.Argument) 88 res.Arg = &anti.Argument{ 89 Ibucket: t.Ibucket, 90 Nbucket: t.Nbucket, 91 Cond: t.Cond, 92 Typs: t.Typs, 93 Conditions: t.Conditions, 94 Result: t.Result, 95 } 96 case vm.Group: 97 t := sourceIns.Arg.(*group.Argument) 98 res.Arg = &group.Argument{ 99 NeedEval: t.NeedEval, 100 Ibucket: t.Ibucket, 101 Nbucket: t.Nbucket, 102 Exprs: t.Exprs, 103 Types: t.Types, 104 Aggs: t.Aggs, 105 } 106 case vm.Join: 107 t := sourceIns.Arg.(*join.Argument) 108 res.Arg = &join.Argument{ 109 Ibucket: t.Ibucket, 110 Nbucket: t.Nbucket, 111 Result: t.Result, 112 Cond: t.Cond, 113 Typs: t.Typs, 114 Conditions: t.Conditions, 115 } 116 case vm.Left: 117 t := sourceIns.Arg.(*left.Argument) 118 res.Arg = &left.Argument{ 119 Ibucket: t.Ibucket, 120 Nbucket: t.Nbucket, 121 Cond: t.Cond, 122 Result: t.Result, 123 Typs: t.Typs, 124 Conditions: t.Conditions, 125 } 126 case vm.Limit: 127 t := sourceIns.Arg.(*limit.Argument) 128 res.Arg = &limit.Argument{ 129 Limit: t.Limit, 130 } 131 case vm.LoopAnti: 132 t := sourceIns.Arg.(*loopanti.Argument) 133 res.Arg = &loopanti.Argument{ 134 Result: t.Result, 135 Cond: t.Cond, 136 Typs: t.Typs, 137 } 138 case vm.LoopJoin: 139 t := sourceIns.Arg.(*loopanti.Argument) 140 res.Arg = &loopanti.Argument{ 141 Result: t.Result, 142 Cond: t.Cond, 143 Typs: t.Typs, 144 } 145 case vm.LoopLeft: 146 t := sourceIns.Arg.(*loopleft.Argument) 147 res.Arg = &loopleft.Argument{ 148 Cond: t.Cond, 149 Typs: t.Typs, 150 Result: t.Result, 151 } 152 case vm.LoopSemi: 153 t := sourceIns.Arg.(*loopsemi.Argument) 154 res.Arg = &loopsemi.Argument{ 155 Result: t.Result, 156 Cond: t.Cond, 157 Typs: t.Typs, 158 } 159 case vm.LoopSingle: 160 t := sourceIns.Arg.(*loopsingle.Argument) 161 res.Arg = &loopsingle.Argument{ 162 Result: t.Result, 163 Cond: t.Cond, 164 Typs: t.Typs, 165 } 166 case vm.LoopMark: 167 t := sourceIns.Arg.(*loopmark.Argument) 168 res.Arg = &loopmark.Argument{ 169 Result: t.Result, 170 Cond: t.Cond, 171 Typs: t.Typs, 172 } 173 case vm.Offset: 174 t := sourceIns.Arg.(*offset.Argument) 175 res.Arg = &offset.Argument{ 176 Offset: t.Offset, 177 } 178 case vm.Order: 179 t := sourceIns.Arg.(*order.Argument) 180 res.Arg = &order.Argument{ 181 Fs: t.Fs, 182 } 183 case vm.Product: 184 t := sourceIns.Arg.(*product.Argument) 185 res.Arg = &product.Argument{ 186 Result: t.Result, 187 Typs: t.Typs, 188 } 189 case vm.Projection: 190 t := sourceIns.Arg.(*projection.Argument) 191 res.Arg = &projection.Argument{ 192 Es: t.Es, 193 } 194 case vm.Restrict: 195 t := sourceIns.Arg.(*restrict.Argument) 196 res.Arg = &restrict.Argument{ 197 E: t.E, 198 } 199 case vm.Semi: 200 t := sourceIns.Arg.(*semi.Argument) 201 res.Arg = &semi.Argument{ 202 Ibucket: t.Ibucket, 203 Nbucket: t.Nbucket, 204 Result: t.Result, 205 Cond: t.Cond, 206 Typs: t.Typs, 207 Conditions: t.Conditions, 208 } 209 case vm.Single: 210 t := sourceIns.Arg.(*single.Argument) 211 res.Arg = &single.Argument{ 212 Ibucket: t.Ibucket, 213 Nbucket: t.Nbucket, 214 Result: t.Result, 215 Cond: t.Cond, 216 Typs: t.Typs, 217 Conditions: t.Conditions, 218 } 219 case vm.Top: 220 t := sourceIns.Arg.(*top.Argument) 221 res.Arg = &top.Argument{ 222 Limit: t.Limit, 223 Fs: t.Fs, 224 } 225 case vm.Intersect: 226 t := sourceIns.Arg.(*intersect.Argument) 227 res.Arg = &intersect.Argument{ 228 IBucket: t.IBucket, 229 NBucket: t.NBucket, 230 } 231 case vm.Minus: // 2 232 t := sourceIns.Arg.(*minus.Argument) 233 res.Arg = &minus.Argument{ 234 IBucket: t.IBucket, 235 NBucket: t.NBucket, 236 } 237 case vm.IntersectAll: 238 t := sourceIns.Arg.(*intersectall.Argument) 239 res.Arg = &intersectall.Argument{ 240 IBucket: t.IBucket, 241 NBucket: t.NBucket, 242 } 243 case vm.Merge: 244 res.Arg = &merge.Argument{} 245 case vm.MergeGroup: 246 t := sourceIns.Arg.(*mergegroup.Argument) 247 res.Arg = &mergegroup.Argument{ 248 NeedEval: t.NeedEval, 249 } 250 case vm.MergeLimit: 251 t := sourceIns.Arg.(*mergelimit.Argument) 252 res.Arg = &mergelimit.Argument{ 253 Limit: t.Limit, 254 } 255 case vm.MergeOffset: 256 t := sourceIns.Arg.(*mergeoffset.Argument) 257 res.Arg = &mergeoffset.Argument{ 258 Offset: t.Offset, 259 } 260 case vm.MergeTop: 261 t := sourceIns.Arg.(*mergetop.Argument) 262 res.Arg = &mergetop.Argument{ 263 Limit: t.Limit, 264 Fs: t.Fs, 265 } 266 case vm.MergeOrder: 267 t := sourceIns.Arg.(*mergeorder.Argument) 268 res.Arg = &mergeorder.Argument{ 269 Fs: t.Fs, 270 } 271 case vm.Mark: 272 t := sourceIns.Arg.(*mark.Argument) 273 res.Arg = &mark.Argument{ 274 Ibucket: t.Ibucket, 275 Nbucket: t.Nbucket, 276 Result: t.Result, 277 Conditions: t.Conditions, 278 Typs: t.Typs, 279 Cond: t.Cond, 280 OnList: t.OnList, 281 } 282 case vm.TableFunction: 283 t := sourceIns.Arg.(*table_function.Argument) 284 res.Arg = &table_function.Argument{ 285 Name: t.Name, 286 Args: t.Args, 287 Rets: t.Rets, 288 Attrs: t.Attrs, 289 Params: t.Params, 290 } 291 292 case vm.HashBuild: 293 t := sourceIns.Arg.(*hashbuild.Argument) 294 res.Arg = &hashbuild.Argument{ 295 NeedHashMap: t.NeedHashMap, 296 NeedExpr: t.NeedExpr, 297 NeedSelectList: t.NeedSelectList, 298 Ibucket: t.Ibucket, 299 Nbucket: t.Nbucket, 300 Typs: t.Typs, 301 Conditions: t.Conditions, 302 } 303 case vm.External: 304 t := sourceIns.Arg.(*external.Argument) 305 res.Arg = &external.Argument{ 306 Es: &external.ExternalParam{ 307 ExParamConst: external.ExParamConst{ 308 Attrs: t.Es.Attrs, 309 Cols: t.Es.Cols, 310 Name2ColIndex: t.Es.Name2ColIndex, 311 CreateSql: t.Es.CreateSql, 312 FileList: t.Es.FileList, 313 OriginCols: t.Es.OriginCols, 314 Extern: t.Es.Extern, 315 }, 316 ExParam: external.ExParam{ 317 Filter: t.Es.Filter, 318 Fileparam: &external.ExFileparam{ 319 End: t.Es.Fileparam.End, 320 FileCnt: t.Es.Fileparam.FileCnt, 321 FileFin: t.Es.Fileparam.FileFin, 322 FileIndex: t.Es.Fileparam.FileIndex, 323 }, 324 }, 325 }, 326 } 327 case vm.Connector: 328 ok := false 329 if regMap != nil { 330 arg := &connector.Argument{} 331 sourceReg := sourceIns.Arg.(*connector.Argument).Reg 332 if arg.Reg, ok = regMap[sourceReg]; !ok { 333 panic("nonexistent wait register") 334 } 335 res.Arg = arg 336 } 337 case vm.Dispatch: 338 ok := false 339 if regMap != nil { 340 sourceArg := sourceIns.Arg.(*dispatch.Argument) 341 arg := &dispatch.Argument{ 342 FuncId: sourceArg.FuncId, 343 LocalRegs: make([]*process.WaitRegister, len(sourceArg.LocalRegs)), 344 RemoteRegs: make([]colexec.ReceiveInfo, len(sourceArg.RemoteRegs)), 345 } 346 for j := range arg.LocalRegs { 347 sourceReg := sourceArg.LocalRegs[j] 348 if arg.LocalRegs[j], ok = regMap[sourceReg]; !ok { 349 panic("nonexistent wait register") 350 } 351 } 352 for j := range arg.RemoteRegs { 353 arg.RemoteRegs[j] = sourceArg.RemoteRegs[j] 354 } 355 res.Arg = arg 356 } 357 case vm.Insert: 358 t := sourceIns.Arg.(*insert.Argument) 359 res.Arg = &insert.Argument{ 360 Ts: t.Ts, 361 // TargetTable: t.TargetTable, 362 // TargetColDefs: t.TargetColDefs, 363 Affected: t.Affected, 364 Engine: t.Engine, 365 // DB: t.DB, 366 // TableID: t.TableID, 367 // CPkeyColDef: t.CPkeyColDef, 368 // DBName: t.DBName, 369 // TableName: t.TableName, 370 // UniqueIndexTables: t.UniqueIndexTables, 371 // UniqueIndexDef: t.UniqueIndexDef, 372 // SecondaryIndexTables: t.SecondaryIndexTables, 373 // SecondaryIndexDef: t.SecondaryIndexDef, 374 // ClusterTable: t.ClusterTable, 375 // ClusterByDef: t.ClusterByDef, 376 IsRemote: t.IsRemote, 377 InsertCtx: t.InsertCtx, 378 // HasAutoCol: t.HasAutoCol, 379 } 380 default: 381 panic(fmt.Sprintf("unexpected instruction type '%d' to dup", sourceIns.Op)) 382 } 383 return res 384 } 385 386 func constructRestrict(n *plan.Node) *restrict.Argument { 387 return &restrict.Argument{ 388 E: colexec.RewriteFilterExprList(n.FilterList), 389 } 390 } 391 392 func constructDeletion(n *plan.Node, eg engine.Engine, proc *process.Process) (*deletion.Argument, error) { 393 oldCtx := n.DeleteCtx 394 delCtx := &deletion.DeleteCtx{ 395 DelSource: make([]engine.Relation, len(oldCtx.Ref)), 396 DelRef: oldCtx.Ref, 397 398 IdxSource: make([]engine.Relation, len(oldCtx.IdxRef)), 399 IdxIdx: oldCtx.IdxIdx, 400 401 OnRestrictIdx: oldCtx.OnRestrictIdx, 402 403 OnCascadeIdx: oldCtx.OnCascadeIdx, 404 OnCascadeSource: make([]engine.Relation, len(oldCtx.OnCascadeRef)), 405 406 OnSetSource: make([]engine.Relation, len(oldCtx.OnSetRef)), 407 OnSetUniqueSource: make([][]engine.Relation, len(oldCtx.Ref)), 408 OnSetIdx: make([][]int32, len(oldCtx.OnSetIdx)), 409 OnSetTableDef: oldCtx.OnSetDef, 410 OnSetRef: oldCtx.OnSetRef, 411 OnSetUpdateCol: make([]map[string]int32, len(oldCtx.OnSetUpdateCol)), 412 413 CanTruncate: oldCtx.CanTruncate, 414 } 415 416 if delCtx.CanTruncate { 417 for i, ref := range oldCtx.Ref { 418 rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil) 419 if err != nil { 420 return nil, err 421 } 422 delCtx.DelSource[i] = rel 423 } 424 } else { 425 for i, list := range oldCtx.OnSetIdx { 426 delCtx.OnSetIdx[i] = make([]int32, len(list.List)) 427 for j, id := range list.List { 428 delCtx.OnSetIdx[i][j] = int32(id) 429 } 430 } 431 for i, ref := range oldCtx.Ref { 432 rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil) 433 if err != nil { 434 return nil, err 435 } 436 delCtx.DelSource[i] = rel 437 } 438 for i, ref := range oldCtx.IdxRef { 439 rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil) 440 if err != nil { 441 return nil, err 442 } 443 delCtx.IdxSource[i] = rel 444 } 445 for i, ref := range oldCtx.OnCascadeRef { 446 rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil) 447 if err != nil { 448 return nil, err 449 } 450 delCtx.OnCascadeSource[i] = rel 451 } 452 for i, ref := range oldCtx.OnSetRef { 453 rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnSetDef[i]) 454 if err != nil { 455 return nil, err 456 } 457 delCtx.OnSetSource[i] = rel 458 delCtx.OnSetUniqueSource[i] = uniqueRels 459 } 460 for i, idxMap := range oldCtx.OnSetUpdateCol { 461 delCtx.OnSetUpdateCol[i] = idxMap.Map 462 } 463 } 464 465 return &deletion.Argument{ 466 DeleteCtx: delCtx, 467 Engine: eg, 468 }, nil 469 } 470 471 func constructInsert(n *plan.Node, eg engine.Engine, proc *process.Process) (*insert.Argument, error) { 472 oldCtx := n.InsertCtx 473 ctx := proc.Ctx 474 if oldCtx.GetClusterTable().GetIsClusterTable() { 475 ctx = context.WithValue(ctx, defines.TenantIDKey{}, catalog.System_Account) 476 } 477 newCtx := &insert.InsertCtx{ 478 Idx: oldCtx.Idx, 479 Ref: oldCtx.Ref, 480 TableDef: oldCtx.TableDef, 481 482 ParentIdx: oldCtx.ParentIdx, 483 ClusterTable: oldCtx.ClusterTable, 484 } 485 486 originRel, indexRels, err := getRel(ctx, proc, eg, oldCtx.Ref, oldCtx.TableDef) 487 if err != nil { 488 return nil, err 489 } 490 newCtx.Source = originRel 491 newCtx.UniqueSource = indexRels 492 493 return &insert.Argument{ 494 InsertCtx: newCtx, 495 Engine: eg, 496 }, nil 497 } 498 499 func constructUpdate(n *plan.Node, eg engine.Engine, proc *process.Process) (*update.Argument, error) { 500 oldCtx := n.UpdateCtx 501 updateCtx := &update.UpdateCtx{ 502 Source: make([]engine.Relation, len(oldCtx.Ref)), 503 Idxs: make([][]int32, len(oldCtx.Idx)), 504 TableDefs: oldCtx.TableDefs, 505 Ref: oldCtx.Ref, 506 UpdateCol: make([]map[string]int32, len(oldCtx.UpdateCol)), 507 UniqueSource: make([][]engine.Relation, len(oldCtx.Ref)), 508 509 IdxSource: make([]engine.Relation, len(oldCtx.IdxRef)), 510 IdxIdx: oldCtx.IdxIdx, 511 512 OnRestrictIdx: oldCtx.OnRestrictIdx, 513 514 OnCascadeIdx: make([][]int32, len(oldCtx.OnCascadeIdx)), 515 OnCascadeSource: make([]engine.Relation, len(oldCtx.OnCascadeRef)), 516 OnCascadeUniqueSource: make([][]engine.Relation, len(oldCtx.OnCascadeRef)), 517 OnCascadeRef: oldCtx.OnCascadeRef, 518 OnCascadeTableDef: oldCtx.OnCascadeDef, 519 OnCascadeUpdateCol: make([]map[string]int32, len(oldCtx.OnCascadeUpdateCol)), 520 521 OnSetSource: make([]engine.Relation, len(oldCtx.OnSetRef)), 522 OnSetUniqueSource: make([][]engine.Relation, len(oldCtx.OnSetRef)), 523 OnSetIdx: make([][]int32, len(oldCtx.OnSetIdx)), 524 OnSetRef: oldCtx.OnSetRef, 525 OnSetTableDef: oldCtx.OnSetDef, 526 OnSetUpdateCol: make([]map[string]int32, len(oldCtx.OnSetUpdateCol)), 527 528 ParentIdx: make([]map[string]int32, len(oldCtx.ParentIdx)), 529 } 530 531 for i, idxMap := range oldCtx.UpdateCol { 532 updateCtx.UpdateCol[i] = idxMap.Map 533 } 534 for i, list := range oldCtx.Idx { 535 updateCtx.Idxs[i] = make([]int32, len(list.List)) 536 for j, id := range list.List { 537 updateCtx.Idxs[i][j] = int32(id) 538 } 539 } 540 for i, list := range oldCtx.OnSetIdx { 541 updateCtx.OnSetIdx[i] = make([]int32, len(list.List)) 542 for j, id := range list.List { 543 updateCtx.OnSetIdx[i][j] = int32(id) 544 } 545 } 546 for i, list := range oldCtx.OnCascadeIdx { 547 updateCtx.OnCascadeIdx[i] = make([]int32, len(list.List)) 548 for j, id := range list.List { 549 updateCtx.OnCascadeIdx[i][j] = int32(id) 550 } 551 } 552 for i, ref := range oldCtx.Ref { 553 rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.TableDefs[i]) 554 if err != nil { 555 return nil, err 556 } 557 updateCtx.Source[i] = rel 558 updateCtx.UniqueSource[i] = uniqueRels 559 } 560 for i, ref := range oldCtx.IdxRef { 561 rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil) 562 if err != nil { 563 return nil, err 564 } 565 updateCtx.IdxSource[i] = rel 566 } 567 for i, ref := range oldCtx.OnCascadeRef { 568 rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnCascadeDef[i]) 569 if err != nil { 570 return nil, err 571 } 572 updateCtx.OnCascadeSource[i] = rel 573 updateCtx.OnCascadeUniqueSource[i] = uniqueRels 574 } 575 for i, ref := range oldCtx.OnSetRef { 576 rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnSetDef[i]) 577 if err != nil { 578 return nil, err 579 } 580 updateCtx.OnSetSource[i] = rel 581 updateCtx.OnSetUniqueSource[i] = uniqueRels 582 } 583 for i, idxMap := range oldCtx.OnCascadeUpdateCol { 584 updateCtx.OnCascadeUpdateCol[i] = idxMap.Map 585 } 586 for i, idxMap := range oldCtx.OnSetUpdateCol { 587 updateCtx.OnSetUpdateCol[i] = idxMap.Map 588 } 589 for i, idxMap := range oldCtx.ParentIdx { 590 updateCtx.ParentIdx[i] = idxMap.Map 591 } 592 593 return &update.Argument{ 594 UpdateCtx: updateCtx, 595 Engine: eg, 596 }, nil 597 } 598 599 func constructProjection(n *plan.Node) *projection.Argument { 600 return &projection.Argument{ 601 Es: n.ProjectList, 602 } 603 } 604 605 func constructExternal(n *plan.Node, param *tree.ExternParam, ctx context.Context, fileList []string, FileSize []int64, fileOffset [][2]int) *external.Argument { 606 attrs := make([]string, len(n.TableDef.Cols)) 607 for j, col := range n.TableDef.Cols { 608 attrs[j] = col.Name 609 } 610 return &external.Argument{ 611 Es: &external.ExternalParam{ 612 ExParamConst: external.ExParamConst{ 613 Attrs: attrs, 614 Cols: n.TableDef.Cols, 615 Extern: param, 616 Name2ColIndex: n.TableDef.Name2ColIndex, 617 FileOffset: fileOffset, 618 CreateSql: n.TableDef.Createsql, 619 Ctx: ctx, 620 FileList: fileList, 621 FileSize: FileSize, 622 OriginCols: n.TableDef.OriginCols, 623 ClusterTable: n.GetClusterTable(), 624 }, 625 ExParam: external.ExParam{ 626 Fileparam: new(external.ExFileparam), 627 Filter: &external.FilterParam{ 628 FilterExpr: colexec.RewriteFilterExprList(n.FilterList), 629 }, 630 }, 631 }, 632 } 633 } 634 func constructTableFunction(n *plan.Node, ctx context.Context, name string) *table_function.Argument { 635 attrs := make([]string, len(n.TableDef.Cols)) 636 for j, col := range n.TableDef.Cols { 637 attrs[j] = col.Name 638 } 639 return &table_function.Argument{ 640 Attrs: attrs, 641 Rets: n.TableDef.Cols, 642 Args: n.TblFuncExprList, 643 Name: name, 644 Params: n.TableDef.TblFunc.Param, 645 } 646 } 647 648 func constructTop(n *plan.Node, topN int64) *top.Argument { 649 return &top.Argument{ 650 Fs: n.OrderBy, 651 Limit: topN, 652 } 653 } 654 655 func constructJoin(n *plan.Node, typs []types.Type, proc *process.Process) *join.Argument { 656 result := make([]colexec.ResultPos, len(n.ProjectList)) 657 for i, expr := range n.ProjectList { 658 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 659 } 660 cond, conds := extraJoinConditions(n.OnList) 661 return &join.Argument{ 662 Typs: typs, 663 Result: result, 664 Cond: cond, 665 Conditions: constructJoinConditions(conds, proc), 666 } 667 } 668 669 func constructSemi(n *plan.Node, typs []types.Type, proc *process.Process) *semi.Argument { 670 result := make([]int32, len(n.ProjectList)) 671 for i, expr := range n.ProjectList { 672 rel, pos := constructJoinResult(expr, proc) 673 if rel != 0 { 674 panic(moerr.NewNYI(proc.Ctx, "semi result '%s'", expr)) 675 } 676 result[i] = pos 677 } 678 cond, conds := extraJoinConditions(n.OnList) 679 return &semi.Argument{ 680 Typs: typs, 681 Result: result, 682 Cond: cond, 683 Conditions: constructJoinConditions(conds, proc), 684 } 685 } 686 687 func constructLeft(n *plan.Node, typs []types.Type, proc *process.Process) *left.Argument { 688 result := make([]colexec.ResultPos, len(n.ProjectList)) 689 for i, expr := range n.ProjectList { 690 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 691 } 692 cond, conds := extraJoinConditions(n.OnList) 693 return &left.Argument{ 694 Typs: typs, 695 Result: result, 696 Cond: cond, 697 Conditions: constructJoinConditions(conds, proc), 698 } 699 } 700 701 func constructSingle(n *plan.Node, typs []types.Type, proc *process.Process) *single.Argument { 702 result := make([]colexec.ResultPos, len(n.ProjectList)) 703 for i, expr := range n.ProjectList { 704 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 705 } 706 cond, conds := extraJoinConditions(n.OnList) 707 return &single.Argument{ 708 Typs: typs, 709 Result: result, 710 Cond: cond, 711 Conditions: constructJoinConditions(conds, proc), 712 } 713 } 714 715 func constructProduct(n *plan.Node, typs []types.Type, proc *process.Process) *product.Argument { 716 result := make([]colexec.ResultPos, len(n.ProjectList)) 717 for i, expr := range n.ProjectList { 718 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 719 } 720 return &product.Argument{Typs: typs, Result: result} 721 } 722 723 func constructAnti(n *plan.Node, typs []types.Type, proc *process.Process) *anti.Argument { 724 result := make([]int32, len(n.ProjectList)) 725 for i, expr := range n.ProjectList { 726 rel, pos := constructJoinResult(expr, proc) 727 if rel != 0 { 728 panic(moerr.NewNYI(proc.Ctx, "anti result '%s'", expr)) 729 } 730 result[i] = pos 731 } 732 cond, conds := extraJoinConditions(n.OnList) 733 return &anti.Argument{ 734 Typs: typs, 735 Result: result, 736 Cond: cond, 737 Conditions: constructJoinConditions(conds, proc), 738 } 739 } 740 741 /* 742 func constructMark(n *plan.Node, typs []types.Type, proc *process.Process) *mark.Argument { 743 result := make([]int32, len(n.ProjectList)) 744 for i, expr := range n.ProjectList { 745 rel, pos := constructJoinResult(expr, proc) 746 if rel == 0 { 747 result[i] = pos 748 } else if rel == -1 { 749 result[i] = -1 750 } else { 751 panic(moerr.NewNYI(proc.Ctx, "loop mark result '%s'", expr)) 752 } 753 } 754 cond, conds := extraJoinConditions(n.OnList) 755 return &mark.Argument{ 756 Typs: typs, 757 Result: result, 758 Cond: cond, 759 Conditions: constructJoinConditions(conds, proc), 760 OnList: n.OnList, 761 } 762 } 763 */ 764 765 func constructOrder(n *plan.Node, proc *process.Process) *order.Argument { 766 return &order.Argument{ 767 Fs: n.OrderBy, 768 } 769 } 770 771 /* 772 func constructOffset(n *plan.Node, proc *process.Process) *offset.Argument { 773 vec, err := colexec.EvalExpr(constBat, proc, n.Offset) 774 if err != nil { 775 panic(err) 776 } 777 return &offset.Argument{ 778 Offset: uint64(vec.Col.([]int64)[0]), 779 } 780 } 781 */ 782 783 func constructLimit(n *plan.Node, proc *process.Process) *limit.Argument { 784 vec, err := colexec.EvalExpr(constBat, proc, n.Limit) 785 if err != nil { 786 panic(err) 787 } 788 defer vec.Free(proc.Mp()) 789 return &limit.Argument{ 790 Limit: uint64(vec.Col.([]int64)[0]), 791 } 792 } 793 794 func constructGroup(ctx context.Context, n, cn *plan.Node, ibucket, nbucket int, needEval bool, proc *process.Process) *group.Argument { 795 var lenAggs, lenMultiAggs int 796 aggs := make([]agg.Aggregate, len(n.AggList)) 797 // multiaggs: is not like the normal agg funcs which have only one arg exclude 'distinct' 798 // for now, we have group_concat 799 multiaggs := make([]group_concat.Argument, len(n.AggList)) 800 for _, expr := range n.AggList { 801 if f, ok := expr.Expr.(*plan.Expr_F); ok { 802 distinct := (uint64(f.F.Func.Obj) & function.Distinct) != 0 803 if len(f.F.Args) > 1 { 804 // vec is separator 805 vec, _ := colexec.EvalExpr(constBat, proc, f.F.Args[len(f.F.Args)-1]) 806 sepa := vec.GetString(0) 807 multiaggs[lenMultiAggs] = group_concat.Argument{ 808 Dist: distinct, 809 GroupExpr: f.F.Args[:len(f.F.Args)-1], 810 Separator: sepa, 811 } 812 lenMultiAggs++ 813 continue 814 } 815 obj := int64(uint64(f.F.Func.Obj) & function.DistinctMask) 816 fun, err := function.GetFunctionByID(ctx, obj) 817 if err != nil { 818 panic(err) 819 } 820 aggs[lenAggs] = agg.Aggregate{ 821 E: f.F.Args[0], 822 Dist: distinct, 823 Op: fun.AggregateInfo, 824 } 825 lenAggs++ 826 } 827 } 828 aggs = aggs[:lenAggs] 829 multiaggs = multiaggs[:lenMultiAggs] 830 typs := make([]types.Type, len(cn.ProjectList)) 831 for i, e := range cn.ProjectList { 832 typs[i].Oid = types.T(e.Typ.Id) 833 typs[i].Width = e.Typ.Width 834 typs[i].Size = e.Typ.Size 835 typs[i].Scale = e.Typ.Scale 836 typs[i].Precision = e.Typ.Precision 837 } 838 return &group.Argument{ 839 Aggs: aggs, 840 MultiAggs: multiaggs, 841 Types: typs, 842 NeedEval: needEval, 843 Exprs: n.GroupBy, 844 Ibucket: uint64(ibucket), 845 Nbucket: uint64(nbucket), 846 } 847 } 848 849 // ibucket: bucket number 850 // nbucket: 851 // construct operator argument 852 func constructIntersectAll(_ *plan.Node, proc *process.Process, ibucket, nbucket int) *intersectall.Argument { 853 return &intersectall.Argument{ 854 IBucket: uint64(ibucket), 855 NBucket: uint64(nbucket), 856 } 857 } 858 859 func constructMinus(n *plan.Node, proc *process.Process, ibucket, nbucket int) *minus.Argument { 860 return &minus.Argument{ 861 IBucket: uint64(ibucket), 862 NBucket: uint64(nbucket), 863 } 864 } 865 866 func constructIntersect(n *plan.Node, proc *process.Process, ibucket, nbucket int) *intersect.Argument { 867 return &intersect.Argument{ 868 IBucket: uint64(ibucket), 869 NBucket: uint64(nbucket), 870 } 871 } 872 873 func constructDispatchLocal(all bool, regs []*process.WaitRegister) *dispatch.Argument { 874 arg := new(dispatch.Argument) 875 arg.LocalRegs = regs 876 if all { 877 arg.FuncId = dispatch.SendToAllLocalFunc 878 } else { 879 arg.FuncId = dispatch.SendToAnyLocalFunc 880 } 881 882 return arg 883 } 884 885 // ShuffleJoinDispatch is a cross-cn dispath 886 // and it will send same batch to all register 887 func constructBroadcastJoinDispatch(idx int, ss []*Scope, currentCNAddr string, proc *process.Process) *dispatch.Argument { 888 arg := new(dispatch.Argument) 889 890 scopeLen := len(ss) 891 arg.LocalRegs = make([]*process.WaitRegister, 0, scopeLen) 892 arg.RemoteRegs = make([]colexec.ReceiveInfo, 0, scopeLen) 893 894 hasRemote := false 895 for _, s := range ss { 896 if s.IsEnd { 897 continue 898 } 899 900 if len(s.NodeInfo.Addr) == 0 || len(currentCNAddr) == 0 || 901 strings.Split(currentCNAddr, ":")[0] == strings.Split(s.NodeInfo.Addr, ":")[0] { 902 // Local reg. 903 // Put them into arg.LocalRegs 904 arg.LocalRegs = append(arg.LocalRegs, s.Proc.Reg.MergeReceivers[idx]) 905 } else { 906 // Remote reg. 907 // Generate uuid for them and put into arg.RemoteRegs & scope. receive info 908 hasRemote = true 909 newUuid := uuid.New() 910 911 arg.RemoteRegs = append(arg.RemoteRegs, colexec.ReceiveInfo{ 912 Uuid: newUuid, 913 NodeAddr: s.NodeInfo.Addr, 914 }) 915 916 s.RemoteReceivRegInfos = append(s.RemoteReceivRegInfos, RemoteReceivRegInfo{ 917 Idx: idx, 918 Uuid: newUuid, 919 FromAddr: currentCNAddr, 920 }) 921 } 922 } 923 924 if hasRemote { 925 arg.FuncId = dispatch.SendToAllFunc 926 } else { 927 arg.FuncId = dispatch.SendToAllLocalFunc 928 } 929 930 return arg 931 } 932 933 func constructMergeGroup(_ *plan.Node, needEval bool) *mergegroup.Argument { 934 return &mergegroup.Argument{ 935 NeedEval: needEval, 936 } 937 } 938 939 func constructMergeTop(n *plan.Node, topN int64) *mergetop.Argument { 940 return &mergetop.Argument{ 941 Fs: n.OrderBy, 942 Limit: topN, 943 } 944 } 945 946 func constructMergeOffset(n *plan.Node, proc *process.Process) *mergeoffset.Argument { 947 vec, err := colexec.EvalExpr(constBat, proc, n.Offset) 948 if err != nil { 949 panic(err) 950 } 951 defer vec.Free(proc.Mp()) 952 return &mergeoffset.Argument{ 953 Offset: uint64(vec.Col.([]int64)[0]), 954 } 955 } 956 957 func constructMergeLimit(n *plan.Node, proc *process.Process) *mergelimit.Argument { 958 vec, err := colexec.EvalExpr(constBat, proc, n.Limit) 959 if err != nil { 960 panic(err) 961 } 962 defer vec.Free(proc.Mp()) 963 return &mergelimit.Argument{ 964 Limit: uint64(vec.Col.([]int64)[0]), 965 } 966 } 967 968 func constructMergeOrder(n *plan.Node, proc *process.Process) *mergeorder.Argument { 969 return &mergeorder.Argument{ 970 Fs: n.OrderBy, 971 } 972 } 973 974 func constructLoopJoin(n *plan.Node, typs []types.Type, proc *process.Process) *loopjoin.Argument { 975 result := make([]colexec.ResultPos, len(n.ProjectList)) 976 for i, expr := range n.ProjectList { 977 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 978 } 979 return &loopjoin.Argument{ 980 Typs: typs, 981 Result: result, 982 Cond: colexec.RewriteFilterExprList(n.OnList), 983 } 984 } 985 986 func constructLoopSemi(n *plan.Node, typs []types.Type, proc *process.Process) *loopsemi.Argument { 987 result := make([]int32, len(n.ProjectList)) 988 for i, expr := range n.ProjectList { 989 rel, pos := constructJoinResult(expr, proc) 990 if rel != 0 { 991 panic(moerr.NewNYI(proc.Ctx, "loop semi result '%s'", expr)) 992 } 993 result[i] = pos 994 } 995 return &loopsemi.Argument{ 996 Typs: typs, 997 Result: result, 998 Cond: colexec.RewriteFilterExprList(n.OnList), 999 } 1000 } 1001 1002 func constructLoopLeft(n *plan.Node, typs []types.Type, proc *process.Process) *loopleft.Argument { 1003 result := make([]colexec.ResultPos, len(n.ProjectList)) 1004 for i, expr := range n.ProjectList { 1005 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 1006 } 1007 return &loopleft.Argument{ 1008 Typs: typs, 1009 Result: result, 1010 Cond: colexec.RewriteFilterExprList(n.OnList), 1011 } 1012 } 1013 1014 func constructLoopSingle(n *plan.Node, typs []types.Type, proc *process.Process) *loopsingle.Argument { 1015 result := make([]colexec.ResultPos, len(n.ProjectList)) 1016 for i, expr := range n.ProjectList { 1017 result[i].Rel, result[i].Pos = constructJoinResult(expr, proc) 1018 } 1019 return &loopsingle.Argument{ 1020 Result: result, 1021 Cond: colexec.RewriteFilterExprList(n.OnList), 1022 } 1023 } 1024 1025 func constructLoopAnti(n *plan.Node, typs []types.Type, proc *process.Process) *loopanti.Argument { 1026 result := make([]int32, len(n.ProjectList)) 1027 for i, expr := range n.ProjectList { 1028 rel, pos := constructJoinResult(expr, proc) 1029 if rel != 0 { 1030 panic(moerr.NewNYI(proc.Ctx, "loop anti result '%s'", expr)) 1031 } 1032 result[i] = pos 1033 } 1034 return &loopanti.Argument{ 1035 Typs: typs, 1036 Result: result, 1037 Cond: colexec.RewriteFilterExprList(n.OnList), 1038 } 1039 } 1040 1041 func constructLoopMark(n *plan.Node, typs []types.Type, proc *process.Process) *loopmark.Argument { 1042 result := make([]int32, len(n.ProjectList)) 1043 for i, expr := range n.ProjectList { 1044 rel, pos := constructJoinResult(expr, proc) 1045 if rel == 0 { 1046 result[i] = pos 1047 } else if rel == -1 { 1048 result[i] = -1 1049 } else { 1050 panic(moerr.NewNYI(proc.Ctx, "loop mark result '%s'", expr)) 1051 } 1052 } 1053 return &loopmark.Argument{ 1054 Typs: typs, 1055 Result: result, 1056 Cond: colexec.RewriteFilterExprList(n.OnList), 1057 } 1058 } 1059 1060 func constructHashBuild(in vm.Instruction, proc *process.Process) *hashbuild.Argument { 1061 switch in.Op { 1062 case vm.Anti: 1063 arg := in.Arg.(*anti.Argument) 1064 return &hashbuild.Argument{ 1065 NeedHashMap: true, 1066 Typs: arg.Typs, 1067 Conditions: arg.Conditions[1], 1068 } 1069 case vm.Mark: 1070 arg := in.Arg.(*mark.Argument) 1071 return &hashbuild.Argument{ 1072 NeedHashMap: true, 1073 NeedSelectList: true, 1074 Typs: arg.Typs, 1075 Conditions: arg.Conditions[1], 1076 } 1077 case vm.Join: 1078 arg := in.Arg.(*join.Argument) 1079 return &hashbuild.Argument{ 1080 NeedHashMap: true, 1081 NeedSelectList: true, 1082 Typs: arg.Typs, 1083 Conditions: arg.Conditions[1], 1084 } 1085 case vm.Left: 1086 arg := in.Arg.(*left.Argument) 1087 return &hashbuild.Argument{ 1088 NeedHashMap: true, 1089 NeedSelectList: true, 1090 Typs: arg.Typs, 1091 Conditions: arg.Conditions[1], 1092 } 1093 case vm.Semi: 1094 arg := in.Arg.(*semi.Argument) 1095 return &hashbuild.Argument{ 1096 NeedHashMap: true, 1097 Typs: arg.Typs, 1098 Conditions: arg.Conditions[1], 1099 } 1100 case vm.Single: 1101 arg := in.Arg.(*single.Argument) 1102 return &hashbuild.Argument{ 1103 NeedHashMap: true, 1104 NeedSelectList: true, 1105 Typs: arg.Typs, 1106 Conditions: arg.Conditions[1], 1107 } 1108 case vm.Product: 1109 arg := in.Arg.(*product.Argument) 1110 return &hashbuild.Argument{ 1111 NeedHashMap: false, 1112 NeedSelectList: true, 1113 Typs: arg.Typs, 1114 } 1115 case vm.LoopAnti: 1116 arg := in.Arg.(*loopanti.Argument) 1117 return &hashbuild.Argument{ 1118 NeedHashMap: false, 1119 NeedSelectList: true, 1120 Typs: arg.Typs, 1121 } 1122 case vm.LoopJoin: 1123 arg := in.Arg.(*loopjoin.Argument) 1124 return &hashbuild.Argument{ 1125 NeedHashMap: false, 1126 NeedSelectList: true, 1127 Typs: arg.Typs, 1128 } 1129 case vm.LoopLeft: 1130 arg := in.Arg.(*loopleft.Argument) 1131 return &hashbuild.Argument{ 1132 NeedHashMap: false, 1133 NeedSelectList: true, 1134 Typs: arg.Typs, 1135 } 1136 case vm.LoopSemi: 1137 arg := in.Arg.(*loopsemi.Argument) 1138 return &hashbuild.Argument{ 1139 NeedHashMap: false, 1140 NeedSelectList: true, 1141 Typs: arg.Typs, 1142 } 1143 case vm.LoopSingle: 1144 arg := in.Arg.(*loopsingle.Argument) 1145 return &hashbuild.Argument{ 1146 NeedHashMap: false, 1147 NeedSelectList: true, 1148 Typs: arg.Typs, 1149 } 1150 case vm.LoopMark: 1151 arg := in.Arg.(*loopmark.Argument) 1152 return &hashbuild.Argument{ 1153 NeedHashMap: false, 1154 NeedSelectList: true, 1155 Typs: arg.Typs, 1156 } 1157 1158 default: 1159 panic(moerr.NewInternalError(proc.Ctx, "unsupport join type '%v'", in.Op)) 1160 } 1161 } 1162 1163 func constructJoinResult(expr *plan.Expr, proc *process.Process) (int32, int32) { 1164 e, ok := expr.Expr.(*plan.Expr_Col) 1165 if !ok { 1166 panic(moerr.NewNYI(proc.Ctx, "join result '%s'", expr)) 1167 } 1168 return e.Col.RelPos, e.Col.ColPos 1169 } 1170 1171 func constructJoinConditions(exprs []*plan.Expr, proc *process.Process) [][]*plan.Expr { 1172 conds := make([][]*plan.Expr, 2) 1173 conds[0] = make([]*plan.Expr, len(exprs)) 1174 conds[1] = make([]*plan.Expr, len(exprs)) 1175 for i, expr := range exprs { 1176 conds[0][i], conds[1][i] = constructJoinCondition(expr, proc) 1177 } 1178 return conds 1179 } 1180 1181 func constructJoinCondition(expr *plan.Expr, proc *process.Process) (*plan.Expr, *plan.Expr) { 1182 if e, ok := expr.Expr.(*plan.Expr_C); ok { // constant bool 1183 b, ok := e.C.Value.(*plan.Const_Bval) 1184 if !ok { 1185 panic(moerr.NewNYI(proc.Ctx, "join condition '%s'", expr)) 1186 } 1187 if b.Bval { 1188 return expr, expr 1189 } 1190 return expr, &plan.Expr{ 1191 Typ: expr.Typ, 1192 Expr: &plan.Expr_C{ 1193 C: &plan.Const{ 1194 Value: &plan.Const_Bval{Bval: true}, 1195 }, 1196 }, 1197 } 1198 } 1199 e, ok := expr.Expr.(*plan.Expr_F) 1200 if !ok || !supportedJoinCondition(e.F.Func.GetObj()) { 1201 panic(moerr.NewNYI(proc.Ctx, "join condition '%s'", expr)) 1202 } 1203 if exprRelPos(e.F.Args[0]) == 1 { 1204 return e.F.Args[1], e.F.Args[0] 1205 } 1206 return e.F.Args[0], e.F.Args[1] 1207 } 1208 1209 func isEquiJoin(exprs []*plan.Expr) bool { 1210 for _, expr := range exprs { 1211 if e, ok := expr.Expr.(*plan.Expr_F); ok { 1212 if !supportedJoinCondition(e.F.Func.GetObj()) { 1213 continue 1214 } 1215 lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1) 1216 if lpos == -1 || rpos == -1 || (lpos == rpos) { 1217 continue 1218 } 1219 return true 1220 } 1221 } 1222 return false || isEquiJoin0(exprs) 1223 } 1224 1225 func isEquiJoin0(exprs []*plan.Expr) bool { 1226 for _, expr := range exprs { 1227 if e, ok := expr.Expr.(*plan.Expr_F); ok { 1228 if !supportedJoinCondition(e.F.Func.GetObj()) { 1229 return false 1230 } 1231 lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1) 1232 if lpos == -1 || rpos == -1 || (lpos == rpos) { 1233 return false 1234 } 1235 } 1236 } 1237 return true 1238 } 1239 1240 func extraJoinConditions(exprs []*plan.Expr) (*plan.Expr, []*plan.Expr) { 1241 exprs = colexec.SplitAndExprs(exprs) 1242 eqConds := make([]*plan.Expr, 0, len(exprs)) 1243 notEqConds := make([]*plan.Expr, 0, len(exprs)) 1244 for i, expr := range exprs { 1245 if e, ok := expr.Expr.(*plan.Expr_F); ok { 1246 if !supportedJoinCondition(e.F.Func.GetObj()) { 1247 notEqConds = append(notEqConds, exprs[i]) 1248 continue 1249 } 1250 lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1) 1251 if lpos == -1 || rpos == -1 || (lpos == rpos) { 1252 notEqConds = append(notEqConds, exprs[i]) 1253 continue 1254 } 1255 eqConds = append(eqConds, exprs[i]) 1256 } 1257 } 1258 if len(notEqConds) == 0 { 1259 return nil, eqConds 1260 } 1261 return colexec.RewriteFilterExprList(notEqConds), eqConds 1262 } 1263 1264 func supportedJoinCondition(id int64) bool { 1265 fid, _ := function.DecodeOverloadID(id) 1266 return fid == function.EQUAL 1267 } 1268 1269 func hasColExpr(expr *plan.Expr, pos int32) int32 { 1270 switch e := expr.Expr.(type) { 1271 case *plan.Expr_Col: 1272 if pos == -1 { 1273 return e.Col.RelPos 1274 } 1275 if pos != e.Col.RelPos { 1276 return -1 1277 } 1278 return pos 1279 case *plan.Expr_F: 1280 for i := range e.F.Args { 1281 pos0 := hasColExpr(e.F.Args[i], pos) 1282 switch { 1283 case pos0 == -1: 1284 case pos == -1: 1285 pos = pos0 1286 case pos != pos0: 1287 return -1 1288 } 1289 } 1290 return pos 1291 default: 1292 return pos 1293 } 1294 } 1295 1296 func exprRelPos(expr *plan.Expr) int32 { 1297 switch e := expr.Expr.(type) { 1298 case *plan.Expr_Col: 1299 return e.Col.RelPos 1300 case *plan.Expr_F: 1301 for i := range e.F.Args { 1302 if relPos := exprRelPos(e.F.Args[i]); relPos >= 0 { 1303 return relPos 1304 } 1305 } 1306 } 1307 return -1 1308 } 1309 1310 // Get the 'engine.Relation' of the table by using 'ObjectRef' and 'TableDef', if 'TableDef' is nil, the relations of its index table will not be obtained 1311 // the first return value is Relation of the original table 1312 // the second return value is Relations of index tables 1313 func getRel(ctx context.Context, proc *process.Process, eg engine.Engine, ref *plan.ObjectRef, tableDef *plan.TableDef) (engine.Relation, []engine.Relation, error) { 1314 var dbSource engine.Database 1315 var relation engine.Relation 1316 var err error 1317 var isTemp bool 1318 oldDbName := ref.SchemaName 1319 if ref.SchemaName != "" { 1320 dbSource, err = eg.Database(ctx, ref.SchemaName, proc.TxnOperator) 1321 if err != nil { 1322 return nil, nil, err 1323 } 1324 relation, err = dbSource.Relation(ctx, ref.ObjName) 1325 if err == nil { 1326 isTemp = false 1327 } else { 1328 dbSource, err = eg.Database(ctx, defines.TEMPORARY_DBNAME, proc.TxnOperator) 1329 if err != nil { 1330 return nil, nil, err 1331 } 1332 newObjeName := engine.GetTempTableName(ref.SchemaName, ref.ObjName) 1333 newSchemaName := defines.TEMPORARY_DBNAME 1334 ref.SchemaName = newSchemaName 1335 ref.ObjName = newObjeName 1336 relation, err = dbSource.Relation(ctx, newObjeName) 1337 if err != nil { 1338 return nil, nil, err 1339 } 1340 isTemp = true 1341 } 1342 } else { 1343 _, _, relation, err = eg.GetRelationById(ctx, proc.TxnOperator, uint64(ref.Obj)) 1344 if err != nil { 1345 return nil, nil, err 1346 } 1347 } 1348 1349 var uniqueIndexTables []engine.Relation 1350 if tableDef != nil { 1351 uniqueIndexTables = make([]engine.Relation, 0) 1352 if tableDef.Indexes != nil { 1353 for _, indexdef := range tableDef.Indexes { 1354 if indexdef.Unique { 1355 var indexTable engine.Relation 1356 if indexdef.TableExist { 1357 if isTemp { 1358 indexTable, err = dbSource.Relation(ctx, engine.GetTempTableName(oldDbName, indexdef.IndexTableName)) 1359 } else { 1360 indexTable, err = dbSource.Relation(ctx, indexdef.IndexTableName) 1361 } 1362 if err != nil { 1363 return nil, nil, err 1364 } 1365 uniqueIndexTables = append(uniqueIndexTables, indexTable) 1366 } 1367 } else { 1368 continue 1369 } 1370 } 1371 } 1372 } 1373 return relation, uniqueIndexTables, err 1374 }