Initial commit. Contains a simple query tool.
This commit is contained in:
commit
edc6df25da
19 changed files with 1245 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
debug/
|
||||
release/
|
||||
Makefile
|
||||
Makefile.Debug
|
||||
Makefile.Release
|
||||
34
Ivory.pro
Normal file
34
Ivory.pro
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2016-11-11T09:17:13
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = Ivory
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += C:\prog\include
|
||||
|
||||
LIBS += c:\prog\lib\libpq.lib
|
||||
|
||||
SOURCES += main.cpp\
|
||||
mainwindow.cpp \
|
||||
serverproperties.cpp \
|
||||
sqlparser.cpp \
|
||||
PgsqlConn.cpp \
|
||||
queryresultmodel.cpp \
|
||||
sqlhighlighter.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
serverproperties.h \
|
||||
sqlparser.h \
|
||||
PgsqlConn.h \
|
||||
queryresultmodel.h \
|
||||
sqlhighlighter.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
serverproperties.ui
|
||||
139
PgsqlConn.cpp
Normal file
139
PgsqlConn.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include "PgsqlConn.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
|
||||
Result::Result(PGresult *res)
|
||||
: result(res)
|
||||
{
|
||||
if (res == nullptr) {
|
||||
throw std::runtime_error("Passing nullptr to Result::Result is not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
Result::~Result()
|
||||
{
|
||||
PQclear(result);
|
||||
}
|
||||
|
||||
|
||||
Result::Result(Result &&rhs)
|
||||
: result(rhs.result)
|
||||
{
|
||||
rhs.result = nullptr;
|
||||
}
|
||||
|
||||
Result& Result::operator=(Result &&rhs)
|
||||
{
|
||||
if (result) {
|
||||
PQclear(result);
|
||||
}
|
||||
result = rhs.result;
|
||||
rhs.result = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Result::operator bool() const
|
||||
{
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
ExecStatusType Result::getResultStatus()
|
||||
{
|
||||
return PQresultStatus(result);
|
||||
}
|
||||
|
||||
std::string Result::getResStatus()
|
||||
{
|
||||
// return PQresStatus(result);
|
||||
return "";
|
||||
}
|
||||
|
||||
int Result::getRows() const
|
||||
{
|
||||
return PQntuples(result);
|
||||
}
|
||||
|
||||
int Result::getCols() const
|
||||
{
|
||||
return PQnfields(result);
|
||||
}
|
||||
|
||||
const char* const Result::getColName(int idx) const
|
||||
{
|
||||
return PQfname(result, idx);
|
||||
}
|
||||
|
||||
const char * Result::getVal(int col, int row) const
|
||||
{
|
||||
return PQgetvalue(result, row, col);
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection() = default;
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
Connection::Connection(Connection &&rhs)
|
||||
: conn(rhs.conn)
|
||||
{
|
||||
rhs.conn = nullptr;
|
||||
}
|
||||
|
||||
Connection& Connection::operator=(Connection &&rhs)
|
||||
{
|
||||
close();
|
||||
conn = rhs.conn;
|
||||
rhs.conn = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Connection::close()
|
||||
{
|
||||
if (conn) {
|
||||
PQfinish(conn);
|
||||
conn = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Connection::connect(const char *params)
|
||||
{
|
||||
bool result = false;
|
||||
conn = PQconnectdb(params);
|
||||
if (conn) {
|
||||
ConnStatusType status = PQstatus(conn);
|
||||
result = (status == CONNECTION_OK);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string Connection::getErrorMessage() const
|
||||
{
|
||||
std::string result;
|
||||
if (conn) {
|
||||
result = PQerrorMessage(conn);
|
||||
}
|
||||
else {
|
||||
result = "no connection";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Result Connection::Query(const char * query)
|
||||
{
|
||||
PGresult *result = PQexec(conn, query);
|
||||
if (result) {
|
||||
return Result(result);
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Failed to allocate result object");
|
||||
}
|
||||
}
|
||||
196
PgsqlConn.h
Normal file
196
PgsqlConn.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <pgsql/libpq-fe.h>
|
||||
#include <cassert>
|
||||
#include <QString>
|
||||
|
||||
namespace Pgsql {
|
||||
|
||||
/*
|
||||
This library has multiple layers.
|
||||
|
||||
Layer 1 delivers lowlevel C++ wrappers for the basic libpq functionality. Adding
|
||||
automatic resource management.
|
||||
|
||||
*/
|
||||
|
||||
class ConnectionParams {
|
||||
public:
|
||||
std::string host;
|
||||
std::string hostaddr;
|
||||
unsigned short port = 5432;
|
||||
std::string dbname;
|
||||
std::string user;
|
||||
std::string password;
|
||||
int connect_timeout = -1; ///< -1 omit (ie uses default)
|
||||
std::string application_name;
|
||||
|
||||
};
|
||||
|
||||
/** Non-copyable but movable wrapper for a postgresql result. */
|
||||
class Result {
|
||||
public:
|
||||
// class iterator {
|
||||
// public:
|
||||
// iterator(Result &r, int rw)
|
||||
// : result(r), row(rw)
|
||||
// {}
|
||||
|
||||
// iterator operator++()
|
||||
// {
|
||||
// iterator t(*this);
|
||||
// ++row;
|
||||
// return t;
|
||||
// }
|
||||
|
||||
// iterator& operator++(int)
|
||||
// {
|
||||
// ++row;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// bool operator!=(const iterator &rhs)
|
||||
// {
|
||||
// assert()
|
||||
// }
|
||||
|
||||
// private:
|
||||
// Result &result;
|
||||
// int row;
|
||||
// };
|
||||
|
||||
Result(PGresult *result);
|
||||
~Result();
|
||||
|
||||
Result(const Result &rhs) = delete;
|
||||
Result& operator=(const Result &rhs) = delete;
|
||||
|
||||
Result(Result &&rhs);
|
||||
Result& operator=(Result &&rhs);
|
||||
|
||||
operator bool() const;
|
||||
|
||||
ExecStatusType getResultStatus();
|
||||
std::string getResStatus();
|
||||
|
||||
|
||||
int getRows() const;
|
||||
int getCols() const;
|
||||
|
||||
const char* const getColName(int idx) const;
|
||||
|
||||
const char * getVal(int col, int row) const;
|
||||
|
||||
// iterator begin();
|
||||
private:
|
||||
PGresult *result = nullptr;
|
||||
};
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection();
|
||||
~Connection();
|
||||
|
||||
Connection(const Connection &rhs) = delete;
|
||||
Connection& operator=(const Connection &rhs) = delete;
|
||||
|
||||
Connection(Connection &&rhs);
|
||||
Connection& operator=(Connection &&rhs);
|
||||
|
||||
// void connect(const ConnectionParams ¶ms);
|
||||
bool connect(const char *params);
|
||||
bool connect(const QString ¶ms)
|
||||
{
|
||||
return connect(params.toUtf8().data());
|
||||
}
|
||||
|
||||
void close();
|
||||
|
||||
std::string getErrorMessage() const;
|
||||
|
||||
Result Query(const char * query);
|
||||
Result Query(const QString &query)
|
||||
{
|
||||
return Query(query.toUtf8().data());
|
||||
}
|
||||
|
||||
private:
|
||||
PGconn *conn = nullptr;
|
||||
};
|
||||
|
||||
class Canceller {
|
||||
public:
|
||||
void Cancel();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Field {
|
||||
public:
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
private:
|
||||
//Tuples tuples;
|
||||
int field;
|
||||
//
|
||||
|
||||
};
|
||||
|
||||
class Tuples {
|
||||
public:
|
||||
int getRowCount() const;
|
||||
int getColCount() const;
|
||||
|
||||
Field getField(const std::string &fname);
|
||||
Field getField(const int idx);
|
||||
|
||||
class const_iterator {
|
||||
public:
|
||||
const_iterator& operator++();
|
||||
};
|
||||
|
||||
void rewind();
|
||||
|
||||
|
||||
};
|
||||
|
||||
class OkResult: public Result {
|
||||
public:
|
||||
/** If the result is a data result then returns an interface for processing this data.
|
||||
|
||||
The returned interface remains valid as long as this OkResult exists.
|
||||
*/
|
||||
Tuples* hasTuples();
|
||||
};
|
||||
|
||||
// class ErrorResult: public Result {
|
||||
//
|
||||
// };
|
||||
|
||||
// class ITransaction {
|
||||
// public:
|
||||
//
|
||||
// Canceller Query(std::string query,
|
||||
// std::function<void(OkResult)> on_success,
|
||||
// std::function<void()> on_cancelled,
|
||||
// std::function<void(ErrorResult)> on_error);
|
||||
//
|
||||
// Canceller Query(std::string query,
|
||||
// std::function<void(OkResult)> on_success,
|
||||
// std::function<void()> on_cancelled,
|
||||
// std::function<void(ErrorResult)> on_error);
|
||||
//
|
||||
//
|
||||
// void Rollback(
|
||||
// std::function<void(OkResult)> on_success,
|
||||
// std::function<void(ErrorResult)> on_error);
|
||||
// void Commit(
|
||||
// std::function<void(OkResult)> on_success,
|
||||
// std::function<void()> on_cancelled,
|
||||
// std::function<void(ErrorResult)> on_error);
|
||||
//
|
||||
// };
|
||||
}
|
||||
11
main.cpp
Normal file
11
main.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
51
mainwindow.cpp
Normal file
51
mainwindow.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "QueryResultModel.h"
|
||||
#include "sqlhighlighter.h"
|
||||
|
||||
namespace pg = Pgsql;
|
||||
|
||||
const char * test_query =
|
||||
"SELECT id, program, version, lic_bedrijf, lic_plaats, "
|
||||
"lic_number, callstack_crc_1, callstack_crc_2, callstack_crc_3, exception_class, "
|
||||
"exception_message \nFROM foutrapport";
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QFont font;
|
||||
font.setFamily("Source Code Pro");
|
||||
font.setFixedPitch(true);
|
||||
font.setPointSize(10);
|
||||
ui->queryEdit->setFont(font);
|
||||
highlighter.reset(new SqlHighlighter(ui->queryEdit->document()));
|
||||
ui->queryEdit->setPlainText(test_query);
|
||||
|
||||
ui->connectionStringEdit->setText("user=postgres dbname=foutrapport password=admin");
|
||||
|
||||
//performQuery();
|
||||
|
||||
QAction *action = ui->mainToolBar->addAction("execute");
|
||||
connect(action, &QAction::triggered, this, &MainWindow::performQuery);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{}
|
||||
|
||||
void MainWindow::performQuery()
|
||||
{
|
||||
ui->ResultView->setModel(nullptr);
|
||||
resultModel.reset();
|
||||
|
||||
QString connstr = ui->connectionStringEdit->text();
|
||||
pg::Connection conn;
|
||||
if (conn.connect(connstr + " application_name=Ivory client_encoding=utf8")) {
|
||||
pg::Result dbres = conn.Query(ui->queryEdit->toPlainText());
|
||||
resultModel.reset(new QueryResultModel(this , std::move(dbres)));
|
||||
ui->ResultView->setModel(resultModel.get());
|
||||
}
|
||||
}
|
||||
32
mainwindow.h
Normal file
32
mainwindow.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <memory>
|
||||
|
||||
class QueryResultModel;
|
||||
class SqlHighlighter;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::MainWindow> ui;
|
||||
std::unique_ptr<SqlHighlighter> highlighter;
|
||||
|
||||
std::unique_ptr<QueryResultModel> resultModel;
|
||||
|
||||
private slots:
|
||||
void performQuery();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
74
mainwindow.ui
Normal file
74
mainwindow.ui
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>726</width>
|
||||
<height>589</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="connectionStringEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTextEdit" name="queryEdit"/>
|
||||
<widget class="QTableView" name="ResultView">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Source Sans Pro</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>726</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuTest">
|
||||
<property name="title">
|
||||
<string>test</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuTest"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="mainToolBar">
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
58
queryresultmodel.cpp
Normal file
58
queryresultmodel.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include "queryresultmodel.h"
|
||||
|
||||
QueryResultModel::QueryResultModel(QObject *parent, Pgsql::Result &&r)
|
||||
: QAbstractTableModel(parent)
|
||||
, result(std::move(r))
|
||||
{}
|
||||
|
||||
|
||||
int QueryResultModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
int r = result.getRows();
|
||||
return r;
|
||||
}
|
||||
|
||||
int QueryResultModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
int r = result.getCols();
|
||||
return r;
|
||||
}
|
||||
|
||||
QVariant QueryResultModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant r;
|
||||
int rij = index.row();
|
||||
int col = index.column();
|
||||
if (role == Qt::DisplayRole) {
|
||||
|
||||
r = QString(result.getVal(col, rij));
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole) {
|
||||
if (col == 0) {
|
||||
r = Qt::AlignRight + Qt::AlignVCenter;
|
||||
}
|
||||
else {
|
||||
r = Qt::AlignLeft + Qt::AlignVCenter;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
QVariant QueryResultModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant r;
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
r = QString(result.getColName(section));
|
||||
}
|
||||
else {
|
||||
r = QString::number(section + 1);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//Qt::ItemFlags QueryResultModel::flags(const QModelIndex &) const
|
||||
//{
|
||||
// return Qt::ItemIsUserCheckable;
|
||||
//}
|
||||
23
queryresultmodel.h
Normal file
23
queryresultmodel.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef QUERYRESULTMODEL_H
|
||||
#define QUERYRESULTMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "PgsqlConn.h"
|
||||
|
||||
class QueryResultModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QueryResultModel(QObject *parent, Pgsql::Result &&r);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
// virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
Pgsql::Result result;
|
||||
};
|
||||
|
||||
#endif // QUERYRESULTMODEL_H
|
||||
14
serverproperties.cpp
Normal file
14
serverproperties.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include "serverproperties.h"
|
||||
#include "ui_serverproperties.h"
|
||||
|
||||
ServerProperties::ServerProperties(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ServerProperties)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
ServerProperties::~ServerProperties()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
22
serverproperties.h
Normal file
22
serverproperties.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef SERVERPROPERTIES_H
|
||||
#define SERVERPROPERTIES_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class ServerProperties;
|
||||
}
|
||||
|
||||
class ServerProperties : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ServerProperties(QWidget *parent = 0);
|
||||
~ServerProperties();
|
||||
|
||||
private:
|
||||
Ui::ServerProperties *ui;
|
||||
};
|
||||
|
||||
#endif // SERVERPROPERTIES_H
|
||||
161
serverproperties.ui
Normal file
161
serverproperties.ui
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ServerProperties</class>
|
||||
<widget class="QDialog" name="ServerProperties">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>326</width>
|
||||
<height>233</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_2"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBox">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Maintenance DB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>postgres</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>template1</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_3"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_4">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ServerProperties</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ServerProperties</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
60
sqlhighlighter.cpp
Normal file
60
sqlhighlighter.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "SqlHighlighter.h"
|
||||
|
||||
static const wchar_t *keywords[] = {
|
||||
L"as", L"alter", L"all", L"and", L"any", L"by", L"column", L"create", L"database", L"from", L"full", L"group", L"having",
|
||||
L"in", L"inner", L"join", L"left", L"not", L"or", L"order", L"outer", L"right", L"select", L"table", L"where"
|
||||
};
|
||||
//static auto types = R"-(bigint|boolean|char|character varying|date|int[248]|integer|numeric|smallint|time|timestamp(?:tz)?|timestamp(?:\s+with\s+timezone)?|varchar)-";
|
||||
//static auto err = R"-(left|right|inner|outer)-";
|
||||
|
||||
static_assert(sizeof(keywords)/4 == 25,
|
||||
"sizeof keywords");
|
||||
|
||||
|
||||
SqlHighlighter::SqlHighlighter(QTextDocument *parent)
|
||||
: QSyntaxHighlighter(parent)
|
||||
{
|
||||
// {
|
||||
// static auto keywords = R"-(as|alter|all|and|any|by|column|create|database|from|group|having|in|not|or|order|select|table|where|(?:(?:inner|(?:left|right|full)(\s+outer)?)\s+)?join)-";
|
||||
// static auto types = R"-(bigint|boolean|char|character varying|date|int[248]|integer|numeric|smallint|time|timestamp(?:tz)?|timestamp(?:\s+with\s+timezone)?|varchar)-";
|
||||
// static auto err = R"-(left|right|inner|outer)-";
|
||||
|
||||
// QTextCharFormat errFormat;
|
||||
// errFormat.setForeground(QColor(255, 128, 128));
|
||||
// errFormat.setFontWeight(QFont::Bold);
|
||||
// highlightingRules.emplace_back(QRegExp(err, Qt::CaseInsensitive), errFormat);
|
||||
|
||||
// QTextCharFormat keywordFormat;
|
||||
// keywordFormat.setForeground(QColor(128, 128, 255));
|
||||
// keywordFormat.setFontWeight(QFont::Bold);
|
||||
// highlightingRules.emplace_back(QRegExp(keywords, Qt::CaseInsensitive), keywordFormat);
|
||||
|
||||
// QTextCharFormat typesFormat;
|
||||
// typesFormat.setForeground(QColor(128, 255, 128));
|
||||
// typesFormat.setFontWeight(QFont::Bold);
|
||||
// highlightingRules.emplace_back(QRegExp(types, Qt::CaseInsensitive), typesFormat);
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
void NextBasicToken(const QString &in, int ofs, int &start, int &length)
|
||||
{
|
||||
// Basically parses for white space and chops based on white space
|
||||
// it does also recognize comments and quoted strings/identifiers
|
||||
|
||||
}
|
||||
|
||||
void SqlHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
// foreach (const HighlightingRule &rule, highlightingRules) {
|
||||
// QRegExp expression(rule.pattern);
|
||||
// int index = expression.indexIn(text);
|
||||
// while (index >= 0) {
|
||||
// int length = expression.matchedLength();
|
||||
// setFormat(index, length, rule.format);
|
||||
// index = expression.indexIn(text, index + length);
|
||||
// }
|
||||
// }
|
||||
setCurrentBlockState(0);
|
||||
}
|
||||
|
||||
40
sqlhighlighter.h
Normal file
40
sqlhighlighter.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SqlHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SqlHighlighter(QTextDocument *parent = 0);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
// struct HighlightingRule
|
||||
// {
|
||||
// QRegExp pattern;
|
||||
// QTextCharFormat format;
|
||||
|
||||
// HighlightingRule(const QRegExp ®ex, const QTextCharFormat &f)
|
||||
// : pattern(regex), format(f)
|
||||
// {}
|
||||
// };
|
||||
//QVector<HighlightingRule> highlightingRules;
|
||||
// std::vector<HighlightingRule> highlightingRules;
|
||||
|
||||
// QRegExp commentStartExpression;
|
||||
// QRegExp commentEndExpression;
|
||||
|
||||
// QTextCharFormat keywordFormat;
|
||||
// QTextCharFormat classFormat;
|
||||
// QTextCharFormat singleLineCommentFormat;
|
||||
// QTextCharFormat multiLineCommentFormat;
|
||||
// QTextCharFormat quotationFormat;
|
||||
// QTextCharFormat functionFormat;
|
||||
};
|
||||
30
sqlparser.cpp
Normal file
30
sqlparser.cpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include "sqlparser.h"
|
||||
|
||||
/** Responsible for splitting the query into logical elements.
|
||||
*
|
||||
* It first uses common seperators to split the input, then it tries
|
||||
* to determine if the fields it gets have a special meaning.
|
||||
*
|
||||
* However because SQL is very forgiving about the use of keywords
|
||||
* as names.
|
||||
*
|
||||
* The lexical analyzer does however distinguish between
|
||||
* - symbols/keywords (symbols might be schema, table, columns, functions etc)
|
||||
* - numbers
|
||||
* - strings
|
||||
* - quoted symbol (a symbol between "" must be the name of something)
|
||||
*
|
||||
* seperators
|
||||
* whitespace
|
||||
* special chars ;,.
|
||||
* operators
|
||||
*/
|
||||
class LexicalAnalyser {
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
SqlParser::SqlParser()
|
||||
{
|
||||
|
||||
}
|
||||
11
sqlparser.h
Normal file
11
sqlparser.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef SQLPARSER_H
|
||||
#define SQLPARSER_H
|
||||
|
||||
|
||||
class SqlParser
|
||||
{
|
||||
public:
|
||||
SqlParser();
|
||||
};
|
||||
|
||||
#endif // SQLPARSER_H
|
||||
114
ui_mainwindow.h
Normal file
114
ui_mainwindow.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/********************************************************************************
|
||||
** Form generated from reading UI file 'mainwindow.ui'
|
||||
**
|
||||
** Created by: Qt User Interface Compiler version 5.7.1
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UI_MAINWINDOW_H
|
||||
#define UI_MAINWINDOW_H
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QAction>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QButtonGroup>
|
||||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QSplitter>
|
||||
#include <QtWidgets/QStatusBar>
|
||||
#include <QtWidgets/QTableView>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
#include <QtWidgets/QToolBar>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_MainWindow
|
||||
{
|
||||
public:
|
||||
QWidget *centralWidget;
|
||||
QVBoxLayout *verticalLayout;
|
||||
QLineEdit *connectionStringEdit;
|
||||
QSplitter *splitter;
|
||||
QTextEdit *queryEdit;
|
||||
QTableView *ResultView;
|
||||
QMenuBar *menuBar;
|
||||
QMenu *menuTest;
|
||||
QToolBar *mainToolBar;
|
||||
QStatusBar *statusBar;
|
||||
|
||||
void setupUi(QMainWindow *MainWindow)
|
||||
{
|
||||
if (MainWindow->objectName().isEmpty())
|
||||
MainWindow->setObjectName(QStringLiteral("MainWindow"));
|
||||
MainWindow->resize(726, 589);
|
||||
centralWidget = new QWidget(MainWindow);
|
||||
centralWidget->setObjectName(QStringLiteral("centralWidget"));
|
||||
verticalLayout = new QVBoxLayout(centralWidget);
|
||||
verticalLayout->setSpacing(6);
|
||||
verticalLayout->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
connectionStringEdit = new QLineEdit(centralWidget);
|
||||
connectionStringEdit->setObjectName(QStringLiteral("connectionStringEdit"));
|
||||
|
||||
verticalLayout->addWidget(connectionStringEdit);
|
||||
|
||||
splitter = new QSplitter(centralWidget);
|
||||
splitter->setObjectName(QStringLiteral("splitter"));
|
||||
splitter->setOrientation(Qt::Vertical);
|
||||
queryEdit = new QTextEdit(splitter);
|
||||
queryEdit->setObjectName(QStringLiteral("queryEdit"));
|
||||
splitter->addWidget(queryEdit);
|
||||
ResultView = new QTableView(splitter);
|
||||
ResultView->setObjectName(QStringLiteral("ResultView"));
|
||||
QFont font;
|
||||
font.setFamily(QStringLiteral("Source Sans Pro"));
|
||||
font.setPointSize(10);
|
||||
ResultView->setFont(font);
|
||||
ResultView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
ResultView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
splitter->addWidget(ResultView);
|
||||
|
||||
verticalLayout->addWidget(splitter);
|
||||
|
||||
MainWindow->setCentralWidget(centralWidget);
|
||||
menuBar = new QMenuBar(MainWindow);
|
||||
menuBar->setObjectName(QStringLiteral("menuBar"));
|
||||
menuBar->setGeometry(QRect(0, 0, 726, 26));
|
||||
menuTest = new QMenu(menuBar);
|
||||
menuTest->setObjectName(QStringLiteral("menuTest"));
|
||||
MainWindow->setMenuBar(menuBar);
|
||||
mainToolBar = new QToolBar(MainWindow);
|
||||
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
|
||||
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
|
||||
statusBar = new QStatusBar(MainWindow);
|
||||
statusBar->setObjectName(QStringLiteral("statusBar"));
|
||||
MainWindow->setStatusBar(statusBar);
|
||||
|
||||
menuBar->addAction(menuTest->menuAction());
|
||||
|
||||
retranslateUi(MainWindow);
|
||||
|
||||
QMetaObject::connectSlotsByName(MainWindow);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QMainWindow *MainWindow)
|
||||
{
|
||||
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", Q_NULLPTR));
|
||||
menuTest->setTitle(QApplication::translate("MainWindow", "test", Q_NULLPTR));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow: public Ui_MainWindow {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // UI_MAINWINDOW_H
|
||||
170
ui_serverproperties.h
Normal file
170
ui_serverproperties.h
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/********************************************************************************
|
||||
** Form generated from reading UI file 'serverproperties.ui'
|
||||
**
|
||||
** Created by: Qt User Interface Compiler version 5.7.1
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UI_SERVERPROPERTIES_H
|
||||
#define UI_SERVERPROPERTIES_H
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QAction>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QButtonGroup>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QFrame>
|
||||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QSpinBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_ServerProperties
|
||||
{
|
||||
public:
|
||||
QVBoxLayout *verticalLayout;
|
||||
QFrame *frame;
|
||||
QFormLayout *formLayout;
|
||||
QLabel *label;
|
||||
QLineEdit *lineEdit;
|
||||
QLabel *label_2;
|
||||
QLineEdit *lineEdit_2;
|
||||
QLabel *label_3;
|
||||
QSpinBox *spinBox;
|
||||
QLabel *label_4;
|
||||
QComboBox *comboBox;
|
||||
QLabel *label_5;
|
||||
QLineEdit *lineEdit_3;
|
||||
QLabel *label_6;
|
||||
QLineEdit *lineEdit_4;
|
||||
QDialogButtonBox *buttonBox;
|
||||
|
||||
void setupUi(QDialog *ServerProperties)
|
||||
{
|
||||
if (ServerProperties->objectName().isEmpty())
|
||||
ServerProperties->setObjectName(QStringLiteral("ServerProperties"));
|
||||
ServerProperties->resize(326, 233);
|
||||
verticalLayout = new QVBoxLayout(ServerProperties);
|
||||
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
frame = new QFrame(ServerProperties);
|
||||
frame->setObjectName(QStringLiteral("frame"));
|
||||
frame->setFrameShape(QFrame::StyledPanel);
|
||||
frame->setFrameShadow(QFrame::Raised);
|
||||
formLayout = new QFormLayout(frame);
|
||||
formLayout->setObjectName(QStringLiteral("formLayout"));
|
||||
label = new QLabel(frame);
|
||||
label->setObjectName(QStringLiteral("label"));
|
||||
|
||||
formLayout->setWidget(0, QFormLayout::LabelRole, label);
|
||||
|
||||
lineEdit = new QLineEdit(frame);
|
||||
lineEdit->setObjectName(QStringLiteral("lineEdit"));
|
||||
|
||||
formLayout->setWidget(0, QFormLayout::FieldRole, lineEdit);
|
||||
|
||||
label_2 = new QLabel(frame);
|
||||
label_2->setObjectName(QStringLiteral("label_2"));
|
||||
|
||||
formLayout->setWidget(1, QFormLayout::LabelRole, label_2);
|
||||
|
||||
lineEdit_2 = new QLineEdit(frame);
|
||||
lineEdit_2->setObjectName(QStringLiteral("lineEdit_2"));
|
||||
|
||||
formLayout->setWidget(1, QFormLayout::FieldRole, lineEdit_2);
|
||||
|
||||
label_3 = new QLabel(frame);
|
||||
label_3->setObjectName(QStringLiteral("label_3"));
|
||||
|
||||
formLayout->setWidget(2, QFormLayout::LabelRole, label_3);
|
||||
|
||||
spinBox = new QSpinBox(frame);
|
||||
spinBox->setObjectName(QStringLiteral("spinBox"));
|
||||
spinBox->setMaximum(65535);
|
||||
|
||||
formLayout->setWidget(2, QFormLayout::FieldRole, spinBox);
|
||||
|
||||
label_4 = new QLabel(frame);
|
||||
label_4->setObjectName(QStringLiteral("label_4"));
|
||||
|
||||
formLayout->setWidget(3, QFormLayout::LabelRole, label_4);
|
||||
|
||||
comboBox = new QComboBox(frame);
|
||||
comboBox->setObjectName(QStringLiteral("comboBox"));
|
||||
comboBox->setEditable(true);
|
||||
|
||||
formLayout->setWidget(3, QFormLayout::FieldRole, comboBox);
|
||||
|
||||
label_5 = new QLabel(frame);
|
||||
label_5->setObjectName(QStringLiteral("label_5"));
|
||||
|
||||
formLayout->setWidget(4, QFormLayout::LabelRole, label_5);
|
||||
|
||||
lineEdit_3 = new QLineEdit(frame);
|
||||
lineEdit_3->setObjectName(QStringLiteral("lineEdit_3"));
|
||||
|
||||
formLayout->setWidget(4, QFormLayout::FieldRole, lineEdit_3);
|
||||
|
||||
label_6 = new QLabel(frame);
|
||||
label_6->setObjectName(QStringLiteral("label_6"));
|
||||
|
||||
formLayout->setWidget(5, QFormLayout::LabelRole, label_6);
|
||||
|
||||
lineEdit_4 = new QLineEdit(frame);
|
||||
lineEdit_4->setObjectName(QStringLiteral("lineEdit_4"));
|
||||
lineEdit_4->setEchoMode(QLineEdit::Password);
|
||||
|
||||
formLayout->setWidget(5, QFormLayout::FieldRole, lineEdit_4);
|
||||
|
||||
|
||||
verticalLayout->addWidget(frame);
|
||||
|
||||
buttonBox = new QDialogButtonBox(ServerProperties);
|
||||
buttonBox->setObjectName(QStringLiteral("buttonBox"));
|
||||
buttonBox->setOrientation(Qt::Horizontal);
|
||||
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
|
||||
retranslateUi(ServerProperties);
|
||||
QObject::connect(buttonBox, SIGNAL(accepted()), ServerProperties, SLOT(accept()));
|
||||
QObject::connect(buttonBox, SIGNAL(rejected()), ServerProperties, SLOT(reject()));
|
||||
|
||||
comboBox->setCurrentIndex(0);
|
||||
|
||||
|
||||
QMetaObject::connectSlotsByName(ServerProperties);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QDialog *ServerProperties)
|
||||
{
|
||||
ServerProperties->setWindowTitle(QApplication::translate("ServerProperties", "Dialog", Q_NULLPTR));
|
||||
label->setText(QApplication::translate("ServerProperties", "Name", Q_NULLPTR));
|
||||
label_2->setText(QApplication::translate("ServerProperties", "Host", Q_NULLPTR));
|
||||
label_3->setText(QApplication::translate("ServerProperties", "Port", Q_NULLPTR));
|
||||
label_4->setText(QApplication::translate("ServerProperties", "Maintenance DB", Q_NULLPTR));
|
||||
comboBox->clear();
|
||||
comboBox->insertItems(0, QStringList()
|
||||
<< QApplication::translate("ServerProperties", "postgres", Q_NULLPTR)
|
||||
<< QApplication::translate("ServerProperties", "template1", Q_NULLPTR)
|
||||
);
|
||||
label_5->setText(QApplication::translate("ServerProperties", "Username", Q_NULLPTR));
|
||||
label_6->setText(QApplication::translate("ServerProperties", "Password", Q_NULLPTR));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class ServerProperties: public Ui_ServerProperties {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // UI_SERVERPROPERTIES_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue