Skip to content

Commit d771207

Browse files
authored
Merge 0afe770 into 5bf2c99
2 parents 5bf2c99 + 0afe770 commit d771207

File tree

5 files changed

+229
-9
lines changed

5 files changed

+229
-9
lines changed

ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ bool IsSuperUser(const NACLib::TUserToken* userToken) {
4141
}
4242

4343
TTableInfo::TAlterDataPtr ParseParams(const TPath& path, TTableInfo::TPtr table, const NKikimrSchemeOp::TTableDescription& alter,
44-
const bool shadowDataAllowed,
44+
const bool shadowDataAllowed, const THashSet<TString>& localSequences,
4545
TString& errStr, NKikimrScheme::EStatus& status, TOperationContext& context) {
4646
const TAppData* appData = AppData(context.Ctx);
4747

@@ -132,7 +132,11 @@ TTableInfo::TAlterDataPtr ParseParams(const TPath& path, TTableInfo::TPtr table,
132132

133133
const TSubDomainInfo& subDomain = *path.DomainInfo();
134134
const TSchemeLimits& limits = subDomain.GetSchemeLimits();
135-
TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(table, copyAlter, *appData->TypeRegistry, limits, subDomain, context.SS->EnableTablePgTypes, errStr);
135+
136+
137+
TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(
138+
table, copyAlter, *appData->TypeRegistry, limits, subDomain,
139+
context.SS->EnableTablePgTypes, errStr, localSequences);
136140
if (!alterData) {
137141
status = NKikimrScheme::StatusInvalidParameter;
138142
return nullptr;
@@ -517,6 +521,40 @@ class TAlterTable: public TSubOperation {
517521
}
518522
}
519523

524+
THashSet<TString> localSequences;
525+
526+
std::optional<TString> defaultFromSequence;
527+
for (const auto& column: alter.GetColumns()) {
528+
if (column.HasDefaultFromSequence()) {
529+
defaultFromSequence = column.GetDefaultFromSequence();
530+
}
531+
}
532+
533+
if (defaultFromSequence.has_value()) {
534+
Y_ABORT_UNLESS(alter.GetColumns().size() == 1);
535+
536+
const auto sequencePath = TPath::Resolve(*defaultFromSequence, context.SS);
537+
{
538+
const auto checks = sequencePath.Check();
539+
checks
540+
.NotEmpty()
541+
.NotUnderDomainUpgrade()
542+
.IsAtLocalSchemeShard()
543+
.IsResolved()
544+
.NotDeleted()
545+
.IsSequence()
546+
.NotUnderDeleting()
547+
.NotUnderOperation();
548+
549+
if (!checks) {
550+
result->SetError(checks.GetStatus(), checks.GetError());
551+
return result;
552+
}
553+
}
554+
555+
localSequences.insert(sequencePath.PathString());
556+
}
557+
520558
TString errStr;
521559

522560
if (!context.SS->CheckApplyIf(Transaction, errStr)) {
@@ -560,7 +598,8 @@ class TAlterTable: public TSubOperation {
560598
}
561599

562600
NKikimrScheme::EStatus status;
563-
TTableInfo::TAlterDataPtr alterData = ParseParams(path, table, alter, IsShadowDataAllowed(), errStr, status, context);
601+
TTableInfo::TAlterDataPtr alterData = ParseParams(
602+
path, table, alter, IsShadowDataAllowed(), localSequences, errStr, status, context);
564603
if (!alterData) {
565604
result->SetError(status, errStr);
566605
return result;

ydb/core/tx/schemeshard/schemeshard_info_types.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,20 +269,47 @@ TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData(
269269
return nullptr;
270270
}
271271

272-
if (!columnFamily) {
272+
if (!columnFamily && !col.HasDefaultFromSequence()) {
273273
errStr = Sprintf("Nothing to alter for column '%s'", colName.data());
274274
return nullptr;
275275
}
276276

277-
if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
278-
errStr = Sprintf("Cannot alter default for column '%s'", colName.c_str());
279-
return nullptr;
277+
if (col.HasDefaultFromSequence()) {
278+
if (!localSequences.contains(col.GetDefaultFromSequence())) {
279+
errStr = Sprintf("Column '%s' cannot use an unknown sequence '%s'", colName.c_str(), col.GetDefaultFromSequence().c_str());
280+
return nullptr;
281+
}
282+
} else {
283+
if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
284+
errStr = Sprintf("Cannot set default from literal for column '%s'", colName.c_str());
285+
return nullptr;
286+
}
280287
}
281288

282289
ui32 colId = colName2Id[colName];
290+
const TTableInfo::TColumn& sourceColumn = source->Columns[colId];
291+
292+
if (col.HasDefaultFromSequence()) {
293+
if (sourceColumn.PType.GetTypeId() != NScheme::NTypeIds::Int64) {
294+
errStr = Sprintf(
295+
"Sequence value type '%s' must be equal to the column type '%s'", "Int64",
296+
NScheme::TypeName(sourceColumn.PType, sourceColumn.PTypeMod).c_str());
297+
return nullptr;
298+
}
299+
}
300+
283301
TTableInfo::TColumn& column = alterData->Columns[colId];
284-
column = source->Columns[colId];
285-
column.Family = columnFamily->GetId();
302+
column = sourceColumn;
303+
if (columnFamily) {
304+
column.Family = columnFamily->GetId();
305+
}
306+
if (col.HasDefaultFromSequence()) {
307+
column.DefaultKind = ETableColumnDefaultKind::FromSequence;
308+
column.DefaultValue = col.GetDefaultFromSequence();
309+
} else if (col.HasDefaultFromLiteral()) {
310+
column.DefaultKind = ETableColumnDefaultKind::FromLiteral;
311+
column.DefaultValue = col.GetDefaultFromLiteral().SerializeAsString();
312+
}
286313
} else {
287314
if (colName2Id.contains(colName)) {
288315
errStr = Sprintf("Column '%s' specified more than once", colName.data());
@@ -1338,6 +1365,8 @@ void TTableInfo::FinishAlter() {
13381365
//oldCol->CreateVersion = col.second.CreateVersion;
13391366
oldCol->DeleteVersion = col.second.DeleteVersion;
13401367
oldCol->Family = col.second.Family;
1368+
oldCol->DefaultKind = col.second.DefaultKind;
1369+
oldCol->DefaultValue = col.second.DefaultValue;
13411370
} else {
13421371
Columns[col.first] = col.second;
13431372
if (col.second.KeyOrder != (ui32)-1) {

ydb/core/tx/schemeshard/ut_helpers/ls_checks.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,12 @@ TCheckFunc IndexDataColumns(const TVector<TString>& dataColumnNames) {
819819
};
820820
}
821821

822+
TCheckFunc SequenceName(const TString& name) {
823+
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
824+
UNIT_ASSERT_VALUES_EQUAL(record.GetPathDescription().GetSequenceDescription().GetName(), name);
825+
};
826+
}
827+
822828
TCheckFunc SequenceIncrement(i64 increment) {
823829
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
824830
UNIT_ASSERT_VALUES_EQUAL(record.GetPathDescription().GetSequenceDescription().GetIncrement(), increment);

ydb/core/tx/schemeshard/ut_helpers/ls_checks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ namespace NLs {
138138
TCheckFunc IndexKeys(const TVector<TString>& keyNames);
139139
TCheckFunc IndexDataColumns(const TVector<TString>& dataColumnNames);
140140

141+
TCheckFunc SequenceName(const TString& name);
141142
TCheckFunc SequenceIncrement(i64 increment);
142143
TCheckFunc SequenceMaxValue(i64 maxValue);
143144
TCheckFunc SequenceMinValue(i64 minValue);

ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,4 +470,149 @@ Y_UNIT_TEST_SUITE(TSequence) {
470470
)", {NKikimrScheme::StatusInvalidParameter});
471471
}
472472

473+
Y_UNIT_TEST(AlterTableSetDefaultFromSequence) {
474+
TTestBasicRuntime runtime;
475+
TTestEnv env(runtime);
476+
ui64 txId = 100;
477+
478+
runtime.SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_TRACE);
479+
runtime.SetLogPriority(NKikimrServices::SEQUENCESHARD, NActors::NLog::PRI_TRACE);
480+
481+
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"(
482+
TableDescription {
483+
Name: "Table1"
484+
Columns { Name: "key" Type: "Int64" }
485+
Columns { Name: "value1" Type: "Int64" }
486+
Columns { Name: "value2" Type: "Int32" }
487+
KeyColumnNames: ["key"]
488+
}
489+
)");
490+
491+
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
492+
Name: "Table2"
493+
Columns { Name: "key" Type: "Int64" }
494+
Columns { Name: "value1" Type: "Int64" }
495+
Columns { Name: "value2" Type: "Int64" }
496+
KeyColumnNames: ["key"]
497+
)");
498+
499+
env.TestWaitNotification(runtime, txId);
500+
501+
TestCreateSequence(runtime, ++txId, "/MyRoot", R"(
502+
Name: "seq1"
503+
)");
504+
env.TestWaitNotification(runtime, txId);
505+
506+
TestCreateSequence(runtime, ++txId, "/MyRoot", R"(
507+
Name: "seq2"
508+
)");
509+
env.TestWaitNotification(runtime, txId);
510+
511+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
512+
Name: "Table1"
513+
Columns { Name: "key" DefaultFromSequence: "/MyRoot/seq1" }
514+
)", {TEvSchemeShard::EStatus::StatusInvalidParameter});
515+
516+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
517+
Name: "Table1"
518+
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq1" }
519+
)");
520+
env.TestWaitNotification(runtime, txId);
521+
522+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
523+
Name: "Table1"
524+
Columns { Name: "value2" DefaultFromSequence: "/MyRoot/seq1" }
525+
)", {TEvSchemeShard::EStatus::StatusInvalidParameter});
526+
527+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
528+
Name: "Table2"
529+
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq1" }
530+
)");
531+
env.TestWaitNotification(runtime, txId);
532+
533+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
534+
Name: "Table2"
535+
Columns { Name: "value2" DefaultFromSequence: "/MyRoot/seq1" }
536+
)");
537+
env.TestWaitNotification(runtime, txId);
538+
539+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
540+
Name: "Table2"
541+
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq3" }
542+
)", {TEvSchemeShard::EStatus::StatusPathDoesNotExist});
543+
544+
auto table1 = DescribePath(runtime, "/MyRoot/Table1")
545+
.GetPathDescription()
546+
.GetTable();
547+
548+
for (const auto& column: table1.GetColumns()) {
549+
if (column.GetName() == "value1") {
550+
UNIT_ASSERT(column.HasDefaultFromSequence());
551+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
552+
553+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
554+
{
555+
NLs::SequenceName("seq1"),
556+
}
557+
);
558+
break;
559+
}
560+
}
561+
562+
auto table2 = DescribePath(runtime, "/MyRoot/Table2")
563+
.GetPathDescription()
564+
.GetTable();
565+
566+
for (const auto& column: table2.GetColumns()) {
567+
if (column.GetName() == "key") {
568+
continue;
569+
}
570+
UNIT_ASSERT(column.HasDefaultFromSequence());
571+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
572+
573+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
574+
{
575+
NLs::SequenceName("seq1"),
576+
}
577+
);
578+
}
579+
580+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
581+
Name: "Table2"
582+
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq2" }
583+
)");
584+
env.TestWaitNotification(runtime, txId);
585+
586+
table2 = DescribePath(runtime, "/MyRoot/Table2")
587+
.GetPathDescription()
588+
.GetTable();
589+
590+
for (const auto& column: table2.GetColumns()) {
591+
if (column.GetName() == "key") {
592+
continue;
593+
}
594+
if (column.GetName() == "value1") {
595+
UNIT_ASSERT(column.HasDefaultFromSequence());
596+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq2");
597+
598+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
599+
{
600+
NLs::SequenceName("seq2"),
601+
}
602+
);
603+
break;
604+
} else if (column.GetName() == "value2") {
605+
UNIT_ASSERT(column.HasDefaultFromSequence());
606+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
607+
608+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
609+
{
610+
NLs::SequenceName("seq1"),
611+
}
612+
);
613+
break;
614+
}
615+
}
616+
}
617+
473618
} // Y_UNIT_TEST_SUITE(TSequence)

0 commit comments

Comments
 (0)