github.com/apache/arrow/go/v10@v10.0.1/parquet/pqarrow/path_builder.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package pqarrow 18 19 import ( 20 "sync/atomic" 21 "unsafe" 22 23 "github.com/apache/arrow/go/v10/arrow" 24 "github.com/apache/arrow/go/v10/arrow/array" 25 "github.com/apache/arrow/go/v10/arrow/memory" 26 "github.com/apache/arrow/go/v10/internal/bitutils" 27 "github.com/apache/arrow/go/v10/parquet/internal/encoding" 28 "golang.org/x/xerrors" 29 ) 30 31 type iterResult int8 32 33 const ( 34 iterDone iterResult = -1 35 iterNext iterResult = 1 36 ) 37 38 type elemRange struct { 39 start int64 40 end int64 41 } 42 43 func (e elemRange) empty() bool { return e.start == e.end } 44 func (e elemRange) size() int64 { return e.end - e.start } 45 46 type rangeSelector interface { 47 GetRange(idx int64) elemRange 48 } 49 50 type varRangeSelector struct { 51 offsets []int32 52 } 53 54 func (v varRangeSelector) GetRange(idx int64) elemRange { 55 return elemRange{int64(v.offsets[idx]), int64(v.offsets[idx+1])} 56 } 57 58 type fixedSizeRangeSelector struct { 59 listSize int32 60 } 61 62 func (f fixedSizeRangeSelector) GetRange(idx int64) elemRange { 63 start := idx * int64(f.listSize) 64 return elemRange{start, start + int64(f.listSize)} 65 } 66 67 type pathNode interface { 68 clone() pathNode 69 } 70 71 type allPresentTerminalNode struct { 72 defLevel int16 73 } 74 75 func (n *allPresentTerminalNode) clone() pathNode { 76 ret := *n 77 return &ret 78 } 79 80 func (n *allPresentTerminalNode) run(rng elemRange, ctx *pathWriteCtx) iterResult { 81 return ctx.AppendDefLevels(int(rng.size()), n.defLevel) 82 } 83 84 type allNullsTerminalNode struct { 85 defLevel int16 86 repLevel int16 87 } 88 89 func (n *allNullsTerminalNode) clone() pathNode { 90 ret := *n 91 return &ret 92 } 93 94 func (n *allNullsTerminalNode) run(rng elemRange, ctx *pathWriteCtx) iterResult { 95 fillRepLevels(int(rng.size()), n.repLevel, ctx) 96 return ctx.AppendDefLevels(int(rng.size()), n.defLevel) 97 } 98 99 type nullableTerminalNode struct { 100 bitmap []byte 101 elemOffset int64 102 defLevelIfPresent int16 103 defLevelIfNull int16 104 } 105 106 func (n *nullableTerminalNode) clone() pathNode { 107 ret := *n 108 return &ret 109 } 110 111 func (n *nullableTerminalNode) run(rng elemRange, ctx *pathWriteCtx) iterResult { 112 elems := rng.size() 113 ctx.ReserveDefLevels(int(elems)) 114 115 var ( 116 present = (*(*[2]byte)(unsafe.Pointer(&n.defLevelIfPresent)))[:] 117 null = (*(*[2]byte)(unsafe.Pointer(&n.defLevelIfNull)))[:] 118 ) 119 rdr := bitutils.NewBitRunReader(n.bitmap, n.elemOffset+rng.start, elems) 120 for { 121 run := rdr.NextRun() 122 if run.Len == 0 { 123 break 124 } 125 if run.Set { 126 ctx.defLevels.UnsafeWriteCopy(int(run.Len), present) 127 } else { 128 ctx.defLevels.UnsafeWriteCopy(int(run.Len), null) 129 } 130 } 131 return iterDone 132 } 133 134 type listNode struct { 135 selector rangeSelector 136 prevRepLevel int16 137 repLevel int16 138 defLevelIfEmpty int16 139 isLast bool 140 } 141 142 func (n *listNode) clone() pathNode { 143 ret := *n 144 return &ret 145 } 146 147 func (n *listNode) run(rng, childRng *elemRange, ctx *pathWriteCtx) iterResult { 148 if rng.empty() { 149 return iterDone 150 } 151 152 // find the first non-empty list (skipping a run of empties) 153 start := rng.start 154 for { 155 // retrieve the range of elements that this list contains 156 *childRng = n.selector.GetRange(rng.start) 157 if !childRng.empty() { 158 break 159 } 160 rng.start++ 161 if rng.empty() { 162 break 163 } 164 } 165 166 // loops post-condition: 167 // * rng is either empty (we're done processing this node) 168 // or start corresponds to a non-empty list 169 // * if rng is non-empty, childRng contains the bounds of the non-empty list 170 171 // handle any skipped over empty lists 172 emptyElems := rng.start - start 173 if emptyElems > 0 { 174 fillRepLevels(int(emptyElems), n.prevRepLevel, ctx) 175 ctx.AppendDefLevels(int(emptyElems), n.defLevelIfEmpty) 176 } 177 178 // start of a new list, note that for nested lists adding the element 179 // here effectively suppresses this code until we either encounter null 180 // elements or empty lists between here and the innermost list (since we 181 // make the rep levels repetition and definition levels unequal). 182 // similarly when we are backtracking up the stack, the repetition 183 // and definition levels are again equal so if we encounter an intermediate 184 // list, with more elements, this will detect it as a new list 185 if ctx.equalRepDeflevlsLen() && !rng.empty() { 186 ctx.AppendRepLevel(n.prevRepLevel) 187 } 188 189 if rng.empty() { 190 return iterDone 191 } 192 193 rng.start++ 194 if n.isLast { 195 // if this is the last repeated node, we can try 196 // to extend the child range as wide as possible, 197 // before continuing to the next node 198 return n.fillForLast(rng, childRng, ctx) 199 } 200 201 return iterNext 202 } 203 204 func (n *listNode) fillForLast(rng, childRng *elemRange, ctx *pathWriteCtx) iterResult { 205 fillRepLevels(int(childRng.size()), n.repLevel, ctx) 206 // once we've reached this point the following preconditions should hold: 207 // 1. there are no more repeated path nodes to deal with 208 // 2. all elements in |range| reperesent contiguous elements in the child 209 // array (null values would have shortened the range to ensure all 210 // remaining list elements are present, though they may be empty) 211 // 3. no element of range spans a parent list (intermediate list nodes 212 // only handle one list entry at a time) 213 // 214 // given these preconditions, it should be safe to fill runs on non-empty lists 215 // here and expand the range in the child node accordingly 216 for !rng.empty() { 217 sizeCheck := n.selector.GetRange(rng.start) 218 if sizeCheck.empty() { 219 // the empty range will need to be handled after we pass down the accumulated 220 // range because it affects def level placement and we need to get the children 221 // def levels entered first 222 break 223 } 224 225 // this is the start of a new list. we can be sure that it only applies to the 226 // previous list (and doesn't jump to the start of any list further up in nesting 227 // due to the contraints mentioned earlier) 228 ctx.AppendRepLevel(n.prevRepLevel) 229 ctx.AppendRepLevels(int(sizeCheck.size())-1, n.repLevel) 230 childRng.end = sizeCheck.end 231 rng.start++ 232 } 233 234 // do book-keeping to track the elements of the arrays that are actually visited 235 // beyond this point. this is necessary to identify "gaps" in values that should 236 // not be processed (written out to parquet) 237 ctx.recordPostListVisit(*childRng) 238 return iterNext 239 } 240 241 type nullableNode struct { 242 bitmap []byte 243 entryOffset int64 244 repLevelIfNull int16 245 defLevelIfNull int16 246 247 validBitsReader bitutils.BitRunReader 248 newRange bool 249 } 250 251 func (n *nullableNode) clone() pathNode { 252 var ret nullableNode = *n 253 return &ret 254 } 255 256 func (n *nullableNode) run(rng, childRng *elemRange, ctx *pathWriteCtx) iterResult { 257 if n.newRange { 258 n.validBitsReader = bitutils.NewBitRunReader(n.bitmap, n.entryOffset+rng.start, rng.size()) 259 } 260 childRng.start = rng.start 261 run := n.validBitsReader.NextRun() 262 if !run.Set { 263 rng.start += run.Len 264 fillRepLevels(int(run.Len), n.repLevelIfNull, ctx) 265 ctx.AppendDefLevels(int(run.Len), n.defLevelIfNull) 266 run = n.validBitsReader.NextRun() 267 } 268 269 if rng.empty() { 270 n.newRange = true 271 return iterDone 272 } 273 childRng.start = rng.start 274 childRng.end = childRng.start 275 childRng.end += run.Len 276 rng.start += childRng.size() 277 n.newRange = false 278 return iterNext 279 } 280 281 type pathInfo struct { 282 path []pathNode 283 primitiveArr arrow.Array 284 maxDefLevel int16 285 maxRepLevel int16 286 leafIsNullable bool 287 } 288 289 func (p pathInfo) clone() pathInfo { 290 ret := p 291 ret.path = make([]pathNode, len(p.path)) 292 for idx, n := range p.path { 293 ret.path[idx] = n.clone() 294 } 295 return ret 296 } 297 298 type pathBuilder struct { 299 info pathInfo 300 paths []pathInfo 301 nullableInParent bool 302 303 refCount int64 304 } 305 306 func (p *pathBuilder) Retain() { 307 atomic.AddInt64(&p.refCount, 1) 308 } 309 310 func (p *pathBuilder) Release() { 311 if atomic.AddInt64(&p.refCount, -1) == 0 { 312 for idx := range p.paths { 313 p.paths[idx].primitiveArr.Release() 314 p.paths[idx].primitiveArr = nil 315 } 316 } 317 } 318 319 // calling NullN on the arr directly will compute the nulls 320 // if we have "UnknownNullCount", calling NullN on the data 321 // object directly will just return the value the data has. 322 // thus we might bet array.UnknownNullCount as the result here. 323 func lazyNullCount(arr arrow.Array) int64 { 324 return int64(arr.Data().NullN()) 325 } 326 327 func lazyNoNulls(arr arrow.Array) bool { 328 nulls := lazyNullCount(arr) 329 return nulls == 0 || (nulls == array.UnknownNullCount && arr.NullBitmapBytes() == nil) 330 } 331 332 type fixupVisitor struct { 333 maxRepLevel int 334 repLevelIfNull int16 335 } 336 337 func (f *fixupVisitor) visit(n pathNode) { 338 switch n := n.(type) { 339 case *listNode: 340 if n.repLevel == int16(f.maxRepLevel) { 341 n.isLast = true 342 f.repLevelIfNull = -1 343 } else { 344 f.repLevelIfNull = n.repLevel 345 } 346 case *nullableTerminalNode: 347 case *allPresentTerminalNode: 348 case *allNullsTerminalNode: 349 if f.repLevelIfNull != -1 { 350 n.repLevel = f.repLevelIfNull 351 } 352 case *nullableNode: 353 if f.repLevelIfNull != -1 { 354 n.repLevelIfNull = f.repLevelIfNull 355 } 356 } 357 } 358 359 func fixup(info pathInfo) pathInfo { 360 // we only need to fixup the path if there were repeated elems 361 if info.maxRepLevel == 0 { 362 return info 363 } 364 365 visitor := fixupVisitor{maxRepLevel: int(info.maxRepLevel)} 366 if visitor.maxRepLevel > 0 { 367 visitor.repLevelIfNull = 0 368 } else { 369 visitor.repLevelIfNull = -1 370 } 371 372 for _, p := range info.path { 373 visitor.visit(p) 374 } 375 return info 376 } 377 378 func (p *pathBuilder) Visit(arr arrow.Array) error { 379 switch arr.DataType().ID() { 380 case arrow.LIST, arrow.MAP: 381 p.maybeAddNullable(arr) 382 // increment necessary due to empty lists 383 p.info.maxDefLevel++ 384 p.info.maxRepLevel++ 385 larr, ok := arr.(*array.List) 386 if !ok { 387 larr = arr.(*array.Map).List 388 } 389 390 p.info.path = append(p.info.path, &listNode{ 391 selector: varRangeSelector{larr.Offsets()[larr.Data().Offset():]}, 392 prevRepLevel: p.info.maxRepLevel - 1, 393 repLevel: p.info.maxRepLevel, 394 defLevelIfEmpty: p.info.maxDefLevel - 1, 395 }) 396 p.nullableInParent = ok 397 return p.Visit(larr.ListValues()) 398 case arrow.FIXED_SIZE_LIST: 399 p.maybeAddNullable(arr) 400 larr := arr.(*array.FixedSizeList) 401 listSize := larr.DataType().(*arrow.FixedSizeListType).Len() 402 // technically we could encoded fixed sized lists with two level encodings 403 // but we always use 3 level encoding, so we increment def levels as well 404 p.info.maxDefLevel++ 405 p.info.maxRepLevel++ 406 p.info.path = append(p.info.path, &listNode{ 407 selector: fixedSizeRangeSelector{listSize}, 408 prevRepLevel: p.info.maxRepLevel - 1, 409 repLevel: p.info.maxRepLevel, 410 defLevelIfEmpty: p.info.maxDefLevel, 411 }) 412 // if arr.data.offset > 0, slice? 413 return p.Visit(larr.ListValues()) 414 case arrow.DICTIONARY: 415 return xerrors.New("dictionary types not implemented yet") 416 case arrow.STRUCT: 417 p.maybeAddNullable(arr) 418 infoBackup := p.info 419 dt := arr.DataType().(*arrow.StructType) 420 for idx, f := range dt.Fields() { 421 p.nullableInParent = f.Nullable 422 if err := p.Visit(arr.(*array.Struct).Field(idx)); err != nil { 423 return err 424 } 425 p.info = infoBackup 426 } 427 return nil 428 case arrow.EXTENSION: 429 return xerrors.New("extension types not implemented yet") 430 case arrow.SPARSE_UNION, arrow.DENSE_UNION: 431 return xerrors.New("union types aren't supported in parquet") 432 default: 433 p.addTerminalInfo(arr) 434 return nil 435 } 436 } 437 438 func (p *pathBuilder) addTerminalInfo(arr arrow.Array) { 439 p.info.leafIsNullable = p.nullableInParent 440 if p.nullableInParent { 441 p.info.maxDefLevel++ 442 } 443 444 // we don't use null_count because if the null_count isn't known 445 // and the array does in fact contain nulls, we will end up traversing 446 // the null bitmap twice. 447 if lazyNoNulls(arr) { 448 p.info.path = append(p.info.path, &allPresentTerminalNode{p.info.maxDefLevel}) 449 p.info.leafIsNullable = false 450 } else if lazyNullCount(arr) == int64(arr.Len()) { 451 p.info.path = append(p.info.path, &allNullsTerminalNode{p.info.maxDefLevel - 1, -1}) 452 } else { 453 p.info.path = append(p.info.path, &nullableTerminalNode{bitmap: arr.NullBitmapBytes(), elemOffset: int64(arr.Data().Offset()), defLevelIfPresent: p.info.maxDefLevel, defLevelIfNull: p.info.maxDefLevel - 1}) 454 } 455 arr.Retain() 456 p.info.primitiveArr = arr 457 p.paths = append(p.paths, fixup(p.info.clone())) 458 } 459 460 func (p *pathBuilder) maybeAddNullable(arr arrow.Array) { 461 if !p.nullableInParent { 462 return 463 } 464 465 p.info.maxDefLevel++ 466 if lazyNoNulls(arr) { 467 return 468 } 469 470 if lazyNullCount(arr) == int64(arr.Len()) { 471 p.info.path = append(p.info.path, &allNullsTerminalNode{p.info.maxDefLevel - 1, -1}) 472 return 473 } 474 475 p.info.path = append(p.info.path, &nullableNode{ 476 bitmap: arr.NullBitmapBytes(), entryOffset: int64(arr.Data().Offset()), 477 defLevelIfNull: p.info.maxDefLevel - 1, repLevelIfNull: -1, 478 newRange: true, 479 }) 480 } 481 482 type multipathLevelBuilder struct { 483 rootRange elemRange 484 data arrow.ArrayData 485 builder pathBuilder 486 487 refCount int64 488 } 489 490 func (m *multipathLevelBuilder) Retain() { 491 atomic.AddInt64(&m.refCount, 1) 492 } 493 494 func (m *multipathLevelBuilder) Release() { 495 if atomic.AddInt64(&m.refCount, -1) == 0 { 496 m.data.Release() 497 m.data = nil 498 m.builder.Release() 499 m.builder = pathBuilder{} 500 } 501 } 502 503 func newMultipathLevelBuilder(arr arrow.Array, fieldNullable bool) (*multipathLevelBuilder, error) { 504 ret := &multipathLevelBuilder{ 505 refCount: 1, 506 rootRange: elemRange{int64(0), int64(arr.Data().Len())}, 507 data: arr.Data(), 508 builder: pathBuilder{nullableInParent: fieldNullable, paths: make([]pathInfo, 0), refCount: 1}, 509 } 510 if err := ret.builder.Visit(arr); err != nil { 511 return nil, err 512 } 513 arr.Data().Retain() 514 return ret, nil 515 } 516 517 func (m *multipathLevelBuilder) leafCount() int { 518 return len(m.builder.paths) 519 } 520 521 func (m *multipathLevelBuilder) write(leafIdx int, ctx *arrowWriteContext) (multipathLevelResult, error) { 522 return writePath(m.rootRange, &m.builder.paths[leafIdx], ctx) 523 } 524 525 func (m *multipathLevelBuilder) writeAll(ctx *arrowWriteContext) (res []multipathLevelResult, err error) { 526 res = make([]multipathLevelResult, m.leafCount()) 527 for idx := range res { 528 res[idx], err = m.write(idx, ctx) 529 if err != nil { 530 break 531 } 532 } 533 return 534 } 535 536 type multipathLevelResult struct { 537 leafArr arrow.Array 538 defLevels []int16 539 defLevelsBuffer encoding.Buffer 540 repLevels []int16 541 repLevelsBuffer encoding.Buffer 542 // contains the element ranges of the required visiting on the descendants of the 543 // final list ancestor for any leaf node. 544 // 545 // the algorithm will attempt to consolidate the visited ranges into the smallest number 546 // 547 // this data is necessary to pass along because after producing the def-rep levels for each 548 // leaf array, it is impossible to determine which values have to be sent to parquet when a 549 // null list value in a nullable listarray is non-empty 550 // 551 // this allows for the parquet writing to determine which values ultimately need to be written 552 postListVisitedElems []elemRange 553 554 leafIsNullable bool 555 } 556 557 func (m *multipathLevelResult) Release() { 558 m.defLevels = nil 559 if m.defLevelsBuffer != nil { 560 m.defLevelsBuffer.Release() 561 } 562 if m.repLevels != nil { 563 m.repLevels = nil 564 m.repLevelsBuffer.Release() 565 } 566 } 567 568 type pathWriteCtx struct { 569 mem memory.Allocator 570 defLevels *int16BufferBuilder 571 repLevels *int16BufferBuilder 572 visitedElems []elemRange 573 } 574 575 func (p *pathWriteCtx) ReserveDefLevels(elems int) iterResult { 576 p.defLevels.Reserve(elems) 577 return iterDone 578 } 579 580 func (p *pathWriteCtx) AppendDefLevel(lvl int16) iterResult { 581 p.defLevels.Append(lvl) 582 return iterDone 583 } 584 585 func (p *pathWriteCtx) AppendDefLevels(count int, defLevel int16) iterResult { 586 p.defLevels.AppendCopies(count, defLevel) 587 return iterDone 588 } 589 590 func (p *pathWriteCtx) UnsafeAppendDefLevel(v int16) iterResult { 591 p.defLevels.UnsafeAppend(v) 592 return iterDone 593 } 594 595 func (p *pathWriteCtx) AppendRepLevel(lvl int16) iterResult { 596 p.repLevels.Append(lvl) 597 return iterDone 598 } 599 600 func (p *pathWriteCtx) AppendRepLevels(count int, lvl int16) iterResult { 601 p.repLevels.AppendCopies(count, lvl) 602 return iterDone 603 } 604 605 func (p *pathWriteCtx) equalRepDeflevlsLen() bool { return p.defLevels.Len() == p.repLevels.Len() } 606 607 func (p *pathWriteCtx) recordPostListVisit(rng elemRange) { 608 if len(p.visitedElems) > 0 && rng.start == p.visitedElems[len(p.visitedElems)-1].end { 609 p.visitedElems[len(p.visitedElems)-1].end = rng.end 610 return 611 } 612 p.visitedElems = append(p.visitedElems, rng) 613 } 614 615 type int16BufferBuilder struct { 616 *encoding.PooledBufferWriter 617 } 618 619 func (b *int16BufferBuilder) Values() []int16 { 620 return arrow.Int16Traits.CastFromBytes(b.PooledBufferWriter.Bytes()) 621 } 622 623 func (b *int16BufferBuilder) Value(i int) int16 { 624 return b.Values()[i] 625 } 626 627 func (b *int16BufferBuilder) Reserve(n int) { 628 b.PooledBufferWriter.Reserve(n * arrow.Int16SizeBytes) 629 } 630 631 func (b *int16BufferBuilder) Len() int { return b.PooledBufferWriter.Len() / arrow.Int16SizeBytes } 632 633 func (b *int16BufferBuilder) AppendCopies(count int, val int16) { 634 b.Reserve(count) 635 b.UnsafeWriteCopy(count, (*(*[2]byte)(unsafe.Pointer(&val)))[:]) 636 } 637 638 func (b *int16BufferBuilder) UnsafeAppend(v int16) { 639 b.PooledBufferWriter.UnsafeWrite((*(*[2]byte)(unsafe.Pointer(&v)))[:]) 640 } 641 642 func (b *int16BufferBuilder) Append(v int16) { 643 b.PooledBufferWriter.Reserve(arrow.Int16SizeBytes) 644 b.PooledBufferWriter.Write((*(*[2]byte)(unsafe.Pointer(&v)))[:]) 645 } 646 647 func fillRepLevels(count int, repLvl int16, ctx *pathWriteCtx) { 648 if repLvl == -1 { 649 return 650 } 651 652 fillCount := count 653 // this condition occurs (rep and def levels equals), in one of a few cases: 654 // 1. before any list is encounted 655 // 2. after rep-level has been filled in due to null/empty values above 656 // 3. after finishing a list 657 if !ctx.equalRepDeflevlsLen() { 658 fillCount-- 659 } 660 ctx.AppendRepLevels(fillCount, repLvl) 661 } 662 663 func writePath(rootRange elemRange, info *pathInfo, arrCtx *arrowWriteContext) (multipathLevelResult, error) { 664 stack := make([]elemRange, len(info.path)) 665 buildResult := multipathLevelResult{ 666 leafArr: info.primitiveArr, 667 leafIsNullable: info.leafIsNullable, 668 } 669 670 if info.maxDefLevel == 0 { 671 // this case only occurs when there are no nullable or repeated columns in the path from the root to the leaf 672 leafLen := buildResult.leafArr.Len() 673 buildResult.postListVisitedElems = []elemRange{{0, int64(leafLen)}} 674 return buildResult, nil 675 } 676 677 stack[0] = rootRange 678 if arrCtx.defLevelsBuffer != nil { 679 arrCtx.defLevelsBuffer.Release() 680 arrCtx.defLevelsBuffer = nil 681 } 682 if arrCtx.repLevelsBuffer != nil { 683 arrCtx.repLevelsBuffer.Release() 684 arrCtx.repLevelsBuffer = nil 685 } 686 687 ctx := pathWriteCtx{arrCtx.props.mem, 688 &int16BufferBuilder{encoding.NewPooledBufferWriter(0)}, 689 &int16BufferBuilder{encoding.NewPooledBufferWriter(0)}, 690 make([]elemRange, 0)} 691 692 ctx.defLevels.Reserve(int(rootRange.size())) 693 if info.maxRepLevel > 0 { 694 ctx.repLevels.Reserve(int(rootRange.size())) 695 } 696 697 stackBase := 0 698 stackPos := stackBase 699 for stackPos >= stackBase { 700 var res iterResult 701 switch n := info.path[stackPos].(type) { 702 case *nullableNode: 703 res = n.run(&stack[stackPos], &stack[stackPos+1], &ctx) 704 case *listNode: 705 res = n.run(&stack[stackPos], &stack[stackPos+1], &ctx) 706 case *nullableTerminalNode: 707 res = n.run(stack[stackPos], &ctx) 708 case *allPresentTerminalNode: 709 res = n.run(stack[stackPos], &ctx) 710 case *allNullsTerminalNode: 711 res = n.run(stack[stackPos], &ctx) 712 } 713 stackPos += int(res) 714 } 715 716 if ctx.repLevels.Len() > 0 { 717 // this case only occurs when there was a repeated element somewhere 718 buildResult.repLevels = ctx.repLevels.Values() 719 buildResult.repLevelsBuffer = ctx.repLevels.Finish() 720 721 buildResult.postListVisitedElems, ctx.visitedElems = ctx.visitedElems, buildResult.postListVisitedElems 722 // if it is possible when processing lists that all lists were empty. in this 723 // case, no elements would have been added to the postListVisitedElements. by 724 // adding an empty element, we avoid special casing later 725 if len(buildResult.postListVisitedElems) == 0 { 726 buildResult.postListVisitedElems = append(buildResult.postListVisitedElems, elemRange{0, 0}) 727 } 728 } else { 729 buildResult.postListVisitedElems = append(buildResult.postListVisitedElems, elemRange{0, int64(buildResult.leafArr.Len())}) 730 buildResult.repLevels = nil 731 } 732 733 buildResult.defLevels = ctx.defLevels.Values() 734 buildResult.defLevelsBuffer = ctx.defLevels.Finish() 735 return buildResult, nil 736 }