Skip to content

Commit f95d5a6

Browse files
authored
Redirect pg_tables reads to system table. Resolves #1918 (#5338)
1 parent 43d5e45 commit f95d5a6

File tree

8 files changed

+206
-43
lines changed

8 files changed

+206
-43
lines changed

ydb/core/kqp/executer_actor/kqp_partition_helper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ TSerializedTableRange MakeKeyRange(const TVector<NScheme::TTypeInfo>& keyColumnT
441441
{
442442
YQL_ENSURE(range.HasFrom());
443443
YQL_ENSURE(range.HasTo());
444+
auto guard = typeEnv.BindAllocator();
444445

445446
auto fromValues = FillKeyValues(keyColumnTypes, range.GetFrom(), stageInfo, holderFactory, typeEnv);
446447
if (range.GetFrom().GetIsInclusive()) {

ydb/core/kqp/provider/yql_kikimr_opt_build.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,53 @@ TExprNode::TPtr KiBuildQuery(TExprBase node, TExprContext& ctx, TIntrusivePtr<TK
854854
auto settings = NCommon::ParseCommitSettings(commit, ctx);
855855
auto kiDataSink = commit.DataSink().Cast<TKiDataSink>();
856856

857+
TNodeOnNodeOwnedMap replaces;
858+
VisitExpr(node.Ptr(), [&replaces](const TExprNode::TPtr& input) -> bool {
859+
if (input->IsCallable("PgTableContent")) {
860+
TPgTableContent content(input);
861+
if (content.Table() == "pg_tables") {
862+
replaces[input.Get()] = nullptr;
863+
}
864+
}
865+
return true;
866+
});
867+
if (!replaces.empty()) {
868+
TExprNode::TPtr path = ctx.NewCallable(node.Pos(), "String", { ctx.NewAtom(node.Pos(), "/Root/.sys/pg_tables") });
869+
auto table = ctx.NewList(node.Pos(), {ctx.NewAtom(node.Pos(), "table"), path});
870+
auto newKey = ctx.NewCallable(node.Pos(), "Key", {table});
871+
872+
for (auto& [key, _] : replaces) {
873+
auto ydbSysTableRead = Build<TCoRead>(ctx, node.Pos())
874+
.World<TCoWorld>().Build()
875+
.DataSource<TCoDataSource>()
876+
.Category(ctx.NewAtom(node.Pos(), KikimrProviderName))
877+
.FreeArgs()
878+
.Add(ctx.NewAtom(node.Pos(), "db"))
879+
.Build()
880+
.Build()
881+
.FreeArgs()
882+
.Add(newKey)
883+
.Add(ctx.NewCallable(node.Pos(), "Void", {}))
884+
.Add(ctx.NewList(node.Pos(), {}))
885+
.Build()
886+
.Done().Ptr();
887+
888+
auto readData = Build<TCoRight>(ctx, node.Pos())
889+
.Input(ydbSysTableRead)
890+
.Done().Ptr();
891+
replaces[key] = readData;
892+
}
893+
ctx.Step
894+
.Repeat(TExprStep::ExprEval)
895+
.Repeat(TExprStep::DiscoveryIO)
896+
.Repeat(TExprStep::Epochs)
897+
.Repeat(TExprStep::Intents)
898+
.Repeat(TExprStep::LoadTablesMetadata)
899+
.Repeat(TExprStep::RewriteIO);
900+
auto res = ctx.ReplaceNodes(std::move(node.Ptr()), replaces);
901+
return res;
902+
}
903+
857904
TKiExploreTxResults txExplore;
858905
txExplore.ConcurrentResults = concurrentResults;
859906
if (!ExploreTx(commit.World(), ctx, kiDataSink, txExplore, tablesData, types) || txExplore.HasErrors) {

ydb/core/kqp/ut/pg/pg_catalog_ut.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,65 @@ Y_UNIT_TEST_SUITE(PgCatalog) {
404404
])", FormatResultSetYson(result.GetResultSet(0)));
405405
}
406406
}
407+
408+
Y_UNIT_TEST(PgTables) {
409+
bool experimentalPg = false;
410+
if (auto* p = std::getenv("YDB_EXPERIMENTAL_PG")) {
411+
experimentalPg = true;
412+
}
413+
TKikimrRunner kikimr(NKqp::TKikimrSettings().SetWithSampleTables(false));
414+
auto db = kikimr.GetQueryClient();
415+
auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
416+
{
417+
auto result = db.ExecuteQuery(R"(
418+
CREATE TABLE table1 (
419+
id int4 primary key
420+
);
421+
CREATE TABLE table2 (
422+
id varchar primary key
423+
);
424+
)", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
425+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
426+
}
427+
{
428+
auto result = db.ExecuteQuery(R"(
429+
SELECT * FROM pg_tables WHERE schemaname = 'public' AND hasindexes = true ORDER BY tablename;
430+
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
431+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
432+
UNIT_ASSERT_C(!result.GetResultSets().empty(), "no result sets");
433+
CompareYson(R"([
434+
["t";"f";"f";"f";"public";"table1";"root@builtin";#];
435+
["t";"f";"f";"f";"public";"table2";"root@builtin";#]
436+
])", FormatResultSetYson(result.GetResultSet(0)));
437+
}
438+
{
439+
auto result = db.ExecuteQuery(R"(
440+
--!syntax_pg
441+
select
442+
min(schemaname) min_s,
443+
min(tablename) min_t,
444+
max(schemaname) max_s,
445+
max(tablename) max_t
446+
from pg_catalog.pg_tables;
447+
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
448+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
449+
UNIT_ASSERT_C(!result.GetResultSets().empty(), "no result sets");
450+
CompareYson(R"([
451+
["information_schema";"_pg_foreign_data_wrappers";"public";"views"]
452+
])", FormatResultSetYson(result.GetResultSet(0)));
453+
}
454+
{
455+
auto result = db.ExecuteQuery(R"(
456+
select count(*)
457+
from pg_catalog.pg_tables;
458+
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
459+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
460+
UNIT_ASSERT_C(!result.GetResultSets().empty(), "no result sets");
461+
CompareYson(
462+
Sprintf("[[\"%u\"]]", experimentalPg ? 208 : 205),
463+
FormatResultSetYson(result.GetResultSet(0)));
464+
}
465+
}
407466
}
408467

409468
} // namespace NKqp

ydb/core/sys_view/common/schema.cpp

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
namespace NKikimr {
66
namespace NSysView {
77

8-
TVector<Schema::PgColumn> Schema::PgTables::Columns = { //lexicographical order
9-
Schema::PgColumn(5, "pgbool", "hasindexes"),
10-
Schema::PgColumn(6, "pgbool", "hasrules"),
11-
Schema::PgColumn(7, "pgbool", "hastriggers"),
12-
Schema::PgColumn(8, "pgbool", "rowsecurity"),
8+
const TVector<Schema::PgColumn> Schema::PgTables::Columns = {
139
Schema::PgColumn(1, "pgname", "schemaname"),
1410
Schema::PgColumn(2, "pgname", "tablename"),
1511
Schema::PgColumn(3, "pgname", "tableowner"),
16-
Schema::PgColumn(4, "pgname", "tablespace")
12+
Schema::PgColumn(4, "pgname", "tablespace"),
13+
Schema::PgColumn(5, "pgbool", "hasindexes"),
14+
Schema::PgColumn(6, "pgbool", "hasrules"),
15+
Schema::PgColumn(7, "pgbool", "hastriggers"),
16+
Schema::PgColumn(8, "pgbool", "rowsecurity")
1717
};
1818

1919
bool MaybeSystemViewPath(const TVector<TString>& path) {
@@ -182,24 +182,14 @@ class TSystemViewResolver : public ISystemViewResolver {
182182
void RegisterPgTablesSystemView() {
183183
auto& dsv = DomainSystemViews[PgTablesName];
184184
auto& sdsv = SubDomainSystemViews[PgTablesName];
185-
auto PgTablesSchema = Schema::PgTables();
186-
for (const auto& column : PgTablesSchema.Columns) {
187-
dsv.Columns[column._ColumnId - 1] = TSysTables::TTableColumnInfo(
188-
column.GetColumnName(), column._ColumnId, column._ColumnTypeInfo, "", -1
185+
for (const auto& column : Schema::PgTables::Columns) {
186+
dsv.Columns[column._ColumnId] = TSysTables::TTableColumnInfo(
187+
column._ColumnName, column._ColumnId, column._ColumnTypeInfo, "", -1
189188
);
190-
sdsv.Columns[column._ColumnId - 1] = TSysTables::TTableColumnInfo(
191-
column.GetColumnName(), column._ColumnId, column._ColumnTypeInfo, "", -1
189+
sdsv.Columns[column._ColumnId] = TSysTables::TTableColumnInfo(
190+
column._ColumnName, column._ColumnId, column._ColumnTypeInfo, "", -1
192191
);
193192
}
194-
auto fillKey = [&](TSchema& schema, i32 index) -> void {
195-
auto& column = schema.Columns[index];
196-
column.KeyOrder = index;
197-
schema.KeyColumnTypes.push_back(column.PType);
198-
};
199-
for (size_t i = 0; i < 2; i++) {
200-
fillKey(dsv, i);
201-
fillKey(sdsv, i);
202-
}
203193
}
204194

205195
template <typename Table>

ydb/core/sys_view/common/schema.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,15 +596,12 @@ struct Schema : NIceDb::Schema {
596596
NScheme::TTypeInfo _ColumnTypeInfo;
597597
TString _ColumnName;
598598
PgColumn(NIceDb::TColumnId columnId, TStringBuf columnTypeName, TStringBuf columnName)
599-
: _ColumnId(columnId), _ColumnTypeInfo(NScheme::TTypeInfo(NScheme::NTypeIds::Pg, NPg::TypeDescFromPgTypeName(columnTypeName))), _ColumnName(columnName) {}
600-
601-
TString GetColumnName() const {
602-
return _ColumnName;
603-
}
599+
: _ColumnId(columnId), _ColumnTypeInfo(NScheme::NTypeIds::Pg, NPg::TypeDescFromPgTypeName(columnTypeName)), _ColumnName(columnName)
600+
{}
604601
};
605602

606603
struct PgTables {
607-
static TVector<PgColumn> Columns;
604+
const static TVector<PgColumn> Columns;
608605
};
609606
};
610607

ydb/core/sys_view/pg_tables/pg_tables.cpp

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,85 @@ class TPgTablesScan : public NKikimr::NSysView::TScanActorBase<TPgTablesScan> {
2222
private:
2323
TCell MakePgCell(const Schema::PgColumn& column, const TString& value, TVector<TString>& cellData) {
2424
NYql::NUdf::TStringRef ref;
25-
auto typeDesc = column._ColumnTypeInfo.GetTypeDesc();
26-
auto convert = NPg::PgNativeBinaryFromNativeText(value, NPg::PgTypeIdFromTypeDesc(typeDesc));
25+
auto convert = NPg::PgNativeBinaryFromNativeText(value, NPg::PgTypeIdFromTypeDesc(column._ColumnTypeInfo.GetTypeDesc()));
2726
if (convert.Error) {
2827
ConvertError_ = *convert.Error;
2928
return TCell();
3029
}
3130
cellData.emplace_back(convert.Str);
3231
ref = NYql::NUdf::TStringRef(cellData.back());
33-
32+
Y_ENSURE(ref.Size() > 0);
3433
return TCell(ref.Data(), ref.Size());
3534
}
3635

3736
TVector<TCell> MakePgTablesRow(const TString& tableName, const TString& tableOwner, TVector<TString>& cellData) {
38-
const auto &Columns = Schema::PgTables::Columns;
39-
return {
40-
MakePgCell(Columns[0], "true", cellData), //hasindexes
41-
MakePgCell(Columns[1], "false", cellData), //hasrules
42-
MakePgCell(Columns[2], "false", cellData), //hastriggers
43-
MakePgCell(Columns[3], "false", cellData), //rowsecurity
44-
MakePgCell(Columns[4], "public", cellData), //schemaname
45-
MakePgCell(Columns[5], tableName, cellData), //tablename
46-
MakePgCell(Columns[6], tableOwner, cellData), //tableowner
47-
TCell() //tablespace
48-
};
37+
TVector<TCell> res;
38+
res.reserve(Columns.size());
39+
for (const auto& column : Columns) {
40+
TCell cell;
41+
switch (column.Tag) {
42+
case 1: {
43+
cell = MakePgCell(Schema::PgTables::Columns[0], "public", cellData);
44+
break;
45+
}
46+
case 2: {
47+
cell = MakePgCell(Schema::PgTables::Columns[1], tableName, cellData);
48+
break;
49+
}
50+
case 3: {
51+
cell = MakePgCell(Schema::PgTables::Columns[2], tableOwner, cellData);
52+
break;
53+
}
54+
case 4: {
55+
cell = TCell();
56+
break;
57+
}
58+
case 5: {
59+
cell = MakePgCell(Schema::PgTables::Columns[4], "true", cellData);
60+
break;
61+
}
62+
case 6: {
63+
cell = MakePgCell(Schema::PgTables::Columns[5], "false", cellData);
64+
break;
65+
}
66+
case 7: {
67+
cell = MakePgCell(Schema::PgTables::Columns[6], "false", cellData);
68+
break;
69+
}
70+
case 8: {
71+
cell = MakePgCell(Schema::PgTables::Columns[7], "false", cellData);
72+
break;
73+
}
74+
75+
}
76+
res.emplace_back(std::move(cell));
77+
}
78+
return res;
79+
}
80+
81+
TVector<TCell> MakePgTablesStaticRow(const NYql::NPg::TTableInfo& tableInfo, TVector<TString>& cellData) {
82+
TVector<TCell> res;
83+
res.reserve(Columns.size());
84+
for (const auto& column : Columns) {
85+
TCell cell;
86+
switch (column.Tag) {
87+
case 1: {
88+
cell = MakePgCell(Schema::PgTables::Columns[0], tableInfo.Schema, cellData);
89+
break;
90+
}
91+
case 2: {
92+
cell = MakePgCell(Schema::PgTables::Columns[1], tableInfo.Name, cellData);
93+
break;
94+
}
95+
default: {
96+
cell = TCell();
97+
break;
98+
}
99+
100+
}
101+
res.emplace_back(std::move(cell));
102+
}
103+
return res;
49104
}
50105
public:
51106
using TBase = NKikimr::NSysView::TScanActorBase<TPgTablesScan>;
@@ -71,6 +126,19 @@ class TPgTablesScan : public NKikimr::NSysView::TScanActorBase<TPgTablesScan> {
71126
Become(&TPgTablesScan::StateWork);
72127
}
73128

129+
void ExpandBatchWithStaticTables(const THolder<NKqp::TEvKqpCompute::TEvScanData>& batch) {
130+
for (const auto& tableDesc : NYql::NPg::GetStaticTables()) {
131+
TVector<TString> cellData;
132+
TVector<TCell> cells = MakePgTablesStaticRow(tableDesc, cellData);
133+
if (!ConvertError_.Empty()) {
134+
ReplyErrorAndDie(Ydb::StatusIds::INTERNAL_ERROR, ConvertError_);
135+
return;
136+
}
137+
TArrayRef<const TCell> ref(cells);
138+
batch->Rows.emplace_back(TOwnedCellVec::Make(ref));
139+
}
140+
}
141+
74142
void Handle(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult::TPtr& ev, const TActorContext& ctx) {
75143
Y_UNUSED(ctx);
76144
const auto& record = ev->Get()->GetRecord();
@@ -102,6 +170,7 @@ class TPgTablesScan : public NKikimr::NSysView::TScanActorBase<TPgTablesScan> {
102170

103171
auto batch = MakeHolder<NKqp::TEvKqpCompute::TEvScanData>(ScanId);
104172

173+
ExpandBatchWithStaticTables(batch);
105174

106175
for (size_t i = 0; i < record.GetPathDescription().ChildrenSize(); ++i) {
107176
TVector<TString> cellData;

ydb/core/sys_view/ut_kqp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ Y_UNIT_TEST_SUITE(SystemView) {
326326
auto session = client.CreateSession().GetValueSync().GetSession();
327327
{
328328
auto result = session.ExecuteDataQuery(R"(
329-
SELECT schemaname, tablename, tableowner, tablespace, hasindexes, hasrules, hastriggers, rowsecurity FROM `Root/.sys/pg_tables`;
329+
SELECT schemaname, tablename, tableowner, tablespace, hasindexes, hasrules, hastriggers, rowsecurity FROM `Root/.sys/pg_tables` WHERE tablename = PgName("Table0") OR tablename = PgName("Table1") ORDER BY tablename;
330330
)", TTxControl::BeginTx().CommitTx()).ExtractValueSync();
331331

332332
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());

ydb/library/yql/providers/pg/provider/yql_pg_provider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ TDataProviderInitializer GetPgDataProviderInitializer() {
6262
};
6363
}
6464

65-
}
65+
}

0 commit comments

Comments
 (0)