|
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 { |
@@ -75,8 +77,37 @@ TDataQueryResult ExecuteDataModificationQuery(TSession& session, |
75 | 77 | return result; |
76 | 78 | } |
77 | 79 |
|
78 | | -TString GetYsonResults(TSession& session, const TString& query, const TExecDataQuerySettings& settings = {}) { |
79 | | - return FormatResultSetYson(ExecuteDataModificationQuery(session, query, settings).GetResultSet(0)); |
| 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 | +TValue GetSingleResult(TSession& session, const TString& query, const TExecDataQuerySettings& settings = {}) { |
| 87 | + return GetSingleResult(ExecuteDataModificationQuery(session, query, settings)); |
| 88 | +} |
| 89 | + |
| 90 | +TInstant GetTimestamp(const TValue& value) { |
| 91 | + return TValueParser(value).GetTimestamp(); |
| 92 | +} |
| 93 | + |
| 94 | +int GetInteger(const TValue& value) { |
| 95 | + return TValueParser(value).GetInt32(); |
| 96 | +} |
| 97 | + |
| 98 | +TMaybe<bool> GetFromCacheStat(const TQueryStats& stats) { |
| 99 | + const auto& proto = TProtoAccessor::GetProto(stats); |
| 100 | + if (!proto.Hascompilation()) { |
| 101 | + return Nothing(); |
| 102 | + } |
| 103 | + return proto.Getcompilation().Getfrom_cache(); |
| 104 | +} |
| 105 | + |
| 106 | +void AssertFromCache(const TMaybe<TQueryStats>& stats, bool expectedValue) { |
| 107 | + UNIT_ASSERT(stats.Defined()); |
| 108 | + const auto isFromCache = GetFromCacheStat(*stats); |
| 109 | + UNIT_ASSERT_C(isFromCache.Defined(), stats->ToString()); |
| 110 | + UNIT_ASSERT_VALUES_EQUAL_C(*isFromCache, expectedValue, stats->ToString()); |
80 | 111 | } |
81 | 112 |
|
82 | 113 | void CompareResults(const TDataQueryResult& first, const TDataQueryResult& second) { |
@@ -384,6 +415,53 @@ Y_UNIT_TEST_SUITE(TSelectFromViewTest) { |
384 | 415 | ExecuteDataDefinitionQuery(session, ReadWholeFile(pathPrefix + "drop_view.sql")); |
385 | 416 | } |
386 | 417 | } |
| 418 | + |
| 419 | + Y_UNIT_TEST(QueryCacheIsUpdated) { |
| 420 | + TKikimrRunner kikimr(TKikimrSettings().SetWithSampleTables(false)); |
| 421 | + EnableViewsFeatureFlag(kikimr); |
| 422 | + auto session = kikimr.GetTableClient().CreateSession().GetValueSync().GetSession(); |
| 423 | + |
| 424 | + constexpr const char* viewName = "TheView"; |
| 425 | + |
| 426 | + const auto getCreationQuery = [&viewName](const char* innerQuery) -> TString { |
| 427 | + return std::format(R"( |
| 428 | + CREATE VIEW {} WITH (security_invoker = TRUE) AS {}; |
| 429 | + )", |
| 430 | + viewName, |
| 431 | + innerQuery |
| 432 | + ); |
| 433 | + }; |
| 434 | + constexpr const char* firstInnerQuery = "SELECT 1"; |
| 435 | + ExecuteDataDefinitionQuery(session, getCreationQuery(firstInnerQuery)); |
| 436 | + |
| 437 | + const TString selectFromViewQuery = std::format(R"( |
| 438 | + SELECT * FROM {}; |
| 439 | + )", |
| 440 | + viewName |
| 441 | + ); |
| 442 | + TExecDataQuerySettings queryExecutionSettings; |
| 443 | + queryExecutionSettings.KeepInQueryCache(true); |
| 444 | + queryExecutionSettings.CollectQueryStats(ECollectQueryStatsMode::Basic); |
| 445 | + ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 446 | + // make sure the server side cache is working by calling the same query twice |
| 447 | + const auto cachedQueryRawResult = ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 448 | + AssertFromCache(cachedQueryRawResult.GetStats(), true); |
| 449 | + UNIT_ASSERT_VALUES_EQUAL(GetInteger(GetSingleResult(cachedQueryRawResult)), 1); |
| 450 | + |
| 451 | + // recreate the view with a different query inside |
| 452 | + ExecuteDataDefinitionQuery(session, std::format(R"( |
| 453 | + DROP VIEW {}; |
| 454 | + )", |
| 455 | + viewName |
| 456 | + ) |
| 457 | + ); |
| 458 | + constexpr const char* secondInnerQuery = "SELECT 2"; |
| 459 | + ExecuteDataDefinitionQuery(session, getCreationQuery(secondInnerQuery)); |
| 460 | + |
| 461 | + const auto secondCallRawResult = ExecuteDataModificationQuery(session, selectFromViewQuery, queryExecutionSettings); |
| 462 | + AssertFromCache(secondCallRawResult.GetStats(), false); |
| 463 | + UNIT_ASSERT_VALUES_EQUAL(GetInteger(GetSingleResult(secondCallRawResult)), 2); |
| 464 | + } |
387 | 465 | } |
388 | 466 |
|
389 | 467 | Y_UNIT_TEST_SUITE(TEvaluateExprInViewTest) { |
@@ -414,9 +492,9 @@ Y_UNIT_TEST_SUITE(TEvaluateExprInViewTest) { |
414 | 492 | TExecDataQuerySettings queryExecutionSettings; |
415 | 493 | queryExecutionSettings.KeepInQueryCache(true); |
416 | 494 | const auto executeTwice = [&](const TString& query) { |
417 | | - return TVector<TString>{ |
418 | | - GetYsonResults(session, query, queryExecutionSettings), |
419 | | - GetYsonResults(session, query, queryExecutionSettings) |
| 495 | + return TVector<TInstant>{ |
| 496 | + GetTimestamp(GetSingleResult(session, query, queryExecutionSettings)), |
| 497 | + GetTimestamp(GetSingleResult(session, query, queryExecutionSettings)) |
420 | 498 | }; |
421 | 499 | }; |
422 | 500 | const auto viewResults = executeTwice(selectFromViewQuery); |
@@ -455,9 +533,9 @@ Y_UNIT_TEST_SUITE(TEvaluateExprInViewTest) { |
455 | 533 | TExecDataQuerySettings queryExecutionSettings; |
456 | 534 | queryExecutionSettings.KeepInQueryCache(true); |
457 | 535 | const auto executeTwice = [&](const TString& query) { |
458 | | - return TVector<TString>{ |
459 | | - GetYsonResults(session, query, queryExecutionSettings), |
460 | | - GetYsonResults(session, query, queryExecutionSettings) |
| 536 | + return TVector<TInstant>{ |
| 537 | + GetTimestamp(GetSingleResult(session, query, queryExecutionSettings)), |
| 538 | + GetTimestamp(GetSingleResult(session, query, queryExecutionSettings)) |
461 | 539 | }; |
462 | 540 | }; |
463 | 541 | const auto viewResults = executeTwice(selectFromViewQuery); |
|
0 commit comments