Skip to content

Commit 4c7bfa7

Browse files
committed
feat: implement SQL query
1 parent 81d367e commit 4c7bfa7

File tree

8 files changed

+266
-4
lines changed

8 files changed

+266
-4
lines changed

src/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ set(SOURCE_FILES main.cpp
33
QConnectionDialog.cpp
44
QSqlQueryPanel.cpp
55
QConnectionCtrl.cpp
6-
QDbTableView.cpp)
6+
QDbTableView.cpp
7+
QQueryHighlighter.cpp)
78

89
set(HEADERS QBrowserApp.h
910
QConnectionDialog.h
1011
QSqlQueryPanel.h
1112
QConnectionCtrl.h
12-
QDbTableView.h)
13+
QDbTableView.h
14+
QQueryHighlighter.h)
1315

1416
if(WIN32)
1517
set(RESOURCES res/app_icon.rc)

src/QBrowserApp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ QBrowserApp::QBrowserApp(QWidget* parent, Qt::WindowFlags flags) : QMainWindow(p
3333
m_mainWidget->setMinimumSize(820, 625);
3434

3535
QObject::connect(m_tree, &QConnectionCtrl::tableModelChanged, m_table, &QDbTableView::setTableModel);
36+
QObject::connect(querypanel, &QSqlQueryPanel::tableModelChanged, m_table, &QDbTableView::setTableModel);
37+
QObject::connect(m_tree, &QConnectionCtrl::dbSelected, querypanel, &QSqlQueryPanel::dbChange);
3638
QObject::connect(m_tree, &QConnectionCtrl::statusMessage, [&](const QString& text) { statusBar()->showMessage(text); });
39+
QObject::connect(querypanel, &QSqlQueryPanel::statusMessage, [&](const QString& text) { statusBar()->showMessage(text); });
3740
}

src/QConnectionCtrl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,5 @@ void QConnectionCtrl::setActiveDb(QTreeWidgetItem* item) {
186186

187187
f_setBold(item, true);
188188
m_activeDb = QSqlDatabase::connectionNames().value(indexOfTopLevelItem(item));
189+
emit dbSelected(m_activeDb);
189190
}

src/QConnectionCtrl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public slots:
3131
signals:
3232
void tableModelChanged(QAbstractItemModel* model, QAbstractItemView::EditTriggers triggers);
3333
void statusMessage(const QString& message);
34+
void dbSelected(const QString& db);
3435
protected:
3536
QString m_activeDb;
3637

