Skip to content

Commit

Permalink
KIKIMR-19719: Lookup for simple PgSelect
Browse files Browse the repository at this point in the history
  • Loading branch information
qrort committed Jan 24, 2024
1 parent acefc40 commit c11a71b
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 49 deletions.
8 changes: 4 additions & 4 deletions ydb/core/kqp/opt/kqp_query_plan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,8 @@ class TxPlanSerializer {
TStringBuilder rangeDesc;
rangeDesc << keyColumns[colId] << " "
<< (from[keyColumns.size()].GetDataText() == "1" ? "[" : "(")
<< (from[colId].HaveValue() ? from[colId].GetDataText() : "-∞") << ", "
<< (to[colId].HaveValue() ? to[colId].GetDataText() : "+∞")
<< (from[colId].HaveValue() ? from[colId].GetSimpleValueText() : "-∞") << ", "
<< (to[colId].HaveValue() ? to[colId].GetSimpleValueText() : "+∞")
<< (to[keyColumns.size()].GetDataText() == "1" ? "]" : ")");

readInfo.ScanBy.push_back(rangeDesc);
Expand Down Expand Up @@ -1469,8 +1469,8 @@ class TxPlanSerializer {
TStringBuilder rangeDesc;
rangeDesc << keyColumns[colId] << " "
<< (from[keyColumns.size()].GetDataText() == "1" ? "[" : "(")
<< (from[colId].HaveValue() ? from[colId].GetDataText() : "-∞") << ", "
<< (to[colId].HaveValue() ? to[colId].GetDataText() : "+∞")
<< (from[colId].HaveValue() ? from[colId].GetSimpleValueText() : "-∞") << ", "
<< (to[colId].HaveValue() ? to[colId].GetSimpleValueText() : "+∞")
<< (to[keyColumns.size()].GetDataText() == "1" ? "]" : ")");

readInfo.ScanBy.push_back(rangeDesc);
Expand Down
4 changes: 2 additions & 2 deletions ydb/core/kqp/opt/logical/kqp_opt_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class TKqpLogicalOptTransformer : public TOptimizeTransformerBase {
, Config(config)
{
#define HNDL(name) "KqpLogical-"#name, Hndl(&TKqpLogicalOptTransformer::name)
AddHandler(0, &TCoFlatMap::Match, HNDL(PushPredicateToReadTable));
AddHandler(0, &TCoFlatMap::Match, HNDL(PushExtractedPredicateToReadTable));
AddHandler(0, &TCoFlatMapBase::Match, HNDL(PushPredicateToReadTable));
AddHandler(0, &TCoFlatMapBase::Match, HNDL(PushExtractedPredicateToReadTable));
AddHandler(0, &TCoAggregate::Match, HNDL(RewriteAggregate));
AddHandler(0, &TCoAggregateCombine::Match, HNDL(PushdownOlapGroupByKeys));
AddHandler(0, &TCoTake::Match, HNDL(RewriteTakeSortToTopSort));
Expand Down
21 changes: 15 additions & 6 deletions ydb/core/kqp/opt/logical/kqp_opt_log_ranges_predext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,11 @@ TMaybeNode<TExprBase> TryBuildTrivialReadTable(TCoFlatMap& flatmap, TKqlReadTabl
TExprBase KqpPushExtractedPredicateToReadTable(TExprBase node, TExprContext& ctx, const TKqpOptimizeContext& kqpCtx,
TTypeAnnotationContext& typesCtx)
{
if (!node.Maybe<TCoFlatMap>()) {
if (!node.Maybe<TCoFlatMapBase>()) {
return node;
}

auto flatmap = node.Cast<TCoFlatMap>();
auto flatmap = node.Cast<TCoFlatMapBase>();

if (!IsPredicateFlatMap(flatmap.Lambda().Body().Ref())) {
return node;
Expand Down Expand Up @@ -252,6 +252,8 @@ TExprBase KqpPushExtractedPredicateToReadTable(TExprBase node, TExprContext& ctx
kqpCtx.Cluster,
mainTableDesc.Metadata->GetIndexMetadata(TString(indexName.Cast())).first->Name)
: mainTableDesc;
YQL_ENSURE(node.Maybe<TCoFlatMap>(), "got OrderedFlatMap with disabled PredicateExtract20");
auto flatmap = node.Cast<TCoFlatMap>();
if (auto expr = TryBuildTrivialReadTable(flatmap, read, *readMatch, tableDesc, ctx, kqpCtx, indexName)) {
return expr.Cast();
}
Expand Down Expand Up @@ -501,10 +503,17 @@ TExprBase KqpPushExtractedPredicateToReadTable(TExprBase node, TExprContext& ctx

*input = readMatch->BuildProcessNodes(*input, ctx);

return Build<TCoFlatMap>(ctx, node.Pos())
.Input(*input)
.Lambda(residualLambda)
.Done();
if (node.Maybe<TCoFlatMap>()) {
return Build<TCoFlatMap>(ctx, node.Pos())
.Input(*input)
.Lambda(residualLambda)
.Done();
} else {
return Build<TCoOrderedFlatMap>(ctx, node.Pos())
.Input(*input)
.Lambda(residualLambda)
.Done();
}
}

} // namespace NKikimr::NKqp::NOpt
Expand Down
22 changes: 0 additions & 22 deletions ydb/core/kqp/opt/query_plan_value/kqp_query_plan_value.cpp

This file was deleted.

12 changes: 0 additions & 12 deletions ydb/core/kqp/opt/query_plan_value/ya.make

This file was deleted.

1 change: 0 additions & 1 deletion ydb/core/kqp/opt/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ PEERDIR(
ydb/core/kqp/opt/logical
ydb/core/kqp/opt/peephole
ydb/core/kqp/opt/physical
ydb/core/kqp/opt/query_plan_value
ydb/library/yql/dq/common
ydb/library/yql/dq/opt
ydb/library/yql/dq/type_ann
Expand Down
124 changes: 123 additions & 1 deletion ydb/core/kqp/ut/pg/kqp_pg_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3529,7 +3529,8 @@ Y_UNIT_TEST_SUITE(KqpPg) {
SELECT * FROM PgTable WHERE key = 'a';
)");
auto result = db.ExecuteQuery(query, NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::PRECONDITION_FAILED, result.GetIssues().ToString());
UNIT_ASSERT(result.GetIssues().ToString().Contains("invalid input syntax for type integer: \"a\""));
}
}

Expand Down Expand Up @@ -3608,6 +3609,127 @@ Y_UNIT_TEST_SUITE(KqpPg) {
UNIT_ASSERT(result.GetIssues().ToString().Contains("invalid byte sequence for encoding \"UTF8\": 0x00"));
}
}

Y_UNIT_TEST(NoSelectFullScan) {
NKikimrConfig::TAppConfig appConfig;
appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
auto setting = NKikimrKqp::TKqpSetting();
auto serverSettings = TKikimrSettings()
.SetAppConfig(appConfig)
.SetKqpSettings({setting});
TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
auto db = kikimr.GetQueryClient();
auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
{
auto result = db.ExecuteQuery(R"(
CREATE TABLE pgbench_accounts(aid int not null,bid int,abalance int,filler char(84), primary key (aid))
)", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}
{
auto result = db.ExecuteQuery(R"(
INSERT INTO pgbench_accounts (aid, bid, abalance, filler) VALUES
(1, 1, 10, ' '::char),
(2, 1, 20, ' '::char),
(3, 1, 30, ' '::char),
(4, 1, 40, '
'::char),
(5, 1, 50, ' '::char),
(6, 1, 60, ' '::char),
(7, 1, 70, ' '::char),
(8, 1, 80, ' '::char),
(9, 1, 90, ' '::char),
(10, 1, 100, ' '::char)
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}
{
auto tc = kikimr.GetTableClient();
TStreamExecScanQuerySettings settings;
settings.Explain(true);
auto it = tc.StreamExecuteScanQuery(R"(
--!syntax_pg
SELECT abalance FROM pgbench_accounts WHERE aid = 7 OR aid = 3 ORDER BY abalance;
)", settings).GetValueSync();

UNIT_ASSERT_C(it.IsSuccess(), it.GetIssues().ToString());

auto res = CollectStreamResult(it);
UNIT_ASSERT(res.PlanJson);

NJson::TJsonValue plan;
NJson::ReadJsonTree(*res.PlanJson, &plan, true);
UNIT_ASSERT(ValidatePlanNodeIds(plan));

auto fullScan = FindPlanNodeByKv(plan, "Node Type", "Filter-TableFullScan");
UNIT_ASSERT_C(!fullScan.IsDefined(), "got fullscan, expected lookup");
auto lookup = FindPlanNodeByKv(plan, "Node Type", "TableLookup");
UNIT_ASSERT_C(lookup.IsDefined(), "no Table Lookup in plan");
}
{
auto result = db.ExecuteQuery(R"(
SELECT abalance FROM pgbench_accounts WHERE aid = 7 OR aid = 3 ORDER BY abalance;
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
CompareYson(R"([
["30"];["70"]
])", FormatResultSetYson(result.GetResultSet(0)));
}
{
auto tc = kikimr.GetTableClient();
TStreamExecScanQuerySettings settings;
settings.Explain(true);
auto it = tc.StreamExecuteScanQuery(R"(
--!syntax_pg
SELECT abalance FROM pgbench_accounts WHERE aid = 7 OR aid < 3 ORDER BY abalance;
)", settings).GetValueSync();

UNIT_ASSERT_C(it.IsSuccess(), it.GetIssues().ToString());

auto res = CollectStreamResult(it);
UNIT_ASSERT(res.PlanJson);
Cerr << res.PlanJson << Endl;

NJson::TJsonValue plan;
NJson::ReadJsonTree(*res.PlanJson, &plan, true);
UNIT_ASSERT(ValidatePlanNodeIds(plan));

auto fullScan = FindPlanNodeByKv(plan, "Node Type", "Filter-TableFullScan");
UNIT_ASSERT_C(!fullScan.IsDefined(), "got fullscan, expected lookup");
auto lookup = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_C(lookup.IsDefined(), "no Table Range Scan in plan");
}
{
auto tc = kikimr.GetTableClient();
TStreamExecScanQuerySettings settings;
settings.Explain(true);
auto it = tc.StreamExecuteScanQuery(R"(
--!syntax_pg
SELECT abalance FROM pgbench_accounts WHERE aid > 4 AND aid < 3;
)", settings).GetValueSync();

UNIT_ASSERT_C(it.IsSuccess(), it.GetIssues().ToString());

auto res = CollectStreamResult(it);
UNIT_ASSERT(res.PlanJson);
Cerr << res.PlanJson << Endl;
NJson::TJsonValue plan;
NJson::ReadJsonTree(*res.PlanJson, &plan, true);
UNIT_ASSERT(ValidatePlanNodeIds(plan));

auto fullScan = FindPlanNodeByKv(plan, "Node Type", "Filter-TableFullScan");
UNIT_ASSERT_C(!fullScan.IsDefined(), "got fullscan, expected lookup");
auto lookup = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_C(lookup.IsDefined(), "no Table Range Scan in plan");
}
{
auto result = db.ExecuteQuery(R"(
SELECT abalance FROM pgbench_accounts WHERE aid > 4 AND aid < 3;
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
CompareYson(R"([])", FormatResultSetYson(result.GetResultSet(0)));
}
}
}

} // namespace NKqp
Expand Down
9 changes: 9 additions & 0 deletions ydb/library/yql/utils/plan/plan_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ TString ToStr(const TCoDataCtor& data) {
return out.Str();
}

TString ToStr(const TCoPgConst& data) {
TStringStream out;
EscapeArbitraryAtom(data.Value().Value(), '"', &out);
return out.Str();
}


TString ToStr(const TCoLambda& lambda) {
return PrettyExprStr(lambda.Body());
}
Expand Down Expand Up @@ -143,6 +150,8 @@ TString PrettyExprStr(const TExprBase& expr) {
return TString(expr.Ref().Child(0)->Content());
} else if (auto data = expr.Maybe<TCoDataCtor>()) {
return ToStr(data.Cast());
} else if (auto pgConst = expr.Maybe<TCoPgConst>()) {
return ToStr(pgConst.Cast());
} else if (auto lambda = expr.Maybe<TCoLambda>()) {
return ToStr(lambda.Cast());
} else if (auto asStruct = expr.Maybe<TCoAsStruct>()) {
Expand Down
20 changes: 20 additions & 0 deletions ydb/public/lib/value/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,26 @@ TString TValue::GetDataText() const {
return TStringBuilder() << "\"<unknown type " << Type.GetData().GetScheme() << ">\"";
}

TString TValue::GetPgText() const {
Y_ASSERT(Type.GetKind() == NKikimrMiniKQL::ETypeKind::Pg);
if (Value.HasNullFlagValue()) {
return TString("null");
}
Y_ENSURE(Value.HasText());
return Value.GetText();
}

TString TValue::GetSimpleValueText() const {
if (Type.GetKind() == NKikimrMiniKQL::ETypeKind::Pg) {
return GetPgText();
}
if (Type.GetKind() == NKikimrMiniKQL::ETypeKind::Data) {
return GetDataText();
}
Y_ENSURE(false, TStringBuilder() << "unexpected NKikimrMiniKQL::ETypeKind: " << ETypeKind_Name(GetType().GetKind()));
}


template <> TString TValue::GetTypeText<TFormatCxx>(const TFormatCxx& format) const {
switch(Type.GetKind()) {
case NKikimrMiniKQL::ETypeKind::Void:
Expand Down
5 changes: 4 additions & 1 deletion ydb/public/lib/value/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,12 @@ class TValue {
NScheme::TTypeId GetDataType() const;
// gets text representation of simple 'Data' types
TString GetDataText() const;

// gets text representation of simple 'Pg' types
// You need to add ydb/core/kqp/opt/query_plan_value to PEERDIRs in order to use this function
TString GetPgText() const;
// gets text representation of simple 'Data' and 'Pg' types
TString GetSimpleValueText() const;

// returns text representation of value's type
template <typename Format> TString GetTypeText(const Format& format = Format()) const;
// returns text representation of value itself
Expand Down

0 comments on commit c11a71b

Please sign in to comment.