Skip to content

Commit 527e9d0

Browse files
flown4qqqqzverevgeny
authored andcommitted
New statement 'ALTER DATABASE path OWNER TO newowner' (#14403)
1 parent d447be9 commit 527e9d0

25 files changed

+718
-137
lines changed

ydb/core/kqp/gateway/kqp_ic_gateway.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,6 @@ namespace {
722722
}
723723

724724
class TKikimrIcGateway : public IKqpGateway {
725-
private:
726-
using TNavigate = NSchemeCache::TSchemeCacheNavigate;
727-
728725
public:
729726
TKikimrIcGateway(const TString& cluster, NKikimrKqp::EQueryType queryType, const TString& database, const TString& databaseId, std::shared_ptr<IKqpTableMetadataLoader>&& metadataLoader,
730727
TActorSystem* actorSystem, ui32 nodeId, TKqpRequestCounters::TPtr counters, const NKikimrConfig::TQueryServiceConfig& queryServiceConfig)
@@ -899,6 +896,48 @@ class TKikimrIcGateway : public IKqpGateway {
899896
return tablePromise.GetFuture();
900897
}
901898

899+
TFuture<TGenericResult> AlterDatabase(const TString& cluster, const NYql::TAlterDatabaseSettings& settings) override {
900+
using TRequest = TEvTxUserProxy::TEvProposeTransaction;
901+
902+
try {
903+
if (!CheckCluster(cluster)) {
904+
return InvalidCluster<TGenericResult>(cluster);
905+
}
906+
907+
auto alterDatabasePromise = NewPromise<TGenericResult>();
908+
909+
auto ev = MakeHolder<TRequest>();
910+
911+
ev->Record.SetDatabaseName(Database);
912+
if (UserToken) {
913+
ev->Record.SetUserToken(UserToken->GetSerializedToken());
914+
}
915+
916+
const auto& [dirname, basename] = NSchemeHelpers::SplitPathByDirAndBaseNames(settings.DatabasePath);
917+
918+
NKikimrSchemeOp::TModifyScheme* modifyScheme = ev->Record.MutableTransaction()->MutableModifyScheme();
919+
modifyScheme->SetOperationType(NKikimrSchemeOp::ESchemeOpModifyACL);
920+
modifyScheme->SetWorkingDir(dirname);
921+
modifyScheme->MutableModifyACL()->SetNewOwner(settings.Owner.value());
922+
modifyScheme->MutableModifyACL()->SetName(basename);
923+
924+
auto condition = modifyScheme->AddApplyIf();
925+
condition->AddPathTypes(NKikimrSchemeOp::EPathType::EPathTypeSubDomain);
926+
condition->AddPathTypes(NKikimrSchemeOp::EPathType::EPathTypeExtSubDomain);
927+
928+
SendSchemeRequest(ev.Release()).Apply(
929+
[alterDatabasePromise](const TFuture<TGenericResult>& future) mutable {
930+
alterDatabasePromise.SetValue(future.GetValue());
931+
}
932+
);
933+
934+
return alterDatabasePromise.GetFuture();
935+
}
936+
catch (yexception& e) {
937+
return MakeFuture(ResultFromException<TGenericResult>(e));
938+
}
939+
}
940+
902941
TFuture<TGenericResult> CreateColumnTable(NYql::TKikimrTableMetadataPtr metadata,
903942
bool createDir, bool existingOk) override {
904943
Y_UNUSED(metadata);
@@ -1422,8 +1461,8 @@ class TKikimrIcGateway : public IKqpGateway {
14221461

14231462
SendSchemeRequest(ev.Release()).Apply(
14241463
[alterUserPromise](const TFuture<TGenericResult>& future) mutable {
1425-
alterUserPromise.SetValue(future.GetValue());
1426-
}
1464+
alterUserPromise.SetValue(future.GetValue());
1465+
}
14271466
);
14281467

14291468
return alterUserPromise.GetFuture();

ydb/core/kqp/host/kqp_gateway_proxy.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,38 @@ class TKqpGatewayProxy : public IKikimrGateway {
620620
return Gateway->LoadTableMetadata(cluster, table, settings);
621621
}
622622

623+
TFuture<TGenericResult> AlterDatabase(const TString& cluster, const TAlterDatabaseSettings& settings) override {
624+
CHECK_PREPARED_DDL(AlterDatabase);
625+
626+
if (IsPrepare()) {
627+
auto alterDatabasePromise = NewPromise<TGenericResult>();
628+
629+
const auto& [dirname, basename] = NSchemeHelpers::SplitPathByDirAndBaseNames(settings.DatabasePath);
630+
631+
NKikimrSchemeOp::TModifyScheme schemeTx;
632+
schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpModifyACL);
633+
schemeTx.SetWorkingDir(dirname);
634+
schemeTx.MutableModifyACL()->SetNewOwner(settings.Owner.value());
635+
schemeTx.MutableModifyACL()->SetName(basename);
636+
637+
auto condition = schemeTx.AddApplyIf();
638+
condition->AddPathTypes(NKikimrSchemeOp::EPathType::EPathTypeSubDomain);
639+
condition->AddPathTypes(NKikimrSchemeOp::EPathType::EPathTypeExtSubDomain);
640+
641+
auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();
642+
auto& phyTx = *phyQuery.AddTransactions();
643+
phyTx.SetType(NKqpProto::TKqpPhyTx::TYPE_SCHEME);
644+
645+
phyTx.MutableSchemeOperation()->MutableModifyPermissions()->Swap(&schemeTx);
646+
TGenericResult result;
647+
result.SetSuccess();
648+
alterDatabasePromise.SetValue(result);
649+
return alterDatabasePromise.GetFuture();
650+
} else {
651+
return Gateway->AlterDatabase(cluster, settings);
652+
}
653+
}
654+
623655
TFuture<TGenericResult> CreateTable(TKikimrTableMetadataPtr metadata, bool createDir, bool existingOk, bool replaceIfExists) override {
624656
Y_UNUSED(replaceIfExists);
625657
CHECK_PREPARED_DDL(CreateTable);

ydb/core/kqp/provider/yql_kikimr_datasink.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,12 @@ class TKiSinkIntentDeterminationTransformer: public TKiSinkVisitorTransformer {
287287
return TStatus::Ok;
288288
}
289289

290+
TStatus HandleAlterDatabase(TKiAlterDatabase node, TExprContext& ctx) override {
291+
Y_UNUSED(ctx);
292+
Y_UNUSED(node);
293+
return TStatus::Ok;
294+
}
295+
290296
TStatus HandleCreateTopic(TKiCreateTopic node, TExprContext& ctx) override {
291297
Y_UNUSED(ctx);
292298
Y_UNUSED(node);
@@ -615,7 +621,8 @@ class TKiSinkIntentDeterminationTransformer: public TKiSinkVisitorTransformer {
615621

616622
case TKikimrKey::Type::TableList:
617623
break;
618-
624+
case TKikimrKey::Type::Database:
625+
return TStatus::Ok;
619626
case TKikimrKey::Type::Role:
620627
return TStatus::Ok;
621628
case TKikimrKey::Type::Object:
@@ -790,6 +797,10 @@ class TKikimrDataSink : public TDataProviderBase
790797
}
791798

792799
bool CanExecute(const TExprNode& node) override {
800+
if (node.IsCallable(TKiAlterDatabase::CallableName())) {
801+
return true;
802+
}
803+
793804
if (node.IsCallable(TKiExecDataQuery::CallableName())) {
794805
return true;
795806
}
@@ -1230,6 +1241,23 @@ class TKikimrDataSink : public TDataProviderBase
12301241
YQL_ENSURE(key.Extract(*node->Child(2)), "Failed to extract ydb key.");
12311242

12321243
switch (key.GetKeyType()) {
1244+
case TKikimrKey::Type::Database: {
1245+
NCommon::TDatabaseSettings settings = NCommon::ParseDatabaseSettings(TExprList(node->Child(4)), ctx);
1246+
YQL_ENSURE(settings.Mode);
1247+
auto mode = settings.Mode.Cast();
1248+
1249+
if (mode == "alterDatabase") {
1250+
return Build<TKiAlterDatabase>(ctx, node->Pos())
1251+
.World(node->Child(0))
1252+
.DataSink(node->Child(1))
1253+
.DatabasePath().Build(key.GetDatabasePath())
1254+
.Settings(settings.Other)
1255+
.Done()
1256+
.Ptr();
1257+
}
1258+
1259+
break;
1260+
}
12331261
case TKikimrKey::Type::Table: {
12341262
NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings(TExprList(node->Child(4)), ctx);
12351263
YQL_ENSURE(settings.Mode);
@@ -2031,6 +2059,10 @@ IGraphTransformer::TStatus TKiSinkVisitorTransformer::DoTransform(TExprNode::TPt
20312059

20322060
auto callable = TCallable(input);
20332061

2062+
if (auto node = callable.Maybe<TKiAlterDatabase>()) {
2063+
return HandleAlterDatabase(node.Cast(), ctx);
2064+
}
2065+
20342066
if (auto node = callable.Maybe<TKiWriteTable>()) {
20352067
return HandleWriteTable(node.Cast(), ctx);
20362068
}

ydb/core/kqp/provider/yql_kikimr_datasource.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ class TKiSourceIntentDeterminationTransformer: public TKiSourceVisitorTransforme
136136
private:
137137
TStatus HandleKey(const TStringBuf& cluster, const TKikimrKey& key) {
138138
switch (key.GetKeyType()) {
139+
case TKikimrKey::Type::Database:
140+
return TStatus::Ok;
141+
139142
case TKikimrKey::Type::Table:
140143
case TKikimrKey::Type::TableScheme: {
141144
auto& table = SessionCtx->Tables().GetOrAddTable(TString(cluster), SessionCtx->GetDatabase(),

ydb/core/kqp/provider/yql_kikimr_exec.cpp

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,31 @@ namespace {
100100
return permissionsSettings;
101101
}
102102

103+
TAlterDatabaseSettings ParseAlterDatabaseSettings(TKiAlterDatabase alterDatabase) {
104+
TAlterDatabaseSettings alterDatabaseSettings;
105+
YQL_ENSURE(alterDatabase.DatabasePath().Value().size() > 0);
106+
alterDatabaseSettings.DatabasePath = alterDatabase.DatabasePath().Value();
107+
108+
for (auto setting : alterDatabase.Settings()) {
109+
const auto& name = setting.Name().Value();
110+
111+
if (name == "owner") {
112+
alterDatabaseSettings.Owner = setting.Value().Cast<TCoAtom>().StringValue();
113+
} else {
114+
YQL_ENSURE(false);
115+
}
116+
}
117+
118+
return alterDatabaseSettings;
119+
}
120+
103121
TCreateUserSettings ParseCreateUserSettings(TKiCreateUser createUser) {
104122
TCreateUserSettings createUserSettings;
105123
createUserSettings.UserName = TString(createUser.UserName());
106124
createUserSettings.CanLogin = true;
107125

108126
for (auto setting : createUser.Settings()) {
109-
auto name = setting.Name().Value();
127+
const auto& name = setting.Name().Value();
110128
if (name == "password") {
111129
createUserSettings.Password = setting.Value().Cast<TCoAtom>().StringValue();
112130
} else if (name == "nullPassword") {
@@ -120,6 +138,8 @@ namespace {
120138
createUserSettings.CanLogin = true;
121139
} else if (name == "noLogin") {
122140
createUserSettings.CanLogin = false;
141+
} else {
142+
YQL_ENSURE(false);
123143
}
124144
}
125145
return createUserSettings;
@@ -130,7 +150,7 @@ namespace {
130150
alterUserSettings.UserName = TString(alterUser.UserName());
131151

132152
for (auto setting : alterUser.Settings()) {
133-
auto name = setting.Name().Value();
153+
const auto& name = setting.Name().Value();
134154
if (name == "password") {
135155
alterUserSettings.Password = setting.Value().Cast<TCoAtom>().StringValue();
136156
} else if (name == "nullPassword") {
@@ -144,6 +164,8 @@ namespace {
144164
alterUserSettings.CanLogin = true;
145165
} else if (name == "noLogin") {
146166
alterUserSettings.CanLogin = false;
167+
} else {
168+
YQL_ENSURE(false);
147169
}
148170
}
149171
return alterUserSettings;
@@ -1361,6 +1383,25 @@ class TKiSinkCallableExecutionTransformer : public TAsyncCallbackTransformer<TKi
13611383
return SyncOk();
13621384
}
13631385

1386+
if (auto maybeAlterDatabase = TMaybeNode<TKiAlterDatabase>(input)) {
1387+
auto requireStatus = RequireChild(*input, TKiExecDataQuery::idx_World);
1388+
if (requireStatus.Level != TStatus::Ok) {
1389+
return SyncStatus(requireStatus);
1390+
}
1391+
1392+
auto cluster = TString(maybeAlterDatabase.Cast().DataSink().Cluster());
1393+
TAlterDatabaseSettings alterDatabaseSettings = ParseAlterDatabaseSettings(maybeAlterDatabase.Cast());
1394+
1395+
auto future = Gateway->AlterDatabase(cluster, alterDatabaseSettings);
1396+
1397+
return WrapFuture(future,
1398+
[](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) {
1399+
Y_UNUSED(res);
1400+
auto resultNode = ctx.NewWorld(input->Pos());
1401+
return resultNode;
1402+
}, "Executing ALTER DATABASE");
1403+
}
1404+
13641405
if (auto maybeCreate = TMaybeNode<TKiCreateTable>(input)) {
13651406
auto requireStatus = RequireChild(*input, 0);
13661407
if (requireStatus.Level != TStatus::Ok) {
@@ -1484,10 +1525,6 @@ class TKiSinkCallableExecutionTransformer : public TAsyncCallbackTransformer<TKi
14841525
auto resultNode = ctx.NewWorld(input->Pos());
14851526
return resultNode;
14861527
}, GetDropTableDebugString(tableTypeItem));
1487-
1488-
input->SetState(TExprNode::EState::ExecutionComplete);
1489-
input->SetResult(ctx.NewWorld(input->Pos()));
1490-
return SyncOk();
14911528
}
14921529

14931530
if (auto maybeAlter = TMaybeNode<TKiAlterTable>(input)) {

ydb/core/kqp/provider/yql_kikimr_expr_nodes.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@
2525
{"Index": 1, "Name": "Cluster", "Type": "TCoAtom"}
2626
]
2727
},
28+
{
29+
"Name": "TKiAlterDatabase",
30+
"Base": "TCallable",
31+
"Match": {"Type": "Callable", "Name": "KiAlterDatabase!"},
32+
"Children": [
33+
{"Index": 0, "Name": "World", "Type": "TExprBase"},
34+
{"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"},
35+
{"Index": 2, "Name": "DatabasePath", "Type": "TCoAtom"},
36+
{"Index": 3, "Name": "Settings", "Type": "TCoNameValueTupleList"}
37+
]
38+
},
2839
{
2940
"Name": "TKiVersionedTable",
3041
"Base": "TExprBase",

ydb/core/kqp/provider/yql_kikimr_gateway.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,11 @@ struct TKikimrTableMetadata : public TThrRefBase {
668668
}
669669
};
670670

671+
struct TAlterDatabaseSettings {
672+
TString DatabasePath;
673+
std::optional<TString> Owner;
674+
};
675+
671676
struct TCreateUserSettings {
672677
TString UserName;
673678
TString Password;
@@ -1142,6 +1147,8 @@ class IKikimrGateway : public TThrRefBase {
11421147
virtual NThreading::TFuture<TTableMetadataResult> LoadTableMetadata(
11431148
const TString& cluster, const TString& table, TLoadTableMetadataSettings settings) = 0;
11441149

1150+
virtual NThreading::TFuture<TGenericResult> AlterDatabase(const TString& cluster, const TAlterDatabaseSettings& settings) = 0;
1151+
11451152
virtual NThreading::TFuture<TGenericResult> CreateTable(TKikimrTableMetadataPtr metadata, bool createDir, bool existingOk = false, bool replaceIfExists = false) = 0;
11461153

11471154
virtual NThreading::TFuture<TGenericResult> SendSchemeExecuterRequest(const TString& cluster,

ydb/core/kqp/provider/yql_kikimr_opt_build.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,17 @@ bool ExploreNode(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink,
690690
return true;
691691
}
692692

693+
if (auto maybeAlterDatabase = node.Maybe<TKiAlterDatabase>()) {
694+
auto alterDatabase = maybeAlterDatabase.Cast();
695+
if (!checkDataSink(alterDatabase.DataSink())) {
696+
return false;
697+
}
698+
699+
txRes.Ops.insert(node.Raw());
700+
txRes.AddTableOperation(BuildYdbOpNode(cluster, TYdbOperation::AlterDatabase, alterDatabase.Pos(), ctx));
701+
return true;
702+
}
703+
693704
if (node.Maybe<TCoCommit>()) {
694705
return true;
695706
}

ydb/core/kqp/provider/yql_kikimr_provider.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct TKikimrData {
4040
DataSourceNames.insert(TKiReadTableScheme::CallableName());
4141
DataSourceNames.insert(TKiReadTableList::CallableName());
4242

43+
DataSinkNames.insert(TKiAlterDatabase::CallableName());
44+
4345
DataSinkNames.insert(TKiWriteTable::CallableName());
4446
DataSinkNames.insert(TKiUpdateTable::CallableName());
4547
DataSinkNames.insert(TKiDeleteTable::CallableName());
@@ -113,6 +115,7 @@ struct TKikimrData {
113115
DataOps = ModifyOps | ReadOps;
114116

115117
SchemeOps =
118+
TYdbOperation::AlterDatabase |
116119
TYdbOperation::CreateTable |
117120
TYdbOperation::DropTable |
118121
TYdbOperation::AlterTable |
@@ -465,6 +468,9 @@ bool TKikimrKey::Extract(const TExprNode& key) {
465468
KeyType = Type::BackupCollection;
466469
Target = key.Child(0)->Child(1)->Child(0)->Content();
467470
ExplicitPrefix = key.Child(0)->Child(2)->Child(0)->Content();
471+
} else if (tagName == "databasePath") {
472+
KeyType = Type::Database;
473+
Target = key.Child(0)->Child(1)->Child(0)->Content();
468474
} else {
469475
Ctx.AddError(TIssue(Ctx.GetPosition(key.Child(0)->Pos()), TString("Unexpected tag for kikimr key: ") + tagName));
470476
return false;

ydb/core/kqp/provider/yql_kikimr_provider_impl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class TKiSinkVisitorTransformer : public TSyncTransformerBase {
3131
void Rewind() override {
3232
}
3333
private:
34+
virtual TStatus HandleAlterDatabase(NNodes::TKiAlterDatabase node, TExprContext& ctx) = 0;
35+
3436
virtual TStatus HandleWriteTable(NNodes::TKiWriteTable node, TExprContext& ctx) = 0;
3537
virtual TStatus HandleUpdateTable(NNodes::TKiUpdateTable node, TExprContext& ctx) = 0;
3638
virtual TStatus HandleDeleteTable(NNodes::TKiDeleteTable node, TExprContext& ctx) = 0;
@@ -91,6 +93,7 @@ class TKiSinkVisitorTransformer : public TSyncTransformerBase {
9193
class TKikimrKey {
9294
public:
9395
enum class Type {
96+
Database,
9497
Table,
9598
TableList,
9699
TableScheme,
@@ -130,6 +133,12 @@ class TKikimrKey {
130133
return Target;
131134
}
132135

136+
TString GetDatabasePath() const {
137+
Y_DEBUG_ABORT_UNLESS(KeyType.Defined());
138+
Y_DEBUG_ABORT_UNLESS(KeyType == Type::Database);
139+
return Target;
140+
}
141+
133142
TString GetTopicPath() const {
134143
Y_DEBUG_ABORT_UNLESS(KeyType.Defined());
135144
Y_DEBUG_ABORT_UNLESS(KeyType == Type::Topic);

0 commit comments

Comments
 (0)