diff options
author | pnv1 <pnv1@yandex-team.ru> | 2022-02-09 18:18:29 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 15:58:17 +0300 |
commit | 542b4cb3a3bbb51b5a1cdedd117ee52a1e8f2032 (patch) | |
tree | a0c41781873047ff7bc2a037e93488bb06a3a1c2 | |
parent | 22c3a4d3d1df813ac66b3f08d979b8f0815bacbe (diff) | |
download | ydb-542b4cb3a3bbb51b5a1cdedd117ee52a1e8f2032.tar.gz |
Add AST handling for static credentials to ydb core, KIKIMR-14086
ref:54e4d239f1dff6dde9f633ab23cd0dad30ce996c
19 files changed, 1479 insertions, 141 deletions
diff --git a/build/mapping.conf.json b/build/mapping.conf.json index 446a792441..8cfa279c70 100644 --- a/build/mapping.conf.json +++ b/build/mapping.conf.json @@ -848,6 +848,7 @@ "1566857525": "https://storage.mds.yandex.net/get-devtools-opensource/233854/1566857525", "1566858079": "https://storage.mds.yandex.net/get-devtools-opensource/233854/1566858079", "1566858823": "https://storage.mds.yandex.net/get-devtools-opensource/233854/1566858823", + "1566898243": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1566898243", "1567835312": "https://storage.mds.yandex.net/get-devtools-opensource/233854/1567835312", "1567836530": "https://storage.mds.yandex.net/get-devtools-opensource/250854/1567836530", "1567836843": "https://storage.mds.yandex.net/get-devtools-opensource/479623/1567836843", @@ -1103,6 +1104,7 @@ "1643218667": "https://storage.mds.yandex.net/get-devtools-opensource/373962/1643218667", "1643218784": "https://storage.mds.yandex.net/get-devtools-opensource/250854/1643218784", "1643218855": "https://storage.mds.yandex.net/get-devtools-opensource/373962/1643218855", + "164589140": "https://storage.mds.yandex.net/get-devtools-opensource/233854/164589140", "1646167191": "https://storage.mds.yandex.net/get-devtools-opensource/479623/1646167191", "1646167769": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1646167769", "1646167961": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1646167961", @@ -1668,6 +1670,7 @@ "1903467824": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1903467824", "1903468113": "https://storage.mds.yandex.net/get-devtools-opensource/250854/1903468113", "1903468394": "https://storage.mds.yandex.net/get-devtools-opensource/373962/1903468394", + "1903522585": "https://storage.mds.yandex.net/get-devtools-opensource/250854/1903522585", "1912161555": "https://storage.mds.yandex.net/get-devtools-opensource/479623/1912161555", "1912161800": "https://storage.mds.yandex.net/get-devtools-opensource/233854/1912161800", "1912162060": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1912162060", @@ -3423,10 +3426,7 @@ "998732993": "https://storage.mds.yandex.net/get-devtools-opensource/250854/998732993", "999994854": "https://storage.mds.yandex.net/get-devtools-opensource/471749/999994854", "999995315": "https://storage.mds.yandex.net/get-devtools-opensource/233854/999995315", - "999995678": "https://storage.mds.yandex.net/get-devtools-opensource/479623/999995678", - "1566898243": "https://storage.mds.yandex.net/get-devtools-opensource/471749/1566898243", - "164589140": "https://storage.mds.yandex.net/get-devtools-opensource/233854/164589140", - "1903522585": "https://storage.mds.yandex.net/get-devtools-opensource/250854/1903522585" + "999995678": "https://storage.mds.yandex.net/get-devtools-opensource/479623/999995678" }, "tasks": { "1003514477": { diff --git a/ydb/core/kqp/kqp_ic_gateway.cpp b/ydb/core/kqp/kqp_ic_gateway.cpp index 26720516fd..47489a9bd5 100644 --- a/ydb/core/kqp/kqp_ic_gateway.cpp +++ b/ydb/core/kqp/kqp_ic_gateway.cpp @@ -963,6 +963,13 @@ void KqpResponseToQueryResult(const NKikimrKqp::TEvQueryResponse& response, IKqp queryResult.QueryStats = queryResponse.GetQueryStats(); } +namespace { + struct TSendRoleWrapper : public TThrRefBase { + using TMethod = std::function<void(TString&&, NYql::TAlterGroupSettings::EAction, std::vector<TString>&&)>; + TMethod SendNextRole; + }; +} + class TKikimrIcGateway : public IKqpGateway { private: struct TUserTokenData { @@ -1278,6 +1285,315 @@ public: } } + TFuture<TGenericResult> CreateUser(const TString& cluster, const NYql::TCreateUserSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + auto createUserPromise = NewPromise<TGenericResult>(); + + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + auto& createUser = *schemeTx.MutableAlterLogin()->MutableCreateUser(); + + createUser.SetUser(settings.UserName); + if (settings.Password) { + createUser.SetPassword(settings.Password); + } + + SendSchemeRequest(ev.Release()).Apply( + [createUserPromise](const TFuture<TGenericResult>& future) mutable { + createUserPromise.SetValue(future.GetValue()); + } + ); + + return createUserPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + + TFuture<TGenericResult> AlterUser(const TString& cluster, const NYql::TAlterUserSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + auto alterUserPromise = NewPromise<TGenericResult>(); + + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + auto& alterUser = *schemeTx.MutableAlterLogin()->MutableModifyUser(); + + alterUser.SetUser(settings.UserName); + if (settings.Password) { + alterUser.SetPassword(settings.Password); + } + + SendSchemeRequest(ev.Release()).Apply( + [alterUserPromise](const TFuture<TGenericResult>& future) mutable { + alterUserPromise.SetValue(future.GetValue()); + } + ); + + return alterUserPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + + TFuture<TGenericResult> DropUser(const TString& cluster, const NYql::TDropUserSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + auto dropUserPromise = NewPromise<TGenericResult>(); + + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + auto& dropUser = *schemeTx.MutableAlterLogin()->MutableRemoveUser(); + + dropUser.SetUser(settings.UserName); + + SendSchemeRequest(ev.Release()).Apply( + [dropUserPromise, &settings](const TFuture<TGenericResult>& future) mutable { + const auto& realResult = future.GetValue(); + if (!realResult.Success() && realResult.Status() == TIssuesIds::DEFAULT_ERROR && settings.Force) { + IKqpGateway::TGenericResult fakeResult; + fakeResult.SetSuccess(); + dropUserPromise.SetValue(std::move(fakeResult)); + } else { + dropUserPromise.SetValue(realResult); + } + } + ); + + return dropUserPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + + TFuture<TGenericResult> CreateGroup(const TString& cluster, const NYql::TCreateGroupSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + auto createGroupPromise = NewPromise<TGenericResult>(); + + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + auto& createGroup = *schemeTx.MutableAlterLogin()->MutableCreateGroup(); + + createGroup.SetGroup(settings.GroupName); + + SendSchemeRequest(ev.Release()).Apply( + [createGroupPromise](const TFuture<TGenericResult>& future) mutable { + createGroupPromise.SetValue(future.GetValue()); + } + ); + + return createGroupPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + + TFuture<TGenericResult> AlterGroup(const TString& cluster, NYql::TAlterGroupSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + if (!settings.Roles.size()) { + return MakeFuture(ResultFromError<TGenericResult>("No roles given for AlterGroup request")); + } + + TPromise<TGenericResult> alterGroupPromise = NewPromise<TGenericResult>(); + + auto sendRoleWrapper = MakeIntrusive<TSendRoleWrapper>(); + + sendRoleWrapper->SendNextRole = [alterGroupPromise, sendRoleWrapper, this, database = std::move(database)] + (TString&& groupName, NYql::TAlterGroupSettings::EAction action, std::vector<TString>&& rolesToSend) + mutable + { + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + switch (action) { + case NYql::TAlterGroupSettings::EAction::AddRoles: + { + auto& alterGroup = *schemeTx.MutableAlterLogin()->MutableAddGroupMembership(); + alterGroup.SetGroup(groupName); + alterGroup.SetMember(*rolesToSend.begin()); + break; + } + case NYql::TAlterGroupSettings::EAction::RemoveRoles: + { + auto& alterGroup = *schemeTx.MutableAlterLogin()->MutableRemoveGroupMembership(); + alterGroup.SetGroup(groupName); + alterGroup.SetMember(*rolesToSend.begin()); + break; + } + default: + break; + } + + std::vector<TString> restOfRoles( + std::make_move_iterator(rolesToSend.begin() + 1), + std::make_move_iterator(rolesToSend.end()) + ); + + SendSchemeRequest(ev.Release()).Apply( + [alterGroupPromise, sendRoleWrapper, groupName = std::move(groupName), action, restOfRoles = std::move(restOfRoles)] + (const TFuture<TGenericResult>& future) mutable + { + auto result = future.GetValue(); + if (!result.Success()) { + alterGroupPromise.SetValue(result); + return; + } + if (restOfRoles.size()) { + try { + sendRoleWrapper->SendNextRole(std::move(groupName), action, std::move(restOfRoles)); + } + catch (yexception& e) { + return alterGroupPromise.SetValue(ResultFromException<TGenericResult>(e)); + } + } else { + alterGroupPromise.SetValue(result); + } + } + ); + }; + + sendRoleWrapper->SendNextRole(std::move(settings.GroupName), settings.Action, std::move(settings.Roles)); + + return alterGroupPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + + TFuture<TGenericResult> DropGroup(const TString& cluster, const NYql::TDropGroupSettings& settings) override { + using TRequest = TEvTxUserProxy::TEvProposeTransaction; + + try { + if (!CheckCluster(cluster)) { + return InvalidCluster<TGenericResult>(cluster); + } + + TString database; + if (!GetDatabaseForLoginOperation(database)) { + return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name")); + } + + auto dropGroupPromise = NewPromise<TGenericResult>(); + + auto ev = MakeHolder<TRequest>(); + ev->Record.SetDatabaseName(database); + if (UserToken) { + ev->Record.SetUserToken(UserToken->Serialized); + } + auto& schemeTx = *ev->Record.MutableTransaction()->MutableModifyScheme(); + schemeTx.SetWorkingDir(database); + schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin); + auto& dropGroup = *schemeTx.MutableAlterLogin()->MutableRemoveGroup(); + + dropGroup.SetGroup(settings.GroupName); + + SendSchemeRequest(ev.Release()).Apply( + [dropGroupPromise, &settings](const TFuture<TGenericResult>& future) mutable { + const auto& realResult = future.GetValue(); + if (!realResult.Success() && realResult.Status() == TIssuesIds::DEFAULT_ERROR && settings.Force) { + IKqpGateway::TGenericResult fakeResult; + fakeResult.SetSuccess(); + dropGroupPromise.SetValue(std::move(fakeResult)); + } else { + dropGroupPromise.SetValue(realResult); + } + } + ); + + return dropGroupPromise.GetFuture(); + } + catch (yexception& e) { + return MakeFuture(ResultFromException<TGenericResult>(e)); + } + } + TFuture<TMkqlResult> ExecuteMkql(const TString& cluster, const TString& program, TKqpParamsMap&& params, const TMkqlSettings& settings, const TKqpSnapshot& snapshot) override { @@ -1822,6 +2138,20 @@ private: return promise.GetFuture(); } + bool GetDatabaseForLoginOperation(TString& database) { + TAppData* appData = AppData(ActorSystem); + if (appData && appData->AuthConfig.GetDomainLoginOnly()) { + if (appData->DomainsInfo && !appData->DomainsInfo->Domains.empty()) { + database = "/" + appData->DomainsInfo->Domains.begin()->second->Name; + return true; + } + } else { + database = Database; + return true; + } + return false; + } + private: static TRunResponse GetRunResponse(NKikimrTxUserProxy::TEvProposeTransactionStatus&& ev) { IKqpGateway::TRunResponse response; diff --git a/ydb/core/kqp/opt/kqp_opt_kql.cpp b/ydb/core/kqp/opt/kqp_opt_kql.cpp index 4e7c72c17c..1eeb95daee 100644 --- a/ydb/core/kqp/opt/kqp_opt_kql.cpp +++ b/ydb/core/kqp/opt/kqp_opt_kql.cpp @@ -566,18 +566,18 @@ TExprBase WriteTableSimple(const TKiWriteTable& write, const TCoAtomList& inputC { auto op = GetTableOp(write); switch (op) { - case TKikimrTableOperation::Upsert: + case TYdbOperation::Upsert: return BuildUpsertTable(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::Replace: + case TYdbOperation::Replace: return BuildReplaceTable(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::InsertAbort: - case TKikimrTableOperation::InsertRevert: - return BuildInsertTable(write, op == TKikimrTableOperation::InsertAbort, inputColumns, tableData, ctx); - case TKikimrTableOperation::UpdateOn: + case TYdbOperation::InsertAbort: + case TYdbOperation::InsertRevert: + return BuildInsertTable(write, op == TYdbOperation::InsertAbort, inputColumns, tableData, ctx); + case TYdbOperation::UpdateOn: return BuildUpdateOnTable(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::Delete: + case TYdbOperation::Delete: return BuildDeleteTable(write, tableData, ctx); - case TKikimrTableOperation::DeleteOn: + case TYdbOperation::DeleteOn: return BuildDeleteTable(write, tableData, ctx); default: YQL_ENSURE(false, "Unsupported table operation: " << op << ", table: " << tableData.Metadata->Name); @@ -589,16 +589,16 @@ TExprBase WriteTableWithIndexUpdate(const TKiWriteTable& write, const TCoAtomLis { auto op = GetTableOp(write); switch (op) { - case TKikimrTableOperation::Upsert: + case TYdbOperation::Upsert: return BuildUpsertTableWithIndex(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::Replace: + case TYdbOperation::Replace: return BuildReplaceTableWithIndex(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::InsertAbort: - case TKikimrTableOperation::InsertRevert: - return BuildInsertTableWithIndex(write, op == TKikimrTableOperation::InsertAbort, inputColumns, tableData, ctx); - case TKikimrTableOperation::UpdateOn: + case TYdbOperation::InsertAbort: + case TYdbOperation::InsertRevert: + return BuildInsertTableWithIndex(write, op == TYdbOperation::InsertAbort, inputColumns, tableData, ctx); + case TYdbOperation::UpdateOn: return BuildUpdateOnTableWithIndex(write, inputColumns, tableData, ctx); - case TKikimrTableOperation::DeleteOn: + case TYdbOperation::DeleteOn: return BuildDeleteTableWithIndex(write, tableData, ctx); default: YQL_ENSURE(false, "Unsupported table operation: " << (ui32)op << ", table: " << tableData.Metadata->Name); diff --git a/ydb/core/kqp/provider/yql_kikimr_datasink.cpp b/ydb/core/kqp/provider/yql_kikimr_datasink.cpp index a54616fa87..035d6b7701 100644 --- a/ydb/core/kqp/provider/yql_kikimr_datasink.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_datasink.cpp @@ -84,6 +84,42 @@ private: return TStatus::Ok; } + TStatus HandleCreateUser(TKiCreateUser node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "CreateUser is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + + TStatus HandleAlterUser(TKiAlterUser node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "AlterUser is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + + TStatus HandleDropUser(TKiDropUser node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "DropUser is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + + TStatus HandleCreateGroup(TKiCreateGroup node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "CreateGroup is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + + TStatus HandleAlterGroup(TKiAlterGroup node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "AlterGroup is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + + TStatus HandleDropGroup(TKiDropGroup node, TExprContext& ctx) override { + ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() + << "DropGroup is not yet implemented for intent determination transformer")); + return TStatus::Error; + } + TStatus HandleWrite(TExprBase node, TExprContext& ctx) override { auto cluster = node.Ref().Child(1)->Child(1)->Content(); TKikimrKey key(ctx); @@ -91,11 +127,10 @@ private: return TStatus::Error; } - NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings( - TExprList(node.Ref().ChildPtr(4)), ctx); - switch (key.GetKeyType()) { case TKikimrKey::Type::Table: { + NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings( + TExprList(node.Ref().ChildPtr(4)), ctx); if (!settings.Mode) { ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() << "Mode option is required for Kikimr table writes.")); @@ -146,6 +181,8 @@ private: } case TKikimrKey::Type::TableScheme: { + NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings( + TExprList(node.Ref().ChildPtr(4)), ctx); if (!settings.Mode) { ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() << "Mode option is required for Kikimr scheme writes.")); @@ -180,6 +217,9 @@ private: case TKikimrKey::Type::TableList: break; + + case TKikimrKey::Type::Role: + return TStatus::Ok; } ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), "Invalid table key type.")); @@ -388,6 +428,15 @@ public: return true; } + if (node.IsCallable(TKiCreateUser::CallableName()) + || node.IsCallable(TKiAlterUser::CallableName()) + || node.IsCallable(TKiDropUser::CallableName()) + || node.IsCallable(TKiCreateGroup::CallableName()) + || node.IsCallable(TKiAlterGroup::CallableName()) + || node.IsCallable(TKiDropGroup::CallableName())) { + return true; + } + if (auto maybeRight = TMaybeNode<TCoNth>(&node).Tuple().Maybe<TCoRight>()) { if (maybeRight.Input().Maybe<TKiExecDataQuery>()) { return true; @@ -431,12 +480,11 @@ public: YQL_ENSURE(node->IsCallable(WriteName), "Expected Write!, got: " << node->Content()); TKikimrKey key(ctx); - YQL_ENSURE(key.Extract(*node->Child(2)), "Failed to extract table key."); - - NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings(TExprList(node->Child(4)), ctx); + YQL_ENSURE(key.Extract(*node->Child(2)), "Failed to extract ydb key."); switch (key.GetKeyType()) { case TKikimrKey::Type::Table: { + NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings(TExprList(node->Child(4)), ctx); YQL_ENSURE(settings.Mode); auto mode = settings.Mode.Cast(); @@ -483,7 +531,7 @@ public: } case TKikimrKey::Type::TableScheme: { - + NCommon::TWriteTableSettings settings = NCommon::ParseWriteTableSettings(TExprList(node->Child(4)), ctx); YQL_ENSURE(settings.Mode); auto mode = settings.Mode.Cast(); if (mode == "create") { @@ -532,12 +580,71 @@ public: .Done() .Ptr(); } else { - YQL_ENSURE(false, "unknown mode"); + YQL_ENSURE(false, "unknown TableScheme mode \"" << TString(mode) << "\""); } } case TKikimrKey::Type::TableList: break; + + case TKikimrKey::Type::Role: { + NCommon::TWriteRoleSettings settings = NCommon::ParseWriteRoleSettings(TExprList(node->Child(4)), ctx); + YQL_ENSURE(settings.Mode); + auto mode = settings.Mode.Cast(); + + if (mode == "createUser") { + return Build<TKiCreateUser>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .UserName().Build(key.GetRoleName()) + .Settings(settings.Other) + .Done() + .Ptr(); + } else if (mode == "alterUser") { + return Build<TKiAlterUser>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .UserName().Build(key.GetRoleName()) + .Settings(settings.Other) + .Done() + .Ptr(); + } else if (mode == "dropUser") { + return Build<TKiDropUser>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .UserName().Build(key.GetRoleName()) + .Settings(settings.Other) + .Done() + .Ptr(); + } else if (mode == "createGroup") { + return Build<TKiCreateGroup>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .GroupName().Build(key.GetRoleName()) + .Done() + .Ptr(); + } else if (mode == "addUsersToGroup" || mode == "dropUsersFromGroup") { + return Build<TKiAlterGroup>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .GroupName().Build(key.GetRoleName()) + .Action().Build(mode) + .Roles(settings.Roles.Cast()) + .Done() + .Ptr(); + } else if (mode == "dropGroup") { + return Build<TKiDropGroup>(ctx, node->Pos()) + .World(node->Child(0)) + .DataSink(node->Child(1)) + .GroupName().Build(key.GetRoleName()) + .Settings(settings.Other) + .Done() + .Ptr(); + } else { + YQL_ENSURE(false, "unknown Role mode \"" << TString(mode) << "\""); + } + break; + } } ctx.AddError(TIssue(ctx.GetPosition(node->Pos()), "Failed to rewrite IO.")); @@ -619,6 +726,30 @@ IGraphTransformer::TStatus TKiSinkVisitorTransformer::DoTransform(TExprNode::TPt return HandleDropTable(node.Cast(), ctx); } + if (auto node = TMaybeNode<TKiCreateUser>(input)) { + return HandleCreateUser(node.Cast(), ctx); + } + + if (auto node = TMaybeNode<TKiAlterUser>(input)) { + return HandleAlterUser(node.Cast(), ctx); + } + + if (auto node = TMaybeNode<TKiDropUser>(input)) { + return HandleDropUser(node.Cast(), ctx); + } + + if (auto node = TMaybeNode<TKiCreateGroup>(input)) { + return HandleCreateGroup(node.Cast(), ctx); + } + + if (auto node = TMaybeNode<TKiAlterGroup>(input)) { + return HandleAlterGroup(node.Cast(), ctx); + } + + if (auto node = TMaybeNode<TKiDropGroup>(input)) { + return HandleDropGroup(node.Cast(), ctx); + } + if (input->IsCallable(WriteName)) { return HandleWrite(TExprBase(input), ctx); } diff --git a/ydb/core/kqp/provider/yql_kikimr_datasource.cpp b/ydb/core/kqp/provider/yql_kikimr_datasource.cpp index ad4aea1319..65ef7eb932 100644 --- a/ydb/core/kqp/provider/yql_kikimr_datasource.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_datasource.cpp @@ -25,7 +25,7 @@ private: return TStatus::Error; } - return HandleTable(cluster, key); + return HandleKey(cluster, key); } TStatus HandleRead(TExprBase node, TExprContext& ctx) override { @@ -35,7 +35,7 @@ private: return TStatus::Error; } - return HandleTable(cluster, key); + return HandleKey(cluster, key); } TStatus HandleLength(TExprBase node, TExprContext& ctx) override { @@ -51,7 +51,7 @@ private: } private: - TStatus HandleTable(const TStringBuf& cluster, const TKikimrKey& key) { + TStatus HandleKey(const TStringBuf& cluster, const TKikimrKey& key) { switch (key.GetKeyType()) { case TKikimrKey::Type::Table: case TKikimrKey::Type::TableScheme: { @@ -66,6 +66,9 @@ private: case TKikimrKey::Type::TableList: return TStatus::Ok; + + case TKikimrKey::Type::Role: + return TStatus::Ok; } return TStatus::Error; diff --git a/ydb/core/kqp/provider/yql_kikimr_exec.cpp b/ydb/core/kqp/provider/yql_kikimr_exec.cpp index f253d657d2..ad360fcaeb 100644 --- a/ydb/core/kqp/provider/yql_kikimr_exec.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_exec.cpp @@ -16,26 +16,111 @@ using namespace NNodes; using namespace NCommon; using namespace NThreading; -bool EnsureNotPrepare(const TString featureName, TPositionHandle pos, const TKikimrQueryContext& queryCtx, - TExprContext& ctx) -{ - if (queryCtx.PrepareOnly && !queryCtx.SuppressDdlChecks) { - ctx.AddError(TIssue(ctx.GetPosition(pos), TStringBuilder() - << "'" << featureName << "' not supported in query prepare mode." )); - return false; +namespace { + bool EnsureNotPrepare(const TString featureName, TPositionHandle pos, const TKikimrQueryContext& queryCtx, + TExprContext& ctx) + { + if (queryCtx.PrepareOnly && !queryCtx.SuppressDdlChecks) { + ctx.AddError(TIssue(ctx.GetPosition(pos), TStringBuilder() + << "'" << featureName << "' not supported in query prepare mode.")); + return false; + } + + return true; } - return true; -} + void FillExecDataQueryAst(TKiExecDataQuery exec, const TString& ast, TExprContext& ctx) { + auto astNode = Build<TCoAtom>(ctx, exec.Pos()) + .Value(ast) + .Done(); -void FillExecDataQueryAst(TKiExecDataQuery exec, const TString& ast, TExprContext& ctx) { - auto astNode = Build<TCoAtom>(ctx, exec.Pos()) - .Value(ast) - .Done(); + astNode.Ptr()->SetTypeAnn(ctx.MakeType<TUnitExprType>()); + + exec.Ptr()->ChildRef(TKiExecDataQuery::idx_Ast) = astNode.Ptr(); + } + + TCreateUserSettings ParseCreateUserSettings(TKiCreateUser createUser) { + TCreateUserSettings createUserSettings; + createUserSettings.UserName = TString(createUser.UserName()); + + for (auto setting : createUser.Settings()) { + auto name = setting.Name().Value(); + if (name == "password") { + createUserSettings.Password = setting.Value().Cast<TCoAtom>().StringValue(); + } else if (name == "nullPassword") { + // Default value + } else if (name == "passwordEncrypted") { + createUserSettings.PasswordEncrypted = true; + } + } + return createUserSettings; + } + + TAlterUserSettings ParseAlterUserSettings(TKiAlterUser alterUser) { + TAlterUserSettings alterUserSettings; + alterUserSettings.UserName = TString(alterUser.UserName()); + + for (auto setting : alterUser.Settings()) { + auto name = setting.Name().Value(); + if (name == "password") { + alterUserSettings.Password = setting.Value().Cast<TCoAtom>().StringValue(); + } else if (name == "nullPassword") { + // Default value + } else if (name == "passwordEncrypted") { + alterUserSettings.PasswordEncrypted = true; + } + } + return alterUserSettings; + } + + TDropUserSettings ParseDropUserSettings(TKiDropUser dropUser) { + TDropUserSettings dropUserSettings; + dropUserSettings.UserName = TString(dropUser.UserName()); + + for (auto setting : dropUser.Settings()) { + auto name = setting.Name().Value(); + if (name == "force") { + dropUserSettings.Force = true; + } + } + return dropUserSettings; + } + + TCreateGroupSettings ParseCreateGroupSettings(TKiCreateGroup createGroup) { + TCreateGroupSettings createGroupSettings; + createGroupSettings.GroupName = TString(createGroup.GroupName()); + return createGroupSettings; + } + + TAlterGroupSettings ParseAlterGroupSettings(TKiAlterGroup alterGroup) { + TAlterGroupSettings alterGroupSettings; + alterGroupSettings.GroupName = TString(alterGroup.GroupName()); + + TString action = TString(alterGroup.Action()); + if (action == "addUsersToGroup") { + alterGroupSettings.Action = TAlterGroupSettings::EAction::AddRoles; + } else if (action == "dropUsersFromGroup") { + alterGroupSettings.Action = TAlterGroupSettings::EAction::RemoveRoles; + } + + for (auto role : alterGroup.Roles()) { + alterGroupSettings.Roles.push_back(role.Cast<TCoAtom>().StringValue()); + } + return alterGroupSettings; + } - astNode.Ptr()->SetTypeAnn(ctx.MakeType<TUnitExprType>()); + TDropGroupSettings ParseDropGroupSettings(TKiDropGroup dropGroup) { + TDropGroupSettings dropGroupSettings; + dropGroupSettings.GroupName = TString(dropGroup.GroupName()); - exec.Ptr()->ChildRef(TKiExecDataQuery::idx_Ast) = astNode.Ptr(); + for (auto setting : dropGroup.Settings()) { + auto name = setting.Name().Value(); + if (name == "force") { + dropGroupSettings.Force = true; + } + } + return dropGroupSettings; + } } class TKiSinkPlanInfoTransformer : public TGraphTransformerBase { @@ -378,7 +463,7 @@ public: auto cluster = TString(maybeCreate.Cast().DataSink().Cluster()); auto& table = SessionCtx->Tables().GetTable(cluster, TString(maybeCreate.Cast().Table())); - if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TKikimrTableOperation::Create, ctx)) { + if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TYdbOperation::CreateTable, ctx)) { return SyncError(); } @@ -405,7 +490,7 @@ public: auto cluster = TString(maybeDrop.Cast().DataSink().Cluster()); auto& table = SessionCtx->Tables().GetTable(cluster, TString(maybeDrop.Cast().Table())); - if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TKikimrTableOperation::Drop, ctx)) { + if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TYdbOperation::DropTable, ctx)) { return SyncError(); } @@ -436,7 +521,7 @@ public: auto cluster = TString(maybeAlter.Cast().DataSink().Cluster()); auto& table = SessionCtx->Tables().GetTable(cluster, TString(maybeAlter.Cast().Table())); - if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TKikimrTableOperation::Alter, ctx)) { + if (!ApplyDdlOperation(cluster, input->Pos(), table.Metadata->Name, TYdbOperation::AlterTable, ctx)) { return SyncError(); } @@ -744,6 +829,144 @@ public: } + if (auto maybeCreateUser = TMaybeNode<TKiCreateUser>(input)) { + if (!EnsureNotPrepare("CREATE USER", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeCreateUser.Cast().DataSink().Cluster()); + TCreateUserSettings createUserSettings = ParseCreateUserSettings(maybeCreateUser.Cast()); + + auto future = Gateway->CreateUser(cluster, createUserSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing CREATE USER"); + } + + if (auto maybeAlterUser = TMaybeNode<TKiAlterUser>(input)) { + if (!EnsureNotPrepare("ALTER USER", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeAlterUser.Cast().DataSink().Cluster()); + TAlterUserSettings alterUserSettings = ParseAlterUserSettings(maybeAlterUser.Cast()); + + auto future = Gateway->AlterUser(cluster, alterUserSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing ALTER USER"); + } + + if (auto maybeDropUser = TMaybeNode<TKiDropUser>(input)) { + if (!EnsureNotPrepare("DROP USER", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeDropUser.Cast().DataSink().Cluster()); + TDropUserSettings dropUserSettings = ParseDropUserSettings(maybeDropUser.Cast()); + + auto future = Gateway->DropUser(cluster, dropUserSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing DROP USER"); + } + + if (auto maybeCreateGroup = TMaybeNode<TKiCreateGroup>(input)) { + if (!EnsureNotPrepare("CREATE GROUP", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeCreateGroup.Cast().DataSink().Cluster()); + TCreateGroupSettings createGroupSettings = ParseCreateGroupSettings(maybeCreateGroup.Cast()); + + auto future = Gateway->CreateGroup(cluster, createGroupSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing CREATE GROUP"); + } + + if (auto maybeAlterGroup = TMaybeNode<TKiAlterGroup>(input)) { + if (!EnsureNotPrepare("ALTER GROUP", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeAlterGroup.Cast().DataSink().Cluster()); + TAlterGroupSettings alterGroupSettings = ParseAlterGroupSettings(maybeAlterGroup.Cast()); + + auto future = Gateway->AlterGroup(cluster, alterGroupSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing ALTER GROUP"); + } + + if (auto maybeDropGroup = TMaybeNode<TKiDropGroup>(input)) { + if (!EnsureNotPrepare("DROP GROUP", input->Pos(), SessionCtx->Query(), ctx)) { + return SyncError(); + } + + auto requireStatus = RequireChild(*input, 0); + if (requireStatus.Level != TStatus::Ok) { + return SyncStatus(requireStatus); + } + + auto cluster = TString(maybeDropGroup.Cast().DataSink().Cluster()); + TDropGroupSettings dropGroupSettings = ParseDropGroupSettings(maybeDropGroup.Cast()); + + auto future = Gateway->DropGroup(cluster, dropGroupSettings); + + return WrapFuture(future, + [](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) { + Y_UNUSED(res); + auto resultNode = ctx.NewWorld(input->Pos()); + return resultNode; + }, "Executing DROP GROUP"); + } + ctx.AddError(TIssue(ctx.GetPosition(input->Pos()), TStringBuilder() << "(Kikimr DataSink) Failed to execute node: " << input->Content())); return SyncError(); @@ -893,7 +1116,7 @@ private: } bool ApplyDdlOperation(const TString& cluster, TPositionHandle pos, const TString& table, - TKikimrTableOperation op, TExprContext& ctx) + TYdbOperation op, TExprContext& ctx) { YQL_ENSURE(op & KikimrSchemeOps()); diff --git a/ydb/core/kqp/provider/yql_kikimr_expr_nodes.json b/ydb/core/kqp/provider/yql_kikimr_expr_nodes.json index f6952f3d86..c54d82a2ca 100644 --- a/ydb/core/kqp/provider/yql_kikimr_expr_nodes.json +++ b/ydb/core/kqp/provider/yql_kikimr_expr_nodes.json @@ -143,6 +143,72 @@ ] }, { + "Name": "TKiCreateUser", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiCreateUser!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "UserName", "Type": "TCoAtom"}, + {"Index": 3, "Name": "Settings", "Type": "TCoNameValueTupleList"} + ] + }, + { + "Name": "TKiAlterUser", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiAlterUser!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "UserName", "Type": "TCoAtom"}, + {"Index": 3, "Name": "Settings", "Type": "TCoNameValueTupleList"} + ] + }, + { + "Name": "TKiDropUser", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiDropUser!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "UserName", "Type": "TCoAtom"}, + {"Index": 3, "Name": "Settings", "Type": "TCoNameValueTupleList"} + ] + }, + { + "Name": "TKiCreateGroup", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiCreateGroup!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "GroupName", "Type": "TCoAtom"} + ] + }, + { + "Name": "TKiAlterGroup", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiAlterGroup!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "GroupName", "Type": "TCoAtom"}, + {"Index": 3, "Name": "Action", "Type": "TCoAtom"}, + {"Index": 4, "Name": "Roles", "Type": "TCoAtomList"} + ] + }, + { + "Name": "TKiDropGroup", + "Base": "TCallable", + "Match": {"Type": "Callable", "Name": "KiDropGroup!"}, + "Children": [ + {"Index": 0, "Name": "World", "Type": "TExprBase"}, + {"Index": 1, "Name": "DataSink", "Type": "TKiDataSink"}, + {"Index": 2, "Name": "GroupName", "Type": "TCoAtom"}, + {"Index": 3, "Name": "Settings", "Type": "TCoNameValueTupleList"} + ] + }, + { "Name": "TKiOperation", "Base": "TExprBase", "Match": {"Type": "Tuple"}, diff --git a/ydb/core/kqp/provider/yql_kikimr_gateway.h b/ydb/core/kqp/provider/yql_kikimr_gateway.h index cf7e704cb2..7598494a2b 100644 --- a/ydb/core/kqp/provider/yql_kikimr_gateway.h +++ b/ydb/core/kqp/provider/yql_kikimr_gateway.h @@ -421,6 +421,42 @@ struct TKikimrTableMetadata : public TThrRefBase { } }; +struct TCreateUserSettings { + TString UserName; + TString Password; + bool PasswordEncrypted = false; +}; + +struct TAlterUserSettings { + TString UserName; + TString Password; + bool PasswordEncrypted = false; +}; + +struct TDropUserSettings { + TString UserName; + bool Force = false; +}; + +struct TCreateGroupSettings { + TString GroupName; +}; + +struct TAlterGroupSettings { + enum class EAction : ui32 { + AddRoles = 0, + RemoveRoles = 1, + }; + + TString GroupName; + EAction Action; + std::vector<TString> Roles; +}; + +struct TDropGroupSettings { + TString GroupName; + bool Force = false; +}; struct TKikimrListPathItem { TKikimrListPathItem(TString name, bool isDirectory) { @@ -567,6 +603,18 @@ public: virtual NThreading::TFuture<TGenericResult> DropTable(const TString& cluster, const TString& table) = 0; + virtual NThreading::TFuture<TGenericResult> CreateUser(const TString& cluster, const TCreateUserSettings& settings) = 0; + + virtual NThreading::TFuture<TGenericResult> AlterUser(const TString& cluster, const TAlterUserSettings& settings) = 0; + + virtual NThreading::TFuture<TGenericResult> DropUser(const TString& cluster, const TDropUserSettings& settings) = 0; + + virtual NThreading::TFuture<TGenericResult> CreateGroup(const TString& cluster, const TCreateGroupSettings& settings) = 0; + + virtual NThreading::TFuture<TGenericResult> AlterGroup(const TString& cluster, TAlterGroupSettings& settings) = 0; + + virtual NThreading::TFuture<TGenericResult> DropGroup(const TString& cluster, const TDropGroupSettings& settings) = 0; + virtual TVector<TString> GetCollectedSchemeData() = 0; public: diff --git a/ydb/core/kqp/provider/yql_kikimr_kql.cpp b/ydb/core/kqp/provider/yql_kikimr_kql.cpp index 3d9256bfb3..95f5915a57 100644 --- a/ydb/core/kqp/provider/yql_kikimr_kql.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_kql.cpp @@ -325,7 +325,7 @@ TExprNode::TPtr KiUpsertTableToKql(const TKiWriteTable& node, TExprContext& ctx, } TExprNode::TPtr KiInsertTableToKql(const TKiWriteTable& node, TExprContext& ctx, const TKikimrTableDescription& table, - const TKikimrTableOperation& op, TExprNode::TPtr& effect) + const TYdbOperation& op, TExprNode::TPtr& effect) { auto fetchItemArg = Build<TCoArgument>(ctx, node.Pos()) .Name("fetchItem") @@ -394,14 +394,14 @@ TExprNode::TPtr KiInsertTableToKql(const TKiWriteTable& node, TExprContext& ctx, TExprNode::TPtr insertEffect; auto insertKql = KiUpsertTableToKql(node, ctx, table, false, true, insertEffect); - if (op == TKikimrTableOperation::InsertAbort) { + if (op == TYdbOperation::InsertAbort) { effect = Build<TKiAbortIf>(ctx, node.Pos()) .Predicate(predicate) .Effect(insertEffect) .Constraint().Build("insert_pk") .Done() .Ptr(); - } else if (op == TKikimrTableOperation::InsertRevert) { + } else if (op == TYdbOperation::InsertRevert) { effect = Build<TKiRevertIf>(ctx, node.Pos()) .Predicate(predicate) .Effect(insertEffect) @@ -790,15 +790,15 @@ TExprNode::TPtr KiWriteTableToKql(TKiWriteTable write, TExprContext& ctx, auto& tableDesc = tablesData.ExistingTable(TString(cluster), TString(table)); switch (op) { - case TKikimrTableOperation::Upsert: - case TKikimrTableOperation::Replace: - return KiUpsertTableToKql(write, ctx, tableDesc, op == TKikimrTableOperation::Replace, false, effect); - case TKikimrTableOperation::InsertRevert: - case TKikimrTableOperation::InsertAbort: + case TYdbOperation::Upsert: + case TYdbOperation::Replace: + return KiUpsertTableToKql(write, ctx, tableDesc, op == TYdbOperation::Replace, false, effect); + case TYdbOperation::InsertRevert: + case TYdbOperation::InsertAbort: return KiInsertTableToKql(write, ctx, tableDesc, op, effect); - case TKikimrTableOperation::DeleteOn: + case TYdbOperation::DeleteOn: return KiDeleteOnTableToKql(write, ctx, tableDesc, effect); - case TKikimrTableOperation::UpdateOn: + case TYdbOperation::UpdateOn: return KiUpdateOnTableToKql(write, ctx, tableDesc, effect); default: return nullptr; diff --git a/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp b/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp index 5510cd5721..0ba0b34952 100644 --- a/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp @@ -10,7 +10,7 @@ namespace { using namespace NNodes; using namespace NCommon; -TKiOperation BuildTableOpNode(const TCoAtom& cluster, const TStringBuf& table, TKikimrTableOperation op, TPositionHandle pos, +TKiOperation BuildTableOpNode(const TCoAtom& cluster, const TStringBuf& table, TYdbOperation op, TPositionHandle pos, TExprContext& ctx) { return Build<TKiOperation>(ctx, pos) @@ -20,6 +20,14 @@ TKiOperation BuildTableOpNode(const TCoAtom& cluster, const TStringBuf& table, T .Done(); } +TKiOperation BuildYdbOpNode(const TCoAtom& cluster, TYdbOperation op, TPositionHandle pos, TExprContext& ctx) { + return Build<TKiOperation>(ctx, pos) + .Cluster().Build(cluster) + .Table().Build("") + .Operation<TCoAtom>().Build(ToString(op)) + .Done(); +} + TCoAtomList GetResultColumns(const TResWriteBase& resWrite, TExprContext& ctx) { TExprNode::TListType columns; auto columnsSetting = GetSetting(resWrite.Settings().Ref(), "columns"); @@ -75,7 +83,7 @@ struct TKiExploreTxResults { hasScheme = false; hasData = false; for (auto& node : TableOperations) { - auto op = FromString<TKikimrTableOperation>(TString(node.Operation())); + auto op = FromString<TYdbOperation>(TString(node.Operation())); hasScheme = hasScheme || (op & KikimrSchemeOps()); hasData = hasData || (op & KikimrDataOps()); } @@ -122,7 +130,7 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = key.GetTablePath(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(maybeRead.Cast().World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Select, read.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::Select, read.Pos(), ctx)); return result; } @@ -150,7 +158,7 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = update.Table().Value(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(update.World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Update, update.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::Update, update.Pos(), ctx)); txRes.Effects.push_back(node); return result; } @@ -164,7 +172,7 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = del.Table().Value(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(del.World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Delete, del.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::Delete, del.Pos(), ctx)); txRes.Effects.push_back(node); return result; } @@ -178,7 +186,7 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = create.Table().Value(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(create.World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Create, create.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::CreateTable, create.Pos(), ctx)); return result; } @@ -191,7 +199,7 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = drop.Table().Value(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(drop.World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Drop, drop.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::DropTable, drop.Pos(), ctx)); return result; } @@ -204,7 +212,79 @@ bool ExploreTx(TExprBase node, TExprContext& ctx, const TKiDataSink& dataSink, T auto table = alter.Table().Value(); txRes.Ops.insert(node.Raw()); auto result = ExploreTx(alter.World(), ctx, dataSink, txRes); - txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TKikimrTableOperation::Alter, alter.Pos(), ctx)); + txRes.TableOperations.push_back(BuildTableOpNode(cluster, table, TYdbOperation::AlterTable, alter.Pos(), ctx)); + return result; + } + + if (auto maybeCreateUser = node.Maybe<TKiCreateUser>()) { + auto createUser = maybeCreateUser.Cast(); + if (!checkDataSink(createUser.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(createUser.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::CreateUser, createUser.Pos(), ctx)); + return result; + } + + if (auto maybeAlterUser = node.Maybe<TKiAlterUser>()) { + auto alterUser = maybeAlterUser.Cast(); + if (!checkDataSink(alterUser.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(alterUser.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::AlterUser, alterUser.Pos(), ctx)); + return result; + } + + if (auto maybeDropUser = node.Maybe<TKiDropUser>()) { + auto dropUser = maybeDropUser.Cast(); + if (!checkDataSink(dropUser.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(dropUser.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::DropUser, dropUser.Pos(), ctx)); + return result; + } + + if (auto maybeCreateGroup = node.Maybe<TKiCreateGroup>()) { + auto createGroup = maybeCreateGroup.Cast(); + if (!checkDataSink(createGroup.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(createGroup.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::CreateGroup, createGroup.Pos(), ctx)); + return result; + } + + if (auto maybeAlterGroup = node.Maybe<TKiAlterGroup>()) { + auto alterGroup = maybeAlterGroup.Cast(); + if (!checkDataSink(alterGroup.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(alterGroup.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::AlterGroup, alterGroup.Pos(), ctx)); + return result; + } + + if (auto maybeDropGroup = node.Maybe<TKiDropGroup>()) { + auto dropGroup = maybeDropGroup.Cast(); + if (!checkDataSink(dropGroup.DataSink())) { + return false; + } + + txRes.Ops.insert(node.Raw()); + auto result = ExploreTx(dropGroup.World(), ctx, dataSink, txRes); + txRes.TableOperations.push_back(BuildYdbOpNode(cluster, TYdbOperation::DropGroup, dropGroup.Pos(), ctx)); return result; } @@ -545,20 +625,20 @@ TExprNode::TPtr KiBuildResult(TExprBase node, const TString& cluster, TExprCont return ctx.ChangeChild(*ctx.ChangeChild(resFill.Ref(), 0, world.Ptr()), 3, data.Ptr()); } -TKikimrTableOperation GetTableOp(const TKiWriteTable& write) { +TYdbOperation GetTableOp(const TKiWriteTable& write) { auto mode = write.Mode().Value(); if (mode == "upsert") { - return TKikimrTableOperation::Upsert; + return TYdbOperation::Upsert; } else if (mode == "replace") { - return TKikimrTableOperation::Replace; + return TYdbOperation::Replace; } else if (mode == "insert_revert") { - return TKikimrTableOperation::InsertRevert; + return TYdbOperation::InsertRevert; } else if (mode == "insert_abort") { - return TKikimrTableOperation::InsertAbort; + return TYdbOperation::InsertAbort; } else if (mode == "delete_on") { - return TKikimrTableOperation::DeleteOn; + return TYdbOperation::DeleteOn; } else if (mode == "update_on") { - return TKikimrTableOperation::UpdateOn; + return TYdbOperation::UpdateOn; } YQL_ENSURE(false, "Unexpected TKiWriteTable mode: " << mode); diff --git a/ydb/core/kqp/provider/yql_kikimr_provider.cpp b/ydb/core/kqp/provider/yql_kikimr_provider.cpp index 94a93c4e0d..635d164827 100644 --- a/ydb/core/kqp/provider/yql_kikimr_provider.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_provider.cpp @@ -25,11 +25,11 @@ struct TKikimrData { THashSet<TStringBuf> CommitModes; THashSet<TStringBuf> SupportedEffects; - TKikimrTableOperations SchemeOps; - TKikimrTableOperations DataOps; - TKikimrTableOperations ModifyOps; - TKikimrTableOperations ReadOps; - TKikimrTableOperations RequireUnmodifiedOps; + TYdbOperations SchemeOps; + TYdbOperations DataOps; + TYdbOperations ModifyOps; + TYdbOperations ReadOps; + TYdbOperations RequireUnmodifiedOps; TMap<TString, NKikimr::NUdf::EDataSlot> SystemColumns; @@ -45,6 +45,12 @@ struct TKikimrData { DataSinkNames.insert(TKiCreateTable::CallableName()); DataSinkNames.insert(TKiAlterTable::CallableName()); DataSinkNames.insert(TKiDropTable::CallableName()); + DataSinkNames.insert(TKiCreateUser::CallableName()); + DataSinkNames.insert(TKiAlterUser::CallableName()); + DataSinkNames.insert(TKiDropUser::CallableName()); + DataSinkNames.insert(TKiCreateGroup::CallableName()); + DataSinkNames.insert(TKiAlterGroup::CallableName()); + DataSinkNames.insert(TKiDropGroup::CallableName()); DataSinkNames.insert(TKiDataQuery::CallableName()); DataSinkNames.insert(TKiExecDataQuery::CallableName()); DataSinkNames.insert(TKiEffects::CallableName()); @@ -71,31 +77,37 @@ struct TKikimrData { SupportedEffects.insert(TKiDeleteTable::CallableName()); ModifyOps = - TKikimrTableOperation::Upsert | - TKikimrTableOperation::Replace | - TKikimrTableOperation::Update | - TKikimrTableOperation::UpdateOn | - TKikimrTableOperation::Delete | - TKikimrTableOperation::DeleteOn | - TKikimrTableOperation::InsertRevert | - TKikimrTableOperation::InsertAbort; + TYdbOperation::Upsert | + TYdbOperation::Replace | + TYdbOperation::Update | + TYdbOperation::UpdateOn | + TYdbOperation::Delete | + TYdbOperation::DeleteOn | + TYdbOperation::InsertRevert | + TYdbOperation::InsertAbort; ReadOps = - TKikimrTableOperation::Select | - TKikimrTableOperation::Update | - TKikimrTableOperation::Delete; + TYdbOperation::Select | + TYdbOperation::Update | + TYdbOperation::Delete; DataOps = ModifyOps | ReadOps; SchemeOps = - TKikimrTableOperation::Create | - TKikimrTableOperation::Drop | - TKikimrTableOperation::Alter; + TYdbOperation::CreateTable | + TYdbOperation::DropTable | + TYdbOperation::AlterTable | + TYdbOperation::CreateUser | + TYdbOperation::AlterUser | + TYdbOperation::DropUser | + TYdbOperation::CreateGroup | + TYdbOperation::AlterGroup | + TYdbOperation::DropGroup; RequireUnmodifiedOps = - TKikimrTableOperation::InsertRevert | - TKikimrTableOperation::InsertAbort | - TKikimrTableOperation::UpdateOn; // TODO: KIKIMR-3206 + TYdbOperation::InsertRevert | + TYdbOperation::InsertAbort | + TYdbOperation::UpdateOn; // TODO: KIKIMR-3206 SystemColumns = { {"_yql_partition_id", NKikimr::NUdf::EDataSlot::Uint64} @@ -328,15 +340,18 @@ bool TKikimrKey::Extract(const TExprNode& key) { return false; } - Path = nameNode->Child(0)->Content(); + Target = nameNode->Child(0)->Content(); } else if (tagName == "tablescheme") { KeyType = Type::TableScheme; - Path = key.Child(0)->Child(1)->Child(0)->Content(); + Target = key.Child(0)->Child(1)->Child(0)->Content(); } else if (tagName == "tablelist") { KeyType = Type::TableList; - Path = key.Child(0)->Child(1)->Child(0)->Content(); + Target = key.Child(0)->Child(1)->Child(0)->Content(); + } else if (tagName == "role") { + KeyType = Type::Role; + Target = key.Child(0)->Child(1)->Child(0)->Content(); } else { - Ctx.AddError(TIssue(Ctx.GetPosition(key.Child(0)->Pos()), TString("Unexpected tag: ") + tagName)); + Ctx.AddError(TIssue(Ctx.GetPosition(key.Child(0)->Pos()), TString("Unexpected tag for kikimr key: ") + tagName)); return false; } @@ -361,7 +376,7 @@ bool TKikimrKey::Extract(const TExprNode& key) { View = viewNode->Child(0)->Content(); } else { - Ctx.AddError(TIssue(Ctx.GetPosition(tag->Pos()), TStringBuilder() << "Unexpected tag: " << tag->Content())); + Ctx.AddError(TIssue(Ctx.GetPosition(tag->Pos()), TStringBuilder() << "Unexpected tag for kikimr key child: " << tag->Content())); return false; } } @@ -473,7 +488,7 @@ TVector<NKqpProto::TKqpTableOp> TableOperationsToProto(const TCoNameValueTupleLi TVector<NKqpProto::TKqpTableOp> protoOps; for (const auto& op : operations) { auto table = TString(op.Name()); - auto tableOp = FromString<TKikimrTableOperation>(TString(op.Value().Cast<TCoAtom>())); + auto tableOp = FromString<TYdbOperation>(TString(op.Value().Cast<TCoAtom>())); auto pos = ctx.GetPosition(op.Pos()); NKqpProto::TKqpTableOp protoOp; @@ -492,7 +507,7 @@ TVector<NKqpProto::TKqpTableOp> TableOperationsToProto(const TKiOperationList& o TVector<NKqpProto::TKqpTableOp> protoOps; for (const auto& op : operations) { auto table = TString(op.Table()); - auto tableOp = FromString<TKikimrTableOperation>(TString(op.Operation())); + auto tableOp = FromString<TYdbOperation>(TString(op.Operation())); auto pos = ctx.GetPosition(op.Pos()); NKqpProto::TKqpTableOp protoOp; @@ -550,7 +565,7 @@ bool TKikimrTransactionContextBase::ApplyTableOperations(const TVector<NKqpProto for (const auto& op : operations) { const auto& table = op.GetTable(); - auto newOp = TKikimrTableOperation(op.GetOperation()); + auto newOp = TYdbOperation(op.GetOperation()); TPosition pos(op.GetPosition().GetColumn(), op.GetPosition().GetRow()); const auto info = tableInfoMap.FindPtr(table); @@ -629,8 +644,8 @@ bool TKikimrTransactionContextBase::ApplyTableOperations(const TVector<NKqpProto } // TODO: KIKIMR-3206 - bool currentDelete = currentOps & (TKikimrTableOperation::Delete | TKikimrTableOperation::DeleteOn); - bool newUpdate = newOp == TKikimrTableOperation::Update; + bool currentDelete = currentOps & (TYdbOperation::Delete | TYdbOperation::DeleteOn); + bool newUpdate = newOp == TYdbOperation::Update; if (currentDelete && newUpdate) { TString message = TStringBuilder() << "Operation '" << newOp << "' may lead to unexpected results when applied to table with deleted rows: " << table; @@ -677,23 +692,23 @@ const TStringBuf& KikimrCommitModeScheme() { return CommitModeScheme; } -const TKikimrTableOperations& KikimrSchemeOps() { +const TYdbOperations& KikimrSchemeOps() { return Singleton<TKikimrData>()->SchemeOps; } -const TKikimrTableOperations& KikimrDataOps() { +const TYdbOperations& KikimrDataOps() { return Singleton<TKikimrData>()->DataOps; } -const TKikimrTableOperations& KikimrModifyOps() { +const TYdbOperations& KikimrModifyOps() { return Singleton<TKikimrData>()->ModifyOps; } -const TKikimrTableOperations& KikimrReadOps() { +const TYdbOperations& KikimrReadOps() { return Singleton<TKikimrData>()->ReadOps; } -const TKikimrTableOperations& KikimrRequireUnmodifiedOps() { +const TYdbOperations& KikimrRequireUnmodifiedOps() { return Singleton<TKikimrData>()->RequireUnmodifiedOps; } diff --git a/ydb/core/kqp/provider/yql_kikimr_provider.h b/ydb/core/kqp/provider/yql_kikimr_provider.h index 59dc659a27..6903e6f193 100644 --- a/ydb/core/kqp/provider/yql_kikimr_provider.h +++ b/ydb/core/kqp/provider/yql_kikimr_provider.h @@ -231,10 +231,10 @@ private: THashMap<std::pair<TString, TString>, TKikimrTableDescription> Tables; }; -enum class TKikimrTableOperation : ui32 { - Create = 1 << 0, - Drop = 1 << 1, - Alter = 1 << 2, +enum class TYdbOperation : ui32 { + CreateTable = 1 << 0, + DropTable = 1 << 1, + AlterTable = 1 << 2, Select = 1 << 3, Upsert = 1 << 4, Replace = 1 << 5, @@ -245,10 +245,16 @@ enum class TKikimrTableOperation : ui32 { ReservedInsertIgnore = 1 << 10, UpdateOn = 1 << 11, DeleteOn = 1 << 12, + CreateUser = 1 << 13, + AlterUser = 1 << 14, + DropUser = 1 << 15, + CreateGroup = 1 << 16, + AlterGroup = 1 << 17, + DropGroup = 1 << 18 }; -Y_DECLARE_FLAGS(TKikimrTableOperations, TKikimrTableOperation) -Y_DECLARE_OPERATORS_FOR_FLAGS(TKikimrTableOperations) +Y_DECLARE_FLAGS(TYdbOperations, TYdbOperation) +Y_DECLARE_OPERATORS_FOR_FLAGS(TYdbOperations) class IKikimrTransactionContext : public TThrRefBase { public: @@ -267,7 +273,7 @@ public: class TKikimrTransactionContextBase : public IKikimrTransactionContext { public: - THashMap<TString, TKikimrTableOperations> TableOperations; + THashMap<TString, TYdbOperations> TableOperations; THashMap<TKikimrPathId, TString> TableByIdMap; TMaybe<NKikimrKqp::EIsolationLevel> EffectiveIsolationLevel; bool Readonly = false; diff --git a/ydb/core/kqp/provider/yql_kikimr_provider_impl.h b/ydb/core/kqp/provider/yql_kikimr_provider_impl.h index 7864e16ae9..e1aa3cda2b 100644 --- a/ydb/core/kqp/provider/yql_kikimr_provider_impl.h +++ b/ydb/core/kqp/provider/yql_kikimr_provider_impl.h @@ -34,6 +34,12 @@ private: virtual TStatus HandleCreateTable(NNodes::TKiCreateTable node, TExprContext& ctx) = 0; virtual TStatus HandleAlterTable(NNodes::TKiAlterTable node, TExprContext& ctx) = 0; virtual TStatus HandleDropTable(NNodes::TKiDropTable node, TExprContext& ctx) = 0; + virtual TStatus HandleCreateUser(NNodes::TKiCreateUser node, TExprContext& ctx) = 0; + virtual TStatus HandleAlterUser(NNodes::TKiAlterUser node, TExprContext& ctx) = 0; + virtual TStatus HandleDropUser(NNodes::TKiDropUser node, TExprContext& ctx) = 0; + virtual TStatus HandleCreateGroup(NNodes::TKiCreateGroup node, TExprContext& ctx) = 0; + virtual TStatus HandleAlterGroup(NNodes::TKiAlterGroup node, TExprContext& ctx) = 0; + virtual TStatus HandleDropGroup(NNodes::TKiDropGroup node, TExprContext& ctx) = 0; virtual TStatus HandleWrite(NNodes::TExprBase node, TExprContext& ctx) = 0; virtual TStatus HandleCommit(NNodes::TCoCommit node, TExprContext& ctx) = 0; virtual TStatus HandleKql(NNodes::TCallable node, TExprContext& ctx) = 0; @@ -47,7 +53,8 @@ public: enum class Type { Table, TableList, - TableScheme + TableScheme, + Role }; public: @@ -62,13 +69,19 @@ public: TString GetTablePath() const { Y_VERIFY_DEBUG(KeyType.Defined()); Y_VERIFY_DEBUG(KeyType == Type::Table || KeyType == Type::TableScheme); - return Path; + return Target; } TString GetFolderPath() const { Y_VERIFY_DEBUG(KeyType.Defined()); Y_VERIFY_DEBUG(KeyType == Type::TableList); - return Path; + return Target; + } + + TString GetRoleName() const { + Y_VERIFY_DEBUG(KeyType.Defined()); + Y_VERIFY_DEBUG(KeyType == Type::Role); + return Target; } const TMaybe<TString>& GetView() const { @@ -80,7 +93,7 @@ public: private: TExprContext& Ctx; TMaybe<Type> KeyType; - TString Path; + TString Target; TMaybe<TString> View; }; @@ -219,7 +232,7 @@ const TTypeAnnotationNode* GetReadTableRowType(TExprContext& ctx, const TKikimrT NKikimrKqp::EIsolationLevel GetIsolationLevel(const TMaybe<TString>& isolationLevel); TMaybe<TString> GetIsolationLevel(const NKikimrKqp::EIsolationLevel& isolationLevel); -TKikimrTableOperation GetTableOp(const NNodes::TKiWriteTable& write); +TYdbOperation GetTableOp(const NNodes::TKiWriteTable& write); TVector<NKqpProto::TKqpTableOp> TableOperationsToProto(const NNodes::TCoNameValueTupleList& operations, TExprContext& ctx); TVector<NKqpProto::TKqpTableOp> TableOperationsToProto(const NNodes::TKiOperationList& operations, TExprContext& ctx); void TableDescriptionToTableInfo(const TKikimrTableDescription& desc, NKqpProto::TKqpTableInfo* info); @@ -257,11 +270,11 @@ const TStringBuf& KikimrCommitModeFlush(); const TStringBuf& KikimrCommitModeRollback(); const TStringBuf& KikimrCommitModeScheme(); -const TKikimrTableOperations& KikimrSchemeOps(); -const TKikimrTableOperations& KikimrDataOps(); -const TKikimrTableOperations& KikimrModifyOps(); -const TKikimrTableOperations& KikimrReadOps(); -const TKikimrTableOperations& KikimrRequireUnmodifiedOps(); +const TYdbOperations& KikimrSchemeOps(); +const TYdbOperations& KikimrDataOps(); +const TYdbOperations& KikimrModifyOps(); +const TYdbOperations& KikimrReadOps(); +const TYdbOperations& KikimrRequireUnmodifiedOps(); const TMap<TString, NKikimr::NUdf::EDataSlot>& KikimrSystemColumns(); bool IsKikimrSystemColumn(const TStringBuf columnName); diff --git a/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp b/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp index 3a73bfe78d..692165204a 100644 --- a/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp @@ -190,6 +190,11 @@ private: node.Ptr()->SetTypeAnn(ctx.MakeType<TTupleExprType>(children)); return TStatus::Ok; } + + case TKikimrKey::Type::Role: + { + return TStatus::Ok; + } } return TStatus::Error; @@ -366,8 +371,8 @@ private: } auto op = GetTableOp(node); - if (op == TKikimrTableOperation::InsertAbort || op == TKikimrTableOperation::InsertRevert || - op == TKikimrTableOperation::Upsert || op == TKikimrTableOperation::Replace) { + if (op == TYdbOperation::InsertAbort || op == TYdbOperation::InsertRevert || + op == TYdbOperation::Upsert || op == TYdbOperation::Replace) { for (const auto& [name, meta] : table->Metadata->Columns) { if (meta.NotNull && !rowType->FindItem(name)) { ctx.AddError(YqlIssue(pos, TIssuesIds::KIKIMR_NO_COLUMN_DEFAULT_VALUE, TStringBuilder() @@ -383,7 +388,7 @@ private: return TStatus::Error; } } - } else if (op == TKikimrTableOperation::UpdateOn) { + } else if (op == TYdbOperation::UpdateOn) { for (const auto& item : rowType->GetItems()) { auto column = table->Metadata->Columns.FindPtr(TString(item->GetName())); YQL_ENSURE(column); @@ -1017,6 +1022,112 @@ private: return TStatus::Ok; } + virtual TStatus HandleCreateUser(TKiCreateUser node, TExprContext& ctx) override { + for (const auto& setting : node.Settings()) { + auto name = setting.Name().Value(); + if (name == "password") { + if (!EnsureAtom(setting.Value().Ref(), ctx)) { + return TStatus::Error; + } + } else if (name == "passwordEncrypted") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "passwordEncrypted node shouldn't have value" << name)); + } + } else if (name == "nullPassword") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "nullPassword node shouldn't have value" << name)); + } + } else { + ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()), + TStringBuilder() << "Unknown create user setting: " << name)); + return TStatus::Error; + } + } + + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + + virtual TStatus HandleAlterUser(TKiAlterUser node, TExprContext& ctx) override { + for (const auto& setting : node.Settings()) { + auto name = setting.Name().Value(); + if (name == "password") { + if (!EnsureAtom(setting.Value().Ref(), ctx)) { + return TStatus::Error; + } + } else if (name == "passwordEncrypted") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "passwordEncrypted node shouldn't have value" << name)); + } + } else if (name == "nullPassword") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "nullPassword node shouldn't have value" << name)); + } + } else { + ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()), + TStringBuilder() << "Unknown alter user setting: " << name)); + return TStatus::Error; + } + } + + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + + virtual TStatus HandleDropUser(TKiDropUser node, TExprContext& ctx) override { + for (const auto& setting : node.Settings()) { + auto name = setting.Name().Value(); + if (name == "force") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "force node shouldn't have value" << name)); + } + } else { + ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()), + TStringBuilder() << "Unknown drop user setting: " << name)); + return TStatus::Error; + } + } + + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + + virtual TStatus HandleCreateGroup(TKiCreateGroup node, TExprContext& ctx) override { + Y_UNUSED(ctx); + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + + virtual TStatus HandleAlterGroup(TKiAlterGroup node, TExprContext& ctx) override { + Y_UNUSED(ctx); + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + + virtual TStatus HandleDropGroup(TKiDropGroup node, TExprContext& ctx) override { + for (const auto& setting : node.Settings()) { + auto name = setting.Name().Value(); + if (name == "force") { + if (setting.Value()) { + ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()), + TStringBuilder() << "force node shouldn't have value" << name)); + } + } else { + ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()), + TStringBuilder() << "Unknown drop group setting: " << name)); + return TStatus::Error; + } + } + + node.Ptr()->SetTypeAnn(node.World().Ref().GetTypeAnn()); + return TStatus::Ok; + } + virtual TStatus HandleWrite(TExprBase node, TExprContext& ctx) override { ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), "Failed to annotate Write!, IO rewrite should handle this")); return TStatus::Error; diff --git a/ydb/core/kqp/ut/kqp_scheme_ut.cpp b/ydb/core/kqp/ut/kqp_scheme_ut.cpp index b1f70501e1..ca7ffa42a4 100644 --- a/ydb/core/kqp/ut/kqp_scheme_ut.cpp +++ b/ydb/core/kqp/ut/kqp_scheme_ut.cpp @@ -1886,7 +1886,272 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_EQUAL(decimalType.Scale, 9); } } + + Y_UNIT_TEST(CreateUserWithPassword) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 ENCRYPTED PASSWORD 'password1'; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 PASSWORD NULL; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); + } + } + + Y_UNIT_TEST(CreateUserWithoutPassword) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1; + )"; + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + } + + Y_UNIT_TEST(CreateAndDropUser) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + { + // Drop non-existing user force + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP USER IF EXISTS user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 PASSWORD 'password1'; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop existing user + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP USER user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 PASSWORD NULL; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop existing user force + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP USER IF EXISTS user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop non-existing user + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP USER user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); + } + } + + Y_UNIT_TEST(AlterUser) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 PASSWORD 'password1'; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER USER user1 WITH PASSWORD 'password2'; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER USER user1 WITH ENCRYPTED PASSWORD 'password3'; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER USER user1 WITH PASSWORD NULL; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + } + + Y_UNIT_TEST(CreateAndDropGroup) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + { + // Drop non-existing group force + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP GROUP IF EXISTS group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE GROUP group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop existing group + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP GROUP group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE GROUP group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop existing group force + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP GROUP IF EXISTS group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + // Drop non-existing group + auto query = TStringBuilder() << R"( + --!syntax_v1 + DROP GROUP group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); + } + } + + Y_UNIT_TEST(AlterGroup) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE USER user1 PASSWORD 'password1'; + CREATE USER user2 PASSWORD 'password2'; + CREATE USER user3; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + CREATE GROUP group1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER GROUP group1 ADD USER user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER GROUP group1 DROP USER user1; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER GROUP group1 ADD USER user1, user2; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + { + auto query = TStringBuilder() << R"( + --!syntax_v1 + ALTER GROUP group1 DROP USER user1, user2; + )"; + auto session = db.CreateSession().GetValueSync().GetSession(); + auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + } } -} // namspace NKqp +} // namespace NKqp } // namespace NKikimr diff --git a/ydb/library/yql/providers/common/provider/yql_provider.cpp b/ydb/library/yql/providers/common/provider/yql_provider.cpp index c57a8093e4..aa782ee93f 100644 --- a/ydb/library/yql/providers/common/provider/yql_provider.cpp +++ b/ydb/library/yql/providers/common/provider/yql_provider.cpp @@ -283,6 +283,38 @@ TWriteTableSettings ParseWriteTableSettings(TExprList node, TExprContext& ctx) { return ret; } +TWriteRoleSettings ParseWriteRoleSettings(TExprList node, TExprContext& ctx) { + TMaybeNode<TCoAtom> mode; + TMaybeNode<TCoAtomList> roles; + TVector<TCoNameValueTuple> other; + for (auto child : node) { + if (auto maybeTuple = child.Maybe<TCoNameValueTuple>()) { + auto tuple = maybeTuple.Cast(); + auto name = tuple.Name().Value(); + + if (name == "mode") { + YQL_ENSURE(tuple.Value().Maybe<TCoAtom>()); + mode = tuple.Value().Cast<TCoAtom>(); + } else if (name == "roles") { + YQL_ENSURE(tuple.Value().Maybe<TCoAtomList>()); + roles = tuple.Value().Cast<TCoAtomList>(); + } else { + other.push_back(tuple); + } + } + } + + const auto& otherSettings = Build<TCoNameValueTupleList>(ctx, node.Pos()) + .Add(other) + .Done(); + + TWriteRoleSettings ret(otherSettings); + ret.Roles = roles; + ret.Mode = mode; + + return ret; +} + TCommitSettings ParseCommitSettings(NNodes::TCoCommit node, TExprContext& ctx) { if (!node.Settings()) { return TCommitSettings(Build<TCoNameValueTupleList>(ctx, node.Pos()).Done()); diff --git a/ydb/library/yql/providers/common/provider/yql_provider.h b/ydb/library/yql/providers/common/provider/yql_provider.h index 15e7738045..9e80cfd135 100644 --- a/ydb/library/yql/providers/common/provider/yql_provider.h +++ b/ydb/library/yql/providers/common/provider/yql_provider.h @@ -51,6 +51,15 @@ struct TWriteTableSettings { : Other(other) {} }; +struct TWriteRoleSettings { + NNodes::TMaybeNode<NNodes::TCoAtom> Mode; + NNodes::TMaybeNode<NNodes::TCoAtomList> Roles; + NNodes::TCoNameValueTupleList Other; + + TWriteRoleSettings(const NNodes::TCoNameValueTupleList& other) + : Other(other) {} +}; + struct TCommitSettings { TPositionHandle Pos; @@ -78,6 +87,8 @@ TVector<TString> GetResOrPullColumnHints(const TExprNode& node); TWriteTableSettings ParseWriteTableSettings(NNodes::TExprList node, TExprContext& ctx); +TWriteRoleSettings ParseWriteRoleSettings(NNodes::TExprList node, TExprContext& ctx); + TCommitSettings ParseCommitSettings(NNodes::TCoCommit node, TExprContext& ctx); TString FullTableName(const TStringBuf& cluster, const TStringBuf& table); diff --git a/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.cpp b/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.cpp index fecbdbb7fc..80a9e5c14d 100644 --- a/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.cpp +++ b/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.cpp @@ -28,15 +28,18 @@ bool TYdbKey::Extract(const TExprNode& key, TExprContext& ctx) { return false; } - Path = nameNode->Head().Content(); + Target = nameNode->Head().Content(); } else if (tagName == "tablescheme") { KeyType = Type::TableScheme; - Path = key.Head().Child(1)->Head().Content(); + Target = key.Head().Child(1)->Head().Content(); } else if (tagName == "tablelist") { KeyType = Type::TableList; - Path = key.Head().Child(1)->Head().Content(); + Target = key.Head().Child(1)->Head().Content(); + } else if (tagName == "role") { + KeyType = Type::Role; + Target = key.Head().Child(1)->Head().Content(); } else { - ctx.AddError(TIssue(ctx.GetPosition(key.Head().Pos()), TString("Unexpected tag: ") += tagName)); + ctx.AddError(TIssue(ctx.GetPosition(key.Head().Pos()), TString("Unexpected tag for YDB key: ") += tagName)); return false; } @@ -60,7 +63,7 @@ bool TYdbKey::Extract(const TExprNode& key, TExprContext& ctx) { View = viewNode->Head().Content(); } else { - ctx.AddError(TIssue(ctx.GetPosition(tag.Pos()), TString("Unexpected tag: ") += tag.Content())); + ctx.AddError(TIssue(ctx.GetPosition(tag.Pos()), TString("Unexpected tag for YDB key child: ") += tag.Content())); return false; } } diff --git a/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.h b/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.h index be21dacf97..454c019d58 100644 --- a/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.h +++ b/ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.h @@ -31,7 +31,8 @@ public: enum class Type { Table, TableList, - TableScheme + TableScheme, + Role }; public: @@ -43,12 +44,12 @@ public: std::string_view GetTablePath() const { Y_VERIFY_DEBUG(KeyType == Type::Table || KeyType == Type::TableScheme); - return Path; + return Target; } std::string_view GetFolderPath() const { Y_VERIFY_DEBUG(KeyType == Type::TableList); - return Path; + return Target; } const std::optional<std::string_view>& GetView() const { @@ -59,7 +60,7 @@ public: private: std::optional<Type> KeyType; - std::string_view Path; + std::string_view Target; std::optional<std::string_view> View; }; |