Skip to content

Show create table (Row-oriented tables) #14789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ydb/core/kqp/provider/yql_kikimr_datasink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ class TKikimrDataSink : public TDataProviderBase
} else {
YQL_ENSURE(false, "Invalid key type for sequence");
}


return Build<TKiAlterSequence>(ctx, node->Pos())
.World(node->Child(0))
Expand Down
170 changes: 170 additions & 0 deletions ydb/core/kqp/provider/yql_kikimr_opt_build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,176 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TStringBuf datab
return res;
}

TNodeOnNodeOwnedMap showCreateTableReadReplaces;
VisitExpr(node.Ptr(), [&showCreateTableReadReplaces](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;
}
}
}
return true;
});

if (!showCreateTableReadReplaces.empty()) {
for (auto& [input, _] : showCreateTableReadReplaces) {
TKiReadTable content(input);

TExprNode::TPtr path = ctx.NewCallable(
node.Pos(),
"String",
{ ctx.NewAtom(node.Pos(), NKikimr::CanonizePath(NKikimr::JoinPath({TString(database), ".sys/show_create"}))) }
);
auto table = ctx.NewList(node.Pos(), {ctx.NewAtom(node.Pos(), "table"), path});
auto newKey = ctx.NewCallable(node.Pos(), "Key", {table});

TKikimrKey key(ctx);
YQL_ENSURE(key.Extract(content.TableKey().Ref()));

auto showCreateValue = Build<TCoNameValueTuple>(ctx, node.Pos())
.Name()
.Build("showCreateTable")
.Value<TCoAtom>()
.Value(key.GetTablePath())
.Build()
.Done();

auto showCreateTableRead = Build<TCoRead>(ctx, node.Pos())
.World<TCoWorld>().Build()
.DataSource<TCoDataSource>()
.Category(ctx.NewAtom(node.Pos(), KikimrProviderName))
.FreeArgs()
.Add(ctx.NewAtom(node.Pos(), "db"))
.Build()
.Build()
.FreeArgs()
.Add(newKey)
.Add(ctx.NewCallable(node.Pos(), "Void", {}))
.Add(ctx.NewList(node.Pos(), {}))
.Add(showCreateValue)
.Build()
.Done().Ptr();

showCreateTableReadReplaces[input] = showCreateTableRead;
}
auto res = ctx.ReplaceNodes(std::move(node.Ptr()), showCreateTableReadReplaces);

TExprBase resNode(res);

TNodeOnNodeOwnedMap showCreateTableRightReplaces;
VisitExpr(resNode.Ptr(), [&showCreateTableRightReplaces](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();
for (auto arg : read.FreeArgs()) {
if (auto tuple = arg.Maybe<TCoNameValueTuple>()) {
auto name = tuple.Cast().Name().Value();
if (name == "showCreateTable") {
showCreateTableRightReplaces[input.Get()] = nullptr;
}
}
}
}
}
return true;
});

for (auto& [input, _] : showCreateTableRightReplaces) {
TCoRight right(input);
TCoRead read(right.Input().Ptr());

TString tablePath;
for (auto arg : read.FreeArgs()) {
if (auto tuple = arg.Maybe<TCoNameValueTuple>()) {
auto name = tuple.Cast().Name().Value();
if (name == "showCreateTable") {
tablePath = tuple.Cast().Value().Cast().Cast<TCoAtom>().StringValue();
}
}
}
YQL_ENSURE(!tablePath.empty(), "Unexpected empty table path for SHOW CREATE TABLE");

auto tempTablePath = tablesData->GetTempTablePath(tablePath);
if (tempTablePath) {
tablePath = tempTablePath.value();
}

auto showCreateArg = Build<TCoArgument>(ctx, resNode.Pos())
.Name("_show_create_arg")
.Done();

TCoAtom columnPathAtom(ctx.NewAtom(resNode.Pos(), "Path"));
auto columnPathArg = Build<TCoArgument>(ctx, resNode.Pos())
.Name("_column_path_arg")
.Done();
auto columnPath = Build<TCoMember>(ctx, resNode.Pos())
.Struct(showCreateArg)
.Name(columnPathAtom)
.Done().Ptr();

auto pathCondition = Build<TCoCmpEqual>(ctx, resNode.Pos())
.Left(columnPath)
.Right<TCoString>()
.Literal().Build(tablePath)
.Build()
.Done();

TCoAtom columnPathTypeAtom(ctx.NewAtom(resNode.Pos(), "PathType"));
auto columnPathType = Build<TCoMember>(ctx, resNode.Pos())
.Struct(showCreateArg)
.Name(columnPathTypeAtom)
.Done().Ptr();

auto pathTypeCondition = Build<TCoCmpEqual>(ctx, resNode.Pos())
.Left(columnPathType)
.Right<TCoString>()
.Literal().Build("Table")
.Build()
.Done();

auto lambda = Build<TCoLambda>(ctx, resNode.Pos())
.Args({showCreateArg})
.Body<TCoCoalesce>()
.Predicate<TCoAnd>()
.Add(pathCondition)
.Add(pathTypeCondition)
.Build()
.Value<TCoBool>()
.Literal().Build("false")
.Build()
.Build()
.Done().Ptr();

auto readData = Build<TCoRight>(ctx, resNode.Pos())
.Input(right.Input().Ptr())
.Done().Ptr();

auto filterData = Build<TCoFilter>(ctx, resNode.Pos())
.Input(readData)
.Lambda(lambda)
.Done().Ptr();

showCreateTableRightReplaces[input] = filterData;
}

ctx.Step
.Repeat(TExprStep::RewriteIO)
.Repeat(TExprStep::ExprEval)
.Repeat(TExprStep::DiscoveryIO)
.Repeat(TExprStep::Epochs)
.Repeat(TExprStep::Intents)
.Repeat(TExprStep::LoadTablesMetadata)
.Repeat(TExprStep::RewriteIO);

return ctx.ReplaceNodes(std::move(resNode.Ptr()), showCreateTableRightReplaces);;
}

