|
1 | 1 | #include <ydb/core/kqp/ut/common/kqp_ut_common.h>
|
2 | 2 | #include <ydb/library/yql/sql/sql.h>
|
3 | 3 | #include <ydb/library/yql/utils/log/log.h>
|
| 4 | +#include <ydb/public/sdk/cpp/client/ydb_proto/accessor.h> |
4 | 5 |
|
5 | 6 | #include <util/folder/filelist.h>
|
6 | 7 |
|
7 | 8 | #include <format>
|
8 | 9 |
|
9 | 10 | using namespace NKikimr;
|
10 | 11 | using namespace NKikimr::NKqp;
|
| 12 | +using namespace NYdb; |
11 | 13 | using namespace NYdb::NTable;
|
12 | 14 |
|
13 | 15 | namespace {
|
@@ -60,17 +62,46 @@ void ExecuteDataDefinitionQuery(TSession& session, const TString& script) {
|
60 | 62 | << script << "\nThe issues:\n" << result.GetIssues().ToString());
|
61 | 63 | }
|
62 | 64 |
|
63 |
| -TDataQueryResult ExecuteDataModificationQuery(TSession& session, const TString& script) { |
| 65 | +TDataQueryResult ExecuteDataModificationQuery(TSession& session, |
| 66 | + const TString& script, |
| 67 | + const TExecDataQuerySettings& settings = {} |
| 68 | +) { |
64 | 69 | const auto result = session.ExecuteDataQuery(
|
65 | 70 | script,
|
66 |
| - TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx() |
| 71 | + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(), |
| 72 | + settings |
67 | 73 | ).ExtractValueSync();
|
68 | 74 | UNIT_ASSERT_C(result.IsSuccess(), "Failed to execute the following DML script:\n"
|
69 | 75 | << script << "\nThe issues:\n" << result.GetIssues().ToString());
|
70 | 76 |
|
71 | 77 | return result;
|
72 | 78 | }
|
73 | 79 |
|
| 80 | +TValue GetSingleResult(const TDataQueryResult& rawResults) { |
| 81 | + auto resultSetParser = rawResults.GetResultSetParser(0); |
| 82 | + UNIT_ASSERT(resultSetParser.TryNextRow()); |
| 83 | + return resultSetParser.GetValue(0); |
| 84 | +} |
| 85 | + |
| 86 | +int GetInteger(const TValue& value) { |
| 87 | + return TValueParser(value).GetInt32(); |
| 88 | +} |
| 89 | + |
| 90 | +TMaybe<bool> GetFromCacheStat(const TQueryStats& stats) { |
| 91 | + const auto& proto = TProtoAccessor::GetProto(stats); |
| 92 | + if (!proto.Hascompilation()) { |
| 93 | + return Nothing(); |
| 94 | + } |
| 95 | + return proto.Getcompilation().Getfrom_cache(); |
| 96 | +} |
| 97 | + |
| 98 | +void AssertFromCache(const TMaybe<TQueryStats>& stats, bool expectedValue) { |
| 99 | + UNIT_ASSERT(stats.Defined()); |
| 100 | + const auto isFromCache = GetFromCacheStat(*stats); |
| 101 | + UNIT_ASSERT_C(isFromCache.Defined(), stats->ToString()); |
| 102 | + UNIT_ASSERT_VALUES_EQUAL_C(*isFromCache, expectedValue, stats->ToString()); |
| 103 | +} |
| 104 | + |
74 | 105 | void CompareResults(const TDataQueryResult& first, const TDataQueryResult& second) {
|
75 | 106 | const auto& firstResults = first.GetResultSets();
|
76 | 107 | const auto& secondResults = second.GetResultSets();
|
@@ -376,4 +407,51 @@ Y_UNIT_TEST_SUITE(TSelectFromViewTest) {
|
376 | 407 | ExecuteDataDefinitionQuery(session, ReadWholeFile(pathPrefix + "drop_view.sql"));
|
377 | 408 | }
|
378 | 409 | }
|
| 410 | + |
| 411 | + Y_UNIT_TEST(QueryCacheIsUpdated) { |
| 412 | + TKikimrRunner kikimr(TKikimrSettings().SetWithSampleTables(false)); |
| 413 | + EnableViewsFeatureFlag(kikimr); |
| 414 | + auto session = kikimr.GetTableClient().CreateSession().GetValueSync().GetSession(); |
| 415 | + |
| 416 | + constexpr const char* viewName = "TheView"; |
| 417 | + |
| 418 | + const auto getCreationQuery = [&viewName](const char* innerQuery) -> TString { |
| 419 | + return std::format(R"( |
| 420 | + CREATE VIEW {} WITH (security_invoker = TRUE) AS {}; |
| 421 | + )", |
| 422 | + viewName, |
| 423 | + innerQuery |
| 424 | + ); |
| 425 | + }; |
| 426 | + constexpr const char* firstInnerQuery = "SELECT 1"; |
| 427 | + ExecuteDataDefinitionQuery(session, getCreationQuery(firstInnerQuery)); |
| 428 | + |
| 429 | + const TString selectFromViewQuery = std::format(R"( |
| 430 | + SELECT * FROM {}; |
| 431 | + )", |
| 432 | + viewName |
| 433 | + ); |
| 434 | + TExecDataQuerySettings queryExecutionSettings; |
| 435 | + queryExecutionSettings.KeepInQueryCache(true); |
| 436 | + queryExecutionSettings.CollectQueryStats(ECollectQueryStatsMode::Basic); |
| 437 | + ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 438 | + // make sure the server side cache is working by calling the same query twice |
| 439 | + const auto cachedQueryRawResult = ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 440 | + AssertFromCache(cachedQueryRawResult.GetStats(), true); |
| 441 | + UNIT_ASSERT_VALUES_EQUAL(GetInteger(GetSingleResult(cachedQueryRawResult)), 1); |
| 442 | + |
| 443 | + // recreate the view with a different query inside |
| 444 | + ExecuteDataDefinitionQuery(session, std::format(R"( |
| 445 | + DROP VIEW {}; |
| 446 | + )", |
| 447 | + viewName |
| 448 | + ) |
| 449 | + ); |
| 450 | + constexpr const char* secondInnerQuery = "SELECT 2"; |
| 451 | + ExecuteDataDefinitionQuery(session, getCreationQuery(secondInnerQuery)); |
| 452 | + |
| 453 | + const auto secondCallRawResult = ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 454 | + AssertFromCache(secondCallRawResult.GetStats(), false); |
| 455 | + UNIT_ASSERT_VALUES_EQUAL(GetInteger(GetSingleResult(secondCallRawResult)), 2); |
| 456 | + } |
379 | 457 | }
|
0 commit comments