Skip to content

Commit 359abe2

Browse files
committed
[UT] Add regression tests for lake scan sample options
Signed-off-by: levin-kitty <levin.de.kitty@gmail.com>
1 parent 98a1ec1 commit 359abe2

2 files changed

Lines changed: 180 additions & 0 deletions

File tree

be/test/storage/lake/lake_data_source_test.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "exec/exec_env.h"
3636
#include "exec/pipeline/fragment_context.h"
3737
#include "exec/pipeline/scan/morsel.h"
38+
#include "exec/runtime/fragment_context.h"
3839
#include "fs/fs_util.h"
3940
#include "runtime/descriptor_helper.h"
4041
#include "runtime/descriptors.h"
@@ -49,6 +50,7 @@
4950
#include "storage/lake/tablet_writer.h"
5051
#include "storage/lake/update_manager.h"
5152
#include "storage/rowset/base_rowset.h"
53+
#include "storage/rowset/segment_options.h"
5254
#include "storage/storage_env.h"
5355
#include "storage/tablet_schema.h"
5456
#include "storage_primitive/vector_search_option.h"
@@ -378,6 +380,109 @@ TEST_F(LakeDataSourceTest, get_tablet_schema) {
378380
ASSERT_EQ(schema_id, tablet_schema->id());
379381
}
380382

