Skip to content

Commit b781da4

Browse files
authored
Merge aa3b529 into f499f08
2 parents f499f08 + aa3b529 commit b781da4

9 files changed

Lines changed: 140 additions & 3 deletions

File tree

ydb/core/protos/flat_tx_scheme.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ message TSchemeLimits {
190190

191191
optional uint64 MaxExports = 16;
192192
optional uint64 MaxImports = 17;
193+
194+
optional uint64 MaxColumnTableColumns = 18;
193195
}
194196

195197
message TEvInitTenantSchemeShard {

ydb/core/tx/schemeshard/olap/operations/alter_table.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,28 @@ class TAlterColumnTable: public TSubOperation {
318318
return result;
319319
}
320320

321+
NSchemeShard::TPath parentPath = NSchemeShard::TPath::Resolve(parentPathStr, context.SS);
322+
auto domainInfo = parentPath.DomainInfo();
323+
const TSchemeLimits& limits = domainInfo->GetSchemeLimits();
324+
325+
if (Transaction.HasAlterColumnTable()) {
326+
auto& alterSchema = Transaction.GetAlterColumnTable().GetAlterSchema();
327+
TTablesStorage::TTableReadGuard table = context.SS->ColumnTables.at(path->PathId);
328+
ui64 curCols = table->Description.GetSchema().GetColumns().size();
329+
ui64 dropCols = alterSchema.GetDropColumns().size();
330+
ui64 addCols = alterSchema.GetAddColumns().size();
331+
if (curCols + addCols - dropCols > limits.MaxColumnTableColumns) {
332+
TString errStr = TStringBuilder()
333+
<< "Too many columns"
334+
<< ": current:" << curCols
335+
<< ", new: " << addCols
336+
<< ", dropping: " << dropCols
337+
<< ". Limit: " << limits.MaxColumnTableColumns;
338+
result->SetError(NKikimrScheme::StatusSchemeError, errStr);
339+
return result;
340+
}
341+
}
342+
321343
NIceDb::TNiceDb db(context.GetDB());
322344

323345
if (update->GetShardIds().size()) {

ydb/core/tx/schemeshard/olap/operations/create_table.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,11 +681,23 @@ class TCreateColumnTable: public TSubOperation {
681681
TProposeErrorCollector errors(*result);
682682
TColumnTableInfo::TPtr tableInfo;
683683
bool needUpdateObject = false;
684+
auto domainInfo = parentPath.DomainInfo();
685+
const TSchemeLimits& limits = domainInfo->GetSchemeLimits();
686+
684687
if (storeInfo) {
685688
TOlapPresetConstructor tableConstructor(*storeInfo);
686689
tableInfo = tableConstructor.BuildTableInfo(createDescription, context, errors);
687690
needUpdateObject = tableConstructor.GetNeedUpdateObject();
688691
} else {
692+
ui64 columnCount = createDescription.schema().columns().size();
693+
if (columnCount > limits.MaxColumnTableColumns) {
694+
TString errStr = TStringBuilder()
695+
<< "Too many columns"
696+
<< ". new: " << columnCount
697+
<< ". Limit: " << limits.MaxColumnTableColumns;
698+
result->SetError(NKikimrScheme::StatusSchemeError, errStr);
699+
return result;
700+
}
689701
TOlapTableConstructor tableConstructor;
690702
tableInfo = tableConstructor.BuildTableInfo(createDescription, context, errors);
691703
}

ydb/core/tx/schemeshard/schemeshard__init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
12431243
.MaxPathElementLength = rowSet.template GetValueOrDefault<Schema::SubDomains::PathElementLength>(defaults.MaxPathElementLength),
12441244
.ExtraPathSymbolsAllowed = rowSet.template GetValueOrDefault<Schema::SubDomains::ExtraPathSymbolsAllowed>(defaults.ExtraPathSymbolsAllowed),
12451245
.MaxTableColumns = rowSet.template GetValueOrDefault<Schema::SubDomains::TableColumnsLimit>(defaults.MaxTableColumns),
1246+
.MaxColumnTableColumns = rowSet.template GetValueOrDefault<Schema::SubDomains::ColumnTableColumnsLimit>(defaults.MaxColumnTableColumns),
12461247
.MaxTableColumnNameLength = rowSet.template GetValueOrDefault<Schema::SubDomains::TableColumnNameLengthLimit>(defaults.MaxTableColumnNameLength),
12471248
.MaxTableKeyColumns = rowSet.template GetValueOrDefault<Schema::SubDomains::TableKeyColumnsLimit>(defaults.MaxTableKeyColumns),
12481249
.MaxTableIndices = rowSet.template GetValueOrDefault<Schema::SubDomains::TableIndicesLimit>(defaults.MaxTableIndices),

ydb/core/tx/schemeshard/schemeshard_schema.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ struct Schema : NIceDb::Schema {
768768
struct ImportsLimit : Column<29, NScheme::NTypeIds::Uint64> {};
769769
struct AuditSettings : Column<30, NScheme::NTypeIds::String> {};
770770
struct ServerlessComputeResourcesMode : Column<31, NScheme::NTypeIds::Uint32> { using Type = EServerlessComputeResourcesMode; };
771+
struct ColumnTableColumnsLimit : Column<32, NScheme::NTypeIds::Uint64> {};
771772

772773
using TKey = TableKey<PathId>;
773774
using TColumns = TableColumns<
@@ -801,7 +802,8 @@ struct Schema : NIceDb::Schema {
801802
ExportsLimit,
802803
ImportsLimit,
803804
AuditSettings,
804-
ServerlessComputeResourcesMode
805+
ServerlessComputeResourcesMode,
806+
ColumnTableColumnsLimit
805807
>;
806808
};
807809

ydb/core/tx/schemeshard/schemeshard_types.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ TSchemeLimits TSchemeLimits::FromProto(const NKikimrScheme::TSchemeLimits& proto
2020
if (proto.HasMaxTableColumns()) {
2121
result.MaxTableColumns = proto.GetMaxTableColumns();
2222
}
23+
if (proto.HasMaxColumnTableColumns()) {
24+
result.MaxColumnTableColumns = proto.GetMaxColumnTableColumns();
25+
}
2326
if (proto.HasMaxTableColumnNameLength()) {
2427
result.MaxTableColumnNameLength = proto.GetMaxTableColumnNameLength();
2528
}
@@ -69,6 +72,7 @@ NKikimrScheme::TSchemeLimits TSchemeLimits::AsProto() const {
6972
result.SetMaxAclBytesSize(MaxAclBytesSize);
7073

7174
result.SetMaxTableColumns(MaxTableColumns);
75+
result.SetMaxColumnTableColumns(MaxColumnTableColumns);
7276
result.SetMaxTableColumnNameLength(MaxTableColumnNameLength);
7377
result.SetMaxTableKeyColumns(MaxTableKeyColumns);
7478
result.SetMaxTableIndices(MaxTableIndices);

ydb/core/tx/schemeshard/schemeshard_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct TSchemeLimits {
3939

4040
// table
4141
ui64 MaxTableColumns = 200;
42+
ui64 MaxColumnTableColumns = 10000;
4243
ui64 MaxTableColumnNameLength = 255;
4344
ui64 MaxTableKeyColumns = 20;
4445
ui64 MaxTableIndices = 20;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,7 @@ namespace NSchemeShardUT_Private {
15061506
(let child '('ChildrenLimit (Uint64 '%lu)))
15071507
(let acl '('AclByteSizeLimit (Uint64 '%lu)))
15081508
(let columns '('TableColumnsLimit (Uint64 '%lu)))
1509+
(let columnColumns '('ColumnTableColumnsLimit (Uint64 '%lu)))
15091510
(let colName '('TableColumnNameLengthLimit (Uint64 '%lu)))
15101511
(let keyCols '('TableKeyColumnsLimit (Uint64 '%lu)))
15111512
(let indices '('TableIndicesLimit (Uint64 '%lu)))
@@ -1518,11 +1519,11 @@ namespace NSchemeShardUT_Private {
15181519
(let pqPartitions '('PQPartitionsLimit (Uint64 '%lu)))
15191520
(let exports '('ExportsLimit (Uint64 '%lu)))
15201521
(let imports '('ImportsLimit (Uint64 '%lu)))
1521-
(let ret (AsList (UpdateRow 'SubDomains key '(depth paths child acl columns colName keyCols indices streams shards pathShards consCopy maxPathLength extraSymbols pqPartitions exports imports))))
1522+
(let ret (AsList (UpdateRow 'SubDomains key '(depth paths child acl columns columnColumns colName keyCols indices streams shards pathShards consCopy maxPathLength extraSymbols pqPartitions exports imports))))
15221523
(return ret)
15231524
)
15241525
)", domainId, limits.MaxDepth, limits.MaxPaths, limits.MaxChildrenInDir, limits.MaxAclBytesSize,
1525-
limits.MaxTableColumns, limits.MaxTableColumnNameLength, limits.MaxTableKeyColumns,
1526+
limits.MaxTableColumns, limits.MaxColumnTableColumns, limits.MaxTableColumnNameLength, limits.MaxTableKeyColumns,
15261527
limits.MaxTableIndices, limits.MaxTableCdcStreams,
15271528
limits.MaxShards, limits.MaxShardsInPath, limits.MaxConsistentCopyTargets,
15281529
limits.MaxPathElementLength, escapedStr.c_str(), limits.MaxPQPartitions,

ydb/core/tx/schemeshard/ut_subdomain/ut_subdomain.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2568,6 +2568,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) {
25682568

25692569
}
25702570

2571+
25712572
//clear subdomain
25722573
{
25732574
TestDescribeResult(DescribePath(runtime, "/MyRoot"),
@@ -2585,6 +2586,97 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) {
25852586
}
25862587
}
25872588

2589+
Y_UNIT_TEST(ColumnSchemeLimitsRejects) {
2590+
TTestBasicRuntime runtime;
2591+
TTestEnv env(runtime);
2592+
ui64 txId = 100;
2593+
2594+
TSchemeLimits lowLimits;
2595+
lowLimits.MaxDepth = 4;
2596+
lowLimits.MaxPaths = 3;
2597+
lowLimits.MaxChildrenInDir = 3;
2598+
lowLimits.MaxAclBytesSize = 25;
2599+
lowLimits.MaxTableColumns = 3;
2600+
lowLimits.MaxColumnTableColumns = 3;
2601+
lowLimits.MaxTableColumnNameLength = 10;
2602+
lowLimits.MaxTableKeyColumns = 1;
2603+
lowLimits.MaxShards = 6;
2604+
lowLimits.MaxShardsInPath = 4;
2605+
lowLimits.MaxPQPartitions = 20;
2606+
2607+
2608+
//lowLimits.ExtraPathSymbolsAllowed = "!\"#$%&'()*+,-.:;<=>?@[\\]^_`{|}~";
2609+
SetSchemeshardSchemaLimits(runtime, lowLimits);
2610+
TestDescribeResult(DescribePath(runtime, "/MyRoot"),
2611+
{NLs::PathExist,
2612+
NLs::DomainLimitsIs(lowLimits.MaxPaths, lowLimits.MaxShards, lowLimits.MaxPQPartitions)});
2613+
2614+
{
2615+
TestCreateSubDomain(runtime, txId++, "/MyRoot",
2616+
"PlanResolution: 50 "
2617+
"Coordinators: 1 "
2618+
"Mediators: 1 "
2619+
"TimeCastBucketsPerMediator: 2 "
2620+
"Name: \"USER_0\""
2621+
" DatabaseQuotas {"
2622+
" data_stream_shards_quota: 2"
2623+
" data_stream_reserved_storage_quota: 200000"
2624+
"}");
2625+
}
2626+
2627+
//create column tables, column limits
2628+
{
2629+
TestMkDir(runtime, txId++, "/MyRoot/USER_0", "C");
2630+
env.TestWaitNotification(runtime, txId - 1);
2631+
2632+
// MaxColumnTableColumns
2633+
TestCreateColumnTable(runtime, txId++, "/MyRoot/USER_0/C", R"(
2634+
Name: "C2"
2635+
ColumnShardCount: 1
2636+
Schema {
2637+
Columns { Name: "RowId" Type: "Uint64", NotNull: true }
2638+
Columns { Name: "Value0" Type: "Utf8" }
2639+
Columns { Name: "Value1" Type: "Utf8" }
2640+
KeyColumnNames: "RowId"
2641+
Engine: COLUMN_ENGINE_REPLACING_TIMESERIES
2642+
}
2643+
)", {NKikimrScheme::StatusAccepted});
2644+
env.TestWaitNotification(runtime, txId - 1);
2645+
2646+
TestAlterColumnTable(runtime, txId++, "/MyRoot/USER_0/C", R"(
2647+
Name: "C2"
2648+
AlterSchema {
2649+
DropColumns {Name: "Value0"}
2650+
}
2651+
)", {NKikimrScheme::StatusAccepted});
2652+
env.TestWaitNotification(runtime, txId - 1);
2653+
2654+
TestAlterColumnTable(runtime, txId++, "/MyRoot/USER_0/C", R"(
2655+
Name: "C2"
2656+
AlterSchema {
2657+
DropColumns {Name: "Value1"}
2658+
AddColumns { Name: "Value2" Type: "Utf8" }
2659+
AddColumns { Name: "Value3" Type: "Utf8" }
2660+
AddColumns { Name: "Value4" Type: "Utf8" }
2661+
}
2662+
)", {NKikimrScheme::StatusSchemeError});
2663+
env.TestWaitNotification(runtime, txId - 1);
2664+
2665+
TestCreateColumnTable(runtime, txId++, "/MyRoot/USER_0/C", R"(
2666+
Name: "C1"
2667+
ColumnShardCount: 1
2668+
Schema {
2669+
Columns { Name: "RowId" Type: "Uint64", NotNull: true }
2670+
Columns { Name: "Value0" Type: "Utf8" }
2671+
Columns { Name: "Value1" Type: "Utf8" }
2672+
Columns { Name: "Value2" Type: "Utf8" }
2673+
KeyColumnNames: "RowId"
2674+
Engine: COLUMN_ENGINE_REPLACING_TIMESERIES
2675+
}
2676+
)", {NKikimrScheme::StatusSchemeError});
2677+
}
2678+
}
2679+
25882680
Y_UNIT_TEST(SchemeLimitsRejectsWithIndexedTables) {
25892681
TTestBasicRuntime runtime;
25902682
TTestEnv env(runtime);

0 commit comments

Comments
 (0)