aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryplishan <yplishan@ydb.tech>2023-11-27 16:36:32 +0300
committeryplishan <yplishan@ydb.tech>2023-11-27 17:58:25 +0300
commit95e4f8a79178e41d0edff55510b472ba55fcdaba (patch)
tree68adf81de8db8497aed8b22d9eeec0155167d8df
parentd682298dbe38d7c7a9021001a779c2cd5beaf39f (diff)
downloadydb-95e4f8a79178e41d0edff55510b472ba55fcdaba.tar.gz
Added filtering of database paths in issues in ydb_connector_actor and ydb_schema_query_actor
-rw-r--r--ydb/core/fq/libs/common/util.cpp39
-rw-r--r--ydb/core/fq/libs/common/util.h5
-rw-r--r--ydb/core/fq/libs/common/util_ut.cpp31
-rw-r--r--ydb/core/fq/libs/compute/ydb/ydb_connector_actor.cpp93
-rw-r--r--ydb/core/fq/libs/control_plane_proxy/actors/ydb_schema_query_actor.cpp3
-rw-r--r--ydb/tests/fq/s3/test_yq_v2.py18
6 files changed, 171 insertions, 18 deletions
diff --git a/ydb/core/fq/libs/common/util.cpp b/ydb/core/fq/libs/common/util.cpp
index 45f1fdb391..e898ceaa15 100644
--- a/ydb/core/fq/libs/common/util.cpp
+++ b/ydb/core/fq/libs/common/util.cpp
@@ -1,9 +1,11 @@
#include "util.h"
+#include <regex>
+#include <re2/re2.h>
+
#include <util/generic/string.h>
#include <util/string/builder.h>
#include <util/string/subst.h>
-#include <regex>
namespace NFq {
@@ -41,6 +43,24 @@ EYdbComputeAuth GetBasicAuthMethod(const FederatedQuery::IamAuth& auth) {
}
}
+class TIssueDatabaseRemover {
+public:
+ explicit TIssueDatabaseRemover(const TString& databasePath)
+ : DatabasePath(databasePath) {}
+
+ TIntrusivePtr<NYql::TIssue> Run(const NYql::TIssue& issue) {
+ auto msg = RemoveDatabaseFromStr(issue.GetMessage(), DatabasePath);
+ auto newIssue = MakeIntrusive<NYql::TIssue>(msg);
+ for (auto issue : issue.GetSubIssues()) {
+ newIssue->AddSubIssue(Run(*issue));
+ }
+ return newIssue;
+ }
+
+private:
+ TString DatabasePath;
+};
+
}
TString EscapeString(const TString& value,
@@ -196,4 +216,21 @@ FederatedQuery::IamAuth GetAuth(const FederatedQuery::Connection& connection) {
}
}
+TString RemoveDatabaseFromStr(TString str, const TString& databasePath) {
+ TString escapedPath = RE2::QuoteMeta(databasePath);
+ RE2::GlobalReplace(&str,
+ TStringBuilder {} << R"(db.\[)" << escapedPath << R"(\/([^ '"]+)\]|)" << escapedPath << R"(\/([^ '"]+))",
+ R"(\1\2)");
+ return str;
+}
+
+NYql::TIssues RemoveDatabaseFromIssues(const NYql::TIssues& issues, const TString& databasePath) {
+ TIssueDatabaseRemover remover(databasePath);
+ TVector<NYql::TIssue> newIssues;
+ for (const auto& issue : issues) {
+ newIssues.emplace_back(*remover.Run(issue));
+ }
+ return NYql::TIssues(newIssues);
+}
+
} // namespace NFq
diff --git a/ydb/core/fq/libs/common/util.h b/ydb/core/fq/libs/common/util.h
index 5c6b22e4b0..86664504d5 100644
--- a/ydb/core/fq/libs/common/util.h
+++ b/ydb/core/fq/libs/common/util.h
@@ -4,6 +4,7 @@
#include <array>
#include <google/protobuf/repeated_field.h>
+#include <ydb/library/yql/public/issue/yql_issue.h>
#include <ydb/public/api/protos/draft/fq.pb.h>
#include <library/cpp/iterator/mapped.h>
@@ -73,4 +74,8 @@ EYdbComputeAuth GetYdbComputeAuthMethod(const FederatedQuery::ConnectionSetting&
FederatedQuery::IamAuth GetAuth(const FederatedQuery::Connection& connection);
+TString RemoveDatabaseFromStr(TString str, const TString& substr);
+
+NYql::TIssues RemoveDatabaseFromIssues(const NYql::TIssues& issues, const TString& str);
+
} // namespace NFq
diff --git a/ydb/core/fq/libs/common/util_ut.cpp b/ydb/core/fq/libs/common/util_ut.cpp
index 03862380e4..3e5a7d3e12 100644
--- a/ydb/core/fq/libs/common/util_ut.cpp
+++ b/ydb/core/fq/libs/common/util_ut.cpp
@@ -34,4 +34,35 @@ Y_UNIT_TEST_SUITE(EscapingBasics) {
UNIT_ASSERT_VALUES_EQUAL(EncloseAndEscapeString("some_secret1}+{\n}+{some_secret2", "}+{", "[*]"), "}+{some_secret1[*]\n[*]some_secret2}+{");
}
}
+
+Y_UNIT_TEST_SUITE(IssuesTextFiltering) {
+ Y_UNIT_TEST(ShouldRemoveDatabasePath) {
+ TVector<NYql::TIssue> vecIssues;
+ auto bottomIssue = MakeIntrusive<NYql::TIssue>("Error /path/to/database/binding_name db.[/path/to/database/binding_name]");
+ auto midIssue = MakeIntrusive<NYql::TIssue>("'db.[/path/to/database/baz]' /path/to/database/foo /path/to/database/bar");
+ midIssue->AddSubIssue(bottomIssue);
+ NYql::TIssue topIssue("While doing smth db.[] /path/to/other/smth");
+ topIssue.AddSubIssue(midIssue);
+ NYql::TIssues issues({topIssue});
+
+ TVector<NYql::TIssue> vecIssuesExpected;
+ auto bottomIssueExpected = MakeIntrusive<NYql::TIssue>("Error binding_name binding_name");
+ auto midIssueExpected = MakeIntrusive<NYql::TIssue>("'baz' foo bar");
+ midIssueExpected->AddSubIssue(bottomIssueExpected);
+ NYql::TIssue topIssueExpected("While doing smth db.[] /path/to/other/smth");
+ topIssueExpected.AddSubIssue(midIssueExpected);
+ NYql::TIssues issuesExpected({topIssueExpected});
+
+ auto issuesActual = RemoveDatabaseFromIssues(issues, "/path/to/database");
+
+ auto iterActual = issuesActual.begin();
+ auto iterExpected = issuesExpected.begin();
+ while (iterActual != issuesActual.end()) {
+ UNIT_ASSERT_VALUES_EQUAL(*iterActual, *iterExpected);
+ ++iterActual;
+ ++iterExpected;
+ }
+ }
+}
+
} // NFq
diff --git a/ydb/core/fq/libs/compute/ydb/ydb_connector_actor.cpp b/ydb/core/fq/libs/compute/ydb/ydb_connector_actor.cpp
index b1fb68170a..9a90de8c76 100644
--- a/ydb/core/fq/libs/compute/ydb/ydb_connector_actor.cpp
+++ b/ydb/core/fq/libs/compute/ydb/ydb_connector_actor.cpp
@@ -1,3 +1,4 @@
+#include <ydb/core/fq/libs/common/util.h>
#include <ydb/core/fq/libs/compute/common/run_actor_params.h>
#include <ydb/core/fq/libs/compute/ydb/events/events.h>
#include <ydb/core/fq/libs/ydb/ydb.h>
@@ -58,16 +59,26 @@ public:
settings.TraceId(event.TraceId);
QueryClient
->ExecuteScript(event.Sql, settings)
- .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie](auto future) {
+ .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie, database = ComputeConnection.database()](auto future) {
try {
auto response = future.ExtractValueSync();
if (response.Status().IsSuccess()) {
actorSystem->Send(recipient, new TEvYdbCompute::TEvExecuteScriptResponse(response.Id(), response.Metadata().ExecutionId), 0, cookie);
} else {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvExecuteScriptResponse(response.Status().GetIssues(), response.Status().GetStatus()), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvExecuteScriptResponse>(
+ response.Status().GetIssues(),
+ response.Status().GetStatus(), database),
+ 0, cookie);
}
} catch (...) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvExecuteScriptResponse(NYql::TIssues{NYql::TIssue{CurrentExceptionMessage()}}, NYdb::EStatus::GENERIC_ERROR), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvExecuteScriptResponse>(
+ CurrentExceptionMessage(),
+ NYdb::EStatus::GENERIC_ERROR, database),
+ 0, cookie);
}
});
}
@@ -75,16 +86,26 @@ public:
void Handle(const TEvYdbCompute::TEvGetOperationRequest::TPtr& ev) {
OperationClient
->Get<NYdb::NQuery::TScriptExecutionOperation>(ev->Get()->OperationId)
- .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie](auto future) {
+ .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie, database = ComputeConnection.database()](auto future) {
try {
auto response = future.ExtractValueSync();
if (response.Id().GetKind() != Ydb::TOperationId::UNUSED) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvGetOperationResponse(response.Metadata().ExecStatus, static_cast<Ydb::StatusIds::StatusCode>(response.Status().GetStatus()), response.Metadata().ResultSetsMeta, response.Metadata().ExecStats, response.Status().GetIssues()), 0, cookie);
+ actorSystem->Send(recipient, new TEvYdbCompute::TEvGetOperationResponse(response.Metadata().ExecStatus, static_cast<Ydb::StatusIds::StatusCode>(response.Status().GetStatus()), response.Metadata().ResultSetsMeta, response.Metadata().ExecStats, RemoveDatabaseFromIssues(response.Status().GetIssues(), database)), 0, cookie);
} else {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvGetOperationResponse(response.Status().GetIssues(), response.Status().GetStatus()), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvGetOperationResponse>(
+ response.Status().GetIssues(),
+ response.Status().GetStatus(), database),
+ 0, cookie);
}
} catch (...) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvGetOperationResponse(NYql::TIssues{NYql::TIssue{CurrentExceptionMessage()}}, NYdb::EStatus::GENERIC_ERROR), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvGetOperationResponse>(
+ CurrentExceptionMessage(),
+ NYdb::EStatus::GENERIC_ERROR, database),
+ 0, cookie);
}
});
}
@@ -94,16 +115,26 @@ public:
settings.FetchToken(ev->Get()->FetchToken);
QueryClient
->FetchScriptResults(ev->Get()->OperationId, ev->Get()->ResultSetId, settings)
- .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie](auto future) {
+ .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie, database = ComputeConnection.database()](auto future) {
try {
auto response = future.ExtractValueSync();
if (response.IsSuccess()) {
actorSystem->Send(recipient, new TEvYdbCompute::TEvFetchScriptResultResponse(response.ExtractResultSet(), response.GetNextFetchToken()), 0, cookie);
} else {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvFetchScriptResultResponse(response.GetIssues(), response.GetStatus()), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvFetchScriptResultResponse>(
+ response.GetIssues(),
+ response.GetStatus(), database),
+ 0, cookie);
}
} catch (...) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvFetchScriptResultResponse(NYql::TIssues{NYql::TIssue{CurrentExceptionMessage()}}, NYdb::EStatus::GENERIC_ERROR), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvFetchScriptResultResponse>(
+ CurrentExceptionMessage(),
+ NYdb::EStatus::GENERIC_ERROR, database),
+ 0, cookie);
}
});
}
@@ -111,12 +142,22 @@ public:
void Handle(const TEvYdbCompute::TEvCancelOperationRequest::TPtr& ev) {
OperationClient
->Cancel(ev->Get()->OperationId)
- .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie](auto future) {
+ .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie, database = ComputeConnection.database()](auto future) {
try {
auto response = future.ExtractValueSync();
- actorSystem->Send(recipient, new TEvYdbCompute::TEvCancelOperationResponse(response.GetIssues(), response.GetStatus()), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvCancelOperationResponse>(
+ response.GetIssues(),
+ response.GetStatus(), database),
+ 0, cookie);
} catch (...) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvCancelOperationResponse(NYql::TIssues{NYql::TIssue{CurrentExceptionMessage()}}, NYdb::EStatus::GENERIC_ERROR), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvCancelOperationResponse>(
+ CurrentExceptionMessage(),
+ NYdb::EStatus::GENERIC_ERROR, database),
+ 0, cookie);
}
});
}
@@ -124,15 +165,35 @@ public:
void Handle(const TEvYdbCompute::TEvForgetOperationRequest::TPtr& ev) {
OperationClient
->Forget(ev->Get()->OperationId)
- .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie](auto future) {
+ .Apply([actorSystem = NActors::TActivationContext::ActorSystem(), recipient = ev->Sender, cookie = ev->Cookie, database = ComputeConnection.database()](auto future) {
try {
auto response = future.ExtractValueSync();
- actorSystem->Send(recipient, new TEvYdbCompute::TEvForgetOperationResponse(response.GetIssues(), response.GetStatus()), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvForgetOperationResponse>(
+ response.GetIssues(),
+ response.GetStatus(), database),
+ 0, cookie);
} catch (...) {
- actorSystem->Send(recipient, new TEvYdbCompute::TEvForgetOperationResponse(NYql::TIssues{NYql::TIssue{CurrentExceptionMessage()}}, NYdb::EStatus::GENERIC_ERROR), 0, cookie);
+ actorSystem->Send(
+ recipient,
+ MakeResponse<TEvYdbCompute::TEvForgetOperationResponse>(
+ CurrentExceptionMessage(),
+ NYdb::EStatus::GENERIC_ERROR, database),
+ 0, cookie);
}
});
}
+
+ template<typename TResponse>
+ static TResponse* MakeResponse(TString msg, NYdb::EStatus status, TString databasePath) {
+ return new TResponse(NYql::TIssues{NYql::TIssue{RemoveDatabaseFromStr(msg, databasePath)}}, status);
+ }
+
+ template<typename TResponse>
+ static TResponse* MakeResponse(const NYql::TIssues& issues, NYdb::EStatus status, TString databasePath) {
+ return new TResponse(RemoveDatabaseFromIssues(issues, databasePath), status);
+ }
private:
TYqSharedResources::TPtr YqSharedResources;
diff --git a/ydb/core/fq/libs/control_plane_proxy/actors/ydb_schema_query_actor.cpp b/ydb/core/fq/libs/control_plane_proxy/actors/ydb_schema_query_actor.cpp
index 20fe6a6ca0..fffc41f051 100644
--- a/ydb/core/fq/libs/control_plane_proxy/actors/ydb_schema_query_actor.cpp
+++ b/ydb/core/fq/libs/control_plane_proxy/actors/ydb_schema_query_actor.cpp
@@ -311,7 +311,8 @@ public:
void SaveIssues(const TString& message, const TStatus& status) {
auto issue = MakeErrorIssue(TIssuesIds::INTERNAL_ERROR, message);
- for (const auto& subIssue : status.GetIssues()) {
+ auto path = Request->Get()->ComputeDatabase->connection().database();
+ for (const auto& subIssue : RemoveDatabaseFromIssues(status.GetIssues(), path)) {
issue.AddSubIssue(MakeIntrusive<NYql::TIssue>(subIssue));
}
diff --git a/ydb/tests/fq/s3/test_yq_v2.py b/ydb/tests/fq/s3/test_yq_v2.py
index 484c801508..88d6837a51 100644
--- a/ydb/tests/fq/s3/test_yq_v2.py
+++ b/ydb/tests/fq/s3/test_yq_v2.py
@@ -85,3 +85,21 @@ Pear;15;33'''
assert result_set.rows[2].items[0].int64_value == 33000000
assert result_set.rows[2].items[1].bytes_value == b"Pear"
assert result_set.rows[2].items[2].int32_value == 15
+
+ @yq_v2
+ @pytest.mark.parametrize("client", [{"folder_id": "my_folder"}], indirect=True)
+ def test_removed_database_path(self, kikimr, s3, client):
+ kikimr.control_plane.wait_bootstrap(1)
+
+ def validate_query(sql, expected_message):
+ query_id = client.create_query("simple", sql, type=fq.QueryContent.QueryType.ANALYTICS).result.query_id
+ response = client.wait_query(query_id, statuses=[fq.QueryMeta.FAILED])
+
+ actual_message = response.query.issue[0].issues[0].issues[0].issues[0].message
+ assert expected_message == actual_message
+
+ validate_query(R"SELECT * FROM `non-existing-binding`;",
+ R"Cannot find table 'non-existing-binding' because it does not exist or you do not have access permissions. Please check correctness of table path and user permissions.")
+
+ validate_query(R"SELECT 1 FROM foo.bar;",
+ R"Cannot find table 'foo.[bar]' because it does not exist or you do not have access permissions. Please check correctness of table path and user permissions.")