Skip to content

Commit c91ca45

Browse files
authored
[Stable-25-3-1] Fix upsert to table with unique index (#26508)
2 parents e54b471 + 61aa203 commit c91ca45

File tree

2 files changed

+117
-5
lines changed

2 files changed

+117
-5
lines changed

ydb/core/kqp/opt/physical/effects/kqp_opt_phy_upsert_index.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,7 @@ RewriteInputForConstraint(const TExprBase& inputRows, const THashSet<TStringBuf>
339339
hasUniqIndex |= (indexDesc->Type == TIndexDescription::EType::GlobalSyncUnique);
340340
for (const auto& indexKeyCol : indexDesc->KeyColumns) {
341341
if (inputColumns.contains(indexKeyCol)) {
342-
if (!usedIndexes.contains(indexDesc->Name) &&
343-
std::find(mainPk.begin(), mainPk.end(), indexKeyCol) == mainPk.end())
344-
{
345-
usedIndexes.insert(indexDesc->Name);
346-
}
342+
usedIndexes.insert(indexDesc->Name);
347343
} else {
348344
// input always contains key columns
349345
YQL_ENSURE(std::find(mainPk.begin(), mainPk.end(), indexKeyCol) == mainPk.end());
@@ -352,6 +348,8 @@ RewriteInputForConstraint(const TExprBase& inputRows, const THashSet<TStringBuf>
352348
}
353349
}
354350

351+
AFL_ENSURE(!hasUniqIndex || !usedIndexes.empty());
352+
355353
if (!hasUniqIndex) {
356354
missedKeyInput.clear();
357355
}

ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5972,6 +5972,120 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda
59725972
);
59735973
}
59745974
}
5975+
5976+
Y_UNIT_TEST_TWIN(IndexUpsert, Uniq) {
5977+
auto setting = NKikimrKqp::TKqpSetting();
5978+
auto serverSettings = TKikimrSettings().SetKqpSettings({setting});
5979+
TKikimrRunner kikimr(serverSettings);
5980+
5981+
auto client = kikimr.GetQueryClient();
5982+
5983+
{
5984+
const TString query(Q_(std::format(R"(
5985+
CREATE TABLE `/Root/TestTable` (
5986+
a Int32,
5987+
b Int32,
5988+
PRIMARY KEY(a,b),
5989+
INDEX ix_b GLOBAL {} SYNC ON (b)
5990+
);
5991+
)", Uniq ? "UNIQUE" : "")));
5992+
5993+
auto result = client.ExecuteQuery(
5994+
query,
5995+
NQuery::TTxControl::NoTx())
5996+
.ExtractValueSync();
5997+
UNIT_ASSERT(result.IsSuccess());
5998+
}
5999+
6000+
{
6001+
const TString query(Q_(R"(
6002+
$v=[<|a:10,b:20|>,<|a:30,b:20|>];
6003+
UPSERT INTO `/Root/TestTable` SELECT * FROM AS_TABLE($v);
6004+
)"));
6005+
6006+
auto result = client.ExecuteQuery(
6007+
query,
6008+
NQuery::TTxControl::NoTx())
6009+
.ExtractValueSync();
6010+
if (Uniq) {
6011+
UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString());
6012+
UNIT_ASSERT_STRING_CONTAINS_C(
6013+
result.GetIssues().ToString(),
6014+
"Duplicated keys found.",
6015+
result.GetIssues().ToString());
6016+
} else {
6017+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
6018+
}
6019+
}
6020+
6021+
{
6022+
const TString query(Q_(R"(
6023+
$v=[<|a:10,b:20|>,<|a:10,b:20|>];
6024+
UPSERT INTO `/Root/TestTable` SELECT * FROM AS_TABLE($v);
6025+
)"));
6026+
6027+
auto result = client.ExecuteQuery(
6028+
query,
6029+
NQuery::TTxControl::NoTx())
6030+
.ExtractValueSync();
6031+
if (Uniq) {
6032+
UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString());
6033+
UNIT_ASSERT_STRING_CONTAINS_C(
6034+
result.GetIssues().ToString(),
6035+
"Duplicated keys found.",
6036+
result.GetIssues().ToString());
6037+
} else {
6038+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
6039+
}
6040+
}
6041+
6042+
{
6043+
const TString query(Q_(R"(
6044+
$v=[<|a:10,b:10|>,<|a:30,b:30|>];
6045+
UPSERT INTO `/Root/TestTable` SELECT * FROM AS_TABLE($v);
6046+
)"));
6047+
6048+
auto result = client.ExecuteQuery(
6049+
query,
6050+
NQuery::TTxControl::NoTx())
6051+
.ExtractValueSync();
6052+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
6053+
}
6054+
6055+
{
6056+
const TString query(Q_(R"(
6057+
$v=[<|a:20,b:10|>,<|a:20,b:30|>];
6058+
UPSERT INTO `/Root/TestTable` SELECT * FROM AS_TABLE($v);
6059+
)"));
6060+
6061+
auto result = client.ExecuteQuery(
6062+
query,
6063+
NQuery::TTxControl::NoTx())
6064+
.ExtractValueSync();
6065+
if (Uniq) {
6066+
UNIT_ASSERT_C(!result.IsSuccess(), result.GetIssues().ToString());
6067+
UNIT_ASSERT_STRING_CONTAINS_C(
6068+
result.GetIssues().ToString(),
6069+
"Conflict with existing key.",
6070+
result.GetIssues().ToString());
6071+
} else {
6072+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
6073+
}
6074+
}
6075+
6076+
{
6077+
const TString query(Q_(R"(
6078+
$v=[<|a:20,b:40|>,<|a:20,b:50|>];
6079+
UPSERT INTO `/Root/TestTable` SELECT * FROM AS_TABLE($v);
6080+
)"));
6081+
6082+
auto result = client.ExecuteQuery(
6083+
query,
6084+
NQuery::TTxControl::NoTx())
6085+
.ExtractValueSync();
6086+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
6087+
}
6088+
}
59756089
}
59766090

59776091
}

0 commit comments

Comments
 (0)