yjhjstz commented on code in PR #1241:
URL: https://github.com/apache/cloudberry/pull/1241#discussion_r2254636003


##########
src/backend/access/appendonly/appendonlyam.c:
##########
@@ -1118,6 +1118,311 @@ getNextBlock(AppendOnlyScanDesc scan)
        return true;
 }
 
+static int
+appendonly_locate_target_segment(AppendOnlyScanDesc scan, int64 targrow)
+{
+       int64 rowcount;
+
+       for (int i = scan->aos_segfiles_processed - 1; i < 
scan->aos_total_segfiles; i++)
+       {
+               if (i < 0)
+                       continue;
+
+               rowcount = scan->aos_segfile_arr[i]->total_tupcount;
+               if (rowcount <= 0)
+                       continue;
+
+               if (scan->aos_segfile_arr[i]->state == 
AOSEG_STATE_AWAITING_DROP)
+               {
+                       /* skip this segment, it is awaiting drop */
+                       continue;
+               }
+
+               if (scan->segfirstrow + rowcount - 1 >= targrow)
+               {
+                       /* found the target segment */
+                       return i;
+               }
+
+               /* continue next segment */
+               scan->segfirstrow += rowcount;
+               scan->segrowsprocessed = 0;
+       }
+
+       /* row is beyond the total number of rows in the relation */
+       return -1;
+}
+
+/*
+ * returns the segfile number in which `targrow` locates  
+ */
+static int
+appendonly_getsegment(AppendOnlyScanDesc scan, int64 targrow)
+{
+       int segidx, segno;
+
+       /* locate the target segment */
+       segidx = appendonly_locate_target_segment(scan, targrow);
+       if (segidx < 0)
+       {
+               CloseScannedFileSeg(scan);
+
+               /* done reading all segfiles */
+               Assert(scan->aos_done_all_segfiles);
+
+               return -1;
+       }
+
+       if (segidx + 1 > scan->aos_segfiles_processed)
+       {
+               /* done current segfile */
+               CloseScannedFileSeg(scan);
+               /*
+                * Adjust aos_segfiles_processed to guide
+                * SetNextFileSegForRead() opening next
+                * right segfile.
+                */
+               scan->aos_segfiles_processed = segidx;
+       }
+
+       segno = scan->aos_segfile_arr[segidx]->segno;
+       Assert(segno > InvalidFileSegNumber && segno <= 
AOTupleId_MaxSegmentFileNum);
+
+       if (scan->aos_need_new_segfile)
+       {
+               if (SetNextFileSegForRead(scan))
+               {
+                       Assert(scan->segrowsprocessed == 0);
+                       scan->needNextBuffer = true;
+               }
+               else
+               {
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INTERNAL_ERROR),
+                                        errmsg("Unexpected behavior, failed to 
open segno %d during scanning AO table %s",
+                                                       segno, 
RelationGetRelationName(scan->aos_rd))));
+               }
+       }
+
+       return segno;
+}
+
+static inline int64
+appendonly_block_remaining_rows(AppendOnlyScanDesc scan)
+{
+       return (scan->executorReadBlock.rowCount - 
scan->executorReadBlock.blockRowsProcessed);
+}
+
+/*
+ * locates the block in which `targrow` exists
+ */
+static void
+appendonly_getblock(AppendOnlyScanDesc scan, int64 targrow, int64 *startrow)
+{
+       AppendOnlyExecutorReadBlock *varblock = &scan->executorReadBlock;
+       int64 rowcount = -1;
+
+       if (!scan->needNextBuffer)
+       {
+               /* we have a current block */
+               rowcount = appendonly_block_remaining_rows(scan);
+               Assert(rowcount >= 0);
+
+               if (*startrow + rowcount - 1 >= targrow)
+               {
+                       /* row lies in current block, nothing to do */
+                       return;
+               }
+               else
+               {
+                       /* skip scanning remaining rows */
+                       *startrow += rowcount;
+                       scan->needNextBuffer = true;
+               }
+       }
+
+       /*
+        * Keep reading block headers until we find the block containing
+        * the target row.
+        */
+       while (true)
+       {
+               elog(DEBUG2, "appendonly_getblock(): [targrow: %ld, currow: 
%ld, diff: %ld, "
+                        "startrow: %ld, rowcount: %ld, segfirstrow: %ld, 
segrowsprocessed: %ld, "
+                        "blockRowsProcessed: %ld, blockRowCount: %d]", 
targrow, *startrow + rowcount - 1,
+                        *startrow + rowcount - 1 - targrow, *startrow, 
rowcount, scan->segfirstrow,
+                        scan->segrowsprocessed, varblock->blockRowsProcessed,
+                        varblock->rowCount);
+
+               if 
(AppendOnlyExecutorReadBlock_GetBlockInfo(&scan->storageRead, varblock))
+               {
+                       /* new block, reset blockRowsProcessed */
+                       varblock->blockRowsProcessed = 0;
+                       rowcount = appendonly_block_remaining_rows(scan);
+                       Assert(rowcount > 0);
+                       if (*startrow + rowcount - 1 >= targrow)
+                       {
+                               
AppendOnlyExecutorReadBlock_GetContents(varblock);
+                               /* got a new buffer to consume */
+                               scan->needNextBuffer = false;
+                               return;
+                       }
+
+                       *startrow += rowcount;
+                       
AppendOnlyExecutionReadBlock_FinishedScanBlock(varblock);
+                       
AppendOnlyStorageRead_SkipCurrentBlock(&scan->storageRead);
+                       /* continue next block */
+               }
+               else
+                       pg_unreachable(); /* unreachable code */
+       }
+}
+
+/*
+ * block directory based get_target_tuple()
+ */
+static bool
+appendonly_blkdirscan_get_target_tuple(AppendOnlyScanDesc scan, int64 targrow, 
TupleTableSlot *slot)
+{
+       int segno, segidx;
+       int64 rownum, rowsprocessed;
+       AOTupleId aotid;
+       AppendOnlyBlockDirectory *blkdir = &scan->aofetch->blockDirectory;
+
+       Assert(scan->blkdirscan != NULL);
+
+       /* locate the target segment */
+       segidx = appendonly_locate_target_segment(scan, targrow);
+       if (segidx < 0)
+               return false;
+
+       scan->aos_segfiles_processed = segidx + 1;
+
+       segno = scan->aos_segfile_arr[segidx]->segno;
+       Assert(segno > InvalidFileSegNumber && segno <= 
AOTupleId_MaxSegmentFileNum);

Review Comment:
   I found the code: 
   ```sql
   static inline void
   AOSegment_PopulateBlockSequence(BlockSequence *sequence,
                                                                Oid segrelid,
                                                                int segno)
   {
        int64 lastSequence = ReadLastSequence(segrelid, segno);
   
        Assert(sequence);
        Assert(OidIsValid(segrelid));
        Assert(segno >= 0 && segno <= AOTupleId_MaxSegmentFileNum);
   
        /* ReadLastSequence() is expected to return 0 if the seg doesn't exist. 
Also,
         * valid last sequence values aren't negative.
         */
        Assert(lastSequence >= 0);
   
        sequence->startblknum = AOSegmentGet_startHeapBlock(segno);
        FastSequenceGetNumHeapBlocks(lastSequence, &sequence->nblocks);
   }
   ```
   
   `Assert(segno >= 0 && segno <= AOTupleId_MaxSegmentFileNum);` equal to  
`Assert(segno > InvalidFileSegNumber && segno <= AOTupleId_MaxSegmentFileNum);` 
?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@cloudberry.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cloudberry.apache.org
For additional commands, e-mail: commits-h...@cloudberry.apache.org

Reply via email to