diff options
author | Daniil Demin <deminds@ydb.tech> | 2025-04-02 15:27:14 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-02 12:27:14 +0000 |
commit | 4d6d0626d1787dfccba27b09e16d200805d0394d (patch) | |
tree | 3006472142fa7832550e5facea4957e45235af92 | |
parent | ced625185b35de68237df07a9012aa069a6fb220 (diff) | |
download | ydb-4d6d0626d1787dfccba27b09e16d200805d0394d.tar.gz |
refactoring before SHOW CREATE VIEW (#16629)
-rw-r--r-- | ydb/core/kqp/provider/yql_kikimr_opt_build.cpp | 68 | ||||
-rw-r--r-- | ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp | 6 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/create_table_formatter.cpp | 141 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/create_table_formatter.h | 58 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/formatters_common.cpp | 19 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/formatters_common.h | 60 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/show_create.cpp | 82 | ||||
-rw-r--r-- | ydb/core/sys_view/show_create/ya.make | 3 |
8 files changed, 247 insertions, 190 deletions
diff --git a/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp b/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp index af58f5ec04..2ee8144948 100644 --- a/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_opt_build.cpp @@ -876,6 +876,13 @@ TVector<TKiDataQueryBlock> MakeKiDataQueryBlocks(TExprBase node, const TKiExplor return queryBlocks; } +TString GetShowCreateType(const TExprNode& settings) { + if (HasSetting(settings, "showCreateTable")) { + return "showCreateTable"; + } + return ""; +} + } // namespace TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf database, TIntrusivePtr<TKikimrTablesData> tablesData, @@ -953,23 +960,23 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab return res; } - TNodeOnNodeOwnedMap showCreateTableReadReplaces; - VisitExpr(node.Ptr(), [&showCreateTableReadReplaces](const TExprNode::TPtr& input) -> bool { + TNodeOnNodeOwnedMap showCreateReadReplacements; + VisitExpr(node.Ptr(), [&showCreateReadReplacements](const TExprNode::TPtr& input) -> bool { TExprBase currentNode(input); if (auto maybeReadTable = currentNode.Maybe<TKiReadTable>()) { auto readTable = maybeReadTable.Cast(); for (auto setting : readTable.Settings()) { auto name = setting.Name().Value(); if (name == "showCreateTable") { - showCreateTableReadReplaces[input.Get()] = nullptr; + showCreateReadReplacements[input.Get()] = nullptr; } } } return true; }); - if (!showCreateTableReadReplaces.empty()) { - for (auto& [input, _] : showCreateTableReadReplaces) { + if (!showCreateReadReplacements.empty()) { + for (auto& [input, _] : showCreateReadReplacements) { TKiReadTable content(input); TExprNode::TPtr path = ctx.NewCallable( @@ -983,6 +990,9 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab TKikimrKey key(ctx); YQL_ENSURE(key.Extract(content.TableKey().Ref())); + auto type = GetShowCreateType(content.Settings().Ref()); + YQL_ENSURE(!type.empty()); + auto sysViewRewrittenValue = Build<TCoNameValueTuple>(ctx, node.Pos()) .Name() .Build("sysViewRewritten") @@ -991,12 +1001,12 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab .Build() .Done(); - auto showCreateTableValue = Build<TCoNameValueTuple>(ctx, node.Pos()) + auto showCreateTypeValue = Build<TCoNameValueTuple>(ctx, node.Pos()) .Name() - .Build("showCreateTable") + .Build(type) .Done(); - auto showCreateTableRead = Build<TCoRead>(ctx, node.Pos()) + auto showCreateRead = Build<TCoRead>(ctx, node.Pos()) .World<TCoWorld>().Build() .DataSource<TCoDataSource>() .Category(ctx.NewAtom(node.Pos(), KikimrProviderName)) @@ -1009,61 +1019,65 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab .Add(ctx.NewCallable(node.Pos(), "Void", {})) .Add(ctx.NewList(node.Pos(), {})) .Add(sysViewRewrittenValue) - .Add(showCreateTableValue) + .Add(showCreateTypeValue) .Build() .Done().Ptr(); - showCreateTableReadReplaces[input] = showCreateTableRead; + showCreateReadReplacements[input] = showCreateRead; } - auto res = ctx.ReplaceNodes(std::move(node.Ptr()), showCreateTableReadReplaces); + auto res = ctx.ReplaceNodes(std::move(node.Ptr()), showCreateReadReplacements); TExprBase resNode(res); - TNodeOnNodeOwnedMap showCreateTableRightReplaces; - VisitExpr(resNode.Ptr(), [&showCreateTableRightReplaces](const TExprNode::TPtr& input) -> bool { + TNodeOnNodeOwnedMap showCreateRightReplacements; + VisitExpr(resNode.Ptr(), [&showCreateRightReplacements](const TExprNode::TPtr& input) -> bool { TExprBase currentNode(input); if (auto rightMaybe = currentNode.Maybe<TCoRight>()) { auto right = rightMaybe.Cast(); if (auto maybeRead = right.Input().Maybe<TCoRead>()) { auto read = maybeRead.Cast(); bool isSysViewRewritten = false; - bool isShowCreateTable = false; + bool isShowCreate = false; for (auto arg : read.FreeArgs()) { if (auto tuple = arg.Maybe<TCoNameValueTuple>()) { auto name = tuple.Cast().Name().Value(); if (name == "sysViewRewritten") { isSysViewRewritten = true; } else if (name == "showCreateTable") { - isShowCreateTable = true; + isShowCreate = true; } } } - if (isShowCreateTable && isSysViewRewritten) { - showCreateTableRightReplaces[input.Get()] = nullptr; + if (isShowCreate && isSysViewRewritten) { + showCreateRightReplacements[input.Get()] = nullptr; } } } return true; }); - for (auto& [input, _] : showCreateTableRightReplaces) { + for (auto& [input, _] : showCreateRightReplacements) { TCoRight right(input); TCoRead read(right.Input().Ptr()); - TString tablePath; + TString path; + TString pathType; for (auto arg : read.FreeArgs()) { if (auto tuple = arg.Maybe<TCoNameValueTuple>()) { auto name = tuple.Cast().Name().Value(); if (name == "sysViewRewritten") { - tablePath = tuple.Cast().Value().Cast().Cast<TCoAtom>().StringValue(); + path = tuple.Cast().Value().Cast().Cast<TCoAtom>().StringValue(); + } + if (name == "showCreateTable") { + pathType = "Table"; } } } - YQL_ENSURE(!tablePath.empty(), "Unexpected empty table path for SHOW CREATE TABLE"); + YQL_ENSURE(!path.empty(), "Unexpected empty path for SHOW CREATE " << pathType.to_upper()); - auto tempTablePath = tablesData->GetTempTablePath(tablePath); + auto tempTablePath = tablesData->GetTempTablePath(path); if (tempTablePath) { - tablePath = tempTablePath.value(); + path = tempTablePath.value(); } auto showCreateArg = Build<TCoArgument>(ctx, resNode.Pos()) @@ -1082,7 +1096,7 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab auto pathCondition = Build<TCoCmpEqual>(ctx, resNode.Pos()) .Left(columnPath) .Right<TCoString>() - .Literal().Build(tablePath) + .Literal().Build(path) .Build() .Done(); @@ -1095,7 +1109,7 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab auto pathTypeCondition = Build<TCoCmpEqual>(ctx, resNode.Pos()) .Left(columnPathType) .Right<TCoString>() - .Literal().Build("Table") + .Literal().Build(pathType) .Build() .Done(); @@ -1121,7 +1135,7 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab .Lambda(lambda) .Done().Ptr(); - showCreateTableRightReplaces[input] = filterData; + showCreateRightReplacements[input] = filterData; } ctx.Step @@ -1133,7 +1147,7 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab .Repeat(TExprStep::LoadTablesMetadata) .Repeat(TExprStep::RewriteIO); - return ctx.ReplaceNodes(std::move(resNode.Ptr()), showCreateTableRightReplaces); + return ctx.ReplaceNodes(std::move(resNode.Ptr()), showCreateRightReplacements); } TKiExploreTxResults txExplore; 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 96d1d6aea1..a40d4f331f 100644 --- a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp +++ b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp @@ -2908,15 +2908,15 @@ Y_UNIT_TEST_SUITE(KqpQueryService) { CREATE VIEW test_view WITH security_invoker = TRUE AS SELECT * FROM KeyValue; )", TTxControl::NoTx()).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); } { auto result = session.ExecuteQuery(R"( SHOW CREATE TABLE test_view; )", TTxControl::NoTx()).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); - UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Invalid path type"); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::BAD_REQUEST, result.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Expected path type: Table"); } } diff --git a/ydb/core/sys_view/show_create/create_table_formatter.cpp b/ydb/core/sys_view/show_create/create_table_formatter.cpp index ab9b40f509..9c53079ec8 100644 --- a/ydb/core/sys_view/show_create/create_table_formatter.cpp +++ b/ydb/core/sys_view/show_create/create_table_formatter.cpp @@ -7,7 +7,6 @@ #include <ydb/public/lib/ydb_cli/dump/util/query_utils.h> -#include <yql/essentials/ast/yql_ast_escaping.h> #include <yql/essentials/minikql/mkql_type_ops.h> #include <util/generic/yexception.h> @@ -19,18 +18,6 @@ using namespace NKikimrSchemeOp; using namespace Ydb::Table; using namespace NYdb; -void TCreateTableFormatter::EscapeName(const TString& str) { - NYql::EscapeArbitraryAtom(str, '`', &Stream); -} - -void TCreateTableFormatter::EscapeString(const TString& str) { - NYql::EscapeArbitraryAtom(str, '\'', &Stream); -} - -void TCreateTableFormatter::EscapeBinary(const TString& str) { - NYql::EscapeBinaryAtom(str, '\'', &Stream); -} - void TCreateTableFormatter::FormatValue(NYdb::TValueParser& parser, bool isPartition, TString del) { TGuard<NMiniKQL::TScopedAlloc> guard(Alloc); switch (parser.GetKind()) { @@ -72,7 +59,7 @@ void TCreateTableFormatter::FormatValue(NYdb::TValueParser& parser, bool isParti auto precision = decimal.DecimalType_.Precision; auto scale = decimal.DecimalType_.Scale; Stream << "CAST("; - EscapeString(decimal.ToString()); + EscapeString(decimal.ToString(), Stream); Stream << " AS Decimal(" << ui32(precision) << "," << ui32(scale) << ")"; Stream << ")"; return; @@ -152,24 +139,24 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { break; } case NYdb::EPrimitiveType::Utf8: { - EscapeString(TString(parser.GetUtf8())); + EscapeString(TString(parser.GetUtf8()), Stream); break; } case NYdb::EPrimitiveType::Date: { Stream << "DATE("; - EscapeString(parser.GetDate().FormatGmTime("%Y-%m-%d")); + EscapeString(parser.GetDate().FormatGmTime("%Y-%m-%d"), Stream); Stream << ")"; break; } case NYdb::EPrimitiveType::Datetime: { Stream << "DATETIME("; - EscapeString(parser.GetDatetime().ToStringUpToSeconds()); + EscapeString(parser.GetDatetime().ToStringUpToSeconds(), Stream); Stream << ")"; break; } case NYdb::EPrimitiveType::Timestamp: { Stream << "TIMESTAMP("; - EscapeString(parser.GetTimestamp().ToString()); + EscapeString(parser.GetTimestamp().ToString(), Stream); Stream << ")"; break; } @@ -177,7 +164,7 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { Stream << "INTERVAL("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Interval, NUdf::TUnboxedValuePod(static_cast<i64>(parser.GetInterval()))); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; break; } @@ -185,7 +172,7 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { Stream << "DATE32("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Date32, NUdf::TUnboxedValuePod(parser.GetDate32())); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; break; } @@ -193,7 +180,7 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { Stream << "DATETIME64("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Datetime64, NUdf::TUnboxedValuePod(static_cast<i64>(parser.GetDatetime64()))); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; break; } @@ -201,7 +188,7 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { Stream << "TIMESTAMP64("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Timestamp64, NUdf::TUnboxedValuePod(static_cast<i64>(parser.GetTimestamp64()))); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; break; } @@ -209,28 +196,28 @@ void TCreateTableFormatter::FormatPrimitive(NYdb::TValueParser& parser) { Stream << "INTERVAL64("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Interval64, NUdf::TUnboxedValuePod(static_cast<i64>(parser.GetInterval64()))); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; break; } case NYdb::EPrimitiveType::String: - EscapeString(TString(parser.GetString())); + EscapeString(TString(parser.GetString()), Stream); break; case NYdb::EPrimitiveType::Yson: - EscapeString(TString(parser.GetYson())); + EscapeString(TString(parser.GetYson()), Stream); break; case NYdb::EPrimitiveType::Json: - EscapeString(TString(parser.GetJson())); + EscapeString(TString(parser.GetJson()), Stream); break; case NYdb::EPrimitiveType::DyNumber: { Stream << "DyNumber("; - EscapeString(TString(parser.GetDyNumber())); + EscapeString(TString(parser.GetDyNumber()), Stream); Stream << ")"; break; } case NYdb::EPrimitiveType::Uuid: { Stream << "UUID("; - EscapeString(TString(parser.GetUuid().ToString())); + EscapeString(TString(parser.GetUuid().ToString()), Stream); Stream << ")"; break; } @@ -258,7 +245,7 @@ private: TStringStream& Stream; }; -TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tablePath, +TFormatResult TCreateTableFormatter::Format(const TString& tablePath, const TTableDescription& tableDesc, bool temporary) { Stream.Clear(); @@ -270,14 +257,14 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl } else { Stream << "CREATE TABLE "; } - EscapeName(tablePath); + EscapeName(tablePath, Stream); Stream << " (\n"; NKikimrMiniKQL::TType mkqlKeyType; try { FillColumnDescription(createRequest, mkqlKeyType, tableDesc); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } Y_ENSURE(!tableDesc.GetColumns().empty()); @@ -298,16 +285,16 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl Format(*it->second); } } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } try { FillTableBoundary(createRequest, tableDesc, mkqlKeyType); FillIndexDescription(createRequest, tableDesc); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what());; + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what());; } if (!createRequest.indexes().empty()) { @@ -319,9 +306,9 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl Format(createRequest.indexes(i)); } } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } } Stream << ",\n"; @@ -340,9 +327,9 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl isFamilyPrinted = Format(partitionConfig.GetColumnFamilies(i)); } } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } } } @@ -352,10 +339,10 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl Stream << ",\n"; } Stream << "\tPRIMARY KEY ("; - EscapeName(columns[tableDesc.GetKeyColumnIds(0)]->GetName()); + EscapeName(columns[tableDesc.GetKeyColumnIds(0)]->GetName(), Stream); for (int i = 1; i < tableDesc.GetKeyColumnIds().size(); i++) { Stream << ", "; - EscapeName(columns[tableDesc.GetKeyColumnIds(i)]->GetName()); + EscapeName(columns[tableDesc.GetKeyColumnIds(i)]->GetName(), Stream); } Stream << ")\n"; Stream << ")"; @@ -374,9 +361,9 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl try { printed |= Format(createRequest.partition_at_keys(), del, !printed); } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } } @@ -408,9 +395,9 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl try { printed |= Format(createRequest.ttl_settings(), del, !printed); } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } } @@ -422,17 +409,17 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl TString formattedStatement; NYql::TIssues issues; if (!NYdb::NDump::Format(statement, formattedStatement, issues)) { - return TResult(Ydb::StatusIds::INTERNAL_ERROR, issues.ToString()); + return TFormatResult(Ydb::StatusIds::INTERNAL_ERROR, issues.ToString()); } - auto result = TResult(std::move(formattedStatement)); + auto result = TFormatResult(std::move(formattedStatement)); return result; } void TCreateTableFormatter::Format(const NKikimrSchemeOp::TColumnDescription& columnDesc) { Stream << "\t"; - EscapeName(columnDesc.GetName()); + EscapeName(columnDesc.GetName(), Stream); Stream << " "; auto type = columnDesc.GetType(); @@ -460,7 +447,7 @@ void TCreateTableFormatter::Format(const NKikimrSchemeOp::TColumnDescription& co if (columnDesc.HasFamilyName()) { Stream << " FAMILY "; - EscapeName(columnDesc.GetFamilyName()); + EscapeName(columnDesc.GetFamilyName(), Stream); } if (columnDesc.GetNotNull()) { Stream << " NOT NULL"; @@ -473,7 +460,7 @@ void TCreateTableFormatter::Format(const NKikimrSchemeOp::TColumnDescription& co void TCreateTableFormatter::Format(const TableIndex& index) { Stream << "\tINDEX "; - EscapeName(index.name()); + EscapeName(index.name(), Stream); std::optional<KMeansTreeSettings> kMeansTreeSettings; switch (index.type_case()) { case TableIndex::kGlobalIndex: { @@ -499,20 +486,20 @@ void TCreateTableFormatter::Format(const TableIndex& index) { Y_ENSURE(!index.index_columns().empty()); Stream << "("; - EscapeName(index.index_columns(0)); + EscapeName(index.index_columns(0), Stream); for (int i = 1; i < index.index_columns().size(); i++) { Stream << ", "; - EscapeName(index.index_columns(i)); + EscapeName(index.index_columns(i), Stream); } Stream << ")"; if (!index.data_columns().empty()) { Stream << " COVER "; Stream << "("; - EscapeName(index.data_columns(0)); + EscapeName(index.data_columns(0), Stream); for (int i = 1; i < index.data_columns().size(); i++) { Stream << ", "; - EscapeName(index.data_columns(i)); + EscapeName(index.data_columns(i), Stream); } Stream << ")"; } @@ -635,7 +622,7 @@ bool TCreateTableFormatter::Format(const TFamilyDescription& familyDesc) { Y_ENSURE(familyName); Stream << "\tFAMILY "; - EscapeName(familyName); + EscapeName(familyName, Stream); Stream << " ("; TString del = ""; @@ -754,11 +741,11 @@ void TCreateTableFormatter::Format(ui64 expireAfterSeconds, std::optional<TStrin Stream << "INTERVAL("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Interval, NUdf::TUnboxedValuePod(expireAfterSeconds * 1000000)); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ") "; if (storage) { Stream << "TO EXTERNAL DATA SOURCE "; - EscapeName(*storage); + EscapeName(*storage, Stream); } else { Stream << "DELETE"; } @@ -885,7 +872,7 @@ bool TCreateTableFormatter::Format(const Ydb::Table::TtlSettings& ttlSettings, T return true; } -TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tablePath, const TColumnTableDescription& tableDesc, bool temporary) { +TFormatResult TCreateTableFormatter::Format(const TString& tablePath, const TColumnTableDescription& tableDesc, bool temporary) { Stream.Clear(); TStringStreamWrapper wrapper(Stream); @@ -896,7 +883,7 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl } else { Stream << "CREATE TABLE "; } - EscapeName(tablePath); + EscapeName(tablePath, Stream); Stream << " (\n"; const auto& schema = tableDesc.GetSchema(); @@ -915,14 +902,14 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl Format(*it->second); } } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } Stream << ",\n"; if (!schema.GetIndexes().empty()) { - return TResult(Ydb::StatusIds::UNSUPPORTED, "Indexes are not supported yet for column tables."); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, "Indexes are not supported yet for column tables."); } bool isFamilyPrinted = false; @@ -936,9 +923,9 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl isFamilyPrinted = Format(schema.GetColumnFamilies(i)); } } catch (const TFormatFail& ex) { - return TResult(ex.Status, ex.Error); + return TFormatResult(ex.Status, ex.Error); } catch (const yexception& e) { - return TResult(Ydb::StatusIds::UNSUPPORTED, e.what()); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, e.what()); } } @@ -947,10 +934,10 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl Stream << ",\n"; } Stream << "\tPRIMARY KEY ("; - EscapeName(schema.GetKeyColumnNames(0)); + EscapeName(schema.GetKeyColumnNames(0), Stream); for (int i = 1; i < schema.GetKeyColumnNames().size(); i++) { Stream << ", "; - EscapeName(schema.GetKeyColumnNames(i)); + EscapeName(schema.GetKeyColumnNames(i), Stream); } Stream << ")\n"; Stream << ") "; @@ -958,16 +945,16 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl if (schema.HasOptions()) { const auto& options = schema.GetOptions(); if (options.GetSchemeNeedActualization()) { - return TResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: SCHEME_NEED_ACTUALIZATION"); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: SCHEME_NEED_ACTUALIZATION"); } if (options.HasScanReaderPolicyName() && !options.GetScanReaderPolicyName().empty()) { - return TResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: SCAN_READER_POLICY_NAME"); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: SCAN_READER_POLICY_NAME"); } if (options.HasCompactionPlannerConstructor()) { - return TResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: COMPACTION_PLANNER"); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: COMPACTION_PLANNER"); } if (options.HasMetadataManagerConstructor()) { - return TResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: METADATA_MEMORY_MANAGER"); + return TFormatResult(Ydb::StatusIds::UNSUPPORTED, "Unsupported setting: METADATA_MEMORY_MANAGER"); } } @@ -993,22 +980,22 @@ TCreateTableFormatter::TResult TCreateTableFormatter::Format(const TString& tabl TString formattedStatement; NYql::TIssues issues; if (!NYdb::NDump::Format(statement, formattedStatement, issues)) { - return TResult(Ydb::StatusIds::INTERNAL_ERROR, issues.ToString()); + return TFormatResult(Ydb::StatusIds::INTERNAL_ERROR, issues.ToString()); } - auto result = TResult(std::move(formattedStatement)); + auto result = TFormatResult(std::move(formattedStatement)); return result; } void TCreateTableFormatter::Format(const TOlapColumnDescription& olapColumnDesc) { Stream << "\t"; - EscapeName(olapColumnDesc.GetName()); + EscapeName(olapColumnDesc.GetName(), Stream); Stream << " " << olapColumnDesc.GetType(); if (olapColumnDesc.HasColumnFamilyName()) { Stream << " FAMILY "; - EscapeName(olapColumnDesc.GetColumnFamilyName()); + EscapeName(olapColumnDesc.GetColumnFamilyName(), Stream); } if (olapColumnDesc.GetNotNull()) { Stream << " NOT NULL"; @@ -1104,10 +1091,10 @@ void TCreateTableFormatter::Format(const NKikimrColumnShardColumnDefaults::TColu Stream << "TIMESTAMP("; const NUdf::TUnboxedValue str = NMiniKQL::ValueToString(NUdf::EDataSlot::Timestamp, NUdf::TUnboxedValuePod(value)); Y_ENSURE(str.HasValue()); - EscapeString(TString(str.AsStringRef())); + EscapeString(TString(str.AsStringRef()), Stream); Stream << ")"; } else if (scalar.HasString()) { - EscapeString(TString(scalar.GetString())); + EscapeString(TString(scalar.GetString()), Stream); } else { ythrow TFormatFail(Ydb::StatusIds::UNSUPPORTED, "Unsupported type for default value"); } @@ -1119,10 +1106,10 @@ void TCreateTableFormatter::Format(const NKikimrSchemeOp::TColumnTableSharding& const auto& hashSharding = sharding.GetHashSharding(); Y_ENSURE(!hashSharding.GetColumns().empty()); Stream << "PARTITION BY HASH("; - EscapeName(hashSharding.GetColumns(0)); + EscapeName(hashSharding.GetColumns(0), Stream); for (int i = 1; i < hashSharding.GetColumns().size(); i++) { Stream << ", "; - EscapeName(hashSharding.GetColumns(i)); + EscapeName(hashSharding.GetColumns(i), Stream); } Stream << ")\n"; break; diff --git a/ydb/core/sys_view/show_create/create_table_formatter.h b/ydb/core/sys_view/show_create/create_table_formatter.h index 249ef6e0fd..bd82bc5a15 100644 --- a/ydb/core/sys_view/show_create/create_table_formatter.h +++ b/ydb/core/sys_view/show_create/create_table_formatter.h @@ -1,5 +1,7 @@ #pragma once +#include "formatters_common.h" + #include <ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/value/value.h> #include <ydb/core/protos/flat_scheme_op.pb.h> @@ -10,60 +12,13 @@ #include <yql/essentials/minikql/mkql_alloc.h> -#include <util/generic/hash.h> #include <util/stream/str.h> -#include <util/string/builder.h> namespace NKikimr { namespace NSysView { class TCreateTableFormatter { public: - class TFormatFail : public yexception { - public: - Ydb::StatusIds::StatusCode Status; - TString Error; - - TFormatFail(Ydb::StatusIds::StatusCode status, TString error = {}) - : Status(status) - , Error(std::move(error)) - {} - }; - - class TResult { - public: - TResult(TString out) - : Out(std::move(out)) - , Status(Ydb::StatusIds::SUCCESS) - {} - - TResult(Ydb::StatusIds::StatusCode status, TString error) - : Status(status) - , Error(std::move(error)) - {} - - bool IsSuccess() const { - return Status == Ydb::StatusIds::SUCCESS; - } - - Ydb::StatusIds::StatusCode GetStatus() const { - return Status; - } - - const TString& GetError() const { - return Error; - } - - TString ExtractOut() { - return std::move(Out); - } - private: - TString Out; - - Ydb::StatusIds::StatusCode Status; - TString Error; - }; - TCreateTableFormatter() : Alloc(__LOCATION__) { @@ -75,11 +30,10 @@ public: Alloc.Acquire(); } - TResult Format(const TString& tablePath, const NKikimrSchemeOp::TTableDescription& tableDesc, bool temporary); - TResult Format(const TString& tablePath, const NKikimrSchemeOp::TColumnTableDescription& tableDesc, bool temporary); + TFormatResult Format(const TString& tablePath, const NKikimrSchemeOp::TTableDescription& tableDesc, bool temporary); + TFormatResult Format(const TString& tablePath, const NKikimrSchemeOp::TColumnTableDescription& tableDesc, bool temporary); private: - void Format(const NKikimrSchemeOp::TColumnDescription& columnDesc); bool Format(const NKikimrSchemeOp::TFamilyDescription& familyDesc); bool Format(const NKikimrSchemeOp::TPartitioningPolicy& policy, ui32 shardsToCreate, TString& del, bool needWith); @@ -101,10 +55,6 @@ private: void FormatValue(NYdb::TValueParser& parser, bool isPartition = false, TString del = ""); void FormatPrimitive(NYdb::TValueParser& parser); - void EscapeName(const TString& str); - void EscapeString(const TString& str); - void EscapeBinary(const TString& str); -private: TStringStream Stream; NMiniKQL::TScopedAlloc Alloc; }; diff --git a/ydb/core/sys_view/show_create/formatters_common.cpp b/ydb/core/sys_view/show_create/formatters_common.cpp new file mode 100644 index 0000000000..04d0808397 --- /dev/null +++ b/ydb/core/sys_view/show_create/formatters_common.cpp @@ -0,0 +1,19 @@ +#include "formatters_common.h" + +#include <yql/essentials/ast/yql_ast_escaping.h> + +namespace NKikimr::NSysView { + +void EscapeName(const TString& str, TStringStream& stream) { + NYql::EscapeArbitraryAtom(str, '`', &stream); +} + +void EscapeString(const TString& str, TStringStream& stream) { + NYql::EscapeArbitraryAtom(str, '\'', &stream); +} + +void EscapeBinary(const TString& str, TStringStream& stream) { + NYql::EscapeBinaryAtom(str, '\'', &stream); +} + +} diff --git a/ydb/core/sys_view/show_create/formatters_common.h b/ydb/core/sys_view/show_create/formatters_common.h new file mode 100644 index 0000000000..64c133da8e --- /dev/null +++ b/ydb/core/sys_view/show_create/formatters_common.h @@ -0,0 +1,60 @@ +#pragma once + +#include <ydb/public/api/protos/ydb_status_codes.pb.h> + +#include <util/generic/yexception.h> +#include <util/stream/str.h> + +namespace NKikimr::NSysView { + +void EscapeName(const TString& str, TStringStream& stream); +void EscapeString(const TString& str, TStringStream& stream); +void EscapeBinary(const TString& str, TStringStream& stream); + +class TFormatFail : public yexception { +public: + Ydb::StatusIds::StatusCode Status; + TString Error; + + TFormatFail(Ydb::StatusIds::StatusCode status, TString error = {}) + : Status(status) + , Error(std::move(error)) + {} +}; + +class TFormatResult { +public: + TFormatResult(TString out) + : Out(std::move(out)) + , Status(Ydb::StatusIds::SUCCESS) + {} + + TFormatResult(Ydb::StatusIds::StatusCode status, TString error) + : Status(status) + , Error(std::move(error)) + {} + + bool IsSuccess() const { + return Status == Ydb::StatusIds::SUCCESS; + } + + Ydb::StatusIds::StatusCode GetStatus() const { + return Status; + } + + const TString& GetError() const { + return Error; + } + + TString ExtractOut() { + return std::move(Out); + } + +private: + TString Out; + + Ydb::StatusIds::StatusCode Status; + TString Error; +}; + +} diff --git a/ydb/core/sys_view/show_create/show_create.cpp b/ydb/core/sys_view/show_create/show_create.cpp index 2c9f4d3df5..51800cbebb 100644 --- a/ydb/core/sys_view/show_create/show_create.cpp +++ b/ydb/core/sys_view/show_create/show_create.cpp @@ -20,6 +20,31 @@ namespace { using namespace NActors; +TString ToString(NKikimrSchemeOp::EPathType pathType) { + switch (pathType) { + case NKikimrSchemeOp::EPathTypeTable: + case NKikimrSchemeOp::EPathTypeColumnTable: + return "Table"; + default: + return "Unknown"; + } +} + +bool RewriteTemporaryTablePath(const TString& database, TString& tablePath, TString& error) { + auto pathVecTmp = SplitPath(tablePath); + auto sz = pathVecTmp.size(); + Y_ENSURE(sz > 3 && pathVecTmp[0] == ".tmp" && pathVecTmp[1] == "sessions"); + + auto pathTmp = JoinPath(TVector<TString>(pathVecTmp.begin() + 3, pathVecTmp.end())); + std::pair<TString, TString> pathPairTmp; + if (!TrySplitPathByDb(pathTmp, database, pathPairTmp, error)) { + return false; + } + + tablePath = pathPairTmp.second; + return true; +} + class TShowCreate : public TScanActorBase<TShowCreate> { public: using TBase = TScanActorBase<TShowCreate>; @@ -136,14 +161,14 @@ private: switch (status) { case NKikimrScheme::StatusSuccess: { const auto& pathDescription = record.GetPathDescription(); - if (pathDescription.GetSelf().GetPathType() != NKikimrSchemeOp::EPathTypeTable - && pathDescription.GetSelf().GetPathType() != NKikimrSchemeOp::EPathTypeColumnTable) { - ReplyErrorAndDie(Ydb::StatusIds::SCHEME_ERROR, "Invalid path type"); - return; + if (auto pathType = ToString(pathDescription.GetSelf().GetPathType()); pathType != PathType) { + return ReplyErrorAndDie(Ydb::StatusIds::BAD_REQUEST, TStringBuilder() + << "Expected path type: " << PathType + << ", actual path type: " << pathType + ); } std::pair<TString, TString> pathPair; - { TString error; if (!TrySplitPathByDb(Path, Database, pathPair, error)) { @@ -152,29 +177,20 @@ private: } } - auto [_, tablePath] = pathPair; - bool temporary = false; - - if (NKqp::IsSessionsDirPath(Database, tablePath)) { - auto pathVecTmp = SplitPath(tablePath); - auto sz = pathVecTmp.size(); - Y_ENSURE(sz > 3 && pathVecTmp[0] == ".tmp" && pathVecTmp[1] == "sessions"); - - auto pathTmp = JoinPath(TVector<TString>(pathVecTmp.begin() + 3, pathVecTmp.end())); - std::pair<TString, TString> pathPairTmp; - TString error; - if (!TrySplitPathByDb(pathTmp, Database, pathPairTmp, error)) { - ReplyErrorAndDie(Ydb::StatusIds::SCHEME_ERROR, error); - return; - } - - tablePath = pathPairTmp.second; - temporary = true; - } - switch (pathDescription.GetSelf().GetPathType()) { case NKikimrSchemeOp::EPathTypeTable: { const auto& tableDesc = pathDescription.GetTable(); + auto tablePath = pathPair.second; + + bool temporary = false; + if (NKqp::IsSessionsDirPath(Database, pathPair.second)) { + TString error; + if (!RewriteTemporaryTablePath(Database, tablePath, error)) { + return ReplyErrorAndDie(Ydb::StatusIds::SCHEME_ERROR, error); + } + temporary = true; + } + TCreateTableFormatter formatter; auto formatterResult = formatter.Format(tablePath, tableDesc, temporary); if (formatterResult.IsSuccess()) { @@ -188,6 +204,17 @@ private: } case NKikimrSchemeOp::EPathTypeColumnTable: { const auto& columnTableDesc = pathDescription.GetColumnTableDescription(); + auto tablePath = pathPair.second; + + bool temporary = false; + if (NKqp::IsSessionsDirPath(Database, pathPair.second)) { + TString error; + if (!RewriteTemporaryTablePath(Database, tablePath, error)) { + return ReplyErrorAndDie(Ydb::StatusIds::SCHEME_ERROR, error); + } + temporary = true; + } + TCreateTableFormatter formatter; auto formatterResult = formatter.Format(tablePath, columnTableDesc, temporary); if (formatterResult.IsSuccess()) { @@ -200,8 +227,9 @@ private: break; } default: { - ReplyErrorAndDie(Ydb::StatusIds::SCHEME_ERROR, "Invalid path type"); - return; + return ReplyErrorAndDie(Ydb::StatusIds::BAD_REQUEST, TStringBuilder() + << "Unsupported path type: " << pathDescription.GetSelf().GetPathType() + ); } } break; diff --git a/ydb/core/sys_view/show_create/ya.make b/ydb/core/sys_view/show_create/ya.make index 16fad0e331..7a3bb3fae3 100644 --- a/ydb/core/sys_view/show_create/ya.make +++ b/ydb/core/sys_view/show_create/ya.make @@ -2,9 +2,8 @@ LIBRARY() SRCS( create_table_formatter.cpp - create_table_formatter.h + formatters_common.cpp show_create.cpp - show_create.h ) PEERDIR( |