From 698ccab6abda126f41f150150699b16e563eb4f8 Mon Sep 17 00:00:00 2001 From: eelke Date: Thu, 7 Apr 2022 19:35:29 +0200 Subject: [PATCH] wip --- pglablib/PgsqlLexer.g4 | 62 +++++++++-------- pglablib/PgsqlParser.g4 | 18 +++++ pglablib/pglablib.pro | 4 ++ .../BuildStandardItemTreeModelNodeVisitor.cpp | 69 +++++++++++++++++++ .../BuildStandardItemTreeModelNodeVisitor.h | 28 ++++++++ pglablib/sqlast/Node.cpp | 6 +- pglablib/sqlast/Node.h | 13 ++++ pglablib/sqlast/NodeVisitor.cpp | 8 +++ pglablib/sqlast/NodeVisitor.h | 27 ++++++++ pglablib/sqlast/SelectItem.cpp | 6 ++ pglablib/sqlast/SelectItem.h | 2 + pglablib/sqlast/SelectList.cpp | 15 +++- pglablib/sqlast/SelectList.h | 11 +-- pglablib/sqlast/SelectStatement.cpp | 6 ++ pglablib/sqlast/SelectStatement.h | 1 + pglablib/sqlast/StatementList.cpp | 7 +- pglablib/sqlast/StatementList.h | 1 + pglablib/sqlast/StringLiteral.cpp | 6 ++ pglablib/sqlast/StringLiteral.h | 1 + tests/pglabtests/tst_newParser.cpp | 11 +++ 20 files changed, 265 insertions(+), 37 deletions(-) create mode 100644 pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp create mode 100644 pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h create mode 100644 pglablib/sqlast/NodeVisitor.cpp create mode 100644 pglablib/sqlast/NodeVisitor.h diff --git a/pglablib/PgsqlLexer.g4 b/pglablib/PgsqlLexer.g4 index 55e2ce3..91109e7 100644 --- a/pglablib/PgsqlLexer.g4 +++ b/pglablib/PgsqlLexer.g4 @@ -11,45 +11,51 @@ Dot: '.'; OpenParen: '('; CloseParen: ')'; -fragment A : 'a' | 'A'; -fragment B : 'B' | 'b'; -fragment C : 'C' | 'c'; -fragment D : 'D' | 'd'; -fragment E : 'E' | 'e'; -fragment F : 'F' | 'f'; -fragment G : 'G' | 'g'; -fragment H : 'H' | 'h'; -fragment I : 'I' | 'i'; -fragment J : 'J' | 'j'; -fragment K : 'K' | 'k'; -fragment L : 'L' | 'l'; -fragment M : 'M' | 'm'; -fragment N : 'N' | 'n'; -fragment O : 'O' | 'o'; -fragment P : 'P' | 'p'; -fragment Q : 'Q' | 'q'; -fragment R : 'R' | 'r'; -fragment S : 'S' | 's'; -fragment T : 'T' | 't'; -fragment U : 'U' | 'u'; -fragment V : 'V' | 'v'; -fragment W : 'W' | 'w'; -fragment X : 'X' | 'x'; -fragment Y : 'Y' | 'y'; -fragment Z : 'Z' | 'z'; +fragment A : [aA]; +fragment B : [bB]; +fragment C : [cC]; +fragment D : [dD]; +fragment E : [eE]; +fragment F : [fF]; +fragment G : [gG]; +fragment H : [hH]; +fragment I : [iI]; +fragment J : [jJ]; +fragment K : [kK]; +fragment L : [lL]; +fragment M : [mM]; +fragment N : [nN]; +fragment O : [oO]; +fragment P : [pP]; +fragment Q : [qQ]; +fragment R : [rR]; +fragment S : [sS]; +fragment T : [tT]; +fragment U : [uU]; +fragment V : [vV]; +fragment W : [wW]; +fragment X : [xX]; +fragment Y : [yY]; +fragment Z : [zZ]; As: A S; By: B Y; +Cross: C R O S S; From: F R O M; Full: F U L L; Group: G R O U P; Having: H A V I N G; +Inner: I N N E R; Join: J O I N; Left : L E F T; +Natural : N A T U R A L; +On : O N; Order : O R D E R; +Outer : O U T E R; Right : R I G H T; -Select: S E L E C T; -Where: W H E R E; +Select : S E L E C T; +Using : U S I N G; +Where : W H E R E; Ident: [\p{Alpha}]~[\p{White_Space}]* { diff --git a/pglablib/PgsqlParser.g4 b/pglablib/PgsqlParser.g4 index 7f817c6..0b2c947 100644 --- a/pglablib/PgsqlParser.g4 +++ b/pglablib/PgsqlParser.g4 @@ -50,6 +50,24 @@ from_item : Ident Dot Ident from_alias? | Ident from_alias? | OpenParen select_stmt CloseParen from_alias + | from_item (Left|Right|Full) Outer? Join from_item (join_on_condition|join_using_condition) + | from_item Natural (Left|Right|Full) Outer? Join from_item + ; + +join_on_condition + : On + ; + +join_using_condition + : Using OpenParen ident_list CloseParen (As join_using_alias) + ; + +join_using_alias + : + ; + +ident_list + : Ident (Comma Ident)* ; from_alias diff --git a/pglablib/pglablib.pro b/pglablib/pglablib.pro index 974b722..5ae18c3 100644 --- a/pglablib/pglablib.pro +++ b/pglablib/pglablib.pro @@ -45,11 +45,13 @@ SOURCES += \ catalog/PgConstraintContainer.cpp \ ParamListJson.cpp \ ParamListModel.cpp \ + sqlast/BuildStandardItemTreeModelNodeVisitor.cpp \ sqlast/ColumnDefinition.cpp \ sqlast/CreateTable.cpp \ sqlast/Expression.cpp \ sqlast/Literal.cpp \ sqlast/Node.cpp \ + sqlast/NodeVisitor.cpp \ sqlast/SelectItem.cpp \ sqlast/SelectList.cpp \ sqlast/SelectStatement.cpp \ @@ -130,11 +132,13 @@ HEADERS += \ catalog/PgConstraintContainer.h \ ParamListJson.h \ ParamListModel.h \ + sqlast/BuildStandardItemTreeModelNodeVisitor.h \ sqlast/ColumnDefinition.h \ sqlast/CreateTable.h \ sqlast/Expression.h \ sqlast/Literal.h \ sqlast/Node.h \ + sqlast/NodeVisitor.h \ sqlast/SelectItem.h \ sqlast/SelectList.h \ sqlast/SelectStatement.h \ diff --git a/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp b/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp new file mode 100644 index 0000000..6839d9d --- /dev/null +++ b/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp @@ -0,0 +1,69 @@ +#include "BuildStandardItemTreeModelNodeVisitor.h" + +using namespace sqlast; + +namespace { + + template + class AutoRevert { + public: + AutoRevert(T& var, const T newValue) + : variable(var) + , previousValue(var) + { + variable = std::move(newValue); + } + + AutoRevert(T& var, const T&& newValue) + : variable(var) + , previousValue(var) + { + variable = std::move(newValue); + } + + ~AutoRevert() + { + variable = std::move(previousValue); + } + + AutoRevert(const AutoRevert&) = delete; + AutoRevert operator=(const AutoRevert&) = delete; + + private: + T& variable; + T previousValue; + }; + + template + AutoRevert MakeAutoRevert(T& var, const T newValue) + { + return AutoRevert(var, newValue); + } +} + +BuildStandardItemTreeModelNodeVisitor::BuildStandardItemTreeModelNodeVisitor() + : model(std::make_unique()) + , currentParent(model->invisibleRootItem()) +{ +} + +void BuildStandardItemTreeModelNodeVisitor::Visit(SelectItem &selectItem) +{ +} + +void BuildStandardItemTreeModelNodeVisitor::Visit(SelectList &selectList) +{ +} + +void BuildStandardItemTreeModelNodeVisitor::Visit(SelectStatement &selectStatement) +{ + auto item = new QStandardItem("SELECT"); + currentParent->appendRow(item); + auto guard = MakeAutoRevert(currentParent, item); + + +} + +void sqlast::BuildStandardItemTreeModelNodeVisitor::Visit(StatementList &statementList) +{ +} diff --git a/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h b/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h new file mode 100644 index 0000000..32dbe63 --- /dev/null +++ b/pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h @@ -0,0 +1,28 @@ +#pragma once + +#include "NodeVisitor.h" + +#include +#include + +namespace sqlast { + + class BuildStandardItemTreeModelNodeVisitor : public NodeVisitor + { + public: + BuildStandardItemTreeModelNodeVisitor(); + + // NodeVisitor interface + public: + virtual void Visit(SelectItem &selectItem) override; + virtual void Visit(SelectList &selectList) override; + virtual void Visit(SelectStatement &selectStatement) override; + virtual void Visit(StatementList &statementList) override; + virtual void Visit(StringLiteral &stringLiteral) override; + private: + std::unique_ptr model; + QStandardItem *currentParent; + + }; + +} diff --git a/pglablib/sqlast/Node.cpp b/pglablib/sqlast/Node.cpp index e194e6e..d995fe8 100644 --- a/pglablib/sqlast/Node.cpp +++ b/pglablib/sqlast/Node.cpp @@ -4,5 +4,9 @@ using namespace sqlast; Node::Node() { - +} + +QString Node::ToString() const +{ + return QString::fromUtf8(typeid(*this).name()); } diff --git a/pglablib/sqlast/Node.h b/pglablib/sqlast/Node.h index ced5599..e754d53 100644 --- a/pglablib/sqlast/Node.h +++ b/pglablib/sqlast/Node.h @@ -1,12 +1,25 @@ #pragma once +#include +#include +#include + namespace sqlast { + class NodeVisitor; + class Node { public: Node(); virtual ~Node() = default; + virtual void Accept(NodeVisitor &visitor) = 0; + /// Every derived class that has child nodes should override these + /// to facilitate +// virtual int ChildCount() const { return 0; } +// virtual const Node* GetChild(int index) const { throw std::out_of_range("GetChild"); } + + virtual QString ToString() const; }; } diff --git a/pglablib/sqlast/NodeVisitor.cpp b/pglablib/sqlast/NodeVisitor.cpp new file mode 100644 index 0000000..61c2374 --- /dev/null +++ b/pglablib/sqlast/NodeVisitor.cpp @@ -0,0 +1,8 @@ +#include "NodeVisitor.h" +#include "sqlast/SelectList.h" + +void sqlast::NodeVisitor::VisitSelectListItems(SelectList &selectList) +{ + for (int idx = 0; idx < selectList.Count(); ++idx) + Visit(selectList.Get(idx)); +} diff --git a/pglablib/sqlast/NodeVisitor.h b/pglablib/sqlast/NodeVisitor.h new file mode 100644 index 0000000..baa8c7e --- /dev/null +++ b/pglablib/sqlast/NodeVisitor.h @@ -0,0 +1,27 @@ +#pragma once + +namespace sqlast { + + class SelectItem; + class SelectList; + class SelectStatement; + class StatementList; + class StringLiteral; + + class NodeVisitor + { + public: + virtual ~NodeVisitor() = default; + + virtual void Visit(SelectItem &selectItem) = 0; + virtual void Visit(SelectList &selectList) = 0; + virtual void Visit(SelectStatement &selectStatement) = 0; + virtual void Visit(StatementList &statementList) = 0; + virtual void Visit(StringLiteral &stringLiteral) = 0; + + protected: + void VisitSelectListItems(SelectList &selectList); + + }; + +} diff --git a/pglablib/sqlast/SelectItem.cpp b/pglablib/sqlast/SelectItem.cpp index 6066eac..5f798e0 100644 --- a/pglablib/sqlast/SelectItem.cpp +++ b/pglablib/sqlast/SelectItem.cpp @@ -1,5 +1,6 @@ #include "SelectItem.h" #include "Expression.h" +#include "NodeVisitor.h" using namespace sqlast; @@ -11,3 +12,8 @@ void SelectItem::SetAlias(const std::string &alias) { this->alias = alias; } + +void SelectItem::Accept(NodeVisitor &visitor) +{ + visitor.Visit(*this); +} diff --git a/pglablib/sqlast/SelectItem.h b/pglablib/sqlast/SelectItem.h index 998f4c3..eadfabc 100644 --- a/pglablib/sqlast/SelectItem.h +++ b/pglablib/sqlast/SelectItem.h @@ -17,6 +17,8 @@ public: void SetAlias(const std::string &alias); std::string GetAlias() const { return alias; } + + void Accept(NodeVisitor &visitor) override; private: std::unique_ptr expression; std::string alias; diff --git a/pglablib/sqlast/SelectList.cpp b/pglablib/sqlast/SelectList.cpp index 26ae4d8..695bb05 100644 --- a/pglablib/sqlast/SelectList.cpp +++ b/pglablib/sqlast/SelectList.cpp @@ -1,5 +1,6 @@ #include "SelectList.h" #include "SelectItem.h" +#include "sqlast/NodeVisitor.h" using namespace sqlast; @@ -9,10 +10,20 @@ SelectList::SelectList() void SelectList::Add(std::unique_ptr select_item) { - list.push_back(std::move(select_item)); + selectItems.push_back(std::move(select_item)); } int SelectList::Count() const { - return static_cast(list.size()); + return static_cast(selectItems.size()); +} + +SelectItem &SelectList::Get(int index) +{ + return *selectItems.at(index); +} + +void SelectList::Accept(NodeVisitor &visitor) +{ + visitor.Visit(*this); } diff --git a/pglablib/sqlast/SelectList.h b/pglablib/sqlast/SelectList.h index cf29565..defbf0b 100644 --- a/pglablib/sqlast/SelectList.h +++ b/pglablib/sqlast/SelectList.h @@ -6,6 +6,8 @@ namespace sqlast { + + class SelectItem; class SelectList : public Node @@ -16,14 +18,13 @@ namespace sqlast { void Add(std::unique_ptr select_item); int Count() const; - SelectItem& Get(int index) - { - return *list.at(index); - } + SelectItem& Get(int index); + + void Accept(NodeVisitor &visitor) override; private: using List = std::vector>; - List list; + List selectItems; }; } diff --git a/pglablib/sqlast/SelectStatement.cpp b/pglablib/sqlast/SelectStatement.cpp index 814e54e..e693c06 100644 --- a/pglablib/sqlast/SelectStatement.cpp +++ b/pglablib/sqlast/SelectStatement.cpp @@ -1,5 +1,6 @@ #include "SelectStatement.h" #include "SelectList.h" +#include "NodeVisitor.h" using namespace sqlast; @@ -17,3 +18,8 @@ void SelectStatement::SetSelectList(std::unique_ptr value) { selectList = std::move(value); } + +void SelectStatement::Accept(NodeVisitor &visitor) +{ + visitor.Visit(*this); +} diff --git a/pglablib/sqlast/SelectStatement.h b/pglablib/sqlast/SelectStatement.h index c6c9b8d..6f7708d 100644 --- a/pglablib/sqlast/SelectStatement.h +++ b/pglablib/sqlast/SelectStatement.h @@ -15,6 +15,7 @@ namespace sqlast { SelectList* GetSelectList(); void SetSelectList(std::unique_ptr value); + void Accept(NodeVisitor &visitor) override; private: std::unique_ptr selectList; }; diff --git a/pglablib/sqlast/StatementList.cpp b/pglablib/sqlast/StatementList.cpp index bf4fcd7..6bfe21b 100644 --- a/pglablib/sqlast/StatementList.cpp +++ b/pglablib/sqlast/StatementList.cpp @@ -1,6 +1,6 @@ #include "StatementList.h" #include "Statement.h" - +#include "sqlast/NodeVisitor.h" using namespace sqlast; @@ -22,3 +22,8 @@ int StatementList::Count() const return static_cast(statements.size()); } +void StatementList::Accept(NodeVisitor &visitor) +{ + visitor.Visit(*this); +} + diff --git a/pglablib/sqlast/StatementList.h b/pglablib/sqlast/StatementList.h index 16bd4ee..2d994c4 100644 --- a/pglablib/sqlast/StatementList.h +++ b/pglablib/sqlast/StatementList.h @@ -18,6 +18,7 @@ namespace sqlast { Statement &Get(int index); int Count() const; + void Accept(NodeVisitor &visitor) override; private: using Statements = std::vector>; diff --git a/pglablib/sqlast/StringLiteral.cpp b/pglablib/sqlast/StringLiteral.cpp index d3179eb..7be79c6 100644 --- a/pglablib/sqlast/StringLiteral.cpp +++ b/pglablib/sqlast/StringLiteral.cpp @@ -1,7 +1,13 @@ #include "StringLiteral.h" +#include "NodeVisitor.h" using namespace sqlast; StringLiteral::StringLiteral(const std::string s) : value(QString::fromStdString(s)) {} + +void StringLiteral::Accept(NodeVisitor &visitor) +{ + visitor.Visit(*this); +} diff --git a/pglablib/sqlast/StringLiteral.h b/pglablib/sqlast/StringLiteral.h index 231c458..dc267b1 100644 --- a/pglablib/sqlast/StringLiteral.h +++ b/pglablib/sqlast/StringLiteral.h @@ -12,6 +12,7 @@ namespace sqlast { explicit StringLiteral(const std::string s); QString GetValue() const { return value; } + void Accept(NodeVisitor &visitor) override; private: QString value; }; diff --git a/tests/pglabtests/tst_newParser.cpp b/tests/pglabtests/tst_newParser.cpp index b8fd06e..11d7b7b 100644 --- a/tests/pglabtests/tst_newParser.cpp +++ b/tests/pglabtests/tst_newParser.cpp @@ -38,6 +38,17 @@ TEST(NewSqlLexer, QuotedIdent) ASSERT_EQ("Abc", token->getText()); } +TEST(NewSqlLexer, AcceptNewLineInQuotedIdent) +{ + std::string source = "\"Ab\nc\""; + antlr4::ANTLRInputStream input(source); + PgsqlLexer lexer(&input); + + auto token = lexer.nextToken(); + ASSERT_EQ(PgsqlLexer::Ident, token->getType()); + ASSERT_EQ("Ab\nc", token->getText()); +} + TEST(NewSqlParser, statementList) {