Skip to content

Commit

Permalink
Use empty parsing context to build view's select in CREATE VIEW state…
Browse files Browse the repository at this point in the history
…ment (#2049) (#2595)

Based on: #2049

KIKIMR-20891

CREATE VIEW statement parses (and validates) the select statement saved in the view. It should be parsed in a context isolated from the statements executed before the CREATE VIEW statement (we haven't decided yet on the exact scope of the context of the view's select statement, see [KIKIMR-20656](https://st.yandex-team.ru/KIKIMR-20656)). It is pretty obvious that one should be able to execute the following statement in one go ("one go" = one press of a "run" button in YDB UI):
```sql
-- create view NecessaryInnerView with (security_invoker = true) as select 1;
-- create view ContextTestingView with (security_invoker = true) as select * from `/local/NecessaryInnerView`; -- where `/local/...` is your cluster name

drop view ContextTestingView;
create view ContextTestingView with (security_invoker = true) as select * from `/local/NecessaryInnerView`;
```

However, executing both drop view and create view in one go currently produces and error:
```
DropObject is not yet implemented for intent determination transformer
```
which indicates that the context of the inner query:
```sql
select * from `/local/NecessaryInnerView`
```
is polluted by the previous:
```sql
drop view ContextTestingView;
```
statement.

This problem is fixed by using an empty parsing context for parsing view's inner select statement during handling of CREATE VIEW statement.
  • Loading branch information
jepett0 authored Mar 13, 2024
1 parent b3004c6 commit c205eed
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
18 changes: 18 additions & 0 deletions ydb/core/kqp/ut/view/view_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,24 @@ Y_UNIT_TEST_SUITE(TKQPViewTest) {
UNIT_ASSERT(dropResult.GetIssues().ToString().Contains("Error: Path does not exist"));
}
}

Y_UNIT_TEST(ContextPollution) {
TKikimrRunner kikimr(TKikimrSettings().SetWithSampleTables(false));
EnableViewsFeatureFlag(kikimr);
auto session = kikimr.GetTableClient().CreateSession().GetValueSync().GetSession();

ExecuteDataDefinitionQuery(session, R"(
CREATE VIEW InnerView WITH (security_invoker = TRUE) AS SELECT 1;
)");
ExecuteDataDefinitionQuery(session, R"(
CREATE VIEW OuterView WITH (security_invoker = TRUE) AS SELECT * FROM InnerView;
)");

ExecuteDataDefinitionQuery(session, R"(
DROP VIEW OuterView;
CREATE VIEW OuterView WITH (security_invoker = TRUE) AS SELECT * FROM InnerView;
)");
}
}

Y_UNIT_TEST_SUITE(TSelectFromViewTest) {
Expand Down
43 changes: 31 additions & 12 deletions ydb/library/yql/sql/v1/sql_translation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,33 @@ TString CollectTokens(const TRule_select_stmt& selectStatement) {
return tokenCollector.Tokens;
}

NSQLTranslation::TTranslationSettings CreateViewTranslationSettings(const NSQLTranslation::TTranslationSettings& base) {
NSQLTranslation::TTranslationSettings settings;

settings.ClusterMapping = base.ClusterMapping;
settings.Mode = NSQLTranslation::ESqlMode::LIMITED_VIEW;

return settings;
}

TNodePtr BuildViewSelect(const TRule_select_stmt& query, TContext& ctx) {
const auto viewTranslationSettings = CreateViewTranslationSettings(ctx.Settings);
TContext viewParsingContext(viewTranslationSettings, {}, ctx.Issues);
TSqlSelect select(viewParsingContext, viewTranslationSettings.Mode);
TPosition pos;
auto source = select.Build(query, pos);
if (!source) {
return nullptr;
}
return BuildSelectResult(
pos,
std::move(source),
false,
false,
viewParsingContext.Scoped
);
}

}

namespace NSQLTranslationV1 {
Expand Down Expand Up @@ -4484,19 +4511,11 @@ bool TSqlTranslation::ParseViewQuery(std::map<TString, TDeferredAtom>& features,
const TString queryText = CollectTokens(query);
features["query_text"] = {Ctx.Pos(), queryText};

{
TSqlSelect select(Ctx, Mode);
TPosition pos;
auto source = select.Build(query, pos);
if (!source) {
return false;
}
features["query_ast"] = {BuildSelectResult(pos,
std::move(source),
false,
false,
Ctx.Scoped), Ctx};
const auto viewSelect = BuildViewSelect(query, Ctx);
if (!viewSelect) {
return false;
}
features["query_ast"] = {viewSelect, Ctx};

return true;
}
Expand Down

0 comments on commit c205eed

Please sign in to comment.