aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvpolka <vpolka@yandex-team.com>2023-11-23 14:31:48 +0300
committervpolka <vpolka@yandex-team.com>2023-11-23 16:10:51 +0300
commit207ac81618e05ade724a8a8193bc9125d466bd06 (patch)
tree3d413edf0790e408136e56c71440360c72f6754f
parent3444af692d32224288c41ba8c21e416d5fd4996c (diff)
downloadydb-207ac81618e05ade724a8a8193bc9125d466bd06.tar.gz
KIKIMR-20078: drop/alter/create user
-rw-r--r--ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp16
-rw-r--r--ydb/core/kqp/gateway/kqp_gateway.h5
-rw-r--r--ydb/core/kqp/gateway/kqp_ic_gateway.cpp49
-rw-r--r--ydb/core/kqp/host/kqp_gateway_proxy.cpp106
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_datasink.cpp2
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_exec.cpp21
-rw-r--r--ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp15
-rw-r--r--ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp30
-rw-r--r--ydb/core/protos/flat_scheme_op.proto1
-rw-r--r--ydb/core/protos/kqp_physical.proto3
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp5
-rw-r--r--ydb/library/login/login.cpp4
-rw-r--r--ydb/library/login/login.h1
-rw-r--r--ydb/library/yql/sql/pg/pg_sql.cpp6
14 files changed, 213 insertions, 51 deletions
diff --git a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
index 60757028b8..2fdbf74c10 100644
--- a/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
+++ b/ydb/core/kqp/executer_actor/kqp_scheme_executer.cpp
@@ -133,6 +133,22 @@ public:
return StartBuildOperation();
}
+ case NKqpProto::TKqpSchemeOperation::kCreateUser: {
+ auto modifyScheme = schemeOp.GetCreateUser();
+ ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ break;
+ }
+ case NKqpProto::TKqpSchemeOperation::kAlterUser: {
+ auto modifyScheme = schemeOp.GetAlterUser();
+ ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ break;
+ }
+ case NKqpProto::TKqpSchemeOperation::kDropUser: {
+ auto modifyScheme = schemeOp.GetDropUser();
+ ev->Record.MutableTransaction()->MutableModifyScheme()->CopyFrom(modifyScheme);
+ break;
+ }
+
default:
InternalError(TStringBuilder() << "Unexpected scheme operation: "
<< (ui32) schemeOp.GetOperationCase());
diff --git a/ydb/core/kqp/gateway/kqp_gateway.h b/ydb/core/kqp/gateway/kqp_gateway.h
index f5d267d09f..42f43b0240 100644
--- a/ydb/core/kqp/gateway/kqp_gateway.h
+++ b/ydb/core/kqp/gateway/kqp_gateway.h
@@ -163,6 +163,8 @@ public:
public:
virtual TString GetDatabase() = 0;
+ virtual bool GetDomainLoginOnly() = 0;
+ virtual TMaybe<TString> GetDomainName() = 0;
/* Scheme */
virtual NThreading::TFuture<TKqpTableProfilesResult> GetTableProfiles() = 0;
@@ -201,6 +203,9 @@ TIntrusivePtr<IKqpGateway> CreateKikimrIcGateway(const TString& cluster, const T
bool SplitTablePath(const TString& tableName, const TString& database, std::pair<TString, TString>& pathPair,
TString& error, bool createDir);
+bool SetDatabaseForLoginOperation(TString& result, bool getDomainLoginOnly, TMaybe<TString> domainName,
+ const TString& database);
+
} // namespace NKikimr::NKqp
template<>
diff --git a/ydb/core/kqp/gateway/kqp_ic_gateway.cpp b/ydb/core/kqp/gateway/kqp_ic_gateway.cpp
index aa024e9613..f9d0c0e262 100644
--- a/ydb/core/kqp/gateway/kqp_ic_gateway.cpp
+++ b/ydb/core/kqp/gateway/kqp_ic_gateway.cpp
@@ -630,6 +630,21 @@ public:
UserToken = token;
}
+ bool GetDomainLoginOnly() override {
+ TAppData* appData = AppData(ActorSystem);
+ return appData && appData->AuthConfig.GetDomainLoginOnly();
+ }
+
+ TMaybe<TString> GetDomainName() override {
+ TAppData* appData = AppData(ActorSystem);
+ if (GetDomainLoginOnly()) {
+ if (appData->DomainsInfo && !appData->DomainsInfo->Domains.empty()) {
+ return appData->DomainsInfo->Domains.begin()->second->Name;
+ }
+ }
+ return {};
+ }
+
TVector<NKikimrKqp::TKqpTableMetadataProto> GetCollectedSchemeData() override {
return MetadataLoader->GetCollectedSchemeData();
}
@@ -1368,17 +1383,11 @@ public:
auto& dropUser = *schemeTx.MutableAlterLogin()->MutableRemoveUser();
dropUser.SetUser(settings.UserName);
+ dropUser.SetMissingOk(settings.Force);
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);
- }
+ [dropUserPromise](const TFuture<TGenericResult>& future) mutable {
+ dropUserPromise.SetValue(future.GetValue());
}
);
@@ -2094,17 +2103,7 @@ private:
}
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;
+ return SetDatabaseForLoginOperation(database, GetDomainLoginOnly(), GetDomainName(), GetDatabase());
}
bool GetPathPair(const TString& tableName, std::pair<TString, TString>& pathPair,
@@ -2267,6 +2266,16 @@ bool SplitTablePath(const TString& tableName, const TString& database, std::pair
}
}
+bool SetDatabaseForLoginOperation(TString& result, bool getDomainLoginOnly, TMaybe<TString> domainName,
+ const TString& database)
+{
+ if (getDomainLoginOnly && !domainName) {
+ return false;
+ }
+ result = domainName ? "/" + *domainName : database;
+ return true;
+}
+
} // namespace NKqp
} // namespace NKikimr
diff --git a/ydb/core/kqp/host/kqp_gateway_proxy.cpp b/ydb/core/kqp/host/kqp_gateway_proxy.cpp
index 97a2f8ddca..eae247ec57 100644
--- a/ydb/core/kqp/host/kqp_gateway_proxy.cpp
+++ b/ydb/core/kqp/host/kqp_gateway_proxy.cpp
@@ -778,15 +778,107 @@ public:
}
TFuture<TGenericResult> CreateUser(const TString& cluster, const TCreateUserSettings& settings) override {
- FORWARD_ENSURE_NO_PREPARE(CreateUser, cluster, settings);
+ CHECK_PREPARED_DDL(CreateUser);
+
+ auto createUserPromise = NewPromise<TGenericResult>();
+
+ TString database;
+ if (!SetDatabaseForLoginOperation(database, GetDomainLoginOnly(), GetDomainName(), GetDatabase())) {
+ return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name"));
+ }
+
+ NKikimrSchemeOp::TModifyScheme schemeTx;
+ schemeTx.SetWorkingDir(database);
+ schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin);
+ auto& createUser = *schemeTx.MutableAlterLogin()->MutableCreateUser();
+ createUser.SetUser(settings.UserName);
+ if (settings.Password) {
+ createUser.SetPassword(settings.Password);
+ }
+
+ if (IsPrepare()) {
+ auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();
+ auto& phyTx = *phyQuery.AddTransactions();
+ phyTx.SetType(NKqpProto::TKqpPhyTx::TYPE_SCHEME);
+
+ phyTx.MutableSchemeOperation()->MutableCreateUser()->Swap(&schemeTx);
+
+ TGenericResult result;
+ result.SetSuccess();
+ createUserPromise.SetValue(result);
+ } else {
+ return Gateway->CreateUser(cluster, settings);
+ }
+
+ return createUserPromise.GetFuture();
}
TFuture<TGenericResult> AlterUser(const TString& cluster, const TAlterUserSettings& settings) override {
- FORWARD_ENSURE_NO_PREPARE(AlterUser, cluster, settings);
+ CHECK_PREPARED_DDL(AlterUser);
+
+ auto alterUserPromise = NewPromise<TGenericResult>();
+
+ TString database;
+ if (!SetDatabaseForLoginOperation(database, GetDomainLoginOnly(), GetDomainName(), GetDatabase())) {
+ return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name"));
+ }
+
+ NKikimrSchemeOp::TModifyScheme schemeTx;
+ schemeTx.SetWorkingDir(database);
+ schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin);
+ auto& alterUser = *schemeTx.MutableAlterLogin()->MutableModifyUser();
+ alterUser.SetUser(settings.UserName);
+ if (settings.Password) {
+ alterUser.SetPassword(settings.Password);
+ }
+
+ if (IsPrepare()) {
+ auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();
+ auto& phyTx = *phyQuery.AddTransactions();
+ phyTx.SetType(NKqpProto::TKqpPhyTx::TYPE_SCHEME);
+
+ phyTx.MutableSchemeOperation()->MutableAlterUser()->Swap(&schemeTx);
+ TGenericResult result;
+ result.SetSuccess();
+ alterUserPromise.SetValue(result);
+ } else {
+ return Gateway->AlterUser(cluster, settings);
+ }
+
+ return alterUserPromise.GetFuture();
}
TFuture<TGenericResult> DropUser(const TString& cluster, const TDropUserSettings& settings) override {
- FORWARD_ENSURE_NO_PREPARE(DropUser, cluster, settings);
+ CHECK_PREPARED_DDL(DropUser);
+
+ auto dropUserPromise = NewPromise<TGenericResult>();
+
+ TString database;
+ if (!SetDatabaseForLoginOperation(database, GetDomainLoginOnly(), GetDomainName(), GetDatabase())) {
+ return MakeFuture(ResultFromError<TGenericResult>("Couldn't get domain name"));
+ }
+
+ NKikimrSchemeOp::TModifyScheme schemeTx;
+ schemeTx.SetWorkingDir(database);
+ schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin);
+ auto& dropUser = *schemeTx.MutableAlterLogin()->MutableRemoveUser();
+ dropUser.SetUser(settings.UserName);
+ dropUser.SetMissingOk(settings.Force);
+
+ if (IsPrepare()) {
+ auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();
+ auto& phyTx = *phyQuery.AddTransactions();
+ phyTx.SetType(NKqpProto::TKqpPhyTx::TYPE_SCHEME);
+
+ phyTx.MutableSchemeOperation()->MutableAlterUser()->Swap(&schemeTx);
+ TGenericResult result;
+ result.SetSuccess();
+ dropUserPromise.SetValue(result);
+ } else {
+ return Gateway->DropUser(cluster, settings);
+ }
+
+ return dropUserPromise.GetFuture();
}
TFuture<TGenericResult> UpsertObject(const TString& cluster, const TUpsertObjectSettings& settings) override {
@@ -890,6 +982,14 @@ private:
return Gateway->GetDatabase();
}
+ bool GetDomainLoginOnly() {
+ return Gateway->GetDomainLoginOnly();
+ }
+
+ TMaybe<TString> GetDomainName() {
+ return Gateway->GetDomainName();
+ }
+
private:
TIntrusivePtr<IKqpGateway> Gateway;
TIntrusivePtr<TKikimrSessionContext> SessionCtx;
diff --git a/ydb/core/kqp/provider/yql_kikimr_datasink.cpp b/ydb/core/kqp/provider/yql_kikimr_datasink.cpp
index 52e7652c3e..9ad5225967 100644
--- a/ydb/core/kqp/provider/yql_kikimr_datasink.cpp
+++ b/ydb/core/kqp/provider/yql_kikimr_datasink.cpp
@@ -794,7 +794,7 @@ public:
.Done()
.Ptr();
- } else if (mode == "drop" || mode == "drop_if_exists") {
+ } else if (mode == "drop" || mode == "drop_if_exists") {
return MakeKiDropTable(node, settings, key, ctx);
} else {
YQL_ENSURE(false, "unknown TableScheme mode \"" << TString(mode) << "\"");
diff --git a/ydb/core/kqp/provider/yql_kikimr_exec.cpp b/ydb/core/kqp/provider/yql_kikimr_exec.cpp
index bd05a99d72..0974582bd6 100644
--- a/ydb/core/kqp/provider/yql_kikimr_exec.cpp
+++ b/ydb/core/kqp/provider/yql_kikimr_exec.cpp
@@ -1684,10 +1684,6 @@ 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);
@@ -1696,8 +1692,7 @@ public:
auto cluster = TString(maybeCreateUser.Cast().DataSink().Cluster());
TCreateUserSettings createUserSettings = ParseCreateUserSettings(maybeCreateUser.Cast());
- bool prepareOnly = SessionCtx->Query().PrepareOnly;
- auto future = prepareOnly ? CreateDummySuccess() : Gateway->CreateUser(cluster, createUserSettings);
+ auto future = Gateway->CreateUser(cluster, createUserSettings);
return WrapFuture(future,
[](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) {
@@ -1708,10 +1703,6 @@ public:
}
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);
@@ -1720,8 +1711,7 @@ public:
auto cluster = TString(maybeAlterUser.Cast().DataSink().Cluster());
TAlterUserSettings alterUserSettings = ParseAlterUserSettings(maybeAlterUser.Cast());
- bool prepareOnly = SessionCtx->Query().PrepareOnly;
- auto future = prepareOnly ? CreateDummySuccess() : Gateway->AlterUser(cluster, alterUserSettings);
+ auto future = Gateway->AlterUser(cluster, alterUserSettings);
return WrapFuture(future,
[](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) {
@@ -1732,10 +1722,6 @@ public:
}
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);
@@ -1744,8 +1730,7 @@ public:
auto cluster = TString(maybeDropUser.Cast().DataSink().Cluster());
TDropUserSettings dropUserSettings = ParseDropUserSettings(maybeDropUser.Cast());
- bool prepareOnly = SessionCtx->Query().PrepareOnly;
- auto future = prepareOnly ? CreateDummySuccess() : Gateway->DropUser(cluster, dropUserSettings);
+ auto future = Gateway->DropUser(cluster, dropUserSettings);
return WrapFuture(future,
[](const IKikimrGateway::TGenericResult& res, const TExprNode::TPtr& input, TExprContext& ctx) {
diff --git a/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp b/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp
index a409057c39..8fdcdb4d96 100644
--- a/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp
+++ b/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp
@@ -3082,7 +3082,6 @@ Y_UNIT_TEST_SUITE(KqpScheme) {
Y_UNIT_TEST(CreateAndDropUser) {
TKikimrRunner kikimr;
auto db = kikimr.GetTableClient();
- /* TODO: Fix flaky test in KIKIMR-18780
{
// Drop non-existing user force
auto query = TStringBuilder() << R"(
@@ -3092,7 +3091,7 @@ Y_UNIT_TEST_SUITE(KqpScheme) {
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
@@ -3121,7 +3120,6 @@ Y_UNIT_TEST_SUITE(KqpScheme) {
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}
- /* TODO: Fix flaky test in KIKIMR-18780
{
// Drop existing user force
auto query = TStringBuilder() << R"(
@@ -3131,7 +3129,16 @@ Y_UNIT_TEST_SUITE(KqpScheme) {
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
auto query = TStringBuilder() << R"(
diff --git a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
index 7eafe2cfb9..e6fcfa5955 100644
--- a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
+++ b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
@@ -584,6 +584,36 @@ Y_UNIT_TEST_SUITE(KqpQueryService) {
SELECT * FROM TestDdl;
)", TTxControl::BeginTx().CommitTx()).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SCHEME_ERROR, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ CREATE USER user1 PASSWORD 'password1';
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ CREATE USER user1 PASSWORD 'password1';
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::PRECONDITION_FAILED, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ ALTER USER user1 WITH ENCRYPTED PASSWORD 'password3';
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ DROP USER user1;
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ DROP USER user1;
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::PRECONDITION_FAILED, result.GetIssues().ToString());
+
+ result = db.ExecuteQuery(R"(
+ DROP USER IF EXISTS user1;
+ )", TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}
Y_UNIT_TEST(DdlCache) {
diff --git a/ydb/core/protos/flat_scheme_op.proto b/ydb/core/protos/flat_scheme_op.proto
index 4e81e669c0..d1b50ed389 100644
--- a/ydb/core/protos/flat_scheme_op.proto
+++ b/ydb/core/protos/flat_scheme_op.proto
@@ -686,6 +686,7 @@ message TLoginModifyUser {
message TLoginRemoveUser {
optional string User = 1;
+ optional bool MissingOk = 2;
}
message TLoginCreateGroup {
diff --git a/ydb/core/protos/kqp_physical.proto b/ydb/core/protos/kqp_physical.proto
index e42211f402..47c9584532 100644
--- a/ydb/core/protos/kqp_physical.proto
+++ b/ydb/core/protos/kqp_physical.proto
@@ -386,6 +386,9 @@ message TKqpSchemeOperation {
NKikimrSchemeOp.TModifyScheme DropTable = 2;
NKikimrSchemeOp.TModifyScheme AlterTable = 3;
NKikimrIndexBuilder.TIndexBuildSettings BuildOperation = 4;
+ NKikimrSchemeOp.TModifyScheme CreateUser = 5;
+ NKikimrSchemeOp.TModifyScheme AlterUser = 6;
+ NKikimrSchemeOp.TModifyScheme DropUser = 7;
string Type = 9;
uint64 Flags = 10;
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
index 374e255eed..f40820a46b 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_login.cpp
@@ -58,7 +58,10 @@ public:
case NKikimrSchemeOp::TAlterLogin::kRemoveUser: {
const auto& removeUser = alterLogin.GetRemoveUser();
const TString& user = removeUser.GetUser();
- auto response = context.SS->LoginProvider.RemoveUser({.User = user});
+ auto response = context.SS->LoginProvider.RemoveUser({
+ .User = user,
+ .MissingOk = removeUser.GetMissingOk()
+ });
if (response.Error) {
result->SetStatus(NKikimrScheme::StatusPreconditionFailed, response.Error);
} else {
diff --git a/ydb/library/login/login.cpp b/ydb/library/login/login.cpp
index f65d753c96..45bd462bf7 100644
--- a/ydb/library/login/login.cpp
+++ b/ydb/library/login/login.cpp
@@ -99,7 +99,9 @@ TLoginProvider::TRemoveUserResponse TLoginProvider::RemoveUser(const TRemoveUser
auto itUserModify = Sids.find(request.User);
if (itUserModify == Sids.end() || itUserModify->second.Type != ESidType::USER) {
- response.Error = "User not found";
+ if (!request.MissingOk) {
+ response.Error = "User not found";
+ }
return response;
}
diff --git a/ydb/library/login/login.h b/ydb/library/login/login.h
index 3cd8d3856b..758520dc75 100644
--- a/ydb/library/login/login.h
+++ b/ydb/library/login/login.h
@@ -73,6 +73,7 @@ public:
struct TRemoveUserRequest : TBasicRequest {
TString User;
+ bool MissingOk;
};
struct TRemoveUserResponse : TBasicResponse {
diff --git a/ydb/library/yql/sql/pg/pg_sql.cpp b/ydb/library/yql/sql/pg/pg_sql.cpp
index e52781ab37..d765e335a2 100644
--- a/ydb/library/yql/sql/pg/pg_sql.cpp
+++ b/ydb/library/yql/sql/pg/pg_sql.cpp
@@ -325,9 +325,9 @@ public:
Statements.push_back(configSource);
for (int i = 0; i < ListLength(raw); ++i) {
- if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) {
- return nullptr;
- }
+ if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) {
+ return nullptr;
+ }
}
if (!Views.empty()) {