-
Notifications
You must be signed in to change notification settings - Fork 3.7k
test #60989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
test #60989
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -109,27 +109,76 @@ class QueryCache : public LRUCachePolicy { | |||||||||||||||||||||||
| static Status build_cache_key(const std::vector<TScanRangeParams>& scan_ranges, | ||||||||||||||||||||||||
| const TQueryCacheParam& cache_param, std::string* cache_key, | ||||||||||||||||||||||||
| int64_t* version) { | ||||||||||||||||||||||||
| if (scan_ranges.size() > 1) { | ||||||||||||||||||||||||
| return Status::InternalError( | ||||||||||||||||||||||||
| "CacheSourceOperator only support one scan range, plan error"); | ||||||||||||||||||||||||
| if (scan_ranges.empty()) { | ||||||||||||||||||||||||
| return Status::InternalError("scan_ranges is empty, plan error"); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| auto& scan_range = scan_ranges[0]; | ||||||||||||||||||||||||
| DCHECK(scan_range.scan_range.__isset.palo_scan_range); | ||||||||||||||||||||||||
| auto tablet_id = scan_range.scan_range.palo_scan_range.tablet_id; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| std::from_chars(scan_range.scan_range.palo_scan_range.version.data(), | ||||||||||||||||||||||||
| scan_range.scan_range.palo_scan_range.version.data() + | ||||||||||||||||||||||||
| scan_range.scan_range.palo_scan_range.version.size(), | ||||||||||||||||||||||||
| *version); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| auto find_tablet = cache_param.tablet_to_range.find(tablet_id); | ||||||||||||||||||||||||
| if (find_tablet == cache_param.tablet_to_range.end()) { | ||||||||||||||||||||||||
| return Status::InternalError("Not find tablet in partition_to_tablets, plan error"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| std::string digest; | ||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||
| digest = cache_param.digest; | ||||||||||||||||||||||||
| } catch (const std::exception&) { | ||||||||||||||||||||||||
| return Status::InternalError("digest is invalid, plan error"); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| if (digest.empty()) { | ||||||||||||||||||||||||
| return Status::InternalError("digest is empty, plan error"); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (cache_param.tablet_to_range.empty()) { | ||||||||||||||||||||||||
| return Status::InternalError("tablet_to_range is empty, plan error"); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| std::vector<int64_t> tablet_ids; | ||||||||||||||||||||||||
| tablet_ids.reserve(scan_ranges.size()); | ||||||||||||||||||||||||
| for (const auto& scan_range : scan_ranges) { | ||||||||||||||||||||||||
| auto tablet_id = scan_range.scan_range.palo_scan_range.tablet_id; | ||||||||||||||||||||||||
| tablet_ids.push_back(tablet_id); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+132
to
+135
|
||||||||||||||||||||||||
| std::sort(tablet_ids.begin(), tablet_ids.end()); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Comment on lines
+130
to
+137
|
||||||||||||||||||||||||
| int64_t first_version = -1; | ||||||||||||||||||||||||
| std::string first_tablet_range; | ||||||||||||||||||||||||
| for (size_t i = 0; i < tablet_ids.size(); ++i) { | ||||||||||||||||||||||||
| auto tablet_id = tablet_ids[i]; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| auto find_tablet = cache_param.tablet_to_range.find(tablet_id); | ||||||||||||||||||||||||
| if (find_tablet == cache_param.tablet_to_range.end()) { | ||||||||||||||||||||||||
| return Status::InternalError("Not find tablet in partition_to_tablets, plan error"); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| return Status::InternalError("Not find tablet in partition_to_tablets, plan error"); | |
| return Status::InternalError("Not find tablet in tablet_to_range, plan error"); |
Copilot
AI
Mar 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
build_cache_key does a std::find_if(scan_ranges.begin(), scan_ranges.end(), ...) inside a loop over tablet_ids, making it O(n^2) per instance. For large instances this adds avoidable CPU overhead; consider a single pass that builds a map (tablet_id -> parsed version) or collects (tablet_id, version, range) pairs and then sorts.
Copilot
AI
Mar 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::from_chars(...) parse result is ignored. If version is empty/non-numeric/partially-numeric, current_version can remain -1 (or parse partially) and still be treated as valid, leading to wrong cache versioning. Please check the returned std::from_chars_result (ec/ptr) and fail fast on parse errors.
| std::from_chars(scan_range_iter->scan_range.palo_scan_range.version.data(), | |
| scan_range_iter->scan_range.palo_scan_range.version.data() + | |
| scan_range_iter->scan_range.palo_scan_range.version.size(), | |
| current_version); | |
| const auto& version_str = scan_range_iter->scan_range.palo_scan_range.version; | |
| const char* version_begin = version_str.data(); | |
| const char* version_end = version_begin + version_str.size(); | |
| auto parse_result = std::from_chars(version_begin, version_end, current_version); | |
| if (parse_result.ec != std::errc() || parse_result.ptr != version_end) { | |
| return Status::InternalError("tablet version is invalid, plan error"); | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,9 +40,24 @@ TEST_F(QueryCacheTest, create_global_cache) { | |
| TEST_F(QueryCacheTest, build_cache_key) { | ||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| scan_ranges.push_back({}); | ||
| scan_ranges.push_back({}); | ||
| TScanRangeParams scan_range1; | ||
| TPaloScanRange palp_scan_range1; | ||
| palp_scan_range1.__set_tablet_id(1); | ||
| palp_scan_range1.__set_version("100"); | ||
|
Comment on lines
+44
to
+46
|
||
| scan_range1.scan_range.__set_palo_scan_range(palp_scan_range1); | ||
| scan_ranges.emplace_back(scan_range1); | ||
|
|
||
| TScanRangeParams scan_range2; | ||
| TPaloScanRange palp_scan_range2; | ||
| palp_scan_range2.__set_tablet_id(2); | ||
| palp_scan_range2.__set_version("100"); | ||
| scan_range2.scan_range.__set_palo_scan_range(palp_scan_range2); | ||
| scan_ranges.emplace_back(scan_range2); | ||
|
|
||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| cache_param.tablet_to_range.insert({1, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({2, "range_xyz"}); | ||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
@@ -59,6 +74,7 @@ TEST_F(QueryCacheTest, build_cache_key) { | |
| scan_range.scan_range.__set_palo_scan_range(palp_scan_range); | ||
| scan_ranges.push_back(scan_range); | ||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
@@ -87,6 +103,156 @@ TEST_F(QueryCacheTest, build_cache_key) { | |
| } | ||
| } | ||
|
|
||
| TEST_F(QueryCacheTest, build_cache_key_multiple_tablets) { | ||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| TScanRangeParams scan_range1; | ||
| TPaloScanRange palp_scan_range1; | ||
| palp_scan_range1.__set_tablet_id(3); | ||
| palp_scan_range1.__set_version("100"); | ||
| scan_range1.scan_range.__set_palo_scan_range(palp_scan_range1); | ||
| scan_ranges.push_back(scan_range1); | ||
|
|
||
| TScanRangeParams scan_range2; | ||
| TPaloScanRange palp_scan_range2; | ||
| palp_scan_range2.__set_tablet_id(1); | ||
| palp_scan_range2.__set_version("100"); | ||
| scan_range2.scan_range.__set_palo_scan_range(palp_scan_range2); | ||
| scan_ranges.push_back(scan_range2); | ||
|
|
||
| TScanRangeParams scan_range3; | ||
| TPaloScanRange palp_scan_range3; | ||
| palp_scan_range3.__set_tablet_id(2); | ||
| palp_scan_range3.__set_version("100"); | ||
| scan_range3.scan_range.__set_palo_scan_range(palp_scan_range3); | ||
| scan_ranges.push_back(scan_range3); | ||
|
|
||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| cache_param.tablet_to_range.insert({1, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({2, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({3, "range_abc"}); | ||
|
|
||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
||
| EXPECT_TRUE(st.ok()); | ||
| EXPECT_EQ(version, 100); | ||
|
|
||
| int64_t expected_tablet1 = 1; | ||
| int64_t expected_tablet2 = 2; | ||
| int64_t expected_tablet3 = 3; | ||
| std::string expected_key = | ||
| "test_digest" + | ||
| std::string(reinterpret_cast<char*>(&expected_tablet1), sizeof(expected_tablet1)) + | ||
| std::string(reinterpret_cast<char*>(&expected_tablet2), sizeof(expected_tablet2)) + | ||
| std::string(reinterpret_cast<char*>(&expected_tablet3), sizeof(expected_tablet3)) + | ||
| "range_abc"; | ||
|
|
||
| EXPECT_EQ(cache_key, expected_key); | ||
| } | ||
|
|
||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| TScanRangeParams scan_range1; | ||
| TPaloScanRange palp_scan_range1; | ||
| palp_scan_range1.__set_tablet_id(1); | ||
| palp_scan_range1.__set_version("100"); | ||
| scan_range1.scan_range.__set_palo_scan_range(palp_scan_range1); | ||
| scan_ranges.push_back(scan_range1); | ||
|
|
||
| TScanRangeParams scan_range2; | ||
| TPaloScanRange palp_scan_range2; | ||
| palp_scan_range2.__set_tablet_id(2); | ||
| palp_scan_range2.__set_version("200"); | ||
| scan_range2.scan_range.__set_palo_scan_range(palp_scan_range2); | ||
| scan_ranges.push_back(scan_range2); | ||
|
|
||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| cache_param.tablet_to_range.insert({1, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({2, "range_abc"}); | ||
|
|
||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
||
| EXPECT_FALSE(st.ok()); | ||
| EXPECT_TRUE(st.msg().find("same version") != std::string::npos); | ||
| } | ||
|
|
||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| TScanRangeParams scan_range1; | ||
| TPaloScanRange palp_scan_range1; | ||
| palp_scan_range1.__set_tablet_id(1); | ||
| palp_scan_range1.__set_version("100"); | ||
| scan_range1.scan_range.__set_palo_scan_range(palp_scan_range1); | ||
| scan_ranges.push_back(scan_range1); | ||
|
|
||
| TScanRangeParams scan_range2; | ||
| TPaloScanRange palp_scan_range2; | ||
| palp_scan_range2.__set_tablet_id(2); | ||
| palp_scan_range2.__set_version("100"); | ||
| scan_range2.scan_range.__set_palo_scan_range(palp_scan_range2); | ||
| scan_ranges.push_back(scan_range2); | ||
|
|
||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| cache_param.tablet_to_range.insert({1, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({2, "range_xyz"}); | ||
|
|
||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
||
| EXPECT_FALSE(st.ok()); | ||
| EXPECT_TRUE(st.msg().find("same tablet_to_range") != std::string::npos); | ||
| } | ||
|
|
||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| TScanRangeParams scan_range1; | ||
| TPaloScanRange palp_scan_range1; | ||
| palp_scan_range1.__set_tablet_id(1); | ||
| palp_scan_range1.__set_version("100"); | ||
| scan_range1.scan_range.__set_palo_scan_range(palp_scan_range1); | ||
| scan_ranges.push_back(scan_range1); | ||
|
|
||
| TScanRangeParams scan_range2; | ||
| TPaloScanRange palp_scan_range2; | ||
| palp_scan_range2.__set_tablet_id(2); | ||
| palp_scan_range2.__set_version("100"); | ||
| scan_range2.scan_range.__set_palo_scan_range(palp_scan_range2); | ||
| scan_ranges.push_back(scan_range2); | ||
|
|
||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| cache_param.tablet_to_range.insert({1, "range_abc"}); | ||
| cache_param.tablet_to_range.insert({3, "range_abc"}); | ||
|
|
||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
||
| EXPECT_FALSE(st.ok()); | ||
| EXPECT_TRUE(st.msg().find("Not find tablet") != std::string::npos); | ||
| } | ||
|
|
||
| { | ||
| std::vector<TScanRangeParams> scan_ranges; | ||
| TQueryCacheParam cache_param; | ||
| cache_param.__set_digest("test_digest"); | ||
| std::string cache_key; | ||
| int64_t version = 0; | ||
| auto st = QueryCache::build_cache_key(scan_ranges, cache_param, &cache_key, &version); | ||
|
|
||
| EXPECT_FALSE(st.ok()); | ||
| EXPECT_TRUE(st.msg().find("empty") != std::string::npos); | ||
| } | ||
| } | ||
|
|
||
| TEST_F(QueryCacheTest, insert_and_lookup) { | ||
| std::unique_ptr<QueryCache> query_cache {QueryCache::create_global_cache(1024 * 1024 * 1024)}; | ||
| std::string cache_key = "be ut"; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CacheTabletIdprofile entry now contains a comma-separated list of multiple tablet ids. Consider renaming the profile key to something plural (e.g.CacheTabletIds) to avoid confusion when debugging profiles.