gfphoenix78 commented on code in PR #1241:
URL: https://github.com/apache/cloudberry/pull/1241#discussion_r2253207252
##########
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:
`segno > InvalidFileSegNumber` is not a good idea. This expression assumes
the value of InvalidFileSegNumber is -1, any possible other values would cause
problem.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]