src/QQueryHighlighter.cpp

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#include "QQueryHighlighter.h"
2+
3+
QQueryHighlighter::QQueryHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) {
4+
HighlightingRule rule;
5+
6+
m_keywordFormat.setForeground(Qt::darkMagenta);
7+
m_keywordFormat.setFontWeight(QFont::Bold);
8+
const QString keywordPatterns[] = {
9+
QStringLiteral("\\b(?i)ADD(?-i)\\b"),
10+
QStringLiteral("\\b(?i)ADD CONSTRAINT(?-i)\\b"),
11+
QStringLiteral("\\b(?i)ALL(?-i)\\b"),
12+
QStringLiteral("\\b(?i)ALTER(?-i)\\b"),
13+
QStringLiteral("\\b(?i)ALTER COLUMN(?-i)\\b"),
14+
QStringLiteral("\\b(?i)ALTER TABLE(?-i)\\b"),
15+
QStringLiteral("\\b(?i)AND(?-i)\\b"),
16+
QStringLiteral("\\b(?i)ANY(?-i)\\b"),
17+
QStringLiteral("\\b(?i)AS(?-i)\\b"),
18+
QStringLiteral("\\b(?i)ASC(?-i)\\b"),
19+
QStringLiteral("\\b(?i)AVG(?-i)\\b"),
20+
QStringLiteral("\\b(?i)BACKUP DATABASE(?-i)\\b"),
21+
QStringLiteral("\\b(?i)BETWEEN(?-i)\\b"),
22+
QStringLiteral("\\b(?i)CASE(?-i)\\b"),
23+
QStringLiteral("\\b(?i)CHECK(?-i)\\b"),
24+
QStringLiteral("\\b(?i)COLUMN(?-i)\\b"),
25+
QStringLiteral("\\b(?i)CONSTRAINT(?-i)\\b"),
26+
QStringLiteral("\\b(?i)COUNT(?-i)\\b"),
27+
QStringLiteral("\\b(?i)CREATE(?-i)\\b"),
28+
QStringLiteral("\\b(?i)CREATE DATABASE(?-i)\\b"),
29+
QStringLiteral("\\b(?i)CREATE INDEX(?-i)\\b"),
30+
QStringLiteral("\\b(?i)CREATE OR REPLACE VIEW(?-i)\\b"),
31+
QStringLiteral("\\b(?i)CREATE TABLE(?-i)\\b"),
32+
QStringLiteral("\\b(?i)CREATE PROCEDURE(?-i)\\b"),
33+
QStringLiteral("\\b(?i)CREATE UNIQUE INDEX(?-i)\\b"),
34+
QStringLiteral("\\b(?i)CREATE VIEW(?-i)\\b"),
35+
QStringLiteral("\\b(?i)DATABASE(?-i)\\b"),
36+
QStringLiteral("\\b(?i)DEFAULT(?-i)\\b"),
37+
QStringLiteral("\\b(?i)DELETE(?-i)\\b"),
38+
QStringLiteral("\\b(?i)DESC(?-i)\\b"),
39+
QStringLiteral("\\b(?i)DISTINCT(?-i)\\b"),
40+
QStringLiteral("\\b(?i)DROP(?-i)\\b"),
41+
QStringLiteral("\\b(?i)DROP COLUMN(?-i)\\b"),
42+
QStringLiteral("\\b(?i)DROP CONSTRAINT(?-i)\\b"),
43+
QStringLiteral("\\b(?i)DROP DATABASE(?-i)\\b"),
44+
QStringLiteral("\\b(?i)DROP DEFAULT(?-i)\\b"),
45+
QStringLiteral("\\b(?i)DROP INDEX(?-i)\\b"),
46+
QStringLiteral("\\b(?i)DROP TABLE(?-i)\\b"),
47+
QStringLiteral("\\b(?i)DROP VIEW(?-i)\\b"),
48+
QStringLiteral("\\b(?i)EXEC(?-i)\\b"),
49+
QStringLiteral("\\b(?i)EXISTS(?-i)\\b"),
50+
QStringLiteral("\\b(?i)FOREIGN KEY(?-i)\\b"),
51+
QStringLiteral("\\b(?i)FROM(?-i)\\b"),
52+
QStringLiteral("\\b(?i)FULL OUTER JOIN(?-i)\\b"),
53+
QStringLiteral("\\b(?i)GROUP BY(?-i)\\b"),
54+
QStringLiteral("\\b(?i)HAVING(?-i)\\b"),
55+
QStringLiteral("\\b(?i)IN(?-i)\\b"),
56+
QStringLiteral("\\b(?i)INDEX(?-i)\\b"),
57+
QStringLiteral("\\b(?i)INNER JOIN(?-i)\\b"),
58+
QStringLiteral("\\b(?i)INSERT INTO(?-i)\\b"),
59+
QStringLiteral("\\b(?i)INSERT INTO SELECT(?-i)\\b"),
60+
QStringLiteral("\\b(?i)IS NULL(?-i)\\b"),
61+
QStringLiteral("\\b(?i)IS NOT NULL(?-i)\\b"),
62+
QStringLiteral("\\b(?i)JOIN(?-i)\\b"),
63+
QStringLiteral("\\b(?i)LEFT JOIN(?-i)\\b"),
64+
QStringLiteral("\\b(?i)LIKE(?-i)\\b"),
65+
QStringLiteral("\\b(?i)MAX(?-i)\\b"),
66+
QStringLiteral("\\b(?i)MIN(?-i)\\b"),
67+
QStringLiteral("\\b(?i)NOT(?-i)\\b"),
68+
QStringLiteral("\\b(?i)NOT NULL(?-i)\\b"),
69+
QStringLiteral("\\b(?i)OR(?-i)\\b"),
70+
QStringLiteral("\\b(?i)ORDER BY(?-i)\\b"),
71+
QStringLiteral("\\b(?i)OUTER JOIN(?-i)\\b"),
72+
QStringLiteral("\\b(?i)PRIMARY KEY(?-i)\\b"),
73+
QStringLiteral("\\b(?i)PROCEDURE(?-i)\\b"),
74+
QStringLiteral("\\b(?i)RIGHT JOIN(?-i)\\b"),
75+
QStringLiteral("\\b(?i)ROWNUM(?-i)\\b"),
76+
QStringLiteral("\\b(?i)SELECT(?-i)\\b"),
77+
QStringLiteral("\\b(?i)SELECT DISTINCT(?-i)\\b"),
78+
QStringLiteral("\\b(?i)SELECT INTO(?-i)\\b"),
79+
QStringLiteral("\\b(?i)SELECT TOP(?-i)\\b"),
80+
QStringLiteral("\\b(?i)SET(?-i)\\b"),
81+
QStringLiteral("\\b(?i)SUM(?-i)\\b"),
82+
QStringLiteral("\\b(?i)TABLE(?-i)\\b"),
83+
QStringLiteral("\\b(?i)TOP(?-i)\\b"),
84+
QStringLiteral("\\b(?i)TRUNCATE TABLE(?-i)\\b"),
85+
QStringLiteral("\\b(?i)UNION(?-i)\\b"),
86+
QStringLiteral("\\b(?i)UNION ALL(?-i)\\b"),
87+
QStringLiteral("\\b(?i)UNIQUE(?-i)\\b"),
88+
QStringLiteral("\\b(?i)UPDATE(?-i)\\b"),
89+
QStringLiteral("\\b(?i)VALUES(?-i)\\b"),
90+
QStringLiteral("\\b(?i)VIEW(?-i)\\b"),
91+
QStringLiteral("\\b(?i)WHERE(?-i)\\b")
92+
};
93+
94+
for (auto pattern : keywordPatterns) {
95+
rule.pattern = QRegularExpression(pattern);
96+
rule.format = m_keywordFormat;
97+
m_highlightingRules.append(rule);
98+
}
99+
100+
101+
m_singleLineCommentFormat.setForeground(QColor(255, 0, 0, 127));
102+
rule.pattern = QRegularExpression(QStringLiteral("--[^\n]*"));
103+
rule.format = m_singleLineCommentFormat;
104+
m_highlightingRules.append(rule);
105+
106+
m_sLiteralFormat.setForeground(Qt::gray);
107+
m_sLiteralFormat.setFontWeight(QFont::Bold);
108+
m_sLiteralDelimiterExpression = QRegularExpression(QStringLiteral("'"));
109+
110+
m_dLiteralFormat.setForeground(Qt::darkRed);
111+
m_dLiteralFormat.setFontWeight(QFont::Bold);
112+
rule.pattern = QRegularExpression(QStringLiteral("[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)"));
113+
rule.format = m_dLiteralFormat;
114+
m_highlightingRules.append(rule);
115+
116+
m_multiLineCommentFormat.setForeground(QColor(255, 0, 0, 127));
117+
m_commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
118+
m_commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
119+
}
120+
121+
void QQueryHighlighter::highlightBlock(const QString& text) {
122+
for (const HighlightingRule& rule : std::as_const(m_highlightingRules)) {
123+
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
124+
while (matchIterator.hasNext()) {
125+
QRegularExpressionMatch match = matchIterator.next();
126+
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
127+
}
128+
}
129+
130+
setCurrentBlockState(0);
131+
qsizetype startIndex = -1;
132+
qsizetype commentIndex = previousBlockState() != 1 ? text.indexOf(m_commentStartExpression) : 0;
133+
qsizetype literalIndex = previousBlockState() != 2 ? text.indexOf(m_sLiteralDelimiterExpression) : 0;
134+
if (commentIndex >= 0 && literalIndex >= 0)
135+
startIndex = std::min(commentIndex, literalIndex);
136+
else if (commentIndex >= 0)
137+
startIndex = commentIndex;
138+
else if (literalIndex >= 0)
139+
startIndex = literalIndex;
140+
141+
while (startIndex >= 0) {
142+
qsizetype blockLength = 0;
143+
int blockState;
144+
QTextCharFormat fmt;
145+
if (startIndex == commentIndex) {
146+
blockState = 1;
147+
fmt = m_multiLineCommentFormat;
148+
}
149+
else {
150+
blockState = 2;
151+
fmt = m_sLiteralFormat;
152+
}
153+
154+
QRegularExpressionMatch match = startIndex == literalIndex ? m_sLiteralDelimiterExpression.match(text, startIndex + 1) : m_commentEndExpression.match(text, startIndex + 2) ;
155+
qsizetype endIndex = match.capturedStart();
156+
if (endIndex == -1) {
157+
setCurrentBlockState(blockState);
158+
blockLength = text.length() - startIndex;
159+
}
160+
else blockLength = endIndex - startIndex + match.capturedLength();
161+
162+
setFormat(startIndex, blockLength, fmt);
163+
164+
commentIndex = text.indexOf(m_commentStartExpression, startIndex + blockLength);
165+
literalIndex = text.indexOf(m_sLiteralDelimiterExpression, startIndex + blockLength);
166+
startIndex = -1;
167+
if (commentIndex >= 0 && literalIndex >= 0)
168+
startIndex = std::min(commentIndex, literalIndex);
169+
else if (commentIndex >= 0)
170+
startIndex = commentIndex;
171+
else if (literalIndex >= 0)
172+
startIndex = literalIndex;
173+
}
174+
}