383+
TEST_F(LakeDataSourceTest, propagate_sample_options) {
384+
SyncPoint::GetInstance()->EnableProcessing();
385+
DeferOp defer([] {
386+
SyncPoint::GetInstance()->ClearAllCallBacks();
387+
SyncPoint::GetInstance()->DisableProcessing();
388+
});
389+
390+
create_rowsets_for_testing(_tablet_metadata.get(), 2);
391+
392+
TTableSampleOptions sample_options;
393+
sample_options.__set_enable_sampling(true);
394+
sample_options.__set_sample_method(SampleMethod::BY_BLOCK);
395+
sample_options.__set_random_seed(7);
396+
sample_options.__set_probability_percent_v2(0.5);
397+
398+
TLakeScanNode lake_scan_node;
399+
lake_scan_node.__set_tuple_id(0);
400+
lake_scan_node.__set_key_column_name({"c0"});
401+
lake_scan_node.__set_key_column_type({TPrimitiveType::INT});
402+
lake_scan_node.__set_is_preaggregation(true);
403+
lake_scan_node.__set_sample_options(sample_options);
404+
405+
TPlanNode plan_node;
406+
plan_node.__set_node_id(0);
407+
plan_node.__set_node_type(TPlanNodeType::LAKE_SCAN_NODE);
408+
plan_node.__set_lake_scan_node(lake_scan_node);
409+
410+
auto runtime_state = create_runtime_state();
411+
pipeline::FragmentContext fragment_ctx;
412+
runtime_state->set_fragment_ctx(&fragment_ctx, &fragment_ctx.fragment_runtime_state());
413+
runtime_state->set_fragment_dict_state(fragment_ctx.dict_state());
414+
415+
TDescriptorTableBuilder desc_tbl_builder;
416+
TSlotDescriptorBuilder slot_desc_builder;
417+
auto slot =
418+
slot_desc_builder.type(LogicalType::TYPE_INT).column_name("c0").column_pos(0).nullable(true).build();
419+
420+
TTupleDescriptorBuilder tuple_desc_builder;
421+
tuple_desc_builder.add_slot(slot);
422+
tuple_desc_builder.build(&desc_tbl_builder);
423+
424+
DescriptorTbl* desc_tbl = nullptr;
425+
ASSERT_OK(DescriptorTbl::create(runtime_state.get(), runtime_state->obj_pool(), desc_tbl_builder.desc_tbl(),
426+
&desc_tbl, config::vector_chunk_size));
427+
runtime_state->set_desc_tbl(desc_tbl);
428+
429+
TTableDescriptor table_descriptor;
430+
table_descriptor.__set_id(0);
431+
table_descriptor.__set_tableType(TTableType::OLAP_TABLE);
432+
table_descriptor.__set_tableName("test_table");
433+
table_descriptor.__set_dbName("test_db");
434+
435+
auto* table_desc = runtime_state->obj_pool()->add(new OlapTableDescriptor(table_descriptor));
436+
desc_tbl->get_tuple_descriptor(0)->set_table_desc(table_desc);
437+
438+
connector::LakeDataSourceProvider provider(/*scan_node=*/nullptr, plan_node);
439+
provider.set_lake_tablet_manager(_tablet_mgr);
440+
441+
TInternalScanRange internal_scan_range;
442+
internal_scan_range.__set_tablet_id(_tablet_metadata->id());
443+
internal_scan_range.__set_version(std::to_string(_tablet_metadata->version()));
444+
445+
TScanRange scan_range;
446+
scan_range.__set_internal_scan_range(internal_scan_range);
447+
448+
ASSIGN_OR_ABORT(auto tablet, _tablet_mgr->get_tablet(_tablet_metadata->id(), _tablet_metadata->version()));
449+
450+
std::vector<BaseRowsetSharedPtr> base_rowsets;
451+
for (auto& rowset : tablet.get_rowsets()) {
452+
base_rowsets.emplace_back(rowset);
453+
}
454+
455+
pipeline::ScanMorsel morsel(plan_node.node_id, scan_range);
456+
morsel.set_rowsets(base_rowsets);
457+
458+
bool seen = false;
459+
TTableSampleOptions propagated;
460+
SyncPoint::GetInstance()->SetCallBack("Rowset::read::seg_options", [&](void* arg) {
461+
auto* segment_options = static_cast<SegmentReadOptions*>(arg);
462+
propagated = segment_options->sample_options;
463+
seen = true;
464+
});
465+
466+
connector::LakeDataSource data_source(&provider, scan_range);
467+
RuntimeProfile profile("LakeDataSourceTest");
468+
data_source.set_runtime_profile(&profile);
469+
data_source.set_morsel(&morsel);
470+
471+
DeferOp close_guard([&] { data_source.close(runtime_state.get()); });
472+
ASSERT_OK(data_source.open(runtime_state.get()));
473+
474+
ASSERT_TRUE(seen);
475+
ASSERT_TRUE(propagated.__isset.enable_sampling);
476+
EXPECT_TRUE(propagated.enable_sampling);
477+
ASSERT_TRUE(propagated.__isset.sample_method);
478+
EXPECT_EQ(SampleMethod::BY_BLOCK, propagated.sample_method);
479+
ASSERT_TRUE(propagated.__isset.random_seed);
480+
EXPECT_EQ(7, propagated.random_seed);
481+
ASSERT_TRUE(propagated.__isset.probability_percent_v2);
482+
EXPECT_DOUBLE_EQ(0.5, propagated.probability_percent_v2);
483+
EXPECT_FALSE(propagated.__isset.probability_percent);
484+
}
485+
381486
// Exercise the vector-search branches of LakeDataSource::open() that were added by
382487
// the shared-data vector index read PR:
383488
// * open() propagation of TVectorSearchOptions from thrift into _use_vector_index etc.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2021-present StarRocks, Inc. All rights reserved.
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+
// https://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 com.starrocks.sql.plan;
16+
17+
import com.starrocks.common.util.UUIDUtil;
18+
import com.starrocks.planner.OlapScanNode;
19+
import com.starrocks.planner.ScanNode;
20+
import com.starrocks.qe.ConnectContext;
21+
import com.starrocks.server.RunMode;
22+
import com.starrocks.thrift.SampleMethod;
23+
import com.starrocks.thrift.TPlanNode;
24+
import com.starrocks.thrift.TPlanNodeType;
25+
import com.starrocks.thrift.TTableSampleOptions;
26+
import com.starrocks.utframe.StarRocksAssert;
27+
import com.starrocks.utframe.UtFrameUtils;
28+
import org.junit.jupiter.api.Assertions;
29+
import org.junit.jupiter.api.BeforeAll;
30+
import org.junit.jupiter.api.Test;
31+
32+
public class LakeTableSamplePlanTest {
33+
private static ConnectContext connectContext;
34+
35+
@BeforeAll
36+
public static void setUp() throws Exception {
37+
UtFrameUtils.createMinStarRocksCluster(RunMode.SHARED_DATA);
38+
connectContext = UtFrameUtils.createDefaultCtx();
39+
40+
StarRocksAssert starRocksAssert = new StarRocksAssert(connectContext);
41+
starRocksAssert.withDatabase("lake_sample_test")
42+
.useDatabase("lake_sample_test")
43+
.withTable("CREATE TABLE lake_sample_test.t0 (c0 INT) " +
44+
"DUPLICATE KEY(c0) " +
45+
"DISTRIBUTED BY HASH(c0) BUCKETS 1");
46+
}
47+
48+
@Test
49+
public void testLakeScanNodeCarriesSampleOptions() throws Exception {
50+
connectContext.setQueryId(UUIDUtil.genUUID());
51+
connectContext.setExecutionId(UUIDUtil.toTUniqueId(connectContext.getQueryId()));
52+
53+
String sql = "SELECT c0 FROM t0 " +
54+
"SAMPLE('method'='by_block', 'seed'='7', 'percent'='0.5')";
55+
ExecPlan execPlan = UtFrameUtils.getPlanAndFragment(connectContext, sql).second;
56+
57+
Assertions.assertEquals(1, execPlan.getScanNodes().size());
58+
ScanNode scanNode = execPlan.getScanNodes().get(0);
59+
Assertions.assertInstanceOf(OlapScanNode.class, scanNode);
60+
61+
TPlanNode thriftNode = scanNode.treeToThrift().getNodes().get(0);
62+
Assertions.assertEquals(TPlanNodeType.LAKE_SCAN_NODE, thriftNode.getNode_type());
63+
Assertions.assertTrue(thriftNode.isSetLake_scan_node());
64+
Assertions.assertTrue(thriftNode.getLake_scan_node().isSetSample_options());
65+
66+
TTableSampleOptions sampleOptions =
67+
thriftNode.getLake_scan_node().getSample_options();
68+
Assertions.assertTrue(sampleOptions.isEnable_sampling());
69+
Assertions.assertEquals(SampleMethod.BY_BLOCK, sampleOptions.getSample_method());
70+
Assertions.assertEquals(7L, sampleOptions.getRandom_seed());
71+
Assertions.assertTrue(sampleOptions.isSetProbability_percent_v2());
72+
Assertions.assertEquals(
73+
0.5, sampleOptions.getProbability_percent_v2(), 0.000001);
74+
}
75+
}

0 commit comments

Comments
 (0)