diff options
author | vvvv <vvvv@yandex-team.ru> | 2022-02-09 14:49:21 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 15:58:17 +0300 |
commit | 29fad848db72e0d01e449a957bc47da6f0051bee (patch) | |
tree | 81763a5253b058b974cc0b24dd03016598837f66 | |
parent | 77305b80c94a0b844372161c355536557b530197 (diff) | |
download | ydb-29fad848db72e0d01e449a957bc47da6f0051bee.tar.gz |
YQL-13710 use raw PG parser
ref:31cd6b1682243483206041ac3d511133e7202b45
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/enum.cpp | 32 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/enum.h | 24 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/ut/wrapper_ut.cpp | 3 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/wrapper.cpp | 2 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/wrapper.h | 6 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_query_wrapper/ya.make | 1 | ||||
-rw-r--r-- | ydb/library/yql/sql/pg/pg_sql.cpp | 665 | ||||
-rw-r--r-- | ydb/library/yql/sql/pg/ya.make | 12 |
8 files changed, 415 insertions, 330 deletions
diff --git a/ydb/library/yql/parser/pg_query_wrapper/enum.cpp b/ydb/library/yql/parser/pg_query_wrapper/enum.cpp deleted file mode 100644 index fee8a50ff3..0000000000 --- a/ydb/library/yql/parser/pg_query_wrapper/enum.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "enum.h" -#ifdef _WIN32 -#define __restrict -#endif -extern "C" { -#include "postgres.h" -#include "nodes/parsenodes.h" -#undef Min -#undef Max -} - -namespace NYql { - -int PG_FRAMEOPTION_NONDEFAULT = FRAMEOPTION_NONDEFAULT; -int PG_FRAMEOPTION_RANGE = FRAMEOPTION_RANGE; -int PG_FRAMEOPTION_ROWS = FRAMEOPTION_ROWS; -int PG_FRAMEOPTION_GROUPS = FRAMEOPTION_GROUPS; -int PG_FRAMEOPTION_START_UNBOUNDED_PRECEDING = FRAMEOPTION_START_UNBOUNDED_PRECEDING; -int PG_FRAMEOPTION_START_OFFSET_PRECEDING = FRAMEOPTION_START_OFFSET_PRECEDING; -int PG_FRAMEOPTION_START_CURRENT_ROW = FRAMEOPTION_START_CURRENT_ROW; -int PG_FRAMEOPTION_START_OFFSET_FOLLOWING = FRAMEOPTION_START_OFFSET_FOLLOWING; -int PG_FRAMEOPTION_START_UNBOUNDED_FOLLOWING = FRAMEOPTION_START_UNBOUNDED_FOLLOWING; -int PG_FRAMEOPTION_END_UNBOUNDED_PRECEDING = FRAMEOPTION_END_UNBOUNDED_PRECEDING; -int PG_FRAMEOPTION_END_OFFSET_PRECEDING = FRAMEOPTION_END_OFFSET_PRECEDING; -int PG_FRAMEOPTION_END_CURRENT_ROW = FRAMEOPTION_END_CURRENT_ROW; -int PG_FRAMEOPTION_END_OFFSET_FOLLOWING = FRAMEOPTION_END_OFFSET_FOLLOWING; -int PG_FRAMEOPTION_END_UNBOUNDED_FOLLOWING = FRAMEOPTION_END_UNBOUNDED_FOLLOWING; -int PG_FRAMEOPTION_EXCLUDE_CURRENT_ROW = FRAMEOPTION_EXCLUDE_CURRENT_ROW; -int PG_FRAMEOPTION_EXCLUDE_GROUP = FRAMEOPTION_EXCLUDE_GROUP; -int PG_FRAMEOPTION_EXCLUDE_TIES = FRAMEOPTION_EXCLUDE_TIES; - -} diff --git a/ydb/library/yql/parser/pg_query_wrapper/enum.h b/ydb/library/yql/parser/pg_query_wrapper/enum.h deleted file mode 100644 index 1877e6e023..0000000000 --- a/ydb/library/yql/parser/pg_query_wrapper/enum.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -namespace NYql { - -extern int PG_FRAMEOPTION_NONDEFAULT; -extern int PG_FRAMEOPTION_RANGE; -extern int PG_FRAMEOPTION_ROWS; -extern int PG_FRAMEOPTION_GROUPS; -extern int PG_FRAMEOPTION_START_UNBOUNDED_PRECEDING; -extern int PG_FRAMEOPTION_START_OFFSET_PRECEDING; -extern int PG_FRAMEOPTION_START_CURRENT_ROW; -extern int PG_FRAMEOPTION_START_OFFSET_FOLLOWING; -extern int PG_FRAMEOPTION_START_UNBOUNDED_FOLLOWING; -extern int PG_FRAMEOPTION_END_UNBOUNDED_PRECEDING; -extern int PG_FRAMEOPTION_END_OFFSET_PRECEDING; -extern int PG_FRAMEOPTION_END_CURRENT_ROW; -extern int PG_FRAMEOPTION_END_OFFSET_FOLLOWING; -extern int PG_FRAMEOPTION_END_UNBOUNDED_FOLLOWING; -extern int PG_FRAMEOPTION_EXCLUDE_CURRENT_ROW; -extern int PG_FRAMEOPTION_EXCLUDE_GROUP; -extern int PG_FRAMEOPTION_EXCLUDE_TIES; - -} - diff --git a/ydb/library/yql/parser/pg_query_wrapper/ut/wrapper_ut.cpp b/ydb/library/yql/parser/pg_query_wrapper/ut/wrapper_ut.cpp index 8bed03dc12..f5aae8d5b1 100644 --- a/ydb/library/yql/parser/pg_query_wrapper/ut/wrapper_ut.cpp +++ b/ydb/library/yql/parser/pg_query_wrapper/ut/wrapper_ut.cpp @@ -7,7 +7,8 @@ using namespace NYql; class TEvents : public IPGParseEvents { public: - void OnResult(const PgQuery__ParseResult* result) override { + void OnResult(const PgQuery__ParseResult* result, const List* raw) override { + Y_UNUSED(raw); Result.ConstructInPlace(); TStringOutput str(*Result); PrintCProto((const ProtobufCMessage*)result, str); diff --git a/ydb/library/yql/parser/pg_query_wrapper/wrapper.cpp b/ydb/library/yql/parser/pg_query_wrapper/wrapper.cpp index de6a2427d0..7627f9a194 100644 --- a/ydb/library/yql/parser/pg_query_wrapper/wrapper.cpp +++ b/ydb/library/yql/parser/pg_query_wrapper/wrapper.cpp @@ -112,7 +112,7 @@ void PGParse(const TString& input, IPGParseEvents& events) { break; } - events.OnResult(&parse_result); + events.OnResult(&parse_result, parsetree_and_error.tree); } } diff --git a/ydb/library/yql/parser/pg_query_wrapper/wrapper.h b/ydb/library/yql/parser/pg_query_wrapper/wrapper.h index 578d7d370b..2f66258e63 100644 --- a/ydb/library/yql/parser/pg_query_wrapper/wrapper.h +++ b/ydb/library/yql/parser/pg_query_wrapper/wrapper.h @@ -1,4 +1,8 @@ #pragma once +extern "C" { +struct List; +} + #include <ydb/library/yql/parser/pg_query_wrapper/contrib/protobuf/pg_query.pb-c.h> #include <ydb/library/yql/public/issue/yql_issue.h> @@ -11,7 +15,7 @@ namespace NYql { class IPGParseEvents { public: virtual ~IPGParseEvents() = default; - virtual void OnResult(const PgQuery__ParseResult* result) = 0; + virtual void OnResult(const PgQuery__ParseResult* result, const List* raw) = 0; virtual void OnError(const TIssue& issue) = 0; }; diff --git a/ydb/library/yql/parser/pg_query_wrapper/ya.make b/ydb/library/yql/parser/pg_query_wrapper/ya.make index 2d7f36a510..2a6b64e6c6 100644 --- a/ydb/library/yql/parser/pg_query_wrapper/ya.make +++ b/ydb/library/yql/parser/pg_query_wrapper/ya.make @@ -10,7 +10,6 @@ ADDINCL( SRCS( wrapper.cpp - enum.cpp contrib/src/pg_query.c contrib/src/pg_query_outfuncs_protobuf.c diff --git a/ydb/library/yql/sql/pg/pg_sql.cpp b/ydb/library/yql/sql/pg/pg_sql.cpp index bfa05df1e6..2a96350015 100644 --- a/ydb/library/yql/sql/pg/pg_sql.cpp +++ b/ydb/library/yql/sql/pg/pg_sql.cpp @@ -1,6 +1,5 @@ #include "pg_sql.h" #include <ydb/library/yql/parser/pg_query_wrapper/wrapper.h> -#include <ydb/library/yql/parser/pg_query_wrapper/enum.h> #include <ydb/library/yql/providers/common/provider/yql_provider_names.h> #include <ydb/library/yql/core/yql_callable_names.h> #include <util/string/builder.h> @@ -8,10 +7,103 @@ #include <util/generic/stack.h> #include <util/generic/hash_set.h> +#ifdef _WIN32 +#define __restrict +#endif + +#define TypeName PG_TypeName +#define SortBy PG_SortBy +#undef SIZEOF_SIZE_T +extern "C" { +#include "postgres.h" +#include "nodes/pg_list.h" +#include "nodes/parsenodes.h" +#include "nodes/value.h" +#undef Min +#undef Max +#undef TypeName +#undef SortBy +} + namespace NSQLTranslationPG { using namespace NYql; +template <typename T> +const T* CastNode(const void* nodeptr, int tag) { + Y_ENSURE(nodeTag(nodeptr) == tag); + return static_cast<const T*>(nodeptr); +} + +int NodeTag(const Node* node) { + return nodeTag(node); +} + +int NodeTag(const Value& node) { + return node.type; +} + +int IntVal(const Value& node) { + Y_ENSURE(node.type == T_Integer); + return intVal(&node); +} + +double FloatVal(const Value& node) { + Y_ENSURE(node.type == T_Float); + return floatVal(&node); +} + +const char* StrFloatVal(const Value& node) { + Y_ENSURE(node.type == T_Float); + return strVal(&node); +} + +const char* StrVal(const Value& node) { + Y_ENSURE(node.type == T_String); + return strVal(&node); +} + +int IntVal(const Node* node) { + Y_ENSURE(node->type == T_Integer); + return intVal((const Value*)node); +} + +double FloatVal(const Node* node) { + Y_ENSURE(node->type == T_Float); + return floatVal((const Value*)node); +} + +const char* StrFloatVal(const Node* node) { + Y_ENSURE(node->type == T_Float); + return strVal((const Value*)node); +} + +const char* StrVal(const Node* node) { + Y_ENSURE(node->type == T_String); + return strVal((const Value*)node); +} + +int ListLength(const List* list) { + return list_length(list); +} + +int StrLength(const char* s) { + return s ? strlen(s) : 0; +} + +int StrCompare(const char* s1, const char* s2) { + return strcmp(s1 ? s1 : "", s2 ? s2 : ""); +} + +#define CAST_NODE(nodeType, nodeptr) CastNode<nodeType>(nodeptr, T_##nodeType) +#define CAST_NODE_EXT(nodeType, tag, nodeptr) CastNode<nodeType>(nodeptr, tag) +#define LIST_CAST_NTH(nodeType, list, index) CAST_NODE(nodeType, list_nth(list, i)) +#define LIST_CAST_EXT_NTH(nodeType, tag, list, index) CAST_NODE_EXT(nodeType, tag, list_nth(list, i)) + +const Node* ListNodeNth(const List* list, int index) { + return static_cast<const Node*>(list_nth(list, index)); +} + class TConverter : public IPGParseEvents { public: static THashMap<TString,TString> BinaryOpTranslation; @@ -42,16 +134,17 @@ public: } } - void OnResult(const PgQuery__ParseResult* result) { + void OnResult(const PgQuery__ParseResult* result, const List* raw) { + Y_UNUSED(result); AstParseResult.Pool = std::make_unique<TMemoryPool>(4096); - AstParseResult.Root = ParseResult(result); + AstParseResult.Root = ParseResult(raw); } void OnError(const TIssue& issue) { AstParseResult.Issues.AddIssue(issue); } - TAstNode* ParseResult(const PgQuery__ParseResult* value) { + TAstNode* ParseResult(const List* raw) { auto configSource = L(A("DataSource"), QA(TString(NYql::ConfigProviderName))); Statements.push_back(L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource, QA("OrderedColumns")))); @@ -60,8 +153,8 @@ public: QA("DqEngine"), QA(DqEngineForce ? "force" : "auto")))); } - for (ui32 i = 0; i < value->n_stmts; ++i) { - if (!RawStmt(value->stmts[i])) { + for (int i = 0; i < ListLength(raw); ++i) { + if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) { return nullptr; } } @@ -71,32 +164,32 @@ public: } [[nodiscard]] - bool RawStmt(const PgQuery__RawStmt* value) { + bool ParseRawStmt(const RawStmt* value) { auto node = value->stmt; - switch (node->node_case) { - case PG_QUERY__NODE__NODE_SELECT_STMT: { - return SelectStmt(node->select_stmt, false) != nullptr; + switch (NodeTag(node)) { + case T_SelectStmt: { + return ParseSelectStmt(CAST_NODE(SelectStmt, node), false) != nullptr; } default: - AltNotImplemented(value, node); + NodeNotImplemented(value, node); return false; } } - using TTraverseSelectStack = TStack<std::pair<const PgQuery__SelectStmt*, bool>>; - using TTraverseNodeStack = TStack<std::pair<const PgQuery__Node*, bool>>; + using TTraverseSelectStack = TStack<std::pair<const SelectStmt*, bool>>; + using TTraverseNodeStack = TStack<std::pair<const Node*, bool>>; [[nodiscard]] - TAstNode* SelectStmt(const PgQuery__SelectStmt* value, bool inner) { + TAstNode* ParseSelectStmt(const SelectStmt* value, bool inner) { TTraverseSelectStack traverseSelectStack; traverseSelectStack.push({ value, false }); - TVector<const PgQuery__SelectStmt*> setItems; + TVector<const SelectStmt*> setItems; TVector<TAstNode*> setOpsNodes; while (!traverseSelectStack.empty()) { auto& top = traverseSelectStack.top(); - if (top.first->op == PG_QUERY__SET_OPERATION__SETOP_NONE) { + if (top.first->op == SETOP_NONE) { // leaf setItems.push_back(top.first); setOpsNodes.push_back(QA("push")); @@ -114,15 +207,14 @@ public: } else { TString op; switch (top.first->op) { - case PG_QUERY__SET_OPERATION__SETOP_UNION: + case SETOP_UNION: op = "union"; break; - case PG_QUERY__SET_OPERATION__SETOP_INTERSECT: + case SETOP_INTERSECT: op = "intersect"; break; - case PG_QUERY__SET_OPERATION__SETOP_EXCEPT: + case SETOP_EXCEPT: op = "except"; break; default: - AddError(TStringBuilder() << "SetOperation unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__set_operation__descriptor, value->op)->name); + AddError(TStringBuilder() << "SetOperation unsupported value: " << (int)top.first->op); return nullptr; } @@ -138,21 +230,22 @@ public: TVector<TAstNode*> setItemNodes; for (const auto& x : setItems) { - if (x->n_distinct_clause) { - AddError("SelectStmt: not supported distinct_clause"); + if (x->distinctClause) { + AddError("SelectStmt: not supported distinctClause"); return nullptr; } - if (x->into_clause) { - AddError("SelectStmt: not supported into_clause"); + if (x->intoClause) { + AddError("SelectStmt: not supported intoClause"); return nullptr; } TVector<TAstNode*> fromList; TVector<TAstNode*> joinOps; - for (ui32 i = 0; i < x->n_from_clause; ++i) { - if (x->from_clause[i]->node_case != PG_QUERY__NODE__NODE_JOIN_EXPR) { - auto p = FromClause(x->from_clause[i]); + for (int i = 0; i < ListLength(x->fromClause); ++i) { + auto node = ListNodeNth(x->fromClause, i); + if (NodeTag(node) != T_JoinExpr) { + auto p = ParseFromClause(node); if (!std::get<0>(p)) { return nullptr; } @@ -161,14 +254,14 @@ public: joinOps.push_back(QL()); } else { TTraverseNodeStack traverseNodeStack; - traverseNodeStack.push({ x->from_clause[i], false }); + traverseNodeStack.push({ node, false }); TVector<TAstNode*> oneJoinGroup; while (!traverseNodeStack.empty()) { auto& top = traverseNodeStack.top(); - if (top.first->node_case != PG_QUERY__NODE__NODE_JOIN_EXPR) { + if (NodeTag(top.first) != T_JoinExpr) { // leaf - auto p = FromClause(top.first); + auto p = ParseFromClause(top.first); if (!std::get<0>(p)) { return nullptr; } @@ -176,24 +269,24 @@ public: AddFrom(p, fromList); traverseNodeStack.pop(); } else { - auto join = top.first->join_expr; + auto join = CAST_NODE(JoinExpr, top.first); if (!join->larg || !join->rarg) { - AddError("join_expr: expected larg and rarg"); + AddError("JoinExpr: expected larg and rarg"); return nullptr; } if (join->alias) { - AddError("join_expr: unsupported alias"); + AddError("JoinExpr: unsupported alias"); return nullptr; } - if (join->is_natural) { - AddError("join_expr: unsupported natural"); + if (join->isNatural) { + AddError("JoinExpr: unsupported isNatural"); return nullptr; } - if (join->n_using_clause) { - AddError("join_expr: unsupported using"); + if (ListLength(join->usingClause) > 0) { + AddError("JoinExpr: unsupported using"); return nullptr; } @@ -204,17 +297,16 @@ public: } else { TString op; switch (join->jointype) { - case PG_QUERY__JOIN_TYPE__JOIN_INNER: + case JOIN_INNER: op = join->quals ? "inner" : "cross"; break; - case PG_QUERY__JOIN_TYPE__JOIN_LEFT: + case JOIN_LEFT: op = "left"; break; - case PG_QUERY__JOIN_TYPE__JOIN_FULL: + case JOIN_FULL: op = "full"; break; - case PG_QUERY__JOIN_TYPE__JOIN_RIGHT: + case JOIN_RIGHT: op = "right"; break; default: - AddError(TStringBuilder() << "jointype unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__join_type__descriptor, join->jointype)->name); + AddError(TStringBuilder() << "jointype unsupported value: " << (int)join->jointype); return nullptr; } @@ -248,26 +340,27 @@ public: } TAstNode* whereFilter = nullptr; - if (x->where_clause) { + if (x->whereClause) { TExprSettings settings; settings.AllowColumns = true; settings.Scope = "WHERE"; - whereFilter = ParseExpr(x->where_clause, settings); + whereFilter = ParseExpr(x->whereClause, settings); if (!whereFilter) { return nullptr; } } TAstNode* groupBy = nullptr; - if (x->n_group_clause) { + if (ListLength(x->groupClause) > 0) { TVector<TAstNode*> groupByItems; - for (ui32 i = 0; i < x->n_group_clause; ++i) { - if (x->group_clause[i]->node_case != PG_QUERY__NODE__NODE_COLUMN_REF) { - AltNotImplemented(x, x->group_clause[i]); + for (int i = 0; i < ListLength(x->groupClause); ++i) { + auto node = ListNodeNth(x->groupClause, i); + if (NodeTag(node) != T_ColumnRef) { + NodeNotImplemented(x, node); return nullptr; } - auto ref = ColumnRef(x->group_clause[i]->column_ref); + auto ref = ParseColumnRef(CAST_NODE(ColumnRef, node)); if (!ref) { return nullptr; } @@ -280,26 +373,27 @@ public: } TAstNode* having = nullptr; - if (x->having_clause) { + if (x->havingClause) { TExprSettings settings; settings.AllowColumns = true; settings.Scope = "HAVING"; settings.AllowAggregates = true; - having = ParseExpr(x->having_clause, settings); + having = ParseExpr(x->havingClause, settings); if (!having) { return nullptr; } } TVector<TAstNode*> windowItems; - if (x->n_window_clause) { - for (ui32 i = 0; i < x->n_window_clause; ++i) { - if (x->window_clause[i]->node_case != PG_QUERY__NODE__NODE_WINDOW_DEF) { - AltNotImplemented(x, x->window_clause[i]); + if (ListLength(x->windowClause) > 0) { + for (int i = 0; i < ListLength(x->windowClause); ++i) { + auto node = ListNodeNth(x->windowClause, i); + if (NodeTag(node) != T_WindowDef) { + NodeNotImplemented(x, node); return nullptr; } - auto win = WindowDef(x->window_clause[i]->window_def); + auto win = ParseWindowDef(CAST_NODE(WindowDef, node)); if (!win) { return nullptr; } @@ -308,45 +402,46 @@ public: } } - if (x->n_values_lists && x->n_from_clause) { + if (ListLength(x->valuesLists) && ListLength(x->fromClause)) { AddError("SelectStmt: values_lists isn't compatible to from_clause"); return nullptr; } - if (!x->n_values_lists == !x->n_target_list) { + if (!ListLength(x->valuesLists) == !ListLength(x->targetList)) { AddError("SelectStmt: only one of values_lists and target_list should be specified"); return nullptr; } - if (x != value && x->n_sort_clause) { - AddError("SelectStmt: sort_clause should be used only on top"); + if (x != value && ListLength(x->sortClause) > 0) { + AddError("SelectStmt: sortClause should be used only on top"); return nullptr; } - if (x != value && x->limit_option != PG_QUERY__LIMIT_OPTION__LIMIT_OPTION_DEFAULT) { + if (x != value && x->limitOption != LIMIT_OPTION_DEFAULT) { AddError("SelectStmt: limit should be used only on top"); return nullptr; } - if (x->n_locking_clause) { - AddError("SelectStmt: not supported locking_clause"); + if (ListLength(x->lockingClause) > 0) { + AddError("SelectStmt: not supported lockingClause"); return nullptr; } - if (x->with_clause) { - AddError("SelectStmt: not supported with_clause"); + if (x->withClause) { + AddError("SelectStmt: not supported withClause"); return nullptr; } TVector<TAstNode*> res; ui32 i = 0; - for (ui32 targetIndex = 0; targetIndex < x->n_target_list; ++targetIndex) { - if (x->target_list[targetIndex]->node_case != PG_QUERY__NODE__NODE_RES_TARGET) { - AltNotImplemented(x, x->target_list[targetIndex]); + for (int targetIndex = 0; targetIndex < ListLength(x->targetList); ++targetIndex) { + auto node = ListNodeNth(x->targetList, targetIndex); + if (NodeTag(node) != T_ResTarget) { + NodeNotImplemented(x, node); return nullptr; } - auto r = x->target_list[targetIndex]->res_target; + auto r = CAST_NODE(ResTarget, node); if (!r->val) { AddError("SelectStmt: expected val"); return nullptr; @@ -364,10 +459,10 @@ public: } bool isStar = false; - if (r->val->node_case == PG_QUERY__NODE__NODE_COLUMN_REF) { - auto ref = r->val->column_ref; - for (ui32 fieldNo = 0; fieldNo < ref->n_fields; ++fieldNo) { - if (ref->fields[fieldNo]->node_case == PG_QUERY__NODE__NODE_A_STAR) { + if (NodeTag(r->val) == T_ColumnRef) { + auto ref = CAST_NODE(ColumnRef, r->val); + for (int fieldNo = 0; fieldNo < ListLength(ref->fields); ++fieldNo) { + if (NodeTag(ListNodeNth(ref->fields, fieldNo)) == T_A_Star) { isStar = true; break; } @@ -378,11 +473,11 @@ public: if (!isStar) { name = r->name; if (name.empty()) { - if (r->val->node_case == PG_QUERY__NODE__NODE_COLUMN_REF) { - auto ref = r->val->column_ref; - auto field = ref->fields[ref->n_fields - 1]; - if (field->node_case == PG_QUERY__NODE__NODE_STRING) { - name = field->string->str; + if (NodeTag(r->val) == T_ColumnRef) { + auto ref = CAST_NODE(ColumnRef, r->val); + auto field = ListNodeNth(ref->fields, ListLength(ref->fields) - 1); + if (NodeTag(field) == T_String) { + name = StrVal(field); } } } @@ -401,31 +496,32 @@ public: TVector<TAstNode*> valNames; val.push_back(A("AsList")); - for (ui32 valueIndex = 0; valueIndex < x->n_values_lists; ++valueIndex) { + for (int valueIndex = 0; valueIndex < ListLength(x->valuesLists); ++valueIndex) { TExprSettings settings; settings.AllowColumns = false; settings.Scope = "VALUES"; - if (x->values_lists[valueIndex]->node_case != PG_QUERY__NODE__NODE_LIST) { - AltNotImplemented(x, x->values_lists[valueIndex]); + auto node = ListNodeNth(x->valuesLists, valueIndex); + if (NodeTag(node) != T_List) { + NodeNotImplemented(x, node); return nullptr; } - auto lst = x->values_lists[valueIndex]->list; + auto lst = CAST_NODE(List, node); TVector<TAstNode*> row; if (valueIndex == 0) { - for (ui32 item = 0; item < lst->n_items; ++item) { + for (int item = 0; item < ListLength(lst); ++item) { valNames.push_back(QA("column" + ToString(i++))); } } else { - if (lst->n_items != valNames.size()) { + if (ListLength(lst) != (int)valNames.size()) { AddError("SelectStmt: VALUES lists must all be the same length"); return nullptr; } } - for (ui32 item = 0; item < lst->n_items; ++item) { - auto cell = ParseExpr(lst->items[item], settings); + for (int item = 0; item < ListLength(lst); ++item) { + auto cell = ParseExpr(ListNodeNth(lst, item), settings); if (!cell) { return nullptr; } @@ -437,7 +533,7 @@ public: } TVector<TAstNode*> setItemOptions; - if (x->n_target_list) { + if (ListLength(x->targetList) > 0) { setItemOptions.push_back(QL(QA("result"), QVL(res.data(), res.size()))); } else { setItemOptions.push_back(QL(QA("values"), QVL(valNames.data(), valNames.size()), VL(val.data(), val.size()))); @@ -471,26 +567,27 @@ public: setItemNodes.push_back(setItem); } - if (value->n_distinct_clause) { - AddError("SelectStmt: not supported distinct_clause"); + if (value->distinctClause) { + AddError("SelectStmt: not supported distinctClause"); return nullptr; } - if (value->into_clause) { - AddError("SelectStmt: not supported into_clause"); + if (value->intoClause) { + AddError("SelectStmt: not supported intoClause"); return nullptr; } TAstNode* sort = nullptr; - if (value->n_sort_clause) { + if (ListLength(value->sortClause) > 0) { TVector<TAstNode*> sortItems; - for (ui32 i = 0; i < value->n_sort_clause; ++i) { - if (value->sort_clause[i]->node_case != PG_QUERY__NODE__NODE_SORT_BY) { - AltNotImplemented(value, value->sort_clause[i]); + for (int i = 0; i < ListLength(value->sortClause); ++i) { + auto node = ListNodeNth(value->sortClause, i); + if (NodeTag(node) != T_SortBy) { + NodeNotImplemented(value, node); return nullptr; } - auto sort = SortBy(value->sort_clause[i]->sort_by); + auto sort = ParseSortBy(CAST_NODE_EXT(PG_SortBy, T_SortBy, node)); if (!sort) { return nullptr; } @@ -501,43 +598,42 @@ public: sort = QVL(sortItems.data(), sortItems.size()); } - if (value->n_locking_clause) { - AddError("SelectStmt: not supported locking_clause"); + if (ListLength(value->lockingClause) > 0) { + AddError("SelectStmt: not supported lockingClause"); return nullptr; } - if (value->with_clause) { - AddError("SelectStmt: not supported with_clause"); + if (value->withClause) { + AddError("SelectStmt: not supported withClause"); return nullptr; } TAstNode* limit = nullptr; TAstNode* offset = nullptr; - if (value->limit_option != PG_QUERY__LIMIT_OPTION__LIMIT_OPTION_DEFAULT) { - if (value->limit_option == PG_QUERY__LIMIT_OPTION__LIMIT_OPTION_COUNT) { - if (!value->limit_count) { - AddError("Expected limit_count"); + if (value->limitOption != LIMIT_OPTION_DEFAULT) { + if (value->limitOption == LIMIT_OPTION_COUNT) { + if (!value->limitCount) { + AddError("Expected limitCount"); return nullptr; } TExprSettings settings; settings.AllowColumns = false; settings.Scope = "LIMIT"; - limit = ParseExpr(value->limit_count, settings); + limit = ParseExpr(value->limitCount, settings); if (!limit) { return nullptr; } - if (value->limit_offset) { + if (value->limitOffset) { settings.Scope = "OFFSET"; - offset = ParseExpr(value->limit_offset, settings); + offset = ParseExpr(value->limitOffset, settings); if (!offset) { return nullptr; } } } else { - AddError(TStringBuilder() << "LimitOption unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__limit_option__descriptor, value->limit_option)->name); + AddError(TStringBuilder() << "LimitOption unsupported value: " << (int)value->limitOption); return nullptr; } } @@ -575,14 +671,14 @@ public: return Statements.back(); } - TFromDesc FromClause(const PgQuery__Node* node) { - switch (node->node_case) { - case PG_QUERY__NODE__NODE_RANGE_VAR: - return RangeVar(node->range_var); - case PG_QUERY__NODE__NODE_RANGE_SUBSELECT: - return RangeSubselect(node->range_subselect); + TFromDesc ParseFromClause(const Node* node) { + switch (NodeTag(node)) { + case T_RangeVar: + return ParseRangeVar(CAST_NODE(RangeVar, node)); + case T_RangeSubselect: + return ParseRangeSubselect(CAST_NODE(RangeSubselect, node)); default: - AltNotImplementedDesc(nullptr, node); + NodeNotImplementedImpl<SelectStmt>(node); return {}; } } @@ -606,32 +702,33 @@ public: } } - bool ParseAlias(const PgQuery__Alias* alias, TString& res, TVector<TString>& colnames) { - for (ui32 i = 0; i < alias->n_colnames; ++i) { - if (alias->colnames[i]->node_case != PG_QUERY__NODE__NODE_STRING) { - AltNotImplemented(alias, alias->colnames[i]); + bool ParseAlias(const Alias* alias, TString& res, TVector<TString>& colnames) { + for (int i = 0; i < ListLength(alias->colnames); ++i) { + auto node = ListNodeNth(alias->colnames, i); + if (NodeTag(node) != T_String) { + NodeNotImplemented(alias, node); return false; } - colnames.push_back(alias->colnames[i]->string->str); + colnames.push_back(StrVal(node)); } res = alias->aliasname; return true; } - TFromDesc RangeVar(const PgQuery__RangeVar* value) { - if (strlen(value->catalogname) > 0) { + TFromDesc ParseRangeVar(const RangeVar* value) { + if (StrLength(value->catalogname) > 0) { AddError("catalogname is not supported"); return {}; } - if (strlen(value->schemaname) == 0) { + if (StrLength(value->schemaname) == 0) { AddError("schemaname should be specified"); return {}; } - if (strlen(value->relname) == 0) { + if (StrLength(value->relname) == 0) { AddError("relname should be specified"); return {}; } @@ -657,7 +754,7 @@ public: QL()), alias, colnames, true }; } - TFromDesc RangeSubselect(const PgQuery__RangeSubselect* value) { + TFromDesc ParseRangeSubselect(const RangeSubselect* value) { if (value->lateral) { AddError("RangeSubselect: unsupported lateral"); return {}; @@ -679,68 +776,68 @@ public: return {}; } - if (value->subquery->node_case != PG_QUERY__NODE__NODE_SELECT_STMT) { - AltNotImplemented(value, value->subquery); + if (NodeTag(value->subquery) != T_SelectStmt) { + NodeNotImplemented(value, value->subquery); return {}; } - return { SelectStmt(value->subquery->select_stmt, true), alias, colnames, false }; + return { ParseSelectStmt(CAST_NODE(SelectStmt, value->subquery), true), alias, colnames, false }; } - TAstNode* ParseExpr(const PgQuery__Node* node, const TExprSettings& settings) { - switch (node->node_case) { - case PG_QUERY__NODE__NODE_A_CONST: { - return AConst(node->a_const); + TAstNode* ParseExpr(const Node* node, const TExprSettings& settings) { + switch (NodeTag(node)) { + case T_A_Const: { + return ParseAConst(CAST_NODE(A_Const, node)); } - case PG_QUERY__NODE__NODE_A_EXPR: { - return AExpr(node->a_expr, settings); + case T_A_Expr: { + return ParseAExpr(CAST_NODE(A_Expr, node), settings); } - case PG_QUERY__NODE__NODE_COLUMN_REF: { + case T_ColumnRef: { if (!settings.AllowColumns) { AddError(TStringBuilder() << "Columns are not allowed in: " << settings.Scope); return nullptr; } - return ColumnRef(node->column_ref); + return ParseColumnRef(CAST_NODE(ColumnRef, node)); } - case PG_QUERY__NODE__NODE_TYPE_CAST: { - return TypeCast(node->type_cast); + case T_TypeCast: { + return ParseTypeCast(CAST_NODE(TypeCast, node)); } - case PG_QUERY__NODE__NODE_BOOL_EXPR: { - return BoolExpr(node->bool_expr, settings); + case T_BoolExpr: { + return ParseBoolExpr(CAST_NODE(BoolExpr, node), settings); } - case PG_QUERY__NODE__NODE_FUNC_CALL: { - return FuncCall(node->func_call, settings); + case T_FuncCall: { + return ParseFuncCall(CAST_NODE(FuncCall, node), settings); } default: - AltNotImplementedDesc(nullptr, node); + NodeNotImplemented(node); return nullptr; } } - TAstNode* AConst(const PgQuery__AConst* value) { - auto node = value->val; - switch (node->node_case) { - case PG_QUERY__NODE__NODE_INTEGER: { - return L(A("Just"), L(A("Int32"), QA(ToString(node->integer->ival)))); + TAstNode* ParseAConst(const A_Const* value) { + const auto& val = value->val; + switch (NodeTag(val)) { + case T_Integer: { + return L(A("Just"), L(A("Int32"), QA(ToString(IntVal(val))))); } - case PG_QUERY__NODE__NODE_FLOAT: { - return L(A("Just"), L(A("Double"), QA(ToString(node->float_->str)))); + case T_Float: { + return L(A("Just"), L(A("Double"), QA(ToString(StrFloatVal(val))))); } - case PG_QUERY__NODE__NODE_STRING: { - return L(A("Just"), L(A("Utf8"), QA(ToString(node->string->str)))); + case T_String: { + return L(A("Just"), L(A("Utf8"), QA(ToString(StrVal(val))))); } - case PG_QUERY__NODE__NODE_NULL: { + case T_Null: { return L(A("Null")); } default: - AltNotImplemented(value, node); + ValueNotImplemented(value, val); return nullptr; } } - TAstNode* FuncCall(const PgQuery__FuncCall* value, const TExprSettings& settings) { - if (value->n_agg_order) { + TAstNode* ParseFuncCall(const FuncCall* value, const TExprSettings& settings) { + if (ListLength(value->agg_order) > 0) { AddError("FuncCall: unsupported agg_order"); return nullptr; } @@ -772,11 +869,11 @@ public: return nullptr; } - if (strlen(value->over->name)) { + if (StrLength(value->over->name)) { window = QA(value->over->name); } else { auto index = settings.WindowItems->size(); - auto def = WindowDef(value->over); + auto def = ParseWindowDef(value->over); if (!def) { return nullptr; } @@ -787,14 +884,14 @@ public: } TVector<TString> names; - for (ui32 i = 0; i < value->n_funcname; ++i) { - auto x = value->funcname[i]; - if (x->node_case != PG_QUERY__NODE__NODE_STRING) { - AltNotImplemented(value, x); + for (int i = 0; i < ListLength(value->funcname); ++i) { + auto x = ListNodeNth(value->funcname, i); + if (NodeTag(x) != T_String) { + NodeNotImplemented(value, x); return nullptr; } - names.push_back(to_lower(TString(x->string->str))); + names.push_back(to_lower(TString(StrVal(x)))); } if (names.empty()) { @@ -847,14 +944,14 @@ public: return nullptr; } } else { - if (name == "count" && value->n_args == 0) { + if (name == "count" && ListLength(value->args) == 0) { AddError("FuncCall: count(*) must be used to call a parameterless aggregate function"); return nullptr; } bool hasError = false; - for (ui32 i = 0; i < value->n_args; ++i) { - auto x = value->args[i]; + for (int i = 0; i < ListLength(value->args); ++i) { + auto x = ListNodeNth(value->args, i); auto arg = ParseExpr(x, settings); if (!arg) { hasError = true; @@ -872,45 +969,46 @@ public: return VL(args.data(), args.size()); } - TAstNode* TypeCast(const PgQuery__TypeCast* value) { + TAstNode* ParseTypeCast(const TypeCast* value) { if (!value->arg) { AddError("Expected arg"); return nullptr; } - if (!value->type_name) { + if (!value->typeName) { AddError("Expected type_name"); return nullptr; } auto arg = value->arg; - auto typeName = value->type_name; - if (arg->node_case == PG_QUERY__NODE__NODE_A_CONST && - (arg->a_const->val->node_case == PG_QUERY__NODE__NODE_STRING || - arg->a_const->val->node_case == PG_QUERY__NODE__NODE_NULL) && - typeName->type_oid == 0 && + auto typeName = value->typeName; + if (NodeTag(arg) == T_A_Const && + (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String || + NodeTag(CAST_NODE(A_Const, arg)->val) == T_Null) && + typeName->typeOid == 0 && !typeName->setof && !typeName->pct_type && - typeName->n_typmods == 0 && - typeName->n_array_bounds == 0 && - (typeName->n_names == 2 && - typeName->names[0]->node_case == PG_QUERY__NODE__NODE_STRING && - !strcmp(typeName->names[0]->string->str, "pg_catalog") || typeName->n_names == 1) && - typeName->names[typeName->n_names - 1]->node_case == PG_QUERY__NODE__NODE_STRING && + ListLength(typeName->typmods) == 0 && + ListLength(typeName->arrayBounds) == 0 && + (ListLength(typeName->names) == 2 && + NodeTag(ListNodeNth(typeName->names, 0)) == T_String && + !StrCompare(StrVal(ListNodeNth(typeName->names, 0)), "pg_catalog") || ListLength(typeName->names) == 1) && + NodeTag(ListNodeNth(typeName->names, ListLength(typeName->names) - 1)) == T_String && typeName->typemod == -1) { - TStringBuf targetType = typeName->names[typeName->n_names - 1]->string->str; - if (arg->a_const->val->node_case == PG_QUERY__NODE__NODE_STRING && targetType == "bool") { - if (!strcmp(arg->a_const->val->string->str, "t")) { + TStringBuf targetType = StrVal(ListNodeNth(typeName->names, ListLength(typeName->names) - 1)); + if (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String && targetType == "bool") { + auto str = StrVal(CAST_NODE(A_Const, arg)->val); + if (!StrCompare(str, "t")) { return L(A("Just"), L(A("Bool"), QA("1"))); - } else if (!strcmp(arg->a_const->val->string->str, "f")) { + } else if (!StrCompare(str, "f")) { return L(A("Just"), L(A("Bool"), QA("0"))); } else { - AddError(TStringBuilder() << "Unsupported boolean literal: " << arg->a_const->val->string->str); + AddError(TStringBuilder() << "Unsupported boolean literal: " << str); return nullptr; } } - if (arg->a_const->val->node_case == PG_QUERY__NODE__NODE_NULL) { + if (NodeTag(CAST_NODE(A_Const, arg)->val) == T_Null) { TString yqlType; if (targetType == "bool") { yqlType = "Bool"; @@ -932,48 +1030,43 @@ public: return nullptr; } - TAstNode* BoolExpr(const PgQuery__BoolExpr* value, const TExprSettings& settings) { - if (value->xpr) { - AddError("BoolExpr: not supported xpr"); - return nullptr; - } - + TAstNode* ParseBoolExpr(const BoolExpr* value, const TExprSettings& settings) { switch (value->boolop) { - case PG_QUERY__BOOL_EXPR_TYPE__AND_EXPR: { - if (value->n_args != 2) { + case AND_EXPR: { + if (ListLength(value->args) != 2) { AddError("Expected 2 args for AND"); return nullptr; } - auto lhs = ParseExpr(value->args[0], settings); - auto rhs = ParseExpr(value->args[1], settings); + auto lhs = ParseExpr(ListNodeNth(value->args, 0), settings); + auto rhs = ParseExpr(ListNodeNth(value->args, 1), settings); if (!lhs || !rhs) { return nullptr; } return L(A("And"), lhs, rhs); } - case PG_QUERY__BOOL_EXPR_TYPE__OR_EXPR: { - if (value->n_args != 2) { + case OR_EXPR: { + if (ListLength(value->args) != 2) { AddError("Expected 2 args for OR"); return nullptr; } - auto lhs = ParseExpr(value->args[0], settings); - auto rhs = ParseExpr(value->args[1], settings); + auto lhs = ParseExpr(ListNodeNth(value->args, 0), settings); + auto rhs = ParseExpr(ListNodeNth(value->args, 1), settings); if (!lhs || !rhs) { return nullptr; } return L(A("Or"), lhs, rhs); } - case PG_QUERY__BOOL_EXPR_TYPE__NOT_EXPR: { - if (value->n_args != 1) { + case NOT_EXPR: { + if (ListLength(value->args) != 1) { AddError("Expected 1 arg for NOT"); return nullptr; } - auto arg = ParseExpr(value->args[0], settings); + auto arg = ParseExpr(ListNodeNth(value->args, 0), settings); if (!arg) { return nullptr; } @@ -981,23 +1074,23 @@ public: return L(A("Not"), arg); } default: - AddError(TStringBuilder() << "BoolExprType unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__bool_expr_type__descriptor, value->boolop)->name); + AddError(TStringBuilder() << "BoolExprType unsupported value: " << (int)value->boolop); return nullptr; } } - TAstNode* WindowDef(const PgQuery__WindowDef* value) { + TAstNode* ParseWindowDef(const WindowDef* value) { auto name = QA(value->name); auto refName = QA(value->refname); TVector<TAstNode*> sortItems; - for (ui32 i = 0; i < value->n_order_clause; ++i) { - if (value->order_clause[i]->node_case != PG_QUERY__NODE__NODE_SORT_BY) { - AltNotImplemented(value, value->order_clause[i]); + for (int i = 0; i < ListLength(value->orderClause); ++i) { + auto node = ListNodeNth(value->orderClause, i); + if (NodeTag(node) != T_SortBy) { + NodeNotImplemented(value, node); return nullptr; } - auto sort = SortBy(value->order_clause[i]->sort_by); + auto sort = ParseSortBy(CAST_NODE_EXT(PG_SortBy, T_SortBy, node)); if (!sort) { return nullptr; } @@ -1007,13 +1100,14 @@ public: auto sort = QVL(sortItems.data(), sortItems.size()); TVector<TAstNode*> groupByItems; - for (ui32 i = 0; i < value->n_partition_clause; ++i) { - if (value->partition_clause[i]->node_case != PG_QUERY__NODE__NODE_COLUMN_REF) { - AltNotImplemented(value, value->partition_clause[i]); + for (int i = 0; i < ListLength(value->partitionClause); ++i) { + auto node = ListNodeNth(value->partitionClause, i); + if (NodeTag(node) != T_ColumnRef) { + NodeNotImplemented(value, node); return nullptr; } - auto ref = ColumnRef(value->partition_clause[i]->column_ref); + auto ref = ParseColumnRef(CAST_NODE(ColumnRef, node)); if (!ref) { return nullptr; } @@ -1024,9 +1118,9 @@ public: auto group = QVL(groupByItems.data(), groupByItems.size()); TVector<TAstNode*> optionItems; - if (value->frame_options & PG_FRAMEOPTION_NONDEFAULT) { + if (value->frameOptions & FRAMEOPTION_NONDEFAULT) { TString exclude; - if (value->frame_options & PG_FRAMEOPTION_EXCLUDE_CURRENT_ROW) { + if (value->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) { if (exclude) { AddError("Wrong frame options"); return nullptr; @@ -1035,7 +1129,7 @@ public: exclude = "c"; } - if (value->frame_options & PG_FRAMEOPTION_EXCLUDE_GROUP) { + if (value->frameOptions & FRAMEOPTION_EXCLUDE_GROUP) { if (exclude) { AddError("Wrong frame options"); return nullptr; @@ -1044,7 +1138,7 @@ public: exclude = "cp"; } - if (value->frame_options & PG_FRAMEOPTION_EXCLUDE_TIES) { + if (value->frameOptions & FRAMEOPTION_EXCLUDE_TIES) { if (exclude) { AddError("Wrong frame options"); return nullptr; @@ -1058,7 +1152,7 @@ public: } TString type; - if (value->frame_options & PG_FRAMEOPTION_RANGE) { + if (value->frameOptions & FRAMEOPTION_RANGE) { if (type) { AddError("Wrong frame options"); return nullptr; @@ -1067,7 +1161,7 @@ public: type = "range"; } - if (value->frame_options & PG_FRAMEOPTION_ROWS) { + if (value->frameOptions & FRAMEOPTION_ROWS) { if (type) { AddError("Wrong frame options"); return nullptr; @@ -1076,7 +1170,7 @@ public: type = "rows"; } - if (value->frame_options & PG_FRAMEOPTION_GROUPS) { + if (value->frameOptions & FRAMEOPTION_GROUPS) { if (type) { AddError("Wrong frame options"); return nullptr; @@ -1091,7 +1185,7 @@ public: } TString from; - if (value->frame_options & PG_FRAMEOPTION_START_UNBOUNDED_PRECEDING) { + if (value->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) { if (from) { AddError("Wrong frame options"); return nullptr; @@ -1100,14 +1194,14 @@ public: from = "up"; } - if (value->frame_options & PG_FRAMEOPTION_START_OFFSET_PRECEDING) { + if (value->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) { if (from) { AddError("Wrong frame options"); return nullptr; } from = "p"; - auto offset = ConvertFrameOffset(value->start_offset); + auto offset = ConvertFrameOffset(value->startOffset); if (!offset) { return nullptr; } @@ -1115,7 +1209,7 @@ public: optionItems.push_back(QL(QA("from_value"), offset)); } - if (value->frame_options & PG_FRAMEOPTION_START_CURRENT_ROW) { + if (value->frameOptions & FRAMEOPTION_START_CURRENT_ROW) { if (from) { AddError("Wrong frame options"); return nullptr; @@ -1124,14 +1218,14 @@ public: from = "c"; } - if (value->frame_options & PG_FRAMEOPTION_START_OFFSET_FOLLOWING) { + if (value->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) { if (from) { AddError("Wrong frame options"); return nullptr; } from = "f"; - auto offset = ConvertFrameOffset(value->start_offset); + auto offset = ConvertFrameOffset(value->startOffset); if (!offset) { return nullptr; } @@ -1139,7 +1233,7 @@ public: optionItems.push_back(QL(QA("from_value"), offset)); } - if (value->frame_options & PG_FRAMEOPTION_START_UNBOUNDED_FOLLOWING) { + if (value->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) { AddError("Wrong frame options"); return nullptr; } @@ -1150,19 +1244,19 @@ public: } TString to; - if (value->frame_options & PG_FRAMEOPTION_END_UNBOUNDED_PRECEDING) { + if (value->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) { AddError("Wrong frame options"); return nullptr; } - if (value->frame_options & PG_FRAMEOPTION_END_OFFSET_PRECEDING) { + if (value->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) { if (to) { AddError("Wrong frame options"); return nullptr; } to = "p"; - auto offset = ConvertFrameOffset(value->end_offset); + auto offset = ConvertFrameOffset(value->endOffset); if (!offset) { return nullptr; } @@ -1170,7 +1264,7 @@ public: optionItems.push_back(QL(QA("to_value"), offset)); } - if (value->frame_options & PG_FRAMEOPTION_END_CURRENT_ROW) { + if (value->frameOptions & FRAMEOPTION_END_CURRENT_ROW) { if (to) { AddError("Wrong frame options"); return nullptr; @@ -1179,14 +1273,14 @@ public: to = "c"; } - if (value->frame_options & PG_FRAMEOPTION_END_OFFSET_FOLLOWING) { + if (value->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING) { if (to) { AddError("Wrong frame options"); return nullptr; } to = "f"; - auto offset = ConvertFrameOffset(value->end_offset); + auto offset = ConvertFrameOffset(value->endOffset); if (!offset) { return nullptr; } @@ -1194,7 +1288,7 @@ public: optionItems.push_back(QL(QA("to_value"), offset)); } - if (value->frame_options & PG_FRAMEOPTION_END_UNBOUNDED_FOLLOWING) { + if (value->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) { if (to) { AddError("Wrong frame options"); return nullptr; @@ -1217,10 +1311,10 @@ public: return L(A("PgWindow"), name, refName, group, sort, options); } - TAstNode* ConvertFrameOffset(const PgQuery__Node* off) { - if (off->node_case == PG_QUERY__NODE__NODE_A_CONST - && off->a_const->val->node_case == PG_QUERY__NODE__NODE_INTEGER) { - return L(A("Int32"), QA(ToString(off->a_const->val->integer->ival))); + TAstNode* ConvertFrameOffset(const Node* off) { + if (NodeTag(off) == T_A_Const + && NodeTag(CAST_NODE(A_Const, off)->val) == T_Integer) { + return L(A("Int32"), QA(ToString(IntVal(CAST_NODE(A_Const, off)->val)))); } else { TExprSettings settings; settings.AllowColumns = false; @@ -1234,29 +1328,27 @@ public: } } - TAstNode* SortBy(const PgQuery__SortBy* value) { + TAstNode* ParseSortBy(const PG_SortBy* value) { bool asc = true; switch (value->sortby_dir) { - case PG_QUERY__SORT_BY_DIR__SORTBY_DEFAULT: + case SORTBY_DEFAULT: break; - case PG_QUERY__SORT_BY_DIR__SORTBY_ASC: + case SORTBY_ASC: break; - case PG_QUERY__SORT_BY_DIR__SORTBY_DESC: + case SORTBY_DESC: asc = false; break; default: - AddError(TStringBuilder() << "sortby_dir unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__sort_by_dir__descriptor, value->sortby_dir)->name); + AddError(TStringBuilder() << "sortby_dir unsupported value: " << (int)value->sortby_dir); return nullptr; } - if (value->sortby_nulls != PG_QUERY__SORT_BY_NULLS__SORTBY_NULLS_DEFAULT) { - AddError(TStringBuilder() << "sortby_nulls unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__sort_by_nulls__descriptor, value->sortby_nulls)->name); + if (value->sortby_nulls != SORTBY_NULLS_DEFAULT) { + AddError(TStringBuilder() << "sortby_nulls unsupported value: " << (int)value->sortby_nulls); return nullptr; } - if (value->n_use_op) { + if (ListLength(value->useOp) > 0) { AddError("Unsupported operators in sort_by"); return nullptr; } @@ -1273,32 +1365,32 @@ public: return L(A("PgSort"), L(A("Void")), lambda, QA(asc ? "asc" : "desc")); } - TAstNode* ColumnRef(const PgQuery__ColumnRef* value) { - if (value->n_fields == 0) { + TAstNode* ParseColumnRef(const ColumnRef* value) { + if (ListLength(value->fields) == 0) { AddError("No fields"); return nullptr; } - if (value->n_fields > 2) { + if (ListLength(value->fields) > 2) { AddError("Too many fields"); return nullptr; } bool isStar = false; TVector<TString> fields; - for (ui32 i = 0; i < value->n_fields; ++i) { - auto x = value->fields[i]; + for (int i = 0; i < ListLength(value->fields); ++i) { + auto x = ListNodeNth(value->fields, i); if (isStar) { AddError("Star is already defined"); return nullptr; } - if (x->node_case == PG_QUERY__NODE__NODE_STRING) { - fields.push_back(x->string->str); - } else if (x->node_case == PG_QUERY__NODE__NODE_A_STAR) { + if (NodeTag(x) == T_String) { + fields.push_back(StrVal(x)); + } else if (NodeTag(x) == T_A_Star) { isStar = true; } else { - AltNotImplemented(value, x); + NodeNotImplemented(value, x); return nullptr; } } @@ -1316,25 +1408,24 @@ public: } } - TAstNode* AExpr(const PgQuery__AExpr* value, const TExprSettings& settings) { - if (value->kind != PG_QUERY__A__EXPR__KIND__AEXPR_OP) { - AddError(TStringBuilder() << "A_Expr_Kind unsupported value: " << - protobuf_c_enum_descriptor_get_value(&pg_query__a__expr__kind__descriptor, value->kind)->name); + TAstNode* ParseAExpr(const A_Expr* value, const TExprSettings& settings) { + if (value->kind != AEXPR_OP) { + AddError(TStringBuilder() << "A_Expr_Kind unsupported value: " << (int)value->kind); return nullptr; } - if (value->n_name != 1) { - AddError(TStringBuilder() << "Unsupported count of names: " << value->n_name); + if (ListLength(value->name) != 1) { + AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name)); return nullptr; } - auto nameNode = value->name[0]; - if (nameNode->node_case != PG_QUERY__NODE__NODE_STRING) { - AltNotImplemented(value, nameNode); + auto nameNode = ListNodeNth(value->name, 0); + if (NodeTag(nameNode) != T_String) { + NodeNotImplemented(value, nameNode); return nullptr; } - auto op = nameNode->string->str; + auto op = StrVal(nameNode); if (!value->rexpr) { AddError("Missing operands"); return nullptr; @@ -1371,6 +1462,40 @@ public: } template <typename T> + void NodeNotImplementedImpl(const Node* nodeptr) { + TStringBuilder b; + b << TypeName<T>() << ": "; + b << "alternative is not implemented yet : " << NodeTag(nodeptr); + AddError(b); + } + + template <typename T> + void NodeNotImplemented(const T* outer, const Node* nodeptr) { + Y_UNUSED(outer); + NodeNotImplementedImpl<T>(nodeptr); + } + + template <typename T> + void ValueNotImplementedImpl(const Value& value) { + TStringBuilder b; + b << TypeName<T>() << ": "; + b << "alternative is not implemented yet : " << NodeTag(value); + AddError(b); + } + + template <typename T> + void ValueNotImplemented(const T* outer, const Value& value) { + Y_UNUSED(outer); + ValueNotImplementedImpl<T>(value); + } + + void NodeNotImplemented(const Node* nodeptr) { + TStringBuilder b; + b << "alternative is not implemented yet : " << NodeTag(nodeptr); + AddError(b); + } + + template <typename T> void AltNotImplemented(const T* outer, const PgQuery__Node* node) { AltNotImplementedDesc(((const ProtobufCMessage*)outer)->descriptor, node); } diff --git a/ydb/library/yql/sql/pg/ya.make b/ydb/library/yql/sql/pg/ya.make index 6d29a9f355..42d2b193a2 100644 --- a/ydb/library/yql/sql/pg/ya.make +++ b/ydb/library/yql/sql/pg/ya.make @@ -8,8 +8,20 @@ PEERDIR( ydb/library/yql/sql/settings ) +ADDINCL( + ydb/library/yql/parser/pg_query_wrapper/contrib + GLOBAL ydb/library/yql/parser/pg_query_wrapper/contrib/vendor + ydb/library/yql/parser/pg_query_wrapper/contrib/src/postgres/include +) + SRCS( pg_sql.cpp ) +IF (OS_WINDOWS) +CFLAGS( + "-D__thread=__declspec(thread)" +) +ENDIF() + END() |