TKiExploreTxResults txExplore;
txExplore.ConcurrentResults = concurrentResults;
if (!ExploreTx(commit.World(), ctx, kiDataSink, txExplore, tablesData, types) || txExplore.HasErrors) {
Expand Down
13 changes: 13 additions & 0 deletions ydb/core/kqp/provider/yql_kikimr_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ const TKikimrTableDescription& TKikimrTablesData::ExistingTable(const TStringBuf
return *desc;
}

std::optional<TString> TKikimrTablesData::GetTempTablePath(const TStringBuf& table) const {
if (!TempTablesState) {
return std::nullopt;
}

auto tempTableInfoIt = TempTablesState->FindInfo(table, false);

if (tempTableInfoIt != TempTablesState->TempTables.end()) {
return NKikimr::NKqp::GetTempTablePath(TempTablesState->Database, TempTablesState->SessionId, tempTableInfoIt->first);
}
return std::nullopt;
}

bool TKikimrTableDescription::Load(TExprContext& ctx, bool withSystemColumns) {
ColumnTypes.clear();

Expand Down
2 changes: 2 additions & 0 deletions ydb/core/kqp/provider/yql_kikimr_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ class TKikimrTablesData : public TThrRefBase {
return Tables;
}

std::optional<TString> GetTempTablePath(const TStringBuf& table) const;

void Reset() {
Tables.clear();
}
Expand Down
2 changes: 1 addition & 1 deletion ydb/core/kqp/provider/yql_kikimr_provider_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ void TableDescriptionToTableInfo(const TKikimrTableDescription& desc, TYdbOperat

Ydb::Table::VectorIndexSettings_Metric VectorIndexSettingsParseDistance(std::string_view distance);
Ydb::Table::VectorIndexSettings_Metric VectorIndexSettingsParseSimilarity(std::string_view similarity);
Ydb::Table::VectorIndexSettings_VectorType VectorIndexSettingsParseVectorType(std::string_view vectorType);
Ydb::Table::VectorIndexSettings_VectorType VectorIndexSettingsParseVectorType(std::string_view vectorType);

bool IsPgNullExprNode(const NNodes::TExprBase& maybeLiteral);
std::optional<TString> FillLiteralProto(NNodes::TExprBase maybeLiteral, const TTypeAnnotationNode* valueType, Ydb::TypedValue& proto);
Expand Down
11 changes: 11 additions & 0 deletions ydb/core/kqp/provider/yql_kikimr_type_ann.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ class TKiSourceTypeAnnotationTransformer : public TKiSourceVisitorTransformer {

auto listSelectType = ctx.MakeType<TListExprType>(selectType);

if (!SessionCtx->Config().FeatureFlags.GetEnableShowCreate()) {
for (auto setting : readTable.Settings()) {
auto name = setting.Name().Value();
if (name == "showCreateTable") {
ctx.AddError(TIssue(ctx.GetPosition(node.Pos()),
TStringBuilder() << "SHOW CREATE statement is not supported"));
return TStatus::Error;
}
}
}

TTypeAnnotationNode::TListType children;
children.push_back(node.World().Ref().GetTypeAnn());
children.push_back(listSelectType);
Expand Down
8 changes: 4 additions & 4 deletions ydb/core/kqp/ut/common/kqp_ut_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,7 @@ std::vector<NJson::TJsonValue> FindPlanNodes(const NJson::TJsonValue& plan, cons

std::vector<NJson::TJsonValue> FindPlanStages(const NJson::TJsonValue& plan) {
std::vector<NJson::TJsonValue> stages;
FindPlanStagesImpl(plan.GetMapSafe().at("Plan"), stages);
FindPlanStagesImpl(plan.GetMapSafe().at("Plan"), stages);
return stages;
}

Expand Down Expand Up @@ -1485,7 +1485,7 @@ NJson::TJsonValue SimplifyPlan(NJson::TJsonValue& opt, const TGetPlanParams& par
if (auto ops = opt.GetMapSafe().find("Operators"); ops != opt.GetMapSafe().end()) {
auto opName = ops->second.GetArraySafe()[0].GetMapSafe().at("Name").GetStringSafe();
if (
opName.find("Join") != TString::npos ||
opName.find("Join") != TString::npos ||
opName.find("Union") != TString::npos ||
(opName.find("Filter") != TString::npos && params.IncludeFilters) ||
(opName.find("HashShuffle") != TString::npos && params.IncludeShuffles)
Expand Down Expand Up @@ -1541,7 +1541,7 @@ bool JoinOrderAndAlgosMatch(const TString& optimized, const TString& reference){
NJson::TJsonValue optRoot;
NJson::ReadJsonTree(optimized, &optRoot, true);
optRoot = SimplifyPlan(optRoot.GetMapSafe().at("SimplifiedPlan"), {});

NJson::TJsonValue refRoot;
NJson::ReadJsonTree(reference, &refRoot, true);

Expand All @@ -1567,7 +1567,7 @@ NJson::TJsonValue GetDetailedJoinOrderImpl(const NJson::TJsonValue& opt, const T
res["table"] = op.GetMapSafe().at("Table").GetStringSafe();
return res;
}

auto subplans = opt.GetMapSafe().at("Plans").GetArraySafe();
for (size_t i = 0; i < subplans.size(); ++i) {
res["args"].AppendValue(GetDetailedJoinOrderImpl(subplans[i], params));
Expand Down
76 changes: 76 additions & 0 deletions ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2761,6 +2761,82 @@ Y_UNIT_TEST_SUITE(KqpQueryService) {
checkUpsert(true, 2);
}

Y_UNIT_TEST(ShowCreateTable) {
auto serverSettings = TKikimrSettings().SetEnableShowCreate(true);

TKikimrRunner kikimr(serverSettings);
auto db = kikimr.GetQueryClient();
auto session = db.GetSession().GetValueSync().GetSession();

{
auto result = session.ExecuteQuery(R"(
CREATE TABLE test_show_create (
Key Uint32,
Value Uint32,
PRIMARY KEY (Key)
);
)", TTxControl::NoTx()).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}

{
auto result = session.ExecuteQuery(R"(
SHOW CREATE TABLE `/Root/test_show_create`;
)", TTxControl::NoTx()).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());

UNIT_ASSERT(!result.GetResultSets().empty());

CompareYson(R"([
[["test_show_create"];["Table"];["CREATE TABLE `test_show_create` (\n `Key` Uint32,\n `Value` Uint32,\n PRIMARY KEY (`Key`)\n);\n"]];
])", FormatResultSetYson(result.GetResultSet(0)));
}
}

Y_UNIT_TEST(ShowCreateTableDisable) {
auto serverSettings = TKikimrSettings().SetEnableShowCreate(false);

TKikimrRunner kikimr(serverSettings);
auto db = kikimr.GetQueryClient();
auto session = db.GetSession().GetValueSync().GetSession();

{
auto result = session.ExecuteQuery(R"(
CREATE TABLE test_show_create (
Key Uint32,
Value Uint32,
PRIMARY KEY (Key)
);
)", TTxControl::NoTx()).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}

{
auto result = session.ExecuteQuery(R"(
SHOW CREATE TABLE `/Root/test_show_create`;
)", TTxControl::NoTx()).ExtractValueSync();
UNIT_ASSERT(!result.IsSuccess());

UNIT_ASSERT_VALUES_EQUAL("<main>: Error: Type annotation, code: 1030\n <main>:2:35: Error: At function: KiReadTable!\n <main>:2:35: Error: SHOW CREATE statement is not supported\n",
result.GetIssues().ToString());
}
}

Y_UNIT_TEST(ShowCreateTableNotSuccess) {
auto serverSettings = TKikimrSettings().SetEnableShowCreate(true);

TKikimrRunner kikimr(serverSettings);
auto db = kikimr.GetQueryClient();
auto session = db.GetSession().GetValueSync().GetSession();

{
auto result = session.ExecuteQuery(R"(
SHOW CREATE TABLE test_show_create;
)", TTxControl::NoTx()).ExtractValueSync();
UNIT_ASSERT(!result.IsSuccess());
}
}

Y_UNIT_TEST(DdlCache) {
NKikimrConfig::TAppConfig appConfig;
auto setting = NKikimrKqp::TKqpSetting();
Expand Down
1 change: 1 addition & 0 deletions ydb/core/protos/feature_flags.proto
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,5 @@ message TFeatureFlags {
optional bool EnableChangefeedsImport = 170 [default = false];
optional bool EnablePermissionsExport = 171 [default = false];
optional bool EnableDataErasure = 172 [default = false];
optional bool EnableShowCreate = 173 [default = false];
}
2 changes: 1 addition & 1 deletion ydb/core/protos/kqp_physical.proto
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ message TKqpPhyColumnId {

message TKqpPhyColumnTypeParam {
oneof TypeParam {
string PgTypeName = 1;
string PgTypeName = 1;
Ydb.DecimalType Decimal = 2;
}
}
Expand Down
2 changes: 2 additions & 0 deletions ydb/core/sys_view/common/schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ class TSystemViewResolver : public ISystemViewResolver {
RegisterSystemView<Schema::AuthPermissions>(PermissionsName);
RegisterSystemView<Schema::AuthPermissions>(EffectivePermissionsName);
}

RegisterSystemView<Schema::ShowCreate>(ShowCreateName);
}

private:
Expand Down
Loading
Loading