src/QQueryHighlighter.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#ifndef QUERYHIGHTLIGHTER_H
4+
#define QUERYHIGHTLIGHTER_H
5+
6+
#include <algorithm>
7+
#include <QSyntaxHighlighter>
8+
#include <QRegularExpression>
9+
10+
class QQueryHighlighter : public QSyntaxHighlighter
11+
{
12+
Q_OBJECT
13+
14+
public:
15+
QQueryHighlighter(QTextDocument* parent = nullptr);
16+
17+
protected:
18+
void highlightBlock(const QString& text) override;
19+
20+
private:
21+
struct HighlightingRule
22+
{
23+
QRegularExpression pattern;
24+
QTextCharFormat format;
25+
};
26+
QList<HighlightingRule> m_highlightingRules;
27+
28+
QRegularExpression m_sLiteralDelimiterExpression;
29+
30+
QRegularExpression m_commentStartExpression;
31+
QRegularExpression m_commentEndExpression;
32+
33+
QTextCharFormat m_keywordFormat;
34+
QTextCharFormat m_sLiteralFormat;
35+
QTextCharFormat m_dLiteralFormat;
36+
QTextCharFormat m_singleLineCommentFormat;
37+
QTextCharFormat m_multiLineCommentFormat;
38+
};
39+
40+
#endif

src/QSqlQueryPanel.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
#include "QSqlQueryPanel.h"
22

33
QSqlQueryPanel::QSqlQueryPanel(QWidget* parent, Qt::WindowFlags f) : QFrame(parent, f) {
4+
QPushButton* submitButton = new QPushButton(tr("Submit"));
5+
46
QPushButton* clearButton = new QPushButton(tr("Clear"));
57
QWidget* buttonpanel = new QWidget;
68
QHBoxLayout* buttonHLayout = new QHBoxLayout;
79
buttonHLayout->addWidget(clearButton, 1, Qt::AlignRight);
8-
buttonHLayout->addWidget(new QPushButton(tr("Submit")), 0);
10+
buttonHLayout->addWidget(submitButton, 0);
911
buttonpanel->setLayout(buttonHLayout);
1012

1113
QPlainTextEdit* textBox = new QPlainTextEdit;
1214
textBox->setPlaceholderText(tr("SQL Query"));
13-
connect(clearButton, &QPushButton::clicked, this, [=]() {textBox->clear(); textBox->setFocus();});
15+
textBox->setObjectName("textBox");
16+
textBox->setFrameStyle(QFrame::NoFrame);
17+
QQueryHighlighter* highlighter = new QQueryHighlighter(textBox->document());
18+
19+
connect(submitButton, &QPushButton::clicked, this, &QSqlQueryPanel::exec);
20+
connect(clearButton, &QPushButton::clicked, this, [=]() {textBox->clear(); textBox->setFocus(); });
1421

1522
QVBoxLayout* mainLayout = new QVBoxLayout;
1623
mainLayout->setContentsMargins(0, 0, 0, 0);
@@ -23,3 +30,23 @@ QSqlQueryPanel::QSqlQueryPanel(QWidget* parent, Qt::WindowFlags f) : QFrame(pare
2330
setFrameStyle(QFrame::Panel | QFrame::Sunken);
2431
setLineWidth(2);
2532
}
33+
34+
void QSqlQueryPanel::dbChange(const QString& db) {
35+
m_activeDb = db;
36+
}
37+
38+
void QSqlQueryPanel::exec() {
39+
40+
QSqlQueryModel* model = new QSqlQueryModel;
41+
model->setQuery(QSqlQuery(findChild<QPlainTextEdit*>("textBox")->toPlainText(), QSqlDatabase::database(m_activeDb)));
42+
43+
if (model->lastError().type() != QSqlError::NoError)
44+
emit statusMessage(model->lastError().text());
45+
else if (model->query().isSelect())
46+
emit statusMessage(tr("Query OK."));
47+
else
48+
emit statusMessage(tr("Query OK, number of affected rows: %1").arg(model->query().numRowsAffected()));
49+
50+
emit tableModelChanged(model, QAbstractItemView::NoEditTriggers);
51+
findChild<QPlainTextEdit*>("textBox")->setFocus();
52+
}

src/QSqlQueryPanel.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,26 @@
66
#include <QHBoxLayout>
77
#include <QPushButton>
88
#include <QPlainTextEdit>
9+
#include <QAbstractItemView>
10+
#include <QSqlTableModel>
11+
#include <QSqlQuery>
12+
#include <QSqlError>
13+
14+
#include "QQueryHighlighter.h"
915

1016
class QSqlQueryPanel : public QFrame
1117
{
1218
Q_OBJECT
1319
public:
1420
explicit QSqlQueryPanel(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
21+
public slots:
22+
void dbChange(const QString& db);
23+
signals:
24+
void tableModelChanged(QAbstractItemModel* model, QAbstractItemView::EditTriggers triggers);
25+
void statusMessage(const QString& message);
26+
protected:
27+
QString m_activeDb;
28+
void exec();
1529
};
1630

1731
#endif

0 commit comments

Comments
 (0)