Skip to content

Commit 8de5470

Browse files
authored
Support drop default and set default for key column (#6289)
1 parent 1c9d9af commit 8de5470

File tree

10 files changed

+222
-53
lines changed

10 files changed

+222
-53
lines changed

ydb/core/kqp/provider/yql_kikimr_exec.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,15 +1397,25 @@ class TKiSinkCallableExecutionTransformer : public TAsyncCallbackTransformer<TKi
13971397
auto alterColumnAction = TString(alterColumnList.Item(0).Cast<TCoAtom>());
13981398
if (alterColumnAction == "setDefault") {
13991399
auto setDefault = alterColumnList.Item(1).Cast<TCoAtomList>();
1400-
auto func = TString(setDefault.Item(0).Cast<TCoAtom>());
1401-
auto arg = TString(setDefault.Item(1).Cast<TCoAtom>());
1402-
if (func != "nextval") {
1403-
ctx.AddError(TIssue(ctx.GetPosition(setDefault.Pos()),
1404-
TStringBuilder() << "Unsupported function to set default: " << func));
1405-
return SyncError();
1400+
if (setDefault.Size() == 1) {
1401+
auto defaultExpr = TString(setDefault.Item(0).Cast<TCoAtom>());
1402+
if (defaultExpr != "Null") {
1403+
ctx.AddError(TIssue(ctx.GetPosition(setDefault.Pos()),
1404+
TStringBuilder() << "Unsupported value to set defualt: " << defaultExpr));
1405+
return SyncError();
1406+
}
1407+
alter_columns->set_empty_default(google::protobuf::NullValue());
1408+
} else {
1409+
auto func = TString(setDefault.Item(0).Cast<TCoAtom>());
1410+
auto arg = TString(setDefault.Item(1).Cast<TCoAtom>());
1411+
if (func != "nextval") {
1412+
ctx.AddError(TIssue(ctx.GetPosition(setDefault.Pos()),
1413+
TStringBuilder() << "Unsupported function to set default: " << func));
1414+
return SyncError();
1415+
}
1416+
auto fromSequence = alter_columns->mutable_from_sequence();
1417+
fromSequence->set_name(arg);
14061418
}
1407-
auto fromSequence = alter_columns->mutable_from_sequence();
1408-
fromSequence->set_name(arg);
14091419
} else if (alterColumnAction == "setFamily") {
14101420
auto families = alterColumnList.Item(1).Cast<TCoAtomList>();
14111421
if (families.Size() > 1) {

ydb/core/kqp/provider/yql_kikimr_type_ann.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,17 +1373,26 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
13731373
auto alterColumnAction = TString(alterColumnList.Item(0).Cast<TCoAtom>());
13741374
if (alterColumnAction == "setDefault") {
13751375
auto setDefault = alterColumnList.Item(1).Cast<TCoAtomList>();
1376-
auto func = TString(setDefault.Item(0).Cast<TCoAtom>());
1377-
auto arg = TString(setDefault.Item(1).Cast<TCoAtom>());
1378-
if (func != "nextval") {
1379-
ctx.AddError(TIssue(ctx.GetPosition(nameNode.Pos()),
1380-
TStringBuilder() << "Unsupported function to set default: " << func));
1381-
return TStatus::Error;
1382-
}
1383-
if (setDefault.Size() > 2) {
1384-
ctx.AddError(TIssue(ctx.GetPosition(nameNode.Pos()),
1385-
TStringBuilder() << "Function nextval has exactly one argument"));
1386-
return TStatus::Error;
1376+
if (setDefault.Size() == 1) {
1377+
auto defaultExpr = TString(setDefault.Item(0).Cast<TCoAtom>());
1378+
if (defaultExpr != "Null") {
1379+
ctx.AddError(TIssue(ctx.GetPosition(setDefault.Pos()),
1380+
TStringBuilder() << "Unsupported value to set defualt: " << defaultExpr));
1381+
return TStatus::Error;
1382+
}
1383+
} else {
1384+
auto func = TString(setDefault.Item(0).Cast<TCoAtom>());
1385+
auto arg = TString(setDefault.Item(1).Cast<TCoAtom>());
1386+
if (func != "nextval") {
1387+
ctx.AddError(TIssue(ctx.GetPosition(nameNode.Pos()),
1388+
TStringBuilder() << "Unsupported function to set default: " << func));
1389+
return TStatus::Error;
1390+
}
1391+
if (setDefault.Size() > 2) {
1392+
ctx.AddError(TIssue(ctx.GetPosition(nameNode.Pos()),
1393+
TStringBuilder() << "Function nextval has exactly one argument"));
1394+
return TStatus::Error;
1395+
}
13871396
}
13881397
} else if (alterColumnAction == "setFamily") {
13891398
auto families = alterColumnList.Item(1).Cast<TCoAtomList>();

ydb/core/kqp/ut/pg/kqp_pg_ut.cpp

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,7 +2592,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
25922592
auto result = session.ExecuteQuery(R"(
25932593
--!syntax_pg
25942594
CREATE TABLE Pg (
2595-
key int4 PRIMARY KEY,
2595+
key int8 PRIMARY KEY,
25962596
value int8
25972597
);
25982598
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
@@ -2627,7 +2627,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
26272627
{
26282628
auto result = session.ExecuteQuery(R"(
26292629
--!syntax_pg
2630-
ALTER TABLE Pg ALTER COLUMN value SET DEFAULT nextval('seq');
2630+
ALTER TABLE Pg ALTER COLUMN key SET DEFAULT nextval('seq');
26312631
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
26322632
UNIT_ASSERT(!result.IsSuccess());
26332633
}
@@ -2650,7 +2650,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
26502650
{
26512651
auto result = session.ExecuteQuery(R"(
26522652
--!syntax_pg
2653-
ALTER TABLE Pg ALTER COLUMN value SET DEFAULT nextval('seq1');
2653+
ALTER TABLE Pg ALTER COLUMN key SET DEFAULT nextval('seq1');
26542654
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
26552655
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
26562656
}
@@ -2663,7 +2663,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
26632663
const auto& tableDescription = describeResult.GetPathDescription().GetTable();
26642664

26652665
for (const auto& column: tableDescription.GetColumns()) {
2666-
if (column.GetName() == "value") {
2666+
if (column.GetName() == "key") {
26672667
UNIT_ASSERT(column.HasDefaultFromSequence());
26682668
UNIT_ASSERT(column.GetDefaultFromSequence() == "/Root/seq1");
26692669
break;
@@ -2674,7 +2674,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
26742674
{
26752675
const auto query = Q_(R"(
26762676
--!syntax_pg
2677-
INSERT INTO Pg (key) values (2), (3);
2677+
INSERT INTO Pg (value) values (2), (3);
26782678
)");
26792679

26802680
auto result = tableClientSession.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx()).ExtractValueSync();
@@ -2692,7 +2692,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
26922692

26932693
UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
26942694
CompareYson(R"(
2695-
[["1";"1"];["2";"10"];["3";"12"]]
2695+
[["1";"1"];["10";"2"];["12";"3"]]
26962696
)", FormatResultSetYson(result.GetResultSet(0)));
26972697
}
26982698

@@ -2714,15 +2714,56 @@ Y_UNIT_TEST_SUITE(KqpPg) {
27142714
{
27152715
auto result = session.ExecuteQuery(R"(
27162716
--!syntax_pg
2717-
ALTER TABLE Pg ALTER COLUMN value SET DEFAULT nextval('seq2');
2717+
ALTER TABLE Pg ALTER COLUMN key SET DEFAULT nextval('seq2');
2718+
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
2719+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
2720+
}
2721+
2722+
{
2723+
const auto query = Q_(R"(
2724+
--!syntax_pg
2725+
INSERT INTO Pg (value) values (4), (5);
2726+
)");
2727+
2728+
auto result = tableClientSession.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx()).ExtractValueSync();
2729+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
2730+
}
2731+
2732+
{
2733+
const auto query = Q_(R"(
2734+
--!syntax_pg
2735+
SELECT * FROM Pg;
2736+
)");
2737+
2738+
auto result = tableClientSession.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx()).ExtractValueSync();
2739+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
2740+
2741+
UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
2742+
CompareYson(R"(
2743+
[["1";"1"];["5";"4"];["8";"5"];["10";"2"];["12";"3"]]
2744+
)", FormatResultSetYson(result.GetResultSet(0)));
2745+
}
2746+
2747+
{
2748+
auto result = session.ExecuteQuery(R"(
2749+
--!syntax_pg
2750+
ALTER TABLE Pg ALTER COLUMN key DROP DEFAULT;
2751+
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
2752+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
2753+
}
2754+
2755+
{
2756+
auto result = session.ExecuteQuery(R"(
2757+
--!syntax_pg
2758+
ALTER TABLE Pg ALTER COLUMN value SET DEFAULT nextval('seq1');
27182759
)", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
27192760
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
27202761
}
27212762

27222763
{
27232764
const auto query = Q_(R"(
27242765
--!syntax_pg
2725-
INSERT INTO Pg (key) values (4), (5);
2766+
INSERT INTO Pg (key) values (13), (14);
27262767
)");
27272768

27282769
auto result = tableClientSession.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx()).ExtractValueSync();
@@ -2740,7 +2781,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
27402781

27412782
UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
27422783
CompareYson(R"(
2743-
[["1";"1"];["2";"10"];["3";"12"];["4";"5"];["5";"8"]]
2784+
[["1";"1"];["5";"4"];["8";"5"];["10";"2"];["12";"3"];["13";"14"];["14";"16"]]
27442785
)", FormatResultSetYson(result.GetResultSet(0)));
27452786
}
27462787
}

ydb/core/protos/flat_scheme_op.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import "ydb/core/tx/columnshard/engines/scheme/defaults/protos/data.proto";
2222
import "ydb/core/tx/columnshard/common/protos/snapshot.proto";
2323

2424
import "google/protobuf/empty.proto";
25+
import "google/protobuf/struct.proto";
2526

2627
package NKikimrSchemeOp;
2728
option java_package = "ru.yandex.kikimr.proto";
@@ -90,6 +91,7 @@ message TColumnDescription {
9091
oneof DefaultValue {
9192
string DefaultFromSequence = 7; // Path to sequence for default values
9293
Ydb.TypedValue DefaultFromLiteral = 10; // Literal default value
94+
google.protobuf.NullValue EmptyDefault = 12; // Drop default case
9395
}
9496
optional bool NotNull = 8;
9597
// flag that indicates that column is currently under the build

ydb/core/tx/schemeshard/schemeshard_info_types.cpp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData(
323323

324324
bool isAlterColumn = (source && colName2Id.contains(colName));
325325
if (isAlterColumn) {
326-
if (keys.contains(colName2Id.at(colName))) {
326+
if (keys.contains(colName2Id.at(colName)) && columnFamily) {
327327
errStr = TStringBuilder()
328-
<< "Cannot alter key column ' " << colName << "' with id " << colName2Id.at(colName);
328+
<< "Cannot set family for key column ' " << colName << "' with id " << colName2Id.at(colName);
329329
return nullptr;
330330
}
331331

@@ -334,20 +334,27 @@ TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData(
334334
return nullptr;
335335
}
336336

337-
if (!columnFamily && !col.HasDefaultFromSequence()) {
337+
if (!columnFamily && !col.HasDefaultFromSequence() && !col.HasEmptyDefault()) {
338338
errStr = Sprintf("Nothing to alter for column '%s'", colName.data());
339339
return nullptr;
340340
}
341341

342-
if (col.HasDefaultFromSequence()) {
343-
if (!localSequences.contains(col.GetDefaultFromSequence())) {
344-
errStr = Sprintf("Column '%s' cannot use an unknown sequence '%s'", colName.c_str(), col.GetDefaultFromSequence().c_str());
345-
return nullptr;
346-
}
347-
} else {
348-
if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
349-
errStr = Sprintf("Cannot set default from literal for column '%s'", colName.c_str());
350-
return nullptr;
342+
if (col.DefaultValue_case() != NKikimrSchemeOp::TColumnDescription::DEFAULTVALUE_NOT_SET) {
343+
switch (col.GetDefaultValueCase()) {
344+
case NKikimrSchemeOp::TColumnDescription::kDefaultFromSequence: {
345+
if (!localSequences.contains(col.GetDefaultFromSequence())) {
346+
errStr = Sprintf("Column '%s' cannot use an unknown sequence '%s'", colName.c_str(), col.GetDefaultFromSequence().c_str());
347+
return nullptr;
348+
}
349+
break;
350+
}
351+
case NKikimrSchemeOp::TColumnDescription::kEmptyDefault: {
352+
break;
353+
}
354+
default: {
355+
errStr = Sprintf("Cannot set default from literal for column '%s'", colName.c_str());
356+
return nullptr;
357+
}
351358
}
352359
}
353360

@@ -372,12 +379,18 @@ TTableInfo::TAlterDataPtr TTableInfo::CreateAlterData(
372379
if (columnFamily) {
373380
column.Family = columnFamily->GetId();
374381
}
375-
if (col.HasDefaultFromSequence()) {
376-
column.DefaultKind = ETableColumnDefaultKind::FromSequence;
377-
column.DefaultValue = col.GetDefaultFromSequence();
378-
} else if (col.HasDefaultFromLiteral()) {
379-
column.DefaultKind = ETableColumnDefaultKind::FromLiteral;
380-
column.DefaultValue = col.GetDefaultFromLiteral().SerializeAsString();
382+
switch (col.GetDefaultValueCase()) {
383+
case NKikimrSchemeOp::TColumnDescription::kDefaultFromSequence: {
384+
column.DefaultKind = ETableColumnDefaultKind::FromSequence;
385+
column.DefaultValue = col.GetDefaultFromSequence();
386+
break;
387+
}
388+
case NKikimrSchemeOp::TColumnDescription::kEmptyDefault: {
389+
column.DefaultKind = ETableColumnDefaultKind::None;
390+
column.DefaultValue = "";
391+
break;
392+
}
393+
default: break;
381394
}
382395
} else {
383396
if (colName2Id.contains(colName)) {

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

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,8 @@ Y_UNIT_TEST_SUITE(TSequence) {
511511
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
512512
Name: "Table1"
513513
Columns { Name: "key" DefaultFromSequence: "/MyRoot/seq1" }
514-
)", {TEvSchemeShard::EStatus::StatusInvalidParameter});
514+
)");
515+
env.TestWaitNotification(runtime, txId);
515516

516517
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
517518
Name: "Table1"
@@ -546,7 +547,7 @@ Y_UNIT_TEST_SUITE(TSequence) {
546547
.GetTable();
547548

548549
for (const auto& column: table1.GetColumns()) {
549-
if (column.GetName() == "value1") {
550+
if (column.GetName() == "key" || column.GetName() == "value1") {
550551
UNIT_ASSERT(column.HasDefaultFromSequence());
551552
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
552553

@@ -555,7 +556,6 @@ Y_UNIT_TEST_SUITE(TSequence) {
555556
NLs::SequenceName("seq1"),
556557
}
557558
);
558-
break;
559559
}
560560
}
561561

@@ -600,7 +600,6 @@ Y_UNIT_TEST_SUITE(TSequence) {
600600
NLs::SequenceName("seq2"),
601601
}
602602
);
603-
break;
604603
} else if (column.GetName() == "value2") {
605604
UNIT_ASSERT(column.HasDefaultFromSequence());
606605
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
@@ -610,7 +609,70 @@ Y_UNIT_TEST_SUITE(TSequence) {
610609
NLs::SequenceName("seq1"),
611610
}
612611
);
613-
break;
612+
}
613+
}
614+
615+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
616+
Name: "Table2"
617+
Columns { Name: "key" DefaultFromSequence: "/MyRoot/seq2" }
618+
Columns { Name: "value1" EmptyDefault: NULL_VALUE }
619+
)");
620+
env.TestWaitNotification(runtime, txId);
621+
622+
table2 = DescribePath(runtime, "/MyRoot/Table2")
623+
.GetPathDescription()
624+
.GetTable();
625+
626+
for (const auto& column: table2.GetColumns()) {
627+
if (column.GetName() == "key") {
628+
UNIT_ASSERT(column.HasDefaultFromSequence());
629+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq2");
630+
631+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
632+
{
633+
NLs::SequenceName("seq2"),
634+
}
635+
);
636+
}
637+
if (column.GetName() == "value1") {
638+
UNIT_ASSERT(!column.HasDefaultFromSequence());
639+
UNIT_ASSERT(!column.HasDefaultFromLiteral());
640+
} else if (column.GetName() == "value2") {
641+
UNIT_ASSERT(column.HasDefaultFromSequence());
642+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
643+
644+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
645+
{
646+
NLs::SequenceName("seq1"),
647+
}
648+
);
649+
}
650+
}
651+
652+
TestAlterTable(runtime, ++txId, "/MyRoot", R"(
653+
Name: "Table1"
654+
Columns { Name: "key" EmptyDefault: NULL_VALUE }
655+
)");
656+
env.TestWaitNotification(runtime, txId);
657+
658+
table1 = DescribePath(runtime, "/MyRoot/Table1")
659+
.GetPathDescription()
660+
.GetTable();
661+
662+
for (const auto& column: table1.GetColumns()) {
663+
if (column.GetName() == "key") {
664+
UNIT_ASSERT(!column.HasDefaultFromSequence());
665+
UNIT_ASSERT(!column.HasDefaultFromLiteral());
666+
}
667+
if (column.GetName() == "value1") {
668+
UNIT_ASSERT(column.HasDefaultFromSequence());
669+
UNIT_ASSERT_VALUES_EQUAL(column.GetDefaultFromSequence(), "/MyRoot/seq1");
670+
671+
TestDescribeResult(DescribePath(runtime, column.GetDefaultFromSequence()),
672+
{
673+
NLs::SequenceName("seq1"),
674+
}
675+
);
614676
}
615677
}
616678
}

0 commit comments

Comments
 (0)