Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
698ccab6ab | ||
|
|
0da32b916c | ||
|
|
81f27a6a18 | ||
|
|
a0ba9b894f | ||
|
|
fbbe832a05 |
47 changed files with 1123 additions and 8 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -11,3 +11,5 @@ srcdoc/
|
||||||
pglabAll.pro.user.4.8-pre1
|
pglabAll.pro.user.4.8-pre1
|
||||||
*.user
|
*.user
|
||||||
/pglabAll.pro.user*
|
/pglabAll.pro.user*
|
||||||
|
.antlr/
|
||||||
|
**/.generated/*
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ error( "Use local.pri.sample to create your own local.pri" )
|
||||||
LIBS += -lUser32 -lws2_32 -llibpq
|
LIBS += -lUser32 -lws2_32 -llibpq
|
||||||
|
|
||||||
CONFIG += c++17
|
CONFIG += c++17
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
# The following define makes your compiler emit warnings if you use
|
||||||
# any feature of Qt which as been marked as deprecated (the exact warnings
|
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||||
# depend on your compiler). Please consult the documentation of the
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ enum class BasicTokenType {
|
||||||
Comma,
|
Comma,
|
||||||
Cast,
|
Cast,
|
||||||
WhiteSpace,
|
WhiteSpace,
|
||||||
NewLine
|
NewLine,
|
||||||
|
|
||||||
|
LastLexerToken
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LexerState {
|
enum class LexerState {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,24 @@ Keyword isKeyword(const QString &symbol)
|
||||||
|
|
||||||
return Keyword::NotAKeyword;
|
return Keyword::NotAKeyword;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
Put tokens on a stack
|
||||||
|
Every time something is put on the stack see if it matches a rule
|
||||||
|
|
||||||
|
The stack needs to contain both tokens from the lexical analyzer as tokens for reductions done by the parser.
|
||||||
|
|
||||||
|
Matching rules, as we need to match against the top of the stack we should match the rules end to start.
|
||||||
|
Meaning if we have on the stack A B C then we need to consider rules ending with a C
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class StackItem {
|
||||||
|
public:
|
||||||
|
int Token;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
SqlParser::SqlParser(SqlLexer &lexer)
|
SqlParser::SqlParser(SqlLexer &lexer)
|
||||||
: lexer(lexer)
|
: lexer(lexer)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ class ConnectionConfig;
|
||||||
class ConnectionNode {
|
class ConnectionNode {
|
||||||
public:
|
public:
|
||||||
virtual ~ConnectionNode() = default;
|
virtual ~ConnectionNode() = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConnectionGroup: public ConnectionNode {
|
class ConnectionGroup: public ConnectionNode {
|
||||||
|
|
@ -115,7 +116,10 @@ public:
|
||||||
bool dirty() const;
|
bool dirty() const;
|
||||||
void clean();
|
void clean();
|
||||||
|
|
||||||
bool operator==(QUuid id) const { return m_uuid == id; }
|
bool operator==(const ConnectionConfig &rhs) const
|
||||||
|
{
|
||||||
|
return m_uuid == rhs.m_uuid;
|
||||||
|
}
|
||||||
|
|
||||||
QString makeLongDescription() const;
|
QString makeLongDescription() const;
|
||||||
QByteArray encodedPassword() const;
|
QByteArray encodedPassword() const;
|
||||||
|
|
|
||||||
77
pglablib/PgsqlLexer.g4
Normal file
77
pglablib/PgsqlLexer.g4
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
lexer grammar PgsqlLexer;
|
||||||
|
|
||||||
|
@lexer::preinclude {
|
||||||
|
#include <QString>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SemiColon: ';';
|
||||||
|
Comma: ',';
|
||||||
|
Dot: '.';
|
||||||
|
OpenParen: '(';
|
||||||
|
CloseParen: ')';
|
||||||
|
|
||||||
|
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;
|
||||||
|
Using : U S I N G;
|
||||||
|
Where : W H E R E;
|
||||||
|
|
||||||
|
Ident: [\p{Alpha}]~[\p{White_Space}]*
|
||||||
|
{
|
||||||
|
setText(QString::fromStdString(getText()).toLower().toStdString());
|
||||||
|
}
|
||||||
|
| '"' ~["]+ '"'
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::string s = getText();
|
||||||
|
s = s.substr(1, s.length() - 2);
|
||||||
|
setText(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IntegerLiteral: [1-9][0-9]*;
|
||||||
|
StringLiteral: '\'' ('\'\'' | ~['])+ '\'' { setText(getText().substr(1, getText().length()-2)); };
|
||||||
|
|
||||||
|
Whitespace: [\p{White_Space}] -> skip ; // skip spaces, tabs, newlines
|
||||||
|
|
||||||
|
UnexpectedSymbol: .;
|
||||||
119
pglablib/PgsqlParser.g4
Normal file
119
pglablib/PgsqlParser.g4
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
// Define a grammar called postgresql
|
||||||
|
parser grammar PgsqlParser;
|
||||||
|
|
||||||
|
options {
|
||||||
|
tokenVocab = PgsqlLexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@parser::preinclude {
|
||||||
|
#include "sqlast/sqlast.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
@parser::includes {
|
||||||
|
}
|
||||||
|
|
||||||
|
@parser::members {
|
||||||
|
}
|
||||||
|
|
||||||
|
main returns [std::unique_ptr<sqlast::StatementList> program]
|
||||||
|
: statement_list { $program = std::move($statement_list.result); }
|
||||||
|
;
|
||||||
|
|
||||||
|
statement_list returns [std::unique_ptr<sqlast::StatementList> result]
|
||||||
|
: { $result = std::make_unique<sqlast::StatementList>(); }
|
||||||
|
(statement SemiColon { $result->Add(std::move($statement.result)); } | empty_statement)*
|
||||||
|
(statement SemiColon? { $result->Add(std::move($statement.result)); } | empty_statement )
|
||||||
|
;
|
||||||
|
|
||||||
|
statement returns [std::unique_ptr<sqlast::Statement> result]
|
||||||
|
: select_stmt { $result = std::move($select_stmt.result); }
|
||||||
|
;
|
||||||
|
|
||||||
|
empty_statement
|
||||||
|
: SemiColon
|
||||||
|
;
|
||||||
|
|
||||||
|
select_stmt returns [std::unique_ptr<sqlast::SelectStatement> result]
|
||||||
|
: Select select_list
|
||||||
|
{
|
||||||
|
$result = std::make_unique<sqlast::SelectStatement>();
|
||||||
|
$result->SetSelectList(std::move($select_list.result));
|
||||||
|
}
|
||||||
|
(From from_item (Comma from_item)* )?
|
||||||
|
(Where condition)?
|
||||||
|
(Group By group_by)?
|
||||||
|
(Order By order_by)?
|
||||||
|
(Having having)?
|
||||||
|
;
|
||||||
|
|
||||||
|
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
|
||||||
|
: As? Ident (OpenParen Ident (Comma Ident)* CloseParen)?
|
||||||
|
;
|
||||||
|
|
||||||
|
condition
|
||||||
|
: expr
|
||||||
|
;
|
||||||
|
|
||||||
|
group_by
|
||||||
|
:
|
||||||
|
;
|
||||||
|
|
||||||
|
order_by
|
||||||
|
:
|
||||||
|
;
|
||||||
|
|
||||||
|
having
|
||||||
|
:
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
select_list returns [std::unique_ptr<sqlast::SelectList> result]
|
||||||
|
: select_item
|
||||||
|
{
|
||||||
|
$result = std::make_unique<sqlast::SelectList>();
|
||||||
|
$result->Add(std::move($select_item.result));
|
||||||
|
}
|
||||||
|
(Comma select_item)* { $result->Add(std::move($select_item.result)); }
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
select_item returns [std::unique_ptr<sqlast::SelectItem> result]
|
||||||
|
: expr { $result = std::make_unique<sqlast::SelectItem>(std::move($expr.result)); }
|
||||||
|
(As? Ident { $result->SetAlias($Ident.text); })?
|
||||||
|
;
|
||||||
|
|
||||||
|
expr returns [std::unique_ptr<sqlast::Expression> result]
|
||||||
|
: expr Dot Ident
|
||||||
|
| Ident
|
||||||
|
| value { $result = std::move($value.result); }
|
||||||
|
;
|
||||||
|
|
||||||
|
value returns [std::unique_ptr<sqlast::Literal> result]
|
||||||
|
: IntegerLiteral
|
||||||
|
| StringLiteral { $result = std::make_unique<sqlast::StringLiteral>($StringLiteral.text); }
|
||||||
|
;
|
||||||
|
|
||||||
1
pglablib/build-cpp.bat
Normal file
1
pglablib/build-cpp.bat
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
java -Xmx500M -cp "c:\prog\antlr\antlr-4.9.2-complete.jar;%CLASSPATH%" org.antlr.v4.Tool -Dlanguage=Cpp PgsqlLexer.g4 PgsqlParser.g4 -o sqlparser/.generated -no-listener %2 %3 %4 %5 %6 %7
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
#
|
#
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
|
|
||||||
QT += widgets core
|
QT += widgets core concurrent
|
||||||
|
|
||||||
TARGET = pglablib
|
TARGET = pglablib
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += staticlib
|
CONFIG += staticlib no_keywords
|
||||||
|
|
||||||
! include( ../common.pri ) {
|
! include( ../common.pri ) {
|
||||||
error( "Couldn't find the common.pri file!" )
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
|
@ -45,6 +45,25 @@ SOURCES += \
|
||||||
catalog/PgConstraintContainer.cpp \
|
catalog/PgConstraintContainer.cpp \
|
||||||
ParamListJson.cpp \
|
ParamListJson.cpp \
|
||||||
ParamListModel.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 \
|
||||||
|
sqlast/Statement.cpp \
|
||||||
|
sqlast/StatementList.cpp \
|
||||||
|
sqlast/StringLiteral.cpp \
|
||||||
|
sqlast/TypeSpecification.cpp \
|
||||||
|
sqlast/Visitor.cpp \
|
||||||
|
sqlparser/.generated/PgsqlLexer.cpp \
|
||||||
|
sqlparser/.generated/PgsqlParser.cpp \
|
||||||
|
sqlparser/ErrorListener.cpp \
|
||||||
|
sqlparser/Parser.cpp \
|
||||||
util.cpp \
|
util.cpp \
|
||||||
SqlFormattingUtils.cpp \
|
SqlFormattingUtils.cpp \
|
||||||
catalog/PgKeywordList.cpp \
|
catalog/PgKeywordList.cpp \
|
||||||
|
|
@ -113,6 +132,26 @@ HEADERS += \
|
||||||
catalog/PgConstraintContainer.h \
|
catalog/PgConstraintContainer.h \
|
||||||
ParamListJson.h \
|
ParamListJson.h \
|
||||||
ParamListModel.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 \
|
||||||
|
sqlast/Statement.h \
|
||||||
|
sqlast/StatementList.h \
|
||||||
|
sqlast/StringLiteral.h \
|
||||||
|
sqlast/TypeSpecification.h \
|
||||||
|
sqlast/Visitor.h \
|
||||||
|
sqlast/sqlast.h \
|
||||||
|
sqlparser/.generated/PgsqlLexer.h \
|
||||||
|
sqlparser/.generated/PgsqlParser.h \
|
||||||
|
sqlparser/ErrorListener.h \
|
||||||
|
sqlparser/Parser.h \
|
||||||
util.h \
|
util.h \
|
||||||
SqlFormattingUtils.h \
|
SqlFormattingUtils.h \
|
||||||
catalog/PgCatalogTypes.h \
|
catalog/PgCatalogTypes.h \
|
||||||
|
|
@ -170,6 +209,10 @@ else:unix:!macx: LIBS += -L$$OUT_PWD/../core/ -lcore
|
||||||
INCLUDEPATH += $$PWD/../core
|
INCLUDEPATH += $$PWD/../core
|
||||||
DEPENDPATH += $$PWD/../core
|
DEPENDPATH += $$PWD/../core
|
||||||
|
|
||||||
|
INCLUDEPATH += C:\Prog\include\antlr
|
||||||
|
win32:CONFIG(debug, debug|release): LIBS += -lantlr4-runtimed
|
||||||
|
else:win32:CONFIG(release, debug|release): LIBS += -lantlr4-runtime
|
||||||
|
|
||||||
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a
|
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a
|
||||||
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a
|
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a
|
||||||
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib
|
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib
|
||||||
|
|
|
||||||
69
pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp
Normal file
69
pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.cpp
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "BuildStandardItemTreeModelNodeVisitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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<class T>
|
||||||
|
AutoRevert<T> MakeAutoRevert(T& var, const T newValue)
|
||||||
|
{
|
||||||
|
return AutoRevert<T>(var, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStandardItemTreeModelNodeVisitor::BuildStandardItemTreeModelNodeVisitor()
|
||||||
|
: model(std::make_unique<QStandardItemModel>())
|
||||||
|
, 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
28
pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h
Normal file
28
pglablib/sqlast/BuildStandardItemTreeModelNodeVisitor.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NodeVisitor.h"
|
||||||
|
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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<QStandardItemModel> model;
|
||||||
|
QStandardItem *currentParent;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
9
pglablib/sqlast/ColumnDefinition.cpp
Normal file
9
pglablib/sqlast/ColumnDefinition.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "ColumnDefinition.h"
|
||||||
|
#include "TypeSpecification.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
ColumnDefinition::ColumnDefinition()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
28
pglablib/sqlast/ColumnDefinition.h
Normal file
28
pglablib/sqlast/ColumnDefinition.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class TypeSpecification;
|
||||||
|
|
||||||
|
/// Defines the details of a table column
|
||||||
|
///
|
||||||
|
/// Constraints are not included here, as we handle constraints can apply to multiple columns
|
||||||
|
/// and we want to put them all in one place. The UI and SQL generator is allowed to display
|
||||||
|
/// column specific constraints with the column they belong to.
|
||||||
|
class ColumnDefinition : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ColumnDefinition();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
std::unique_ptr<TypeSpecification> typeName;
|
||||||
|
bool notNull = true;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
8
pglablib/sqlast/CreateTable.cpp
Normal file
8
pglablib/sqlast/CreateTable.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "CreateTable.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
CreateTable::CreateTable()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
21
pglablib/sqlast/CreateTable.h
Normal file
21
pglablib/sqlast/CreateTable.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Statement.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class ColumnDefinition;
|
||||||
|
class TableConstraint;
|
||||||
|
|
||||||
|
class CreateTable: public Statement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateTable();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
8
pglablib/sqlast/Expression.cpp
Normal file
8
pglablib/sqlast/Expression.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Expression.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
Expression::Expression()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
pglablib/sqlast/Expression.h
Normal file
13
pglablib/sqlast/Expression.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Expression: public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Expression();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
8
pglablib/sqlast/Literal.cpp
Normal file
8
pglablib/sqlast/Literal.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Literal.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
Literal::Literal()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
pglablib/sqlast/Literal.h
Normal file
13
pglablib/sqlast/Literal.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Expression.h"
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Literal: public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Literal();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
12
pglablib/sqlast/Node.cpp
Normal file
12
pglablib/sqlast/Node.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
Node::Node()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Node::ToString() const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(typeid(*this).name());
|
||||||
|
}
|
||||||
37
pglablib/sqlast/Node.h
Normal file
37
pglablib/sqlast/Node.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
- Node
|
||||||
|
- INSERT
|
||||||
|
- UPDATE
|
||||||
|
- DELETE
|
||||||
|
- SELECT
|
||||||
|
- WITH
|
||||||
|
- CTE
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
8
pglablib/sqlast/NodeVisitor.cpp
Normal file
8
pglablib/sqlast/NodeVisitor.cpp
Normal file
|
|
@ -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));
|
||||||
|
}
|
||||||
27
pglablib/sqlast/NodeVisitor.h
Normal file
27
pglablib/sqlast/NodeVisitor.h
Normal file
|
|
@ -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);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
19
pglablib/sqlast/SelectItem.cpp
Normal file
19
pglablib/sqlast/SelectItem.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "SelectItem.h"
|
||||||
|
#include "Expression.h"
|
||||||
|
#include "NodeVisitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
SelectItem::SelectItem(std::unique_ptr<sqlast::Expression> expr)
|
||||||
|
: expression(std::move(expr))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SelectItem::SetAlias(const std::string &alias)
|
||||||
|
{
|
||||||
|
this->alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectItem::Accept(NodeVisitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.Visit(*this);
|
||||||
|
}
|
||||||
27
pglablib/sqlast/SelectItem.h
Normal file
27
pglablib/sqlast/SelectItem.h
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Expression;
|
||||||
|
|
||||||
|
class SelectItem : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SelectItem(std::unique_ptr<sqlast::Expression> expr);
|
||||||
|
|
||||||
|
Expression& GetExpression() { return *expression; }
|
||||||
|
|
||||||
|
void SetAlias(const std::string &alias);
|
||||||
|
std::string GetAlias() const { return alias; }
|
||||||
|
|
||||||
|
void Accept(NodeVisitor &visitor) override;
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Expression> expression;
|
||||||
|
std::string alias;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
29
pglablib/sqlast/SelectList.cpp
Normal file
29
pglablib/sqlast/SelectList.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "SelectList.h"
|
||||||
|
#include "SelectItem.h"
|
||||||
|
#include "sqlast/NodeVisitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
SelectList::SelectList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectList::Add(std::unique_ptr<SelectItem> select_item)
|
||||||
|
{
|
||||||
|
selectItems.push_back(std::move(select_item));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SelectList::Count() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(selectItems.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectItem &SelectList::Get(int index)
|
||||||
|
{
|
||||||
|
return *selectItems.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectList::Accept(NodeVisitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.Visit(*this);
|
||||||
|
}
|
||||||
30
pglablib/sqlast/SelectList.h
Normal file
30
pglablib/sqlast/SelectList.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SelectItem;
|
||||||
|
|
||||||
|
class SelectList : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SelectList();
|
||||||
|
|
||||||
|
void Add(std::unique_ptr<SelectItem> select_item);
|
||||||
|
int Count() const;
|
||||||
|
|
||||||
|
SelectItem& Get(int index);
|
||||||
|
|
||||||
|
void Accept(NodeVisitor &visitor) override;
|
||||||
|
private:
|
||||||
|
using List = std::vector<std::unique_ptr<SelectItem>>;
|
||||||
|
|
||||||
|
List selectItems;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
25
pglablib/sqlast/SelectStatement.cpp
Normal file
25
pglablib/sqlast/SelectStatement.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "SelectStatement.h"
|
||||||
|
#include "SelectList.h"
|
||||||
|
#include "NodeVisitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
SelectStatement::SelectStatement()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectList* SelectStatement::GetSelectList()
|
||||||
|
{
|
||||||
|
return selectList.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectStatement::SetSelectList(std::unique_ptr<SelectList> value)
|
||||||
|
{
|
||||||
|
selectList = std::move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectStatement::Accept(NodeVisitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.Visit(*this);
|
||||||
|
}
|
||||||
23
pglablib/sqlast/SelectStatement.h
Normal file
23
pglablib/sqlast/SelectStatement.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Statement.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class SelectList;
|
||||||
|
|
||||||
|
class SelectStatement: public Statement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SelectStatement();
|
||||||
|
|
||||||
|
SelectList* GetSelectList();
|
||||||
|
void SetSelectList(std::unique_ptr<SelectList> value);
|
||||||
|
|
||||||
|
void Accept(NodeVisitor &visitor) override;
|
||||||
|
private:
|
||||||
|
std::unique_ptr<SelectList> selectList;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
10
pglablib/sqlast/Statement.cpp
Normal file
10
pglablib/sqlast/Statement.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "Statement.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
Statement::Statement()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
13
pglablib/sqlast/Statement.h
Normal file
13
pglablib/sqlast/Statement.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Statement: public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Statement();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
29
pglablib/sqlast/StatementList.cpp
Normal file
29
pglablib/sqlast/StatementList.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "StatementList.h"
|
||||||
|
#include "Statement.h"
|
||||||
|
#include "sqlast/NodeVisitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
StatementList::StatementList()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void StatementList::Add(std::unique_ptr<Statement> &&statement)
|
||||||
|
{
|
||||||
|
statements.push_back(std::move(statement));
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement &StatementList::Get(int index)
|
||||||
|
{
|
||||||
|
return *statements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int StatementList::Count() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(statements.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatementList::Accept(NodeVisitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.Visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
28
pglablib/sqlast/StatementList.h
Normal file
28
pglablib/sqlast/StatementList.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Statement;
|
||||||
|
|
||||||
|
class StatementList: public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StatementList();
|
||||||
|
|
||||||
|
void Add(std::unique_ptr<Statement> &&statement);
|
||||||
|
Statement &Get(int index);
|
||||||
|
int Count() const;
|
||||||
|
|
||||||
|
void Accept(NodeVisitor &visitor) override;
|
||||||
|
private:
|
||||||
|
using Statements = std::vector<std::unique_ptr<Statement>>;
|
||||||
|
|
||||||
|
Statements statements;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
13
pglablib/sqlast/StringLiteral.cpp
Normal file
13
pglablib/sqlast/StringLiteral.cpp
Normal file
|
|
@ -0,0 +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);
|
||||||
|
}
|
||||||
20
pglablib/sqlast/StringLiteral.h
Normal file
20
pglablib/sqlast/StringLiteral.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Literal.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class StringLiteral : public Literal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit StringLiteral(const std::string s);
|
||||||
|
|
||||||
|
QString GetValue() const { return value; }
|
||||||
|
void Accept(NodeVisitor &visitor) override;
|
||||||
|
private:
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
8
pglablib/sqlast/TypeSpecification.cpp
Normal file
8
pglablib/sqlast/TypeSpecification.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "TypeSpecification.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
TypeSpecification::TypeSpecification()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
23
pglablib/sqlast/TypeSpecification.h
Normal file
23
pglablib/sqlast/TypeSpecification.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
/// These object define not only the base type, but also
|
||||||
|
/// parameters used with the type
|
||||||
|
/// Think the precision of numeric, max length of char, array
|
||||||
|
class TypeSpecification : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TypeSpecification();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// We do not use the PgType from the catalog here as the type used might be defined
|
||||||
|
/// inside the script and not present yet in the catalog.
|
||||||
|
QString baseType;
|
||||||
|
// is_array
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
8
pglablib/sqlast/Visitor.cpp
Normal file
8
pglablib/sqlast/Visitor.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Visitor.h"
|
||||||
|
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
Visitor::Visitor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
pglablib/sqlast/Visitor.h
Normal file
13
pglablib/sqlast/Visitor.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sqlast {
|
||||||
|
|
||||||
|
class Visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Visitor();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
12
pglablib/sqlast/sqlast.h
Normal file
12
pglablib/sqlast/sqlast.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include "SelectStatement.h"
|
||||||
|
#include "SelectItem.h"
|
||||||
|
#include "SelectList.h"
|
||||||
|
#include "Statement.h"
|
||||||
|
#include "StatementList.h"
|
||||||
|
#include "StringLiteral.h"
|
||||||
|
#undef emit
|
||||||
|
|
||||||
|
|
||||||
22
pglablib/sqlparser/ErrorListener.cpp
Normal file
22
pglablib/sqlparser/ErrorListener.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "ErrorListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
void ErrorListener::syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr e)
|
||||||
|
{
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorListener::reportAmbiguity(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact, const antlrcpp::BitSet &ambigAlts, antlr4::atn::ATNConfigSet *configs)
|
||||||
|
{
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorListener::reportAttemptingFullContext(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, const antlrcpp::BitSet &conflictingAlts, antlr4::atn::ATNConfigSet *configs)
|
||||||
|
{
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorListener::reportContextSensitivity(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, size_t prediction, antlr4::atn::ATNConfigSet *configs)
|
||||||
|
{
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
21
pglablib/sqlparser/ErrorListener.h
Normal file
21
pglablib/sqlparser/ErrorListener.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
#include "antlr4-runtime.h"
|
||||||
|
|
||||||
|
class ErrorListener : public antlr4::ANTLRErrorListener
|
||||||
|
{
|
||||||
|
// ANTLRErrorListener interface
|
||||||
|
public:
|
||||||
|
virtual void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override;
|
||||||
|
virtual void reportAmbiguity(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact, const antlrcpp::BitSet &ambigAlts, antlr4::atn::ATNConfigSet *configs) override;
|
||||||
|
virtual void reportAttemptingFullContext(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, const antlrcpp::BitSet &conflictingAlts, antlr4::atn::ATNConfigSet *configs) override;
|
||||||
|
virtual void reportContextSensitivity(antlr4::Parser *recognizer, const antlr4::dfa::DFA &dfa, size_t startIndex, size_t stopIndex, size_t prediction, antlr4::atn::ATNConfigSet *configs) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int errorCount() const
|
||||||
|
{
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int errors = 0;
|
||||||
|
};
|
||||||
24
pglablib/sqlparser/Parser.cpp
Normal file
24
pglablib/sqlparser/Parser.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "Parser.h"
|
||||||
|
#include "antlr4-runtime.h"
|
||||||
|
|
||||||
|
|
||||||
|
Parser::Parser(const std::string &input_string)
|
||||||
|
: Parser(std::make_unique<antlr4::ANTLRInputStream>(input_string))
|
||||||
|
{}
|
||||||
|
|
||||||
|
Parser::Parser(std::unique_ptr<antlr4::CharStream> stream)
|
||||||
|
: InputStream(std::move(stream))
|
||||||
|
, Lexer(InputStream.get())
|
||||||
|
, TokenStream(&Lexer)
|
||||||
|
, AParser(&TokenStream)
|
||||||
|
{
|
||||||
|
AParser.removeErrorListeners();
|
||||||
|
AParser.addErrorListener(&Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<sqlast::StatementList> Parser::Parse()
|
||||||
|
{
|
||||||
|
auto context = AParser.main();
|
||||||
|
return std::move(context->program);
|
||||||
|
}
|
||||||
|
|
||||||
26
pglablib/sqlparser/Parser.h
Normal file
26
pglablib/sqlparser/Parser.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include ".generated/PgsqlLexer.h"
|
||||||
|
#include ".generated/PgsqlParser.h"
|
||||||
|
#include "ErrorListener.h"
|
||||||
|
|
||||||
|
class Parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Parser(const std::string &input_string);
|
||||||
|
Parser(std::unique_ptr<antlr4::CharStream> stream);
|
||||||
|
|
||||||
|
std::unique_ptr<sqlast::StatementList> Parse();
|
||||||
|
|
||||||
|
int errorCount() const
|
||||||
|
{
|
||||||
|
return Errors.errorCount();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::unique_ptr<antlr4::CharStream> InputStream;
|
||||||
|
PgsqlLexer Lexer;
|
||||||
|
antlr4::CommonTokenStream TokenStream;
|
||||||
|
PgsqlParser AParser;
|
||||||
|
ErrorListener Errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ QString msfloatToHumanReadableString(float ms)
|
||||||
if (ms < 1.0f) {
|
if (ms < 1.0f) {
|
||||||
val = ms * 1000.f;
|
val = ms * 1000.f;
|
||||||
//result = QString::asprintf("%0.3f", ms * 1000.0f);
|
//result = QString::asprintf("%0.3f", ms * 1000.0f);
|
||||||
unit = u8"μs";
|
unit = QString::fromUtf8("μs");
|
||||||
}
|
}
|
||||||
else if (ms >= 1000.0) {
|
else if (ms >= 1000.0) {
|
||||||
val = ms / 1000.0f;
|
val = ms / 1000.0f;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ include(gtest_dependency.pri)
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += console
|
CONFIG += console
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
CONFIG += thread
|
CONFIG += thread no_keywords
|
||||||
CONFIG += qt
|
CONFIG += qt
|
||||||
|
|
||||||
QT += core widgets
|
QT += core widgets
|
||||||
|
|
@ -20,6 +20,7 @@ SOURCES += main.cpp \
|
||||||
tst_escapeConnectionStringValue.cpp \
|
tst_escapeConnectionStringValue.cpp \
|
||||||
tst_expected.cpp \
|
tst_expected.cpp \
|
||||||
tst_SqlLexer.cpp \
|
tst_SqlLexer.cpp \
|
||||||
|
tst_newParser.cpp \
|
||||||
tst_scopeguard.cpp \
|
tst_scopeguard.cpp \
|
||||||
tst_CsvWriter.cpp \
|
tst_CsvWriter.cpp \
|
||||||
tst_PasswordManager.cpp \
|
tst_PasswordManager.cpp \
|
||||||
|
|
@ -39,6 +40,10 @@ DEPENDPATH += $$PWD/../../core
|
||||||
win32:CONFIG(debug, debug|release): LIBS += -lbotand
|
win32:CONFIG(debug, debug|release): LIBS += -lbotand
|
||||||
else:win32:CONFIG(release, debug|release): LIBS += -lbotan
|
else:win32:CONFIG(release, debug|release): LIBS += -lbotan
|
||||||
|
|
||||||
|
INCLUDEPATH += C:\Prog\include\antlr
|
||||||
|
win32:CONFIG(debug, debug|release): LIBS += -lantlr4-runtimed
|
||||||
|
else:win32:CONFIG(release, debug|release): LIBS += -lantlr4-runtime
|
||||||
|
|
||||||
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/libcore.a
|
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/libcore.a
|
||||||
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/debug/libcore.a
|
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/debug/libcore.a
|
||||||
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/core.lib
|
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../core/release/core.lib
|
||||||
|
|
|
||||||
135
tests/pglabtests/tst_newParser.cpp
Normal file
135
tests/pglabtests/tst_newParser.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
#include "sqlparser/Parser.h"
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
using namespace sqlast;
|
||||||
|
|
||||||
|
TEST(NewSqlLexer, Select)
|
||||||
|
{
|
||||||
|
std::string source = "SELECT";
|
||||||
|
antlr4::ANTLRInputStream input(source);
|
||||||
|
PgsqlLexer lexer(&input);
|
||||||
|
|
||||||
|
auto token = lexer.nextToken();
|
||||||
|
ASSERT_EQ(PgsqlLexer::Select, token->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlLexer, Ident)
|
||||||
|
{
|
||||||
|
std::string source = "Abc";
|
||||||
|
antlr4::ANTLRInputStream input(source);
|
||||||
|
PgsqlLexer lexer(&input);
|
||||||
|
|
||||||
|
auto token = lexer.nextToken();
|
||||||
|
ASSERT_EQ(PgsqlLexer::Ident, token->getType());
|
||||||
|
ASSERT_EQ("abc", token->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlLexer, QuotedIdent)
|
||||||
|
{
|
||||||
|
std::string source = "\"Abc\"";
|
||||||
|
antlr4::ANTLRInputStream input(source);
|
||||||
|
PgsqlLexer lexer(&input);
|
||||||
|
|
||||||
|
auto token = lexer.nextToken();
|
||||||
|
ASSERT_EQ(PgsqlLexer::Ident, token->getType());
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
std::string input_string = "SEleCT 1; Select 2;";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_TRUE(program != nullptr);
|
||||||
|
ASSERT_EQ(2, program->Count());
|
||||||
|
ASSERT_EQ(0, parser.errorCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlParser, missingSemi)
|
||||||
|
{
|
||||||
|
std::string input_string = "1";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_EQ(1, parser.errorCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlParser, selectList)
|
||||||
|
{
|
||||||
|
std::string input_string = "SEleCT 1, 'Tekst'";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_TRUE(program != nullptr);
|
||||||
|
ASSERT_EQ(1, program->Count());
|
||||||
|
ASSERT_EQ(0, parser.errorCount());
|
||||||
|
|
||||||
|
SelectStatement &s = dynamic_cast<SelectStatement&>(program->Get(0));
|
||||||
|
SelectList* sl = s.GetSelectList();
|
||||||
|
ASSERT_TRUE(sl != nullptr);
|
||||||
|
ASSERT_EQ(2, sl->Count());
|
||||||
|
|
||||||
|
SelectItem& si = sl->Get(1);
|
||||||
|
StringLiteral& string_literal = dynamic_cast<StringLiteral&>(si.GetExpression());
|
||||||
|
ASSERT_EQ("Tekst", string_literal.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlParser, selectAliasWithoutAs)
|
||||||
|
{
|
||||||
|
std::string input_string = "SELECT 1 a";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_TRUE(program != nullptr);
|
||||||
|
ASSERT_EQ(1, program->Count());
|
||||||
|
ASSERT_EQ(0, parser.errorCount());
|
||||||
|
|
||||||
|
SelectStatement &s = dynamic_cast<SelectStatement&>(program->Get(0));
|
||||||
|
SelectList* sl = s.GetSelectList();
|
||||||
|
SelectItem& si = sl->Get(0);
|
||||||
|
ASSERT_EQ("a", si.GetAlias());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(NewSqlParser, selectAliasWithAs)
|
||||||
|
{
|
||||||
|
std::string input_string = "SELECT 1 AS b";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_TRUE(program != nullptr);
|
||||||
|
ASSERT_EQ(1, program->Count());
|
||||||
|
ASSERT_EQ(0, parser.errorCount());
|
||||||
|
|
||||||
|
SelectStatement &s = dynamic_cast<SelectStatement&>(program->Get(0));
|
||||||
|
SelectList* sl = s.GetSelectList();
|
||||||
|
SelectItem& si = sl->Get(0);
|
||||||
|
ASSERT_EQ("b", si.GetAlias());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewSqlParser, selectFrom)
|
||||||
|
{
|
||||||
|
std::string input_string = "SELECT 1 FROM a";
|
||||||
|
Parser parser(input_string);
|
||||||
|
std::unique_ptr<sqlast::StatementList> program = parser.Parse();
|
||||||
|
|
||||||
|
ASSERT_TRUE(program != nullptr);
|
||||||
|
ASSERT_EQ(1, program->Count());
|
||||||
|
ASSERT_EQ(0, parser.errorCount());
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue