HappenLee commented on code in PR #68097:
URL: https://github.com/apache/doris/pull/68097#discussion_r4036884374


##########
be/src/storage/segment/segment.cpp:
##########
@@ -1012,9 +983,30 @@ Status Segment::new_column_iterator(const TabletColumn& 
tablet_column,
     return Status::OK();
 }
 
-Status Segment::get_column_reader(int32_t col_uid, 
std::shared_ptr<ColumnReader>* column_reader,
-                                  OlapReaderStatistics* stats, const 
io::IOContext* source_io_ctx,
-                                  std::optional<Field> const_value) {
+Status Segment::get_column_reader(const TabletColumn& col,
+                                  std::shared_ptr<ColumnReader>* column_reader,
+                                  const StorageReadOptions& read_options) {
+    // The on-disk column is a placeholder until compaction materializes 
per-row commit TSOs.
+    // Resolve the logical value before any metadata/cache lookup, including 
for older segments
+    // that do not contain this column. Never put this reader in the physical 
metadata cache:
+    // unpublished reads and published reads can share the same Segment object.
+    if (col.name() == COMMIT_TSO_COL && read_options.version.first == 
read_options.version.second &&
+        read_options.commit_tso.end_tso() != -1) {
+        DORIS_CHECK_GT(read_options.commit_tso.end_tso(), 0);
+        DORIS_CHECK_EQ(read_options.commit_tso.start_tso(), 
read_options.commit_tso.end_tso());
+        *column_reader = std::make_shared<ConstantColumnReader>(
+                
Field::create_field<TYPE_BIGINT>(read_options.commit_tso.end_tso()));
+        return Status::OK();
+    }
+    // An unassigned TSO (-1) is expected on unpublished internal reads. 
Multi-version rowsets
+    // contain materialized TSOs, which must be read from the physical column.
+    return get_physical_column_reader(col, column_reader, read_options.stats, 
&read_options.io_ctx);

Review Comment:
   Confirmed this is a real correctness issue, but it predates this PR and will 
be handled in a separate follow-up PR.
   
   I checked the pre-PR base `846d9b2ebfc5`: [ordered 
compaction](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/compaction/compaction.cpp#L461)
 already links the singleton files without materializing per-row TSOs and 
produces a spanning-version rowset. The [old data-reader 
path](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/segment/segment.cpp#L946)
 already substitutes a logical constant only for a single-version rowset with 
assigned TSO. Consequently, a cold read of the linked multi-version output can 
expose the physical zero before this PR as well. The compaction implementation 
is unchanged by this PR.
   
   This is tracked separately for a producer-side fix (exclude such 
placeholder-bearing inputs from ordered link compaction, or materialize their 
per-row TSOs), with the requested distinct-publish-TSO coverage. It remains an 
outstanding bug; I am not claiming it is fixed by the reader changes here.



##########
be/src/storage/segment/segment.cpp:
##########
@@ -1012,9 +983,30 @@ Status Segment::new_column_iterator(const TabletColumn& 
tablet_column,
     return Status::OK();
 }
 
-Status Segment::get_column_reader(int32_t col_uid, 
std::shared_ptr<ColumnReader>* column_reader,
-                                  OlapReaderStatistics* stats, const 
io::IOContext* source_io_ctx,
-                                  std::optional<Field> const_value) {
+Status Segment::get_column_reader(const TabletColumn& col,
+                                  std::shared_ptr<ColumnReader>* column_reader,
+                                  const StorageReadOptions& read_options) {
+    // The on-disk column is a placeholder until compaction materializes 
per-row commit TSOs.
+    // Resolve the logical value before any metadata/cache lookup, including 
for older segments
+    // that do not contain this column. Never put this reader in the physical 
metadata cache:
+    // unpublished reads and published reads can share the same Segment object.
+    if (col.name() == COMMIT_TSO_COL && read_options.version.first == 
read_options.version.second &&

Review Comment:
   Confirmed both metadata-loss paths are pre-existing bugs and will be 
addressed in separate follow-up work, rather than in this reader-entrypoint PR.
   
   At the pre-PR base `846d9b2ebfc5`, 
[IndexBuilder](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/task/index_builder.cpp#L348)
 already constructs fresh metadata without copying the source commit TSO. 
[Snapshot rowset-ID 
conversion](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/snapshot/snapshot_manager.cpp#L343)
 likewise creates the writer context and calls `add_rowset` without preserving 
it; [the existing add_rowset 
implementation](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/rowset/beta_rowset_writer.cpp#L845)
 links files without copying TSO. All three implementations are unchanged by 
this PR.
   
   The [pre-PR 
reader](https://github.com/apache/doris/blob/846d9b2ebfc595ddfd77579447db16a674c901f7/be/src/storage/segment/segment.cpp#L946)
 also requires an assigned TSO to substitute the singleton's logical value. 
Thus losing it to `[-1,-1]` already makes a cold read fall back to the on-disk 
placeholder, independently of this change.
   
   These paths are tracked separately for preserving source metadata and adding 
index add/drop plus rowset-ID conversion coverage. They are not being marked as 
fixed here.



##########
be/src/storage/segment/segment.cpp:
##########
@@ -532,9 +514,15 @@ Status Segment::new_iterator(ReadSchemaSPtr schema, const 
StorageReadOptions& re
             if (ordinal < 0) {
                 continue;
             }
+            // This enumeration contains physical readers only. A cached TSO 
placeholder must
+            // not make a logical predicate look unconditionally true.
+            auto reader = it.second;
+            if (ordinal == schema->commit_tso_ordinal()) {

Review Comment:
   Fixed in [6363e04f6bd](https://github.com/apache/doris/commit/6363e04f6bd), 
included in current head `b21ac4087032`.
   
   `Segment::new_iterator` now retains the TSO reader obtained during 
first-phase pruning and explicitly reuses it for predicate simplification, 
independently of physical-cache warmup. TSO is skipped in the physical-reader 
cache traversal. `prune_predicates_by_zone_map` now uses virtual 
`has_zone_map()` / `get_segment_zone_map()` and the existing `is_always_true()` 
logic, so the logical constant's ZoneMap participates without putting a 
scan-specific reader in the shared cache.
   
   
[Tests](https://github.com/apache/doris/blob/b21ac408703240c9237f5b3ba6a7c7c586de863e/be/test/storage/segment/segment_iterator_expr_zonemap_test.cpp#L471)
 cover cold/warm physical caches, TSO projected/not projected, removal from 
both predicate representations, and the no-need-read flag. They also verify 
that other expression dependencies still require TSO and that 
multi-version/unknown-TSO reads retain the physical behavior. These cases 
passed in the final 85-test ASAN run.



##########
be/src/service/point_query_executor.cpp:
##########
@@ -605,11 +615,24 @@ Status PointQueryExecutor::_lookup_row_data() {
                     StorageReadOptions storage_read_options;
                     storage_read_options.stats = &_read_stats;
                     storage_read_options.io_ctx = io_ctx;
+                    storage_read_options.tablet_schema = 
rowset->tablet_schema();
+                    storage_read_options.rowset_id = rowset->rowset_id();
+                    storage_read_options.version = rowset->version();
+                    storage_read_options.commit_tso = rowset->commit_tso();
                     
RETURN_IF_ERROR(segment->seek_and_read_by_rowid(*_tablet->tablet_schema(), slot,
                                                                     row_ids, 
column,
                                                                     
storage_read_options, iter));
                 }
             }
+            if (tso_idx != -1) {
+                const auto& loc = _row_read_ctxs[i]._row_location.value();
+                auto& column = result_columns[tso_idx];
+                column->resize(old_tso_rows);
+                const auto* slot = _reusable->tuple_desc()->slots()[tso_idx];
+                RETURN_IF_ERROR(BaseTablet::fetch_value_by_rowids(

Review Comment:
   Fixed in 
[b21ac408703](https://github.com/apache/doris/commit/b21ac408703240c9237f5b3ba6a7c7c586de863e)
 by removing the independent point-query TSO fetch and reusing the existing 
missing-column path.
   
   Point queries now always treat TSO as unavailable from JSONB. Explicit 
row-store projections prevent both decoding and default-filling its 
placeholder; an empty projection skips JSONB entirely. TSO and other missing 
columns share the normal segment lookup and `seek_and_read_by_rowid`, with the 
pinned source rowset, query `IOContext` and `_remote_scan_cache_write_limiter`. 
All point-query reads now write to `_profile_metrics.read_stats`, the same 
object consumed by `print_profile`, so the former `_read_stats`/profile split 
is also removed.
   
   The tests cover TSO-only/mixed projections, full/partial/no row store, 
ordinary missing-column restrictions with column-store access disabled, and 
delete-sign filtering. Physical multi-version TSO tests verify zero and 
exhausted cache-write budgets, an unlimited control, correct TSO values, no 
cache admission when limited, and query byte/timer accounting. They use the 
real `CachedRemoteFileReader` with a local file standing in for object storage; 
this is not a live-cloud integration test.
   
   The final ASAN run passed 85 tests in 8 suites. SQL regression coverage was 
extended but not run locally.



-- 
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]

Reply via email to