aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpnv1 <pnv1@yandex-team.ru>2022-02-09 18:18:29 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 15:58:17 +0300
commit542b4cb3a3bbb51b5a1cdedd117ee52a1e8f2032 (patch)
treea0c41781873047ff7bc2a037e93488bb06a3a1c2
parent22c3a4d3d1df813ac66b3f08d979b8f0815bacbe (diff)
downloadydb-542b4cb3a3bbb51b5a1cdedd117ee52a1e8f2032.tar.gz
Add AST handling for static credentials to ydb core, KIKIMR-14086
ref:54e4d239f1dff6dde9f633ab23cd0dad30ce996c
-rw-r--r--build/mapping.conf.json8
-rw-r--r--ydb/core/kqp/kqp_ic_gateway.cpp330
-rw-r--r--ydb/core/kqp/opt/kqp_opt_kql.cpp30
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_datasink.cpp147
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_datasource.cpp9
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_exec.cpp261
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_expr_nodes.json66
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_gateway.h48
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_kql.cpp20
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_opt_build.cpp110
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_provider.cpp89
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_provider.h20
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_provider_impl.h33
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_type_ann.cpp117
-rw-r--r--ydb/core/kqp/ut/kqp_scheme_ut.cpp267
-rw-r--r--ydb/library/yql/providers/common/provider/yql_provider.cpp32
-rw-r--r--ydb/library/yql/providers/common/provider/yql_provider.h11
-rw-r--r--ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.cpp13
-rw-r--r--ydb/library/yql/providers/ydb/provider/yql_ydb_provider_impl.h9
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;
};