Skip to content

Commit

Permalink
Support set default from sequence (schemeshard) (ydb-platform#4575)
Browse files Browse the repository at this point in the history
  • Loading branch information
shnikd authored and MrLolthe1st committed May 28, 2024
1 parent d39abf9 commit b73f50f
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 9 deletions.
45 changes: 42 additions & 3 deletions ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ bool IsSuperUser(const NACLib::TUserToken* userToken) {
}

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

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

const TSubDomainInfo& subDomain = *path.DomainInfo();
const TSchemeLimits& limits = subDomain.GetSchemeLimits();
TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(table, copyAlter, *appData->TypeRegistry, limits, subDomain, context.SS->EnableTablePgTypes, errStr);


TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(
table, copyAlter, *appData->TypeRegistry, limits, subDomain,
context.SS->EnableTablePgTypes, errStr, localSequences);
if (!alterData) {
status = NKikimrScheme::StatusInvalidParameter;
return nullptr;
Expand Down Expand Up @@ -517,6 +521,40 @@ class TAlterTable: public TSubOperation {
}
}

THashSet<TString> localSequences;

std::optional<TString> defaultFromSequence;
for (const auto& column: alter.GetColumns()) {
if (column.HasDefaultFromSequence()) {
defaultFromSequence = column.GetDefaultFromSequence();
}
}

if (defaultFromSequence.has_value()) {
Y_ABORT_UNLESS(alter.GetColumns().size() == 1);

const auto sequencePath = TPath::Resolve(*defaultFromSequence, context.SS);
{
const auto checks = sequencePath.Check();
checks
.NotEmpty()
.NotUnderDomainUpgrade()
.IsAtLocalSchemeShard()
.IsResolved()
.NotDeleted()
.IsSequence()
.NotUnderDeleting()
.NotUnderOperation();

if (!checks) {
result->SetError(checks.GetStatus(), checks.GetError());
return result;
}
}

localSequences.insert(sequencePath.PathString());
}

TString errStr;

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

NKikimrScheme::EStatus status;
TTableInfo::TAlterDataPtr alterData = ParseParams(path, table, alter, IsShadowDataAllowed(), errStr, status, context);
TTableInfo::TAlterDataPtr alterData = ParseParams(
path, table, alter, IsShadowDataAllowed(), localSequences, errStr, status, context);
if (!alterData) {
result->SetError(status, errStr);
return result;
Expand Down
41 changes: 35 additions & 6 deletions ydb/core/tx/schemeshard/schemeshard_info_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,20 +269,47 @@ TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData(
return nullptr;
}

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

if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
errStr = Sprintf("Cannot alter default for column '%s'", colName.c_str());
return nullptr;
if (col.HasDefaultFromSequence()) {
if (!localSequences.contains(col.GetDefaultFromSequence())) {
errStr = Sprintf("Column '%s' cannot use an unknown sequence '%s'", colName.c_str(), col.GetDefaultFromSequence().c_str());
return nullptr;
}
} else {
if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
errStr = Sprintf("Cannot set default from literal for column '%s'", colName.c_str());
return nullptr;
}
}

ui32 colId = colName2Id[colName];
const TTableInfo::TColumn& sourceColumn = source->Columns[colId];

if (col.HasDefaultFromSequence()) {
if (sourceColumn.PType.GetTypeId() != NScheme::NTypeIds::Int64) {
errStr = Sprintf(
"Sequence value type '%s' must be equal to the column type '%s'", "Int64",
NScheme::TypeName(sourceColumn.PType, sourceColumn.PTypeMod).c_str());
return nullptr;
}
}

TTableInfo::TColumn& column = alterData->Columns[colId];
column = source->Columns[colId];
column.Family = columnFamily->GetId();
column = sourceColumn;
if (columnFamily) {
column.Family = columnFamily->GetId();
}
if (col.HasDefaultFromSequence()) {
column.DefaultKind = ETableColumnDefaultKind::FromSequence;
column.DefaultValue = col.GetDefaultFromSequence();
} else if (col.HasDefaultFromLiteral()) {
column.DefaultKind = ETableColumnDefaultKind::FromLiteral;
column.DefaultValue = col.GetDefaultFromLiteral().SerializeAsString();
}
} else {
if (colName2Id.contains(colName)) {
errStr = Sprintf("Column '%s' specified more than once", colName.data());
Expand Down Expand Up @@ -1338,6 +1365,8 @@ void TTableInfo::FinishAlter() {
//oldCol->CreateVersion = col.second.CreateVersion;
oldCol->DeleteVersion = col.second.DeleteVersion;
oldCol->Family = col.second.Family;
oldCol->DefaultKind = col.second.DefaultKind;
oldCol->DefaultValue = col.second.DefaultValue;
} else {
Columns[col.first] = col.second;
if (col.second.KeyOrder != (ui32)-1) {
Expand Down
6 changes: 6 additions & 0 deletions ydb/core/tx/schemeshard/ut_helpers/ls_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,12 @@ TCheckFunc IndexDataColumns(const TVector<TString>& dataColumnNames) {
};
}

TCheckFunc SequenceName(const TString& name) {
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
UNIT_ASSERT_VALUES_EQUAL(record.GetPathDescription().GetSequenceDescription().GetName(), name);
};
}

TCheckFunc SequenceIncrement(i64 increment) {
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
UNIT_ASSERT_VALUES_EQUAL(record.GetPathDescription().GetSequenceDescription().GetIncrement(), increment);
Expand Down
1 change: 1 addition & 0 deletions ydb/core/tx/schemeshard/ut_helpers/ls_checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ namespace NLs {
TCheckFunc IndexKeys(const TVector<TString>& keyNames);
TCheckFunc IndexDataColumns(const TVector<TString>& dataColumnNames);

TCheckFunc SequenceName(const TString& name);
TCheckFunc SequenceIncrement(i64 increment);
TCheckFunc SequenceMaxValue(i64 maxValue);
TCheckFunc SequenceMinValue(i64 minValue);
Expand Down
145 changes: 145 additions & 0 deletions ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,4 +470,149 @@ Y_UNIT_TEST_SUITE(TSequence) {
)", {NKikimrScheme::StatusInvalidParameter});
}

Y_UNIT_TEST(AlterTableSetDefaultFromSequence) {
TTestBasicRuntime runtime;
TTestEnv env(runtime);
ui64 txId = 100;

runtime.SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_TRACE);
runtime.SetLogPriority(NKikimrServices::SEQUENCESHARD, NActors::NLog::PRI_TRACE);

TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"(
TableDescription {
Name: "Table1"
Columns { Name: "key" Type: "Int64" }
Columns { Name: "value1" Type: "Int64" }
Columns { Name: "value2" Type: "Int32" }
KeyColumnNames: ["key"]
}
)");

TestCreateTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table2"
Columns { Name: "key" Type: "Int64" }
Columns { Name: "value1" Type: "Int64" }
Columns { Name: "value2" Type: "Int64" }
KeyColumnNames: ["key"]
)");

env.TestWaitNotification(runtime, txId);

TestCreateSequence(runtime, ++txId, "/MyRoot", R"(
Name: "seq1"
)");
env.TestWaitNotification(runtime, txId);

TestCreateSequence(runtime, ++txId, "/MyRoot", R"(
Name: "seq2"
)");
env.TestWaitNotification(runtime, txId);

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table1"
Columns { Name: "key" DefaultFromSequence: "/MyRoot/seq1" }
)", {TEvSchemeShard::EStatus::StatusInvalidParameter});

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table1"
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq1" }
)");
env.TestWaitNotification(runtime, txId);

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table1"
Columns { Name: "value2" DefaultFromSequence: "/MyRoot/seq1" }
)", {TEvSchemeShard::EStatus::StatusInvalidParameter});

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table2"
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq1" }
)");
env.TestWaitNotification(runtime, txId);

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table2"
Columns { Name: "value2" DefaultFromSequence: "/MyRoot/seq1" }
)");
env.TestWaitNotification(runtime, txId);

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table2"
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq3" }
)", {TEvSchemeShard::EStatus::StatusPathDoesNotExist});

auto table1 = DescribePath(runtime, "/MyRoot/Table1")
.GetPathDescription()
.GetTable();

for (const auto& column: table1.GetColumns()) {
if (column.GetName() == "value1") {
UNIT_ASSERT(column.HasDefaultFromSequence());
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");

TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
{
NLs::SequenceName("seq1"),
}
);
break;
}
}

auto table2 = DescribePath(runtime, "/MyRoot/Table2")
.GetPathDescription()
.GetTable();

for (const auto& column: table2.GetColumns()) {
if (column.GetName() == "key") {
continue;
}
UNIT_ASSERT(column.HasDefaultFromSequence());
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");

TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
{
NLs::SequenceName("seq1"),
}
);
}

TestAlterTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table2"
Columns { Name: "value1" DefaultFromSequence: "/MyRoot/seq2" }
)");
env.TestWaitNotification(runtime, txId);

table2 = DescribePath(runtime, "/MyRoot/Table2")
.GetPathDescription()
.GetTable();

for (const auto& column: table2.GetColumns()) {
if (column.GetName() == "key") {
continue;
}
if (column.GetName() == "value1") {
UNIT_ASSERT(column.HasDefaultFromSequence());
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq2");

TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
{
NLs::SequenceName("seq2"),
}
);
break;
} else if (column.GetName() == "value2") {
UNIT_ASSERT(column.HasDefaultFromSequence());
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");

TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
{
NLs::SequenceName("seq1"),
}
);
break;
}
}
}

} // Y_UNIT_TEST_SUITE(TSequence)

0 comments on commit b73f50f

Please sign in to comment.