aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Stoyan <vitstn@gmail.com>2022-05-24 22:14:54 +0300
committerVitaly Stoyan <vitstn@gmail.com>2022-05-24 22:14:54 +0300
commitb1826fcfe6cc1ada0fa9bd0fc4366ef04e2c52d9 (patch)
tree9078ebf8b8a37dca7eb16bf887c8416858c4cfdf
parent30efb7cf3661c8170af80ec2c9ba01b99fcd4a73 (diff)
downloadydb-b1826fcfe6cc1ada0fa9bd0fc4366ef04e2c52d9.tar.gz
YQL-14728 views
ref:a4cef1272fed6eb42a91272055ee9ab34b96e139
-rw-r--r--ydb/library/yql/sql/pg/pg_sql.cpp145
1 files changed, 140 insertions, 5 deletions
diff --git a/ydb/library/yql/sql/pg/pg_sql.cpp b/ydb/library/yql/sql/pg/pg_sql.cpp
index cba5991b87..c79b5cac3f 100644
--- a/ydb/library/yql/sql/pg/pg_sql.cpp
+++ b/ydb/library/yql/sql/pg/pg_sql.cpp
@@ -155,6 +155,14 @@ public:
TString Scope;
};
+ struct TView {
+ TString Name;
+ TVector<TString> ColNames;
+ TAstNode* Source = nullptr;
+ };
+
+ using TViews = THashMap<TString, TView>;
+
TConverter(TAstParseResult& astParseResult, const NSQLTranslation::TTranslationSettings& settings)
: AstParseResult(astParseResult)
, Settings(settings)
@@ -194,6 +202,11 @@ public:
}
}
+ if (!Views.empty()) {
+ AddError("Not all views have been dropped");
+ return nullptr;
+ }
+
Statements.push_back(L(A("let"), A("world"), L(A("CommitAll!"),
A("world"))));
Statements.push_back(L(A("return"), A("world")));
@@ -208,6 +221,10 @@ public:
return ParseSelectStmt(CAST_NODE(SelectStmt, node), false) != nullptr;
case T_InsertStmt:
return ParseInsertStmt(CAST_NODE(InsertStmt, node)) != nullptr;
+ case T_ViewStmt:
+ return ParseViewStmt(CAST_NODE(ViewStmt, node)) != nullptr;
+ case T_DropStmt:
+ return ParseDropStmt(CAST_NODE(DropStmt, node)) != nullptr;
default:
NodeNotImplemented(value, node);
return false;
@@ -757,6 +774,113 @@ public:
return Statements.back();
}
+ [[nodiscard]]
+ TAstNode* ParseViewStmt(const ViewStmt* value) {
+ if (ListLength(value->options) > 0) {
+ AddError("Create view: not supported options");
+ return nullptr;
+ }
+
+ TView view;
+ if (StrLength(value->view->catalogname) > 0) {
+ AddError("catalogname is not supported");
+ return nullptr;
+ }
+
+ if (StrLength(value->view->schemaname) > 0) {
+ AddError("schemaname is not supported");
+ return nullptr;
+ }
+
+ if (StrLength(value->view->relname) == 0) {
+ AddError("relname should be specified");
+ return nullptr;
+ }
+
+ view.Name = value->view->relname;
+ if (value->view->alias) {
+ AddError("alias is not supported");
+ return nullptr;
+ }
+
+ if (ListLength(value->aliases) == 0) {
+ AddError("expected at least one target column");
+ return nullptr;
+ }
+
+ for (int i = 0; i < ListLength(value->aliases); ++i) {
+ auto node = ListNodeNth(value->aliases, i);
+ if (NodeTag(node) != T_String) {
+ NodeNotImplemented(value, node);
+ return nullptr;
+ }
+
+ view.ColNames.push_back(StrVal(node));
+ }
+
+ if (value->withCheckOption != NO_CHECK_OPTION) {
+ AddError("Create view: not supported options");
+ return nullptr;
+ }
+
+
+ view.Source = ParseSelectStmt(CAST_NODE(SelectStmt, value->query), true);
+ if (!view.Source) {
+ return nullptr;
+ }
+
+ auto it = Views.find(view.Name);
+ if (it != Views.end() && !value->replace) {
+ AddError(TStringBuilder() << "View already exists: '" << view.Name << "'");
+ return nullptr;
+ }
+
+ Views[view.Name] = view;
+ return Statements.back();
+ }
+
+ [[nodiscard]]
+ TAstNode* ParseDropStmt(const DropStmt* value) {
+ if (value->removeType != OBJECT_VIEW) {
+ AddError("Not supported object type for DROP");
+ return nullptr;
+ }
+
+ // behavior and concurrent don't matter here
+ for (int i = 0; i < ListLength(value->objects); ++i) {
+ auto object = ListNodeNth(value->objects, i);
+ if (NodeTag(object) != T_List) {
+ NodeNotImplemented(value, object);
+ return nullptr;
+ }
+
+ auto lst = CAST_NODE(List, object);
+ if (ListLength(lst) != 1) {
+ AddError("Expected view name");
+ return nullptr;
+ }
+
+ auto nameNode = ListNodeNth(lst, 0);
+ if (NodeTag(nameNode) != T_String) {
+ NodeNotImplemented(value, nameNode);
+ return nullptr;
+ }
+
+ auto name = StrVal(nameNode);
+ auto it = Views.find(name);
+ if (!value->missing_ok && it == Views.end()) {
+ AddError(TStringBuilder() << "View not found: '" << name << "'");
+ return nullptr;
+ }
+
+ if (it != Views.end()) {
+ Views.erase(it);
+ }
+ }
+
+ return Statements.back();
+ }
+
TFromDesc ParseFromClause(const Node* node) {
switch (NodeTag(node)) {
case T_RangeVar:
@@ -843,16 +967,22 @@ public:
return {};
}
- if (StrLength(value->schemaname) == 0) {
- AddError("schemaname should be specified");
- return {};
- }
-
if (StrLength(value->relname) == 0) {
AddError("relname should be specified");
return {};
}
+ const TView* view = nullptr;
+ if (StrLength(value->schemaname) == 0) {
+ auto it = Views.find(value->relname);
+ if (it == Views.end()) {
+ AddError(TStringBuilder() << "View not found: '" << value->relname << "'");
+ return {};
+ }
+
+ view = &it->second;
+ }
+
TString alias;
TVector<TString> colnames;
if (value->alias) {
@@ -861,6 +991,10 @@ public:
}
}
+ if (view) {
+ return { view->Source, alias, colnames.empty() ? view->ColNames : colnames, false };
+ }
+
auto p = Settings.ClusterMapping.FindPtr(value->schemaname);
if (!p) {
AddError(TStringBuilder() << "Unknown cluster: " << value->schemaname);
@@ -2077,6 +2211,7 @@ private:
bool DqEngineForce = false;
TVector<TAstNode*> Statements;
ui32 ReadIndex = 0;
+ TViews Views;
};
NYql::TAstParseResult PGToYql(const TString& query, const NSQLTranslation::TTranslationSettings& settings) {