aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnaury <snaury@ydb.tech>2022-09-12 18:47:58 +0300
committersnaury <snaury@ydb.tech>2022-09-12 18:47:58 +0300
commit00dfcee7413b85be81812a8b9482e0754ccabcea (patch)
treee00e7e15ed63816c804764ca3a82ef097b5914e7
parentf68b69214c16dbfdf12930b40f4e415abf2e4093 (diff)
downloadydb-00dfcee7413b85be81812a8b9482e0754ccabcea.tar.gz
Fix ambiguous ranges in dynamic erase/update, add validation in debug builds
-rw-r--r--ydb/core/client/flat_ut.cpp63
-rw-r--r--ydb/core/client/locks_ut.cpp10
-rw-r--r--ydb/core/client/minikql_compile/yql_expr_minikql_compile_ut.cpp4
-rw-r--r--ydb/core/engine/kikimr_program_builder_ut.cpp6
-rw-r--r--ydb/core/engine/minikql/minikql_engine_host.cpp7
-rw-r--r--ydb/core/engine/mkql_engine_flat_ut.cpp78
-rw-r--r--ydb/core/engine/mkql_keys.cpp1
-rw-r--r--ydb/core/scheme/scheme_tabledefs.cpp42
-rw-r--r--ydb/core/scheme/scheme_tabledefs.h6
-rw-r--r--ydb/core/tablet_flat/flat_database.cpp44
-rw-r--r--ydb/core/tx/datashard/datashard__read_iterator.cpp73
-rw-r--r--ydb/core/tx/datashard/datashard__s3.cpp7
-rw-r--r--ydb/core/tx/datashard/datashard_dep_tracker.cpp18
-rw-r--r--ydb/core/tx/datashard/datashard_ut_minikql.cpp44
-rw-r--r--ydb/core/tx/datashard/datashard_ut_order.cpp3
-rw-r--r--ydb/core/tx/datashard/datashard_ut_rs.cpp4
-rw-r--r--ydb/core/tx/schemeshard/ut_restore.cpp9
-rw-r--r--ydb/core/tx/tx_proxy/datareq.cpp15
-rw-r--r--ydb/core/tx/tx_proxy/read_table_impl.cpp22
-rw-r--r--ydb/public/lib/deprecated/kicli/cpp_ut.cpp13
20 files changed, 330 insertions, 139 deletions
diff --git a/ydb/core/client/flat_ut.cpp b/ydb/core/client/flat_ut.cpp
index e2e48c3ab0..4a4baba554 100644
--- a/ydb/core/client/flat_ut.cpp
+++ b/ydb/core/client/flat_ut.cpp
@@ -315,7 +315,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
((return (AsList
(SetResult 'x
(SelectRange '"/dc-1/test/perf/FlatDaoPerfTestClient"
- '('ExcFrom 'ExcTo '('ls (Utf8 '"") (Void)))
+ '('ExcFrom 'IncTo '('ls (Utf8 '"") (Void)))
'('ls 'kg 'localId 'createdSeconds 'mode1)
'('('BytesLimit (Uint64 '3000000)))
)
@@ -1528,7 +1528,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
NKikimrClient::TResponse response;
status = annoyingClient.FlatQueryRaw(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (Member (SelectRange '/dc-1/Dir/Table range '('Key 'Value) '()) 'List))
(let result (Filter data (lambda '(row)
(Coalesce (NotEqual (Member row 'Key) (Uint32 '1)) (Bool 'false))
@@ -1855,6 +1855,33 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
return strResult;
}
+ TString ReadFromTwoKeysTable(TFlatMsgBusClient& annoyingClient, TString table, ui32 fromKey = 0, ui32 fromKey2 = 0, bool follower = false) {
+ const char* readQuery =
+ "("
+ "(let range1 '('IncFrom '('Key (Uint32 '%d) (Void)) '('Key2 (Uint32 '%d) (Void)) ))"
+ "(let select '('Key 'Key2 'Value 'Large))"
+ "(let options '())"
+ "(let pgmReturn (AsList"
+ " (SetResult 'range1 (SelectRange '%s range1 select options (Uint32 '%d)))"
+ "))"
+ "(return pgmReturn)"
+ ")";
+
+ TFlatMsgBusClient::TFlatQueryOptions opts;
+ NKikimrClient::TResponse response;
+ annoyingClient.FlatQueryRaw(Sprintf(readQuery, fromKey, fromKey2, table.data(), follower ? TReadTarget::Follower().GetMode()
+ : TReadTarget::Head().GetMode()), opts, response);
+
+ UNIT_ASSERT_VALUES_EQUAL(response.GetStatus(), NMsgBusProxy::MSTATUS_OK);
+ UNIT_ASSERT(response.GetExecutionEngineResponseStatus() == ui32(NMiniKQL::IEngineFlat::EStatus::Complete));
+ NKikimrMiniKQL::TResult result;
+ result.Swap(response.MutableExecutionEngineEvaluatedResponse());
+
+ TString strResult;
+ ::google::protobuf::TextFormat::PrintToString(result.GetValue(), &strResult);
+ return strResult;
+ }
+
template <class TSetType>
void WaitForTabletsToBeDeletedInHive(TFlatMsgBusClient& annoyingClient, TTestActorRuntime* runtime,
const TSetType& tabletIds, const TDuration& timeout = TDuration::Seconds(20)) {
@@ -2332,12 +2359,12 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
WaitForTabletsToBeDeletedInHive(annoyingClient, cleverServer.GetRuntime(), datashards);
}
- void DoSplitMergeTable(TFlatMsgBusClient& annoyingClient, TString table, const TVector<ui64>& srcPartitions, const TVector<ui32>& splitPoints) {
+ void DoSplitMergeTable(TFlatMsgBusClient& annoyingClient, TString table, const TVector<ui64>& srcPartitions, const TVector<ui32>& splitPoints, bool twoKeys = false) {
TVector<ui64> partitionsBefore;
partitionsBefore = annoyingClient.GetTablePartitions(table);
UNIT_ASSERT(partitionsBefore.size() > 0);
- TString strResultBefore = ReadFromTable(annoyingClient, table);
+ TString strResultBefore = twoKeys ? ReadFromTwoKeysTable(annoyingClient, table) : ReadFromTable(annoyingClient, table);
TStringStream splitDescr;
for (ui32 src : srcPartitions) {
@@ -2355,10 +2382,14 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
// TODO: check paritions that were not supposed to change
//UNIT_ASSERT_VALUES_EQUAL(partitionsAfter.back(), partitionsBefore.back());
- TString strResultAfter = ReadFromTable(annoyingClient, table);
+ TString strResultAfter = twoKeys ? ReadFromTwoKeysTable(annoyingClient, table) : ReadFromTable(annoyingClient, table);
UNIT_ASSERT_NO_DIFF(strResultBefore, strResultAfter);
}
+ void SplitTwoKeysTable(TFlatMsgBusClient& annoyingClient, TString table, ui64 partitionIdx, const TVector<ui32>& splitPoints) {
+ DoSplitMergeTable(annoyingClient, table, {partitionIdx}, splitPoints, /* twoKeys */ true);
+ }
+
void SplitTable(TFlatMsgBusClient& annoyingClient, TString table, ui64 partitionIdx, const TVector<ui32>& splitPoints) {
DoSplitMergeTable(annoyingClient, table, {partitionIdx}, splitPoints);
}
@@ -2614,7 +2645,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG);
cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG);
- SplitTable(annoyingClient, "/dc-1/Dir/TableOld", 0, {splitKey});
+ SplitTwoKeysTable(annoyingClient, "/dc-1/Dir/TableOld", 0, {splitKey});
}
Y_UNIT_TEST(SplitThenMerge) {
@@ -3267,7 +3298,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
client.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (Member (SelectRange '"/dc-1/test/BlobTable" range '('Key 'Value) '()) 'List))
(let result (Filter data (lambda '(row)
(Coalesce (NotEqual (Member row 'Key) (Uint64 '1)) (Bool 'false))
@@ -3361,7 +3392,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (Member (SelectRange '"/dc-1/test/BlobTable" range '('Key 'Value) '()) 'List))
(let result (Take (Skip (Filter data (lambda '(row)
(Coalesce (NotEqual (Member row 'Key) (Uint64 '1)) (Bool 'false))
@@ -3408,7 +3439,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (Member (SelectRange '"/dc-1/test/BlobTable" range '('Key 'Value) '()) 'List))
(let result (OrderedMap data (lambda '(row)
(AddMember row 'Value2 (Member row 'Value))
@@ -3463,7 +3494,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (Member (SelectRange '"/dc-1/test/BlobTable" range '('Key 'Value) '()) 'List))
(let result (OrderedMap data (lambda '(row)
(AddMember row 'Value2 (Member row 'Value))
@@ -3616,7 +3647,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
auto res = annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
@@ -3677,7 +3708,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
auto res = annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
@@ -3738,7 +3769,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
auto res = annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
@@ -3812,7 +3843,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
Y_UNIT_TEST(SelectRangeSkipNullKeys) {
auto res = CreateTableAndExecuteMkql(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key1 (Null) (Void)) '('Key2 (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key1 (Null) (Void)) '('Key2 (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
@@ -4012,7 +4043,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
auto res = annoyingClient.FlatQuery(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
@@ -4080,7 +4111,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) {
auto res = annoyingClient.FlatQuery(Sprintf(R"(
(
- (let range '('ExcFrom 'ExcTo '('Key (Null) (Void))))
+ (let range '('ExcFrom 'IncTo '('Key (Null) (Void))))
(let data (SelectRange
'"/dc-1/test/TestTable"
range
diff --git a/ydb/core/client/locks_ut.cpp b/ydb/core/client/locks_ut.cpp
index a6e9a9bcb5..11b76611e3 100644
--- a/ydb/core/client/locks_ut.cpp
+++ b/ydb/core/client/locks_ut.cpp
@@ -245,7 +245,7 @@ struct TLocksTestOptions {
Range0Begin = "(Uint32 '0)";
Range0End = BreakPoint;
Range0OptKey = "";
- Range1Inc = "'ExcFrom 'ExcTo";
+ Range1Inc = "'ExcFrom 'IncTo";
Range1Begin = BreakPoint;
Range1End = "(Void)";
Range1OptKey = "";
@@ -264,7 +264,7 @@ struct TLocksTestOptions {
Range0Begin = "(Uint32 '0)";
Range0End = BreakPoint;
Range0OptKey = "'('keyX (Uint64 '0) (Void))";
- Range1Inc = "'ExcFrom 'ExcTo";
+ Range1Inc = "'ExcFrom 'IncTo";
Range1Begin = BreakPoint;
Range1End = "(Uint32 '4294967295)";
Range1OptKey = "'('keyX (Uint64 '0) (Void))";
@@ -283,7 +283,7 @@ struct TLocksTestOptions {
Range0Begin = "(String '\"0\")";
Range0End = BreakPoint;
Range0OptKey = "";
- Range1Inc = "'ExcFrom 'ExcTo";
+ Range1Inc = "'ExcFrom 'IncTo";
Range1Begin = BreakPoint;
Range1End = "(Void)";
Range1OptKey = "";
@@ -852,7 +852,7 @@ Y_UNIT_TEST(Range_BrokenLockMax) {
TLocksTestOptions opts;
opts.TestRange = true;
opts.BreakKey = "'('key (Uint32 '4294967295))";
- opts.Range1Inc = "'ExcFrom 'ExcTo";
+ opts.Range1Inc = "'ExcFrom 'IncTo";
opts.Break = true;
TestLock<TLocksV1>(opts);
TestLock<TLocksV2>(opts);
@@ -1021,7 +1021,7 @@ Y_UNIT_TEST(Range_EmptyKey) {
opts.SetOnly = true;
//opts.TestErase = true;
opts.TestRange = true;
- opts.Range0Inc = "'IncFrom 'ExcTo";
+ opts.Range0Inc = "'IncFrom 'IncTo";
opts.Range0Begin = "(String '\"\")";
opts.Range0End = "(Void)";
TestLock<TLocksV1>(opts);
diff --git a/ydb/core/client/minikql_compile/yql_expr_minikql_compile_ut.cpp b/ydb/core/client/minikql_compile/yql_expr_minikql_compile_ut.cpp
index 1a99dce069..df56ab1c27 100644
--- a/ydb/core/client/minikql_compile/yql_expr_minikql_compile_ut.cpp
+++ b/ydb/core/client/minikql_compile/yql_expr_minikql_compile_ut.cpp
@@ -203,7 +203,7 @@ Y_UNIT_TEST_SUITE(TTestYqlToMiniKQLCompile) {
Y_UNIT_TEST(SelectRange) {
auto programText = R"___(
(
-(let range '('IncFrom 'ExcTo '('key (Uint32 '23) (Void))))
+(let range '('IncFrom 'IncTo '('key (Uint32 '23) (Void))))
(let select '('value))
(let options '('('ItemsLimit (Uint64 '2)) '('BytesLimit (Uint64 '1000))))
(let pgmReturn (AsList
@@ -323,7 +323,7 @@ Y_UNIT_TEST_SUITE(TTestYqlToMiniKQLCompile) {
Y_UNIT_TEST(Extract) {
auto programText = R"___(
(
-(let range '('IncFrom 'ExcTo '('key (Uint32 '23) (Void))))
+(let range '('IncFrom 'IncTo '('key (Uint32 '23) (Void))))
(let select '('key 'value))
(let options '('('ItemsLimit (Uint64 '2))))
(let tupleList (AsList '((Uint32 '1) (Uint32 '2)) '((Uint32 '3) (Uint32 '4))))
diff --git a/ydb/core/engine/kikimr_program_builder_ut.cpp b/ydb/core/engine/kikimr_program_builder_ut.cpp
index 168e58422d..00c58c32b7 100644
--- a/ydb/core/engine/kikimr_program_builder_ut.cpp
+++ b/ydb/core/engine/kikimr_program_builder_ut.cpp
@@ -150,7 +150,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLProgramBuilderTest) {
UNIT_ASSERT(tableKeys[0]->TableId.HasSamePath(TTableId(1, 2)));
UNIT_ASSERT(tableKeys[0]->RowOperation == TKeyDesc::ERowOperation::Erase);
UNIT_ASSERT(tableKeys[0]->Range.InclusiveFrom);
- UNIT_ASSERT(!tableKeys[0]->Range.InclusiveTo);
+ UNIT_ASSERT(tableKeys[0]->Range.InclusiveTo);
UNIT_ASSERT(!tableKeys[0]->Range.Point);
UNIT_ASSERT(tableKeys[0]->Range.From.size() == 3);
UNIT_ASSERT(tableKeys[0]->Range.From[0].IsNull());
@@ -192,7 +192,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLProgramBuilderTest) {
UNIT_ASSERT(tableKeys[0]->TableId.HasSamePath(TTableId(1, 2)));
UNIT_ASSERT(tableKeys[0]->RowOperation == TKeyDesc::ERowOperation::Erase);
UNIT_ASSERT(tableKeys[0]->Range.InclusiveFrom);
- UNIT_ASSERT(!tableKeys[0]->Range.InclusiveTo);
+ UNIT_ASSERT(tableKeys[0]->Range.InclusiveTo);
UNIT_ASSERT(!tableKeys[0]->Range.Point);
UNIT_ASSERT(tableKeys[0]->Range.From.size() == 2);
UNIT_ASSERT(tableKeys[0]->Range.From[0].IsNull());
@@ -349,7 +349,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLProgramBuilderTest) {
UNIT_ASSERT(tableKeys[0]->TableId.HasSamePath(TTableId(1, 2)));
UNIT_ASSERT(tableKeys[0]->RowOperation == TKeyDesc::ERowOperation::Update);
UNIT_ASSERT(tableKeys[0]->Range.InclusiveFrom);
- UNIT_ASSERT(!tableKeys[0]->Range.InclusiveTo);
+ UNIT_ASSERT(tableKeys[0]->Range.InclusiveTo);
UNIT_ASSERT(!tableKeys[0]->Range.Point);
UNIT_ASSERT(tableKeys[0]->Range.From.size() == 3);
UNIT_ASSERT(tableKeys[0]->Range.From[0].IsNull());
diff --git a/ydb/core/engine/minikql/minikql_engine_host.cpp b/ydb/core/engine/minikql/minikql_engine_host.cpp
index 6966fb700f..d362d93806 100644
--- a/ydb/core/engine/minikql/minikql_engine_host.cpp
+++ b/ydb/core/engine/minikql/minikql_engine_host.cpp
@@ -231,6 +231,10 @@ void TEngineHost::PinPages(const TVector<THolder<TKeyDesc>>& keys, ui64 pageFaul
ui64 localTid = LocalTableId(key.TableId);
Y_VERIFY(localTid, "table not exist");
const TScheme::TTableInfo* tableInfo = Scheme.GetTableInfo(localTid);
+
+ Y_VERIFY_DEBUG(!key.Range.IsAmbiguous(tableInfo->KeyColumns.size()),
+ "%s", key.Range.IsAmbiguousReason(tableInfo->KeyColumns.size()));
+
TSmallVec<TRawTypeValue> keyFrom;
TSmallVec<TRawTypeValue> keyTo;
ConvertKeys(tableInfo, key.Range.From, keyFrom);
@@ -654,6 +658,9 @@ public:
const TScheme::TTableInfo* tableInfo = Scheme.GetTableInfo(LocalTid);
auto tableRange = RangeHolder.ToTableRange();
+ Y_VERIFY_DEBUG(!tableRange.IsAmbiguous(tableInfo->KeyColumns.size()),
+ "%s", tableRange.IsAmbiguousReason(tableInfo->KeyColumns.size()));
+
TSmallVec<TRawTypeValue> keyFrom;
TSmallVec<TRawTypeValue> keyTo;
ConvertTableKeys(Scheme, tableInfo, tableRange.From, keyFrom, nullptr);
diff --git a/ydb/core/engine/mkql_engine_flat_ut.cpp b/ydb/core/engine/mkql_engine_flat_ut.cpp
index e355bf3d8b..84fcf280cb 100644
--- a/ydb/core/engine/mkql_engine_flat_ut.cpp
+++ b/ydb/core/engine/mkql_engine_flat_ut.cpp
@@ -1059,7 +1059,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1130,7 +1130,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewNull();
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1220,7 +1220,7 @@ Value {
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1337,7 +1337,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(1);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1448,7 +1448,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewNull();
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(1);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1563,7 +1563,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.BytesLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(32);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1685,7 +1685,7 @@ Value {
rowFrom[0] = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(43);
auto options = pgmBuilder.GetDefaultTableRangeOptions();
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.FromColumns = rowFrom;
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -1809,7 +1809,7 @@ Value {
auto options = pgmBuilder.GetDefaultTableRangeOptions();
options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(
TReadRangeOptions::TFlags::ExcludeInitValue |
- TReadRangeOptions::TFlags::ExcludeTermValue);
+ TReadRangeOptions::TFlags::IncludeTermValue);
options.FromColumns = rowFrom;
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -3277,7 +3277,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -3475,7 +3475,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -3601,7 +3601,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(1);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -3731,7 +3731,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
const ui64 RowOverheadBytes = 8;
options.BytesLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(4 + RowOverheadBytes);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
@@ -3865,7 +3865,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.Reverse = pgmBuilder.TProgramBuilder::NewDataLiteral<bool>(true);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto pgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("myRes", value)));
@@ -4012,7 +4012,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(1);
options.Reverse = pgmBuilder.TProgramBuilder::NewDataLiteral<bool>(true);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
@@ -4139,7 +4139,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(2);
options.Reverse = pgmBuilder.TProgramBuilder::NewDataLiteral<bool>(true);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
@@ -4273,7 +4273,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
options.ItemsLimit = pgmBuilder.TProgramBuilder::NewDataLiteral<ui64>(3);
options.Reverse = pgmBuilder.TProgramBuilder::NewDataLiteral<bool>(true);
auto value = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
@@ -4778,7 +4778,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
TVector<TStringBuf> filterNullColumns {"Value"};
@@ -4856,7 +4856,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
auto mapped = pgmBuilder.Map(list, [&pgmBuilder](TRuntimeNode item) {
@@ -4926,7 +4926,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
auto mapped = pgmBuilder.Map(list, [&pgmBuilder, keyTypes, columns](TRuntimeNode item) {
@@ -4990,7 +4990,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
auto filtered = pgmBuilder.OrderedFilter(list, [&pgmBuilder, &okValue](TRuntimeNode item) {
@@ -5078,7 +5078,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
auto mapped = pgmBuilder.Map(list, [&pgmBuilder](TRuntimeNode item) {
@@ -5123,7 +5123,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table2Id), keyTypes, columns, options);
auto checkpgm = pgmBuilder.Build(pgmBuilder.AsList(pgmBuilder.SetResult("Result", range)));
@@ -5186,7 +5186,7 @@ Value {
TRuntimeNode::TList rowFrom1(1);
rowFrom1[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options1.FromColumns = rowFrom1;
- options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range1 = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes1, columns1, options1);
auto list1 = pgmBuilder.Member(range1, "List");
@@ -5201,7 +5201,7 @@ Value {
TRuntimeNode::TList rowFrom2(1);
rowFrom2[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id);
options2.FromColumns = rowFrom2;
- options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range2 = pgmBuilder.SelectRange(TTableId(OwnerId, Table2Id), keyTypes2, columns2, options2);
auto list2 = pgmBuilder.Member(range2, "List");
@@ -5280,7 +5280,7 @@ Value {
TRuntimeNode::TList rowFrom1(1);
rowFrom1[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options1.FromColumns = rowFrom1;
- options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range1 = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes1, columns1, options1);
auto list1 = pgmBuilder.Member(range1, "List");
@@ -5295,7 +5295,7 @@ Value {
TRuntimeNode::TList rowFrom2(1);
rowFrom2[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id);
options2.FromColumns = rowFrom2;
- options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range2 = pgmBuilder.SelectRange(TTableId(OwnerId, Table2Id), keyTypes2, columns2, options2);
auto list2 = pgmBuilder.Member(range2, "List");
@@ -5388,7 +5388,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5504,7 +5504,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5615,7 +5615,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5699,7 +5699,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5777,7 +5777,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5858,7 +5858,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -5947,7 +5947,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -6034,7 +6034,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -6125,7 +6125,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -6220,7 +6220,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, columns, options);
auto list = pgmBuilder.Member(range, "List");
@@ -6289,7 +6289,7 @@ Value {
TRuntimeNode::TList rowFrom(1);
rowFrom[0] = pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id);
options.FromColumns = rowFrom;
- options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), keyTypes, {}, options);
auto list = pgmBuilder.Member(range, "List");
auto length = pgmBuilder.Length(list);
@@ -6367,7 +6367,7 @@ Value {
TRuntimeNode::TList fromColumns1{pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id)};
auto options1 = pgmBuilder.GetDefaultTableRangeOptions();
options1.FromColumns = fromColumns1;
- options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options1.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range1 = pgmBuilder.SelectRange(TTableId(OwnerId, Table1Id), {(ui32)NUdf::TDataType<ui32>::Id},
columns1, options1);
auto list1 = pgmBuilder.Member(range1, "List");
@@ -6390,7 +6390,7 @@ Value {
TRuntimeNode::TList fromColumns2{pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id)};
auto options2 = pgmBuilder.GetDefaultTableRangeOptions();
options2.FromColumns = fromColumns2;
- options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::ExcludeTermValue);
+ options2.Flags = pgmBuilder.TProgramBuilder::NewDataLiteral<ui32>(TReadRangeOptions::TFlags::IncludeTermValue);
auto range2 = pgmBuilder.SelectRange(TTableId(OwnerId, Table2Id), {(ui32)NUdf::TDataType<ui64>::Id},
columns2, options2);
auto list2 = pgmBuilder.Member(range2, "List");
diff --git a/ydb/core/engine/mkql_keys.cpp b/ydb/core/engine/mkql_keys.cpp
index 91d5f35a9a..720e00325e 100644
--- a/ydb/core/engine/mkql_keys.cpp
+++ b/ydb/core/engine/mkql_keys.cpp
@@ -70,7 +70,6 @@ THolder<TKeyDesc> ExtractKeyTuple(const TTableId& tableId, TTupleLiteral* tuple,
if (!hasImmediateData) {
MKQL_ENSURE(!requireStaticKey, "Expected static key components");
point = false;
- inclusiveTo = false;
continue;
}
diff --git a/ydb/core/scheme/scheme_tabledefs.cpp b/ydb/core/scheme/scheme_tabledefs.cpp
index 3ea0f6dd81..672957e1fc 100644
--- a/ydb/core/scheme/scheme_tabledefs.cpp
+++ b/ydb/core/scheme/scheme_tabledefs.cpp
@@ -32,6 +32,48 @@ bool TTableRange::IsFullRange(ui32 columnsCount) const {
return true;
}
+namespace {
+ // There are many places that use a non-inclusive -inf/+inf
+ // We special case empty keys anyway, so the requirement is temporarily relaxed
+ static constexpr bool RelaxEmptyKeys = true;
+}
+
+const char* TTableRange::IsAmbiguousReason(size_t keyColumnsCount) const noexcept {
+ if (Point) {
+ if (Y_UNLIKELY(From.size() != keyColumnsCount)) {
+ return "Ambiguous table point: does not match key columns count";
+ }
+
+ return nullptr;
+ }
+
+ if (!From) {
+ if (Y_UNLIKELY(!InclusiveFrom) && !RelaxEmptyKeys) {
+ return "Ambiguous table range: empty From must be inclusive";
+ }
+ } else if (From.size() < keyColumnsCount) {
+ if (Y_UNLIKELY(InclusiveFrom)) {
+ return "Ambiguous table range: incomplete From must be non-inclusive (any/+inf is ambiguous otherwise)";
+ }
+ } else if (Y_UNLIKELY(From.size() > keyColumnsCount)) {
+ return "Ambiguous table range: From is too large";
+ }
+
+ if (!To) {
+ if (Y_UNLIKELY(!InclusiveTo && !RelaxEmptyKeys)) {
+ return "Ambiguous table range: empty To must be inclusive";
+ }
+ } else if (To.size() < keyColumnsCount) {
+ if (Y_UNLIKELY(!InclusiveTo)) {
+ return "Ambiguous table range: incomplete To must be inclusive (any/+inf is ambiguous otherwise)";
+ }
+ } else if (Y_UNLIKELY(To.size() > keyColumnsCount)) {
+ return "Ambiguous table range: To is too large";
+ }
+
+ return nullptr;
+}
+
bool TSerializedTableRange::IsEmpty(TConstArrayRef<NScheme::TTypeId> type) const
{
auto cmp = CompareBorders<true, false>(To.GetCells(), From.GetCells(), ToInclusive, FromInclusive, type);
diff --git a/ydb/core/scheme/scheme_tabledefs.h b/ydb/core/scheme/scheme_tabledefs.h
index ccf0b73f29..d7206c301f 100644
--- a/ydb/core/scheme/scheme_tabledefs.h
+++ b/ydb/core/scheme/scheme_tabledefs.h
@@ -181,6 +181,12 @@ public:
bool IsEmptyRange(TConstArrayRef<const NScheme::TTypeId> cellTypeIds) const;
bool IsFullRange(ui32 columnsCount) const;
+
+ bool IsAmbiguous(size_t keyColumnsCount) const noexcept {
+ return IsAmbiguousReason(keyColumnsCount) != nullptr;
+ }
+
+ const char* IsAmbiguousReason(size_t keyColumnsCount) const noexcept;
};
class TSerializedTableRange {
diff --git a/ydb/core/tablet_flat/flat_database.cpp b/ydb/core/tablet_flat/flat_database.cpp
index 9a1db399d0..6d705ab3de 100644
--- a/ydb/core/tablet_flat/flat_database.cpp
+++ b/ydb/core/tablet_flat/flat_database.cpp
@@ -88,6 +88,44 @@ TAutoPtr<TTableIt> TDatabase::IterateExact(ui32 table, TRawVals key, TTagsRef ta
return iter;
}
+namespace {
+ // There are many places that use a non-inclusive -inf/+inf
+ // We special case empty keys anyway, so the requirement is temporarily relaxed
+ static constexpr bool RelaxEmptyKeys = true;
+
+ const char* IsAmbiguousRangeReason(const TKeyRange& range, ui32 keyColumnsCount) {
+ if (!range.MinKey) {
+ if (Y_UNLIKELY(!range.MinInclusive) && !RelaxEmptyKeys) {
+ return "Ambiguous table range: empty MinKey must be inclusive";
+ }
+ } else if (range.MinKey.size() < keyColumnsCount) {
+ if (Y_UNLIKELY(range.MinInclusive)) {
+ return "Ambiguous table range: incomplete MinKey must be non-inclusive (any/+inf is ambiguous otherwise)";
+ }
+ } else if (Y_UNLIKELY(range.MinKey.size() > keyColumnsCount)) {
+ return "Ambiguous table range: MinKey is too large";
+ }
+
+ if (!range.MaxKey) {
+ if (Y_UNLIKELY(!range.MaxInclusive) && !RelaxEmptyKeys) {
+ return "Ambiguous table range: empty MaxKey must be inclusive";
+ }
+ } else if (range.MaxKey.size() < keyColumnsCount) {
+ if (Y_UNLIKELY(!range.MaxInclusive)) {
+ return "Ambiguous table range: incomplete MaxKey must be inclusive (any/+inf is ambiguous otherwise)";
+ }
+ } else if (Y_UNLIKELY(range.MaxKey.size() > keyColumnsCount)) {
+ return "Ambiguous table range: MaxKey is too large";
+ }
+
+ return nullptr;
+ }
+
+ bool IsAmbiguousRange(const TKeyRange& range, ui32 keyColumnsCount) {
+ return IsAmbiguousRangeReason(range, keyColumnsCount) != nullptr;
+ }
+}
+
TAutoPtr<TTableIt> TDatabase::IterateRange(ui32 table, const TKeyRange& range, TTagsRef tags,
TRowVersion snapshot,
const ITransactionMapPtr& visible,
@@ -95,6 +133,9 @@ TAutoPtr<TTableIt> TDatabase::IterateRange(ui32 table, const TKeyRange& range, T
{
Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
+ Y_VERIFY_DEBUG(!IsAmbiguousRange(range, Require(table)->GetScheme()->Keys->Size()),
+ "%s", IsAmbiguousRangeReason(range, Require(table)->GetScheme()->Keys->Size()));
+
IteratedTables.insert(table);
ESeek seek = !range.MinKey || range.MinInclusive ? ESeek::Lower : ESeek::Upper;
@@ -121,6 +162,9 @@ TAutoPtr<TTableReverseIt> TDatabase::IterateRangeReverse(ui32 table, const TKeyR
{
Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
+ Y_VERIFY_DEBUG(!IsAmbiguousRange(range, Require(table)->GetScheme()->Keys->Size()),
+ "%s", IsAmbiguousRangeReason(range, Require(table)->GetScheme()->Keys->Size()));
+
IteratedTables.insert(table);
ESeek seek = !range.MaxKey || range.MaxInclusive ? ESeek::Lower : ESeek::Upper;
diff --git a/ydb/core/tx/datashard/datashard__read_iterator.cpp b/ydb/core/tx/datashard/datashard__read_iterator.cpp
index 3145f6f50e..97f7107c56 100644
--- a/ydb/core/tx/datashard/datashard__read_iterator.cpp
+++ b/ydb/core/tx/datashard/datashard__read_iterator.cpp
@@ -931,42 +931,6 @@ public:
}
}
- // TODO: remove later, when we sure that key prefix is properly
- // interpreted same way everywhere: i.e. treated as 0 at the left and
- // inf on the right.
- // We really do weird transformations here, not sure if we can do better though
- for (size_t i = 0; i < Request->Ranges.size(); ++i) {
- auto& range = Request->Ranges[i];
- auto& keyFrom = range.From;
- auto& keyTo = Request->Ranges[i].To;
-
- if (range.FromInclusive && keyFrom.GetCells().size() != TableInfo.KeyColumnCount) {
- keyFrom = ExtendWithNulls(keyFrom, TableInfo.KeyColumnCount);
- }
-
- if (!range.ToInclusive && keyTo.GetCells().size() != TableInfo.KeyColumnCount) {
- keyTo = ExtendWithNulls(keyTo, TableInfo.KeyColumnCount);
- }
- }
-
- // TODO: remove later, when we sure that key prefix is properly
- // interpreted same way everywhere: i.e. treated as 0 at the left and
- // inf on the right.
- // We really do weird transformations here, not sure if we can do better though
- for (size_t i = 0; i < Request->Keys.size(); ++i) {
- const auto& key = Request->Keys[i];
- if (key.GetCells().size() == TableInfo.KeyColumnCount)
- continue;
-
- if (state.Keys.size() != Request->Keys.size()) {
- state.Keys.resize(Request->Keys.size());
- }
-
- // we can safely use cells referencing original Request->Keys[x],
- // because request will live until the end
- state.Keys[i] = ExtendWithNulls(key, TableInfo.KeyColumnCount);
- }
-
userTableInfo->Stats.AccessTime = TAppData::TimeProvider->Now();
} else {
// DS is owner, read system table
@@ -984,6 +948,36 @@ public:
TableInfo = TShortTableInfo(state.PathId.LocalPathId, *schema);
}
+ // Make ranges in the new 'any' form compatible with the old '+inf' form
+ for (size_t i = 0; i < Request->Ranges.size(); ++i) {
+ auto& range = Request->Ranges[i];
+ auto& keyFrom = range.From;
+ auto& keyTo = Request->Ranges[i].To;
+
+ if (range.FromInclusive && keyFrom.GetCells().size() != TableInfo.KeyColumnCount) {
+ keyFrom = ExtendWithNulls(keyFrom, TableInfo.KeyColumnCount);
+ }
+
+ if (!range.ToInclusive && keyTo.GetCells().size() != TableInfo.KeyColumnCount) {
+ keyTo = ExtendWithNulls(keyTo, TableInfo.KeyColumnCount);
+ }
+ }
+
+ // Make prefixes in the new 'any' form compatible with the old '+inf' form
+ for (size_t i = 0; i < Request->Keys.size(); ++i) {
+ const auto& key = Request->Keys[i];
+ if (key.GetCells().size() == TableInfo.KeyColumnCount)
+ continue;
+
+ if (state.Keys.size() != Request->Keys.size()) {
+ state.Keys.resize(Request->Keys.size());
+ }
+
+ // we can safely use cells referencing original Request->Keys[x],
+ // because request will live until the end
+ state.Keys[i] = ExtendWithNulls(key, TableInfo.KeyColumnCount);
+ }
+
state.Columns.reserve(record.ColumnsSize());
for (auto col: record.GetColumns()) {
auto it = TableInfo.Columns.find(col);
@@ -1004,7 +998,12 @@ public:
Y_ASSERT(Result);
- PrepareValidationInfo(ctx, state);
+ if (state.PathId.OwnerId != Self->TabletID()) {
+ PrepareValidationInfo(ctx, state);
+ } else {
+ // There should be no keys when reading sysm tables
+ ValidationInfo.Loaded = true;
+ }
}
void SendResult(const TActorContext& ctx) override {
diff --git a/ydb/core/tx/datashard/datashard__s3.cpp b/ydb/core/tx/datashard/datashard__s3.cpp
index 2f7a74bbab..f5dfe0d65e 100644
--- a/ydb/core/tx/datashard/datashard__s3.cpp
+++ b/ydb/core/tx/datashard/datashard__s3.cpp
@@ -62,6 +62,7 @@ public:
TVector<TRawTypeValue> key;
TVector<TRawTypeValue> endKey;
+ bool endKeyInclusive = true;
// TODO: check prefix column count against key column count
const TSerializedCellVec prefixColumns(Ev->Get()->Record.GetSerializedKeyPrefix());
@@ -113,6 +114,10 @@ public:
const TString pathEndPrefix = NextPrefix(pathPrefix);
if (pathEndPrefix) {
endKey.emplace_back(pathEndPrefix.data(), pathEndPrefix.size(), NScheme::NTypeIds::Utf8);
+ while (endKey.size() < tableInfo.KeyColumnTypes.size()) {
+ endKey.emplace_back();
+ }
+ endKeyInclusive = false;
}
LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, Self->TabletID() << " S3 Listing: start at key ("
@@ -135,7 +140,7 @@ public:
keyRange.MinKey = key;
keyRange.MinInclusive = suffixColumns.GetCells().empty();
keyRange.MaxKey = endKey;
- keyRange.MaxInclusive = false;
+ keyRange.MaxInclusive = endKeyInclusive;
if (LastPath) {
// Don't include the last key in case of restart
diff --git a/ydb/core/tx/datashard/datashard_dep_tracker.cpp b/ydb/core/tx/datashard/datashard_dep_tracker.cpp
index 9e46cb3604..1a35cb5092 100644
--- a/ydb/core/tx/datashard/datashard_dep_tracker.cpp
+++ b/ydb/core/tx/datashard/datashard_dep_tracker.cpp
@@ -3,6 +3,8 @@
#include "const.h"
+#include <util/string/escape.h>
+
namespace NKikimr {
namespace NDataShard {
@@ -181,6 +183,14 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp
const auto& k = *vk.Key;
if (Parent.Self->IsUserTable(k.TableId)) {
const ui64 tableId = k.TableId.PathId.LocalPathId;
+ Y_VERIFY_DEBUG_S(!k.Range.IsAmbiguous(Parent.Self->GetUserTables().at(tableId)->KeyColumnTypes.size()),
+ (vk.IsWrite ? "Write" : "Read")
+ << " From# \"" << EscapeC(TSerializedCellVec::Serialize(k.Range.From)) << "\""
+ << " To# \"" << EscapeC(TSerializedCellVec::Serialize(k.Range.To)) << "\""
+ << " InclusiveFrom# " << (k.Range.InclusiveFrom ? "true" : "false")
+ << " InclusiveTo# " << (k.Range.InclusiveTo ? "true" : "false")
+ << " Point# " << (k.Range.Point ? "true" : "false")
+ << ": " << k.Range.IsAmbiguousReason(Parent.Self->GetUserTables().at(tableId)->KeyColumnTypes.size()));
if (!tooManyKeys && ++keysCount > MAX_REORDER_TX_KEYS) {
tooManyKeys = true;
}
@@ -617,6 +627,14 @@ void TDependencyTracker::TMvccDependencyTrackingLogic::AddOperation(const TOpera
const auto& k = *vk.Key;
if (Parent.Self->IsUserTable(k.TableId)) {
const ui64 tableId = k.TableId.PathId.LocalPathId;
+ Y_VERIFY_DEBUG_S(!k.Range.IsAmbiguous(Parent.Self->GetUserTables().at(tableId)->KeyColumnTypes.size()),
+ (vk.IsWrite ? "Write" : "Read")
+ << " From# \"" << EscapeC(TSerializedCellVec::Serialize(k.Range.From)) << "\""
+ << " To# \"" << EscapeC(TSerializedCellVec::Serialize(k.Range.To)) << "\""
+ << " InclusiveFrom# " << (k.Range.InclusiveFrom ? "true" : "false")
+ << " InclusiveTo# " << (k.Range.InclusiveTo ? "true" : "false")
+ << " Point# " << (k.Range.Point ? "true" : "false")
+ << ": " << k.Range.IsAmbiguousReason(Parent.Self->GetUserTables().at(tableId)->KeyColumnTypes.size()));
if (!tooManyKeys && ++keysCount > MAX_REORDER_TX_KEYS) {
tooManyKeys = true;
}
diff --git a/ydb/core/tx/datashard/datashard_ut_minikql.cpp b/ydb/core/tx/datashard/datashard_ut_minikql.cpp
index 7974e47486..b788107f87 100644
--- a/ydb/core/tx/datashard/datashard_ut_minikql.cpp
+++ b/ydb/core/tx/datashard/datashard_ut_minikql.cpp
@@ -537,7 +537,7 @@ Y_UNIT_TEST(SelectRangeWithNotFullKey) {
{
auto programText = R"___((
(let r1 '('key1 (Uint32 '345) (Uint32 '347)))
- (let r2 '('key2 (Void) (Void)))
+ (let r2 '('key2 (Nothing (OptionalType (DataType 'Utf8))) (Nothing (OptionalType (DataType 'Utf8)))))
(let range '('IncFrom 'ExcTo r1 r2))
(let select '('key1 'key2 'value))
(let options '())
@@ -557,18 +557,18 @@ Y_UNIT_TEST(SelectRangeWithNotFullKey) {
UNIT_ASSERT_EQUAL(rsl.Size(), 2);
TValue row1 = rsl[0];
TValue row2 = rsl[1];
- UNIT_ASSERT_EQUAL(ui32(row1["key1"]), 346);
- UNIT_ASSERT_EQUAL(ui32(row2["key1"]), 347);
- UNIT_ASSERT_EQUAL(TString(row1["key2"]), "id345");
- UNIT_ASSERT_EQUAL(TString(row2["key2"]), "idXYZ");
- UNIT_ASSERT_EQUAL(TString(row1["value"]), "Tables");
- UNIT_ASSERT_EQUAL(TString(row2["value"]), "Paulson");
+ UNIT_ASSERT_EQUAL(ui32(row1["key1"]), 345);
+ UNIT_ASSERT_EQUAL(ui32(row2["key1"]), 346);
+ UNIT_ASSERT_EQUAL(TString(row1["key2"]), "id123");
+ UNIT_ASSERT_EQUAL(TString(row2["key2"]), "id345");
+ UNIT_ASSERT_EQUAL(TString(row1["value"]), "Robert");
+ UNIT_ASSERT_EQUAL(TString(row2["value"]), "Tables");
}
{
auto programText = R"___((
(let r1 '('key1 (Uint32 '345) (Uint32 '347)))
- (let r2 '('key2 (Void) (Void)))
+ (let r2 '('key2 (Void) (Nothing (OptionalType (DataType 'Utf8)))))
(let range '('ExcFrom 'ExcTo r1 r2))
(let select '('key1 'key2 'value))
(let options '())
@@ -585,21 +585,17 @@ Y_UNIT_TEST(SelectRangeWithNotFullKey) {
TValue rs0 = value["myRes"];
UNIT_ASSERT_EQUAL(bool(rs0["Truncated"]), false);
TValue rsl = rs0["List"];
- UNIT_ASSERT_EQUAL(rsl.Size(), 2);
+ UNIT_ASSERT_EQUAL(rsl.Size(), 1);
TValue row1 = rsl[0];
- TValue row2 = rsl[1];
UNIT_ASSERT_EQUAL(ui32(row1["key1"]), 346);
- UNIT_ASSERT_EQUAL(ui32(row2["key1"]), 347);
UNIT_ASSERT_EQUAL(TString(row1["key2"]), "id345");
- UNIT_ASSERT_EQUAL(TString(row2["key2"]), "idXYZ");
UNIT_ASSERT_EQUAL(TString(row1["value"]), "Tables");
- UNIT_ASSERT_EQUAL(TString(row2["value"]), "Paulson");
}
{
auto programText = R"___((
(let r1 '('key1 (Uint32 '345) (Uint32 '347)))
- (let r2 '('key2 (Void) (Void)))
+ (let r2 '('key2 (Nothing (OptionalType (DataType 'Utf8))) (Void)))
(let range '('IncFrom 'IncTo r1 r2))
(let select '('key1 'key2 'value))
(let options '())
@@ -616,22 +612,26 @@ Y_UNIT_TEST(SelectRangeWithNotFullKey) {
auto rs0 = value["myRes"];
UNIT_ASSERT_EQUAL(bool(rs0["Truncated"]), false);
auto rsl = rs0["List"];
- UNIT_ASSERT_EQUAL(rsl.Size(), 2);
+ UNIT_ASSERT_EQUAL(rsl.Size(), 3);
auto row1 = rsl[0];
auto row2 = rsl[1];
- UNIT_ASSERT_EQUAL(ui32(row1["key1"]), 346);
- UNIT_ASSERT_EQUAL(ui32(row2["key1"]), 347);
- UNIT_ASSERT_EQUAL(TString(row1["key2"]), "id345");
- UNIT_ASSERT_EQUAL(TString(row2["key2"]), "idXYZ");
- UNIT_ASSERT_EQUAL(TString(row1["value"]), "Tables");
- UNIT_ASSERT_EQUAL(TString(row2["value"]), "Paulson");
+ auto row3 = rsl[2];
+ UNIT_ASSERT_EQUAL(ui32(row1["key1"]), 345);
+ UNIT_ASSERT_EQUAL(ui32(row2["key1"]), 346);
+ UNIT_ASSERT_EQUAL(ui32(row3["key1"]), 347);
+ UNIT_ASSERT_EQUAL(TString(row1["key2"]), "id123");
+ UNIT_ASSERT_EQUAL(TString(row2["key2"]), "id345");
+ UNIT_ASSERT_EQUAL(TString(row3["key2"]), "idXYZ");
+ UNIT_ASSERT_EQUAL(TString(row1["value"]), "Robert");
+ UNIT_ASSERT_EQUAL(TString(row2["value"]), "Tables");
+ UNIT_ASSERT_EQUAL(TString(row3["value"]), "Paulson");
}
// (345,inf).. (347,inf)
{
auto programText = R"___((
(let r1 '('key1 (Uint32 '345) (Uint32 '347)))
- (let range '('IncFrom 'ExcTo r1))
+ (let range '('ExcFrom 'IncTo r1))
(let select '('key1 'key2 'value))
(let options '())
(let pgmReturn (AsList
diff --git a/ydb/core/tx/datashard/datashard_ut_order.cpp b/ydb/core/tx/datashard/datashard_ut_order.cpp
index b64b30c167..4b21b7a23a 100644
--- a/ydb/core/tx/datashard/datashard_ut_order.cpp
+++ b/ydb/core/tx/datashard/datashard_ut_order.cpp
@@ -1193,6 +1193,9 @@ Y_UNIT_TEST_WITH_MVCC(ScanFollowedByUpdate) {
auto &tx = *dataTransaction.MutableReadTableTransaction();
tx.MutableTableId()->SetOwnerId(FAKE_SCHEMESHARD_TABLET_ID);
tx.MutableTableId()->SetTableId(13);
+ auto &range = *tx.MutableRange();
+ range.SetFromInclusive(true);
+ range.SetToInclusive(true);
auto &c = *tx.AddColumns();
c.SetId(56);
c.SetName("value");
diff --git a/ydb/core/tx/datashard/datashard_ut_rs.cpp b/ydb/core/tx/datashard/datashard_ut_rs.cpp
index 06c5e83b37..6442648fdc 100644
--- a/ydb/core/tx/datashard/datashard_ut_rs.cpp
+++ b/ydb/core/tx/datashard/datashard_ut_rs.cpp
@@ -17,7 +17,7 @@ ui64 GetRSCount(TTestActorRuntime &runtime, TActorId sender, ui64 shard)
{
auto request = MakeHolder<TEvTablet::TEvLocalMKQL>();
TString miniKQL = R"___((
- (let range '('IncFrom '('TxId (Uint64 '0) (Void))))
+ (let range '('ExcFrom '('TxId (Uint64 '0) (Void))))
(let select '('TxId))
(let options '())
(let pgmReturn (AsList
@@ -158,7 +158,7 @@ Y_UNIT_TEST_SUITE(TDataShardRSTest) {
{
auto request = MakeHolder<TEvTablet::TEvLocalMKQL>();
TString miniKQL = R"___((
- (let range '('IncFrom '('TxId (Uint64 '0) (Void))))
+ (let range '('ExcFrom '('TxId (Uint64 '0) (Void))))
(let select '('TxId))
(let options '())
(let pgmReturn (AsList
diff --git a/ydb/core/tx/schemeshard/ut_restore.cpp b/ydb/core/tx/schemeshard/ut_restore.cpp
index 42272ebe11..422f4cb6a8 100644
--- a/ydb/core/tx/schemeshard/ut_restore.cpp
+++ b/ydb/core/tx/schemeshard/ut_restore.cpp
@@ -269,19 +269,20 @@ namespace {
NKikimrMiniKQL::TResult ReadTable(TTestActorRuntime& runtime, ui64 tabletId,
const TString& table = "Table",
const TReadKeyDesc& keyDesc = {"key", "Utf8", "\"\""},
- const TVector<TString>& columns = {"key", "value"}) {
+ const TVector<TString>& columns = {"key", "value"},
+ const TString& rangeFlags = "") {
const auto rangeFmt = Sprintf("'%s (%s '%s)", keyDesc.Name.data(), keyDesc.Type.data(), keyDesc.Atom.data());
const auto columnsFmt = "'" + JoinSeq(" '", columns);
return ReadTableImpl(runtime, tabletId, Sprintf(R"(
(
- (let range '( '(%s (Void) )))
+ (let range '(%s '(%s (Void) )))
(let columns '(%s) )
(let result (SelectRange '__user__%s range columns '()))
(return (AsList (SetResult 'Result result) ))
)
- )", rangeFmt.data(), columnsFmt.data(), table.data()));
+ )", rangeFlags.c_str(), rangeFmt.data(), columnsFmt.data(), table.data()));
}
using TDelayFunc = std::function<bool(TAutoPtr<IEventHandle>&)>;
@@ -1592,7 +1593,7 @@ Y_UNIT_TEST_SUITE(TImportTests) {
for (ui32 i = 0; i < indexes; ++i) {
auto content = ReadTable(runtime, TTestTxConfig::FakeHiveTablets + 1 + i,
- "indexImplTable", {"value", "Utf8", "\"\""}, {"value", "key"});
+ "indexImplTable", {"value", "Utf8", "\"\""}, {"value", "key"}, "'ExcFrom");
NKqp::CompareYson(data.Data[0].YsonStr, content);
}
}
diff --git a/ydb/core/tx/tx_proxy/datareq.cpp b/ydb/core/tx/tx_proxy/datareq.cpp
index c933a19412..cd37e9c42a 100644
--- a/ydb/core/tx/tx_proxy/datareq.cpp
+++ b/ydb/core/tx/tx_proxy/datareq.cpp
@@ -1166,6 +1166,14 @@ void TDataReq::ProcessReadTableResolve(NSchemeCache::TSchemeCacheRequest *cacheR
auto &range = *tx.MutableRange();
ReadTableRequest->KeySpace.GetSpace().Serialize(range);
+ // Normalize range's From/ToInclusive
+ if (range.GetFrom().empty() && !range.GetFromInclusive()) {
+ range.SetFromInclusive(true);
+ }
+ if (range.GetTo().empty() && !range.GetToInclusive()) {
+ range.SetToInclusive(true);
+ }
+
if (!ReadTableRequest->Snapshot.IsMax()) {
tx.SetSnapshotStep(ReadTableRequest->Snapshot.Step);
tx.SetSnapshotTxId(ReadTableRequest->Snapshot.TxId);
@@ -1561,6 +1569,13 @@ void TDataReq::Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr &ev,
return Die(ctx);
}
+ if (!ReadTableRequest->FromValues.GetCells() && !ReadTableRequest->Range.HasFromInclusive()) {
+ fromInclusive = true; // default to inclusive -inf
+ }
+ if (!ReadTableRequest->ToValues.GetCells() && !ReadTableRequest->Range.HasToInclusive()) {
+ toInclusive = true; // default to inclusive +inf
+ }
+
TTableRange range(ReadTableRequest->FromValues.GetCells(),
fromInclusive,
ReadTableRequest->ToValues.GetCells(),
diff --git a/ydb/core/tx/tx_proxy/read_table_impl.cpp b/ydb/core/tx/tx_proxy/read_table_impl.cpp
index 3cb6dfb87d..f2d7539787 100644
--- a/ydb/core/tx/tx_proxy/read_table_impl.cpp
+++ b/ydb/core/tx/tx_proxy/read_table_impl.cpp
@@ -578,8 +578,8 @@ private:
return ReplyAndDie(TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::ResolveError, NKikimrIssues::TStatusIds::SCHEME_ERROR, ctx);
}
- const bool fromInclusive = Settings.KeyRange.GetFromInclusive();
- const bool toInclusive = Settings.KeyRange.GetToInclusive();
+ bool fromInclusive = Settings.KeyRange.GetFromInclusive();
+ bool toInclusive = Settings.KeyRange.GetToInclusive();
const EParseRangeKeyExp fromExpand = (
Settings.KeyRange.HasFrom()
? (fromInclusive ? EParseRangeKeyExp::TO_NULL : EParseRangeKeyExp::NONE)
@@ -601,6 +601,16 @@ private:
return ReplyAndDie(TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::ResolveError, NKikimrIssues::TStatusIds::QUERY_ERROR, ctx);
}
+ if (KeyFromValues.GetCells().size() < keyTypes.size() && !Settings.KeyRange.HasFromInclusive()) {
+ // Default: non-inclusive for incomplete From, except when From is empty
+ fromInclusive = KeyFromValues.GetCells().size() == 0;
+ }
+
+ if (KeyToValues.GetCells().size() < keyTypes.size() && !Settings.KeyRange.HasToInclusive()) {
+ // Default: inclusive for incomplete To
+ toInclusive = true;
+ }
+
TTableRange range(
KeyFromValues.GetCells(), fromInclusive,
KeyToValues.GetCells(), toInclusive);
@@ -1428,6 +1438,14 @@ private:
auto& txRange = *tx.MutableRange();
state.Ranges.front().Serialize(txRange);
+ // Normalize range's From/ToInclusive
+ if (txRange.GetFrom().empty() && !txRange.GetFromInclusive()) {
+ txRange.SetFromInclusive(true);
+ }
+ if (txRange.GetTo().empty() && !txRange.GetToInclusive()) {
+ txRange.SetToInclusive(true);
+ }
+
if (Settings.ReadVersion.IsMax()) {
// Use snapshot that we have created
tx.SetSnapshotStep(PlanStep);
diff --git a/ydb/public/lib/deprecated/kicli/cpp_ut.cpp b/ydb/public/lib/deprecated/kicli/cpp_ut.cpp
index cb7dc3ed6d..a4f5e480ba 100644
--- a/ydb/public/lib/deprecated/kicli/cpp_ut.cpp
+++ b/ydb/public/lib/deprecated/kicli/cpp_ut.cpp
@@ -1472,9 +1472,9 @@ Y_UNIT_TEST_SUITE(ClientLib) {
'('Rank rank)
'('UrlHash urlHash)))
(let column1 '('UrlHash))
- (let range '('IncFrom '('ShardId shardId (Void))
- '('HostTitleHash hostTitleHash (Void))
- '('GroupSimHash groupSimHash (Void))
+ (let range '('ExcFrom 'IncTo '('ShardId shardId (Void))
+ '('HostTitleHash hostTitleHash (Void))
+ '('GroupSimHash groupSimHash (Void))
))
(let column2 '('UrlHash))
(let options '('('ItemsLimit (Uint64 '1))))
@@ -1510,6 +1510,9 @@ Y_UNIT_TEST_SUITE(ClientLib) {
{
using namespace NClient;
+ Y_UNUSED(includeFrom);
+ Y_UNUSED(includeTo);
+
auto rawq = kikimr.Query(
Sprintf(R"___(
(
@@ -1524,8 +1527,8 @@ Y_UNIT_TEST_SUITE(ClientLib) {
(return pgmReturn)
)
)___",
- includeFrom ? "IncFrom" : "ExcFrom",
- includeTo ? "IncTo" : "ExcTo"
+ "ExcFrom" /* incomplete From is always non-inclusive */,
+ "IncTo" /* incomplete To is always inclusive */
));
auto q = rawq.SyncPrepare();
UNIT_ASSERT_VALUES_EQUAL_C(q.GetStatus(), NMsgBusProxy::MSTATUS_OK, q.GetError().GetMessage().c_str());