wip: codegenerator, basic widget present for showing the generated code and specifying
parameters. Some code is also generated but it is not complete yet. minimum still required - field assignments - properly format and escape the query string
This commit is contained in:
parent
daf9536bed
commit
f5145f36ed
19 changed files with 380 additions and 32 deletions
|
|
@ -4,6 +4,9 @@
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
/** This class adds some capabilities to QPlainTextEdit that are useful
|
||||||
|
* in code editor scenarios.
|
||||||
|
*/
|
||||||
class CodeEditor : public QPlainTextEdit
|
class CodeEditor : public QPlainTextEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
51
pglab/CodeGenerator.cpp
Normal file
51
pglab/CodeGenerator.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "CodeGenerator.h"
|
||||||
|
#include "ui_CodeGenerator.h"
|
||||||
|
#include "codebuilder/CodeBuilder.h"
|
||||||
|
#include "codebuilder/DefaultConfigs.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
CodeGenerator::CodeGenerator(QWidget *parent) :
|
||||||
|
PlgPage(parent),
|
||||||
|
ui(new Ui::CodeGenerator)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->generatedCodeEditor->setFont(UserConfiguration::instance()->codeFont());
|
||||||
|
ui->generatedCodeEditor->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeGenerator::~CodeGenerator()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::Init(QString query, std::shared_ptr<const Pgsql::Result> dbres)
|
||||||
|
{
|
||||||
|
m_query = query;
|
||||||
|
m_dbres = dbres;
|
||||||
|
generateCode();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CodeGenerator::on_updateCodeButton_clicked()
|
||||||
|
{
|
||||||
|
generateCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::generateCode()
|
||||||
|
{
|
||||||
|
QString struct_name = ui->structNameEdit->text();
|
||||||
|
|
||||||
|
QString buffer;
|
||||||
|
QTextStream stream(&buffer);
|
||||||
|
CodeBuilder builder;
|
||||||
|
builder.setLanguageConfig(getDefaultCppLanguageConfig());
|
||||||
|
builder.GenCodeForExecutingQuery(stream, m_query, *m_dbres, struct_name);
|
||||||
|
stream.flush();
|
||||||
|
ui->generatedCodeEditor->setPlainText(buffer);
|
||||||
|
// QApplication::clipboard()->setText(buffer);
|
||||||
|
|
||||||
|
}
|
||||||
33
pglab/CodeGenerator.h
Normal file
33
pglab/CodeGenerator.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef CODEGENERATOR_H
|
||||||
|
#define CODEGENERATOR_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "PlgPage.h"
|
||||||
|
#include "Pgsql_declare.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CodeGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CodeGenerator : public PlgPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CodeGenerator(QWidget *parent = nullptr);
|
||||||
|
~CodeGenerator();
|
||||||
|
|
||||||
|
void Init(QString query, std::shared_ptr<const Pgsql::Result> dbres);
|
||||||
|
private slots:
|
||||||
|
void on_updateCodeButton_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::CodeGenerator *ui;
|
||||||
|
|
||||||
|
QString m_query;
|
||||||
|
std::shared_ptr<const Pgsql::Result> m_dbres;
|
||||||
|
|
||||||
|
void generateCode();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CODEGENERATOR_H
|
||||||
80
pglab/CodeGenerator.ui
Normal file
80
pglab/CodeGenerator.ui
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CodeGenerator</class>
|
||||||
|
<widget class="QWidget" name="CodeGenerator">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1127</width>
|
||||||
|
<height>762</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="splitter">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="structNameLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Struct name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="structNameEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="updateCodeButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Update code</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Configuration</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="CodeEditor" name="generatedCodeEditor">
|
||||||
|
<property name="tabChangesFocus">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CodeEditor</class>
|
||||||
|
<extends>QPlainTextEdit</extends>
|
||||||
|
<header>CodeEditor.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "QueryTab.h"
|
#include "QueryTab.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "PlgPage.h"
|
#include "PlgPage.h"
|
||||||
|
#include "CodeGenerator.h"
|
||||||
#include "MasterController.h"
|
#include "MasterController.h"
|
||||||
#include "CrudTab.h"
|
#include "CrudTab.h"
|
||||||
#include "WorkManager.h"
|
#include "WorkManager.h"
|
||||||
|
|
@ -58,6 +59,14 @@ void MainWindow::newCrudPage(const PgClass &table)
|
||||||
addPage(ct, table.name);
|
addPage(ct, table.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres)
|
||||||
|
{
|
||||||
|
auto cgtab = new CodeGenerator(this);
|
||||||
|
cgtab->Init(query, dbres);
|
||||||
|
addPage(cgtab, "Codegen");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QueryTab *MainWindow::GetActiveQueryTab()
|
QueryTab *MainWindow::GetActiveQueryTab()
|
||||||
{
|
{
|
||||||
QWidget *widget = ui->tabWidget->currentWidget();
|
QWidget *widget = ui->tabWidget->currentWidget();
|
||||||
|
|
@ -344,3 +353,12 @@ void MainWindow::on_tabWidget_currentChanged(int index)
|
||||||
}
|
}
|
||||||
m_previousPage = page;
|
m_previousPage = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionGenerate_code_triggered()
|
||||||
|
{
|
||||||
|
QueryTab *tab = GetActiveQueryTab();
|
||||||
|
if (tab) {
|
||||||
|
tab->generateCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ public:
|
||||||
std::shared_ptr<OpenDatabase> getDatabase() { return m_database; }
|
std::shared_ptr<OpenDatabase> getDatabase() { return m_database; }
|
||||||
|
|
||||||
void newCrudPage(const PgClass &table);
|
void newCrudPage(const PgClass &table);
|
||||||
|
void newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
|
|
@ -116,6 +117,7 @@ private slots:
|
||||||
void on_actionCopy_as_C_string_triggered();
|
void on_actionCopy_as_C_string_triggered();
|
||||||
void on_actionCopy_as_raw_Cpp_string_triggered();
|
void on_actionCopy_as_raw_Cpp_string_triggered();
|
||||||
void on_tabWidget_currentChanged(int index);
|
void on_tabWidget_currentChanged(int index);
|
||||||
|
void on_actionGenerate_code_triggered();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>993</width>
|
<width>993</width>
|
||||||
<height>20</height>
|
<height>25</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuTest">
|
<widget class="QMenu" name="menuTest">
|
||||||
|
|
@ -86,6 +86,7 @@
|
||||||
<addaction name="actionCopy"/>
|
<addaction name="actionCopy"/>
|
||||||
<addaction name="actionCopy_as_C_string"/>
|
<addaction name="actionCopy_as_C_string"/>
|
||||||
<addaction name="actionCopy_as_raw_Cpp_string"/>
|
<addaction name="actionCopy_as_raw_Cpp_string"/>
|
||||||
|
<addaction name="actionGenerate_code"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuTest"/>
|
<addaction name="menuTest"/>
|
||||||
<addaction name="menuEdit"/>
|
<addaction name="menuEdit"/>
|
||||||
|
|
@ -233,6 +234,11 @@
|
||||||
<string>Copy as raw C++-string</string>
|
<string>Copy as raw C++-string</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionGenerate_code">
|
||||||
|
<property name="text">
|
||||||
|
<string>Generate code</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ public:
|
||||||
virtual QVariant headerData(int section, Qt::Orientation orientation, 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;
|
// virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
std::shared_ptr<const Pgsql::Result> GetPgsqlResult() const { return result; }
|
||||||
protected:
|
protected:
|
||||||
// virtual Oid getType(int column) const override;
|
// virtual Oid getType(int column) const override;
|
||||||
// virtual QVariant getData(const QModelIndex &index) const override;
|
// virtual QVariant getData(const QModelIndex &index) const override;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "QueryParamListController.h"
|
#include "QueryParamListController.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "GlobalIoService.h"
|
#include "GlobalIoService.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
|
||||||
QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
||||||
PlgPage(parent),
|
PlgPage(parent),
|
||||||
|
|
@ -34,11 +35,7 @@ QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
||||||
connect(&m_dbConnection, &ASyncDBConnection::onStateChanged, this, &QueryTab::connectionStateChanged);
|
connect(&m_dbConnection, &ASyncDBConnection::onStateChanged, this, &QueryTab::connectionStateChanged);
|
||||||
connect(&m_dbConnection, &ASyncDBConnection::onNotice, this, &QueryTab::receiveNotice);
|
connect(&m_dbConnection, &ASyncDBConnection::onNotice, this, &QueryTab::receiveNotice);
|
||||||
|
|
||||||
QFont font;
|
ui->queryEdit->setFont(UserConfiguration::instance()->codeFont());
|
||||||
font.setFamily("Source Code Pro");
|
|
||||||
font.setFixedPitch(true);
|
|
||||||
font.setPointSize(10);
|
|
||||||
ui->queryEdit->setFont(font);
|
|
||||||
|
|
||||||
highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document());
|
highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document());
|
||||||
auto open_database = m_win->getDatabase();
|
auto open_database = m_win->getDatabase();
|
||||||
|
|
@ -583,14 +580,30 @@ void QueryTab::copyQueryAsCString()
|
||||||
QApplication::clipboard()->setText(cs);
|
QApplication::clipboard()->setText(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <codebuilder/CodeBuilder.h>
|
||||||
|
#include <codebuilder/DefaultConfigs.h>
|
||||||
|
|
||||||
void QueryTab::copyQueryAsRawCppString()
|
void QueryTab::copyQueryAsRawCppString()
|
||||||
{
|
{
|
||||||
//auto sql = getAllOrSelectedSql();
|
|
||||||
QString command = getCommand();
|
QString command = getCommand();
|
||||||
|
//auto sql = getAllOrSelectedSql();
|
||||||
QString cs = ConvertToMultiLineRawCppString(command);
|
QString cs = ConvertToMultiLineRawCppString(command);
|
||||||
QApplication::clipboard()->setText(cs);
|
QApplication::clipboard()->setText(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QueryTab::generateCode()
|
||||||
|
{
|
||||||
|
QString command = getCommand();
|
||||||
|
|
||||||
|
if (resultList.empty()) {
|
||||||
|
QMessageBox::question(this, "pglab", tr("Please execute the query first"), QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
if (resultList.size() == 1) {
|
||||||
|
std::shared_ptr<const Pgsql::Result> dbres = resultList[0]->GetPgsqlResult();
|
||||||
|
m_win->newCodeGenPage(command, dbres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QueryTab::exportData(const QString &file_name)
|
void QueryTab::exportData(const QString &file_name)
|
||||||
{
|
{
|
||||||
auto widget = ui->tabWidget->currentWidget();
|
auto widget = ui->tabWidget->currentWidget();
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ public:
|
||||||
|
|
||||||
void copyQueryAsCString();
|
void copyQueryAsCString();
|
||||||
void copyQueryAsRawCppString();
|
void copyQueryAsRawCppString();
|
||||||
|
void generateCode();
|
||||||
void exportData(const QString &filename);
|
void exportData(const QString &filename);
|
||||||
|
|
||||||
QString fileName() const { return m_fileName; }
|
QString fileName() const { return m_fileName; }
|
||||||
|
|
|
||||||
25
pglab/UserConfiguration.cpp
Normal file
25
pglab/UserConfiguration.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
UserConfiguration* UserConfiguration::instance()
|
||||||
|
{
|
||||||
|
static UserConfiguration config; // in C++ 11 static ensures thread safe initialization at first call of function
|
||||||
|
return &config;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserConfiguration::UserConfiguration()
|
||||||
|
: m_settings(nullptr)
|
||||||
|
{
|
||||||
|
m_settings.setIniCodec("UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont UserConfiguration::codeFont() const
|
||||||
|
{
|
||||||
|
QString family = m_settings.value("fonts/code/family", QString("Source Code Pro")).toString();
|
||||||
|
int size = m_settings.value("fonts/code/size", 10).toInt();
|
||||||
|
QFont font;
|
||||||
|
font.setFamily(family);
|
||||||
|
font.setFixedPitch(true);
|
||||||
|
font.setPointSize(size);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
24
pglab/UserConfiguration.h
Normal file
24
pglab/UserConfiguration.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef USERCONFIGURATION_H
|
||||||
|
#define USERCONFIGURATION_H
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
/** Class for most of the program configuration
|
||||||
|
*
|
||||||
|
* The settings represented by this class are stored in a settings file
|
||||||
|
* that is user specific. Depending on OS setup it might be shared with
|
||||||
|
* other machines in the network because for instance on windows it is
|
||||||
|
* part of the roaming profile.
|
||||||
|
*/
|
||||||
|
class UserConfiguration
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static UserConfiguration* instance();
|
||||||
|
|
||||||
|
UserConfiguration();
|
||||||
|
|
||||||
|
QFont codeFont() const;
|
||||||
|
private:
|
||||||
|
QSettings m_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USERCONFIGURATION_H
|
||||||
|
|
@ -73,7 +73,9 @@ SOURCES += main.cpp\
|
||||||
EditorGutter.cpp \
|
EditorGutter.cpp \
|
||||||
CodeEditor.cpp \
|
CodeEditor.cpp \
|
||||||
PlgPage.cpp \
|
PlgPage.cpp \
|
||||||
PropertyProxyModel.cpp
|
PropertyProxyModel.cpp \
|
||||||
|
CodeGenerator.cpp \
|
||||||
|
UserConfiguration.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
QueryResultModel.h \
|
QueryResultModel.h \
|
||||||
|
|
@ -121,7 +123,9 @@ HEADERS += \
|
||||||
PlgPage.h \
|
PlgPage.h \
|
||||||
AbstractCommand.h \
|
AbstractCommand.h \
|
||||||
PropertyProxyModel.h \
|
PropertyProxyModel.h \
|
||||||
CustomDataRole.h
|
CustomDataRole.h \
|
||||||
|
CodeGenerator.h \
|
||||||
|
UserConfiguration.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
ConnectionManagerWindow.ui \
|
ConnectionManagerWindow.ui \
|
||||||
|
|
@ -134,7 +138,8 @@ FORMS += mainwindow.ui \
|
||||||
TablesPage.ui \
|
TablesPage.ui \
|
||||||
NamespaceFilterWidget.ui \
|
NamespaceFilterWidget.ui \
|
||||||
ApplicationWindow.ui \
|
ApplicationWindow.ui \
|
||||||
CrudTab.ui
|
CrudTab.ui \
|
||||||
|
CodeGenerator.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ public:
|
||||||
|
|
||||||
void setResult(std::shared_ptr<QueryResultModel> res, float ms);
|
void setResult(std::shared_ptr<QueryResultModel> res, float ms);
|
||||||
void exportData(const QString &file_name) const;
|
void exportData(const QString &file_name) const;
|
||||||
|
|
||||||
|
std::shared_ptr<const Pgsql::Result> GetPgsqlResult() const { return resultModel->GetPgsqlResult(); }
|
||||||
private:
|
private:
|
||||||
Ui::TuplesResultWidget *ui;
|
Ui::TuplesResultWidget *ui;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "CodeBuilder.h"
|
#include "CodeBuilder.h"
|
||||||
|
#include "FormatToStream.h"
|
||||||
#include "Pgsql_Result.h"
|
#include "Pgsql_Result.h"
|
||||||
#include "IndentationConfig.h"
|
#include "IndentationConfig.h"
|
||||||
#include "LanguageConfig.h"
|
#include "LanguageConfig.h"
|
||||||
|
|
@ -6,31 +7,41 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result)
|
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result, QString structname)
|
||||||
{
|
{
|
||||||
// %1 query string
|
// %1 query string
|
||||||
// %2 struct_name
|
// %2 struct_name
|
||||||
// %3 list of field assignments
|
// %3 list of field assignments
|
||||||
QString exec_query_template = "Pgsql::Result result = conn.query(%1);";
|
QString exec_query_template = "Pgsql::Result result = conn.query(%1);";
|
||||||
|
|
||||||
QString loop_start_template =
|
QString loop_start_template = R"__(Pgsql::Result result = conn.query(/%queryliteral%/);
|
||||||
"Pgsql::Result result = conn.query(/%query_literal%/);"
|
for (auto row: result) {
|
||||||
"for (auto row: result) {\n"
|
Pgsql::Col col(row);
|
||||||
" Pgsql::Col col(row);\n"
|
/%structname%/ v;
|
||||||
" /%struct_type%/ v;\n"
|
/%assignfields%/
|
||||||
"/%assign_fields%/"
|
})__";
|
||||||
"}";
|
|
||||||
|
|
||||||
// %field_name%
|
// %field_name%
|
||||||
// %column_name%
|
// %column_name%
|
||||||
// %column_index%
|
// %column_index%
|
||||||
QString assign_result_field_template = "col >> v./%field_name%/";
|
QString assign_result_field_template = "col >> v./%fieldname%/";
|
||||||
QString query_string_literal = ConvertToMultiLineCString(query);
|
QString query_string_literal = ConvertToMultiLineCString(query);
|
||||||
|
|
||||||
|
ColumnDataList columnData = createColumnDataList(result);
|
||||||
|
|
||||||
|
auto get_var_func = [&] (QTextStream &out, QString var) {
|
||||||
|
if (var == "structname") out << structname;
|
||||||
|
//else if (var == "assign_fields") GenFieldAssignments(out);
|
||||||
|
else if (var == "queryliteral") out << query;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// [optional] Gen declaration of result structure
|
// [optional] Gen declaration of result structure
|
||||||
GenReturnStructDefinition(q, result);
|
GenReturnStructDefinition(q, result, structname);
|
||||||
|
|
||||||
// assume we have connection? What name???
|
// assume we have connection? What name???
|
||||||
|
FormatToStream(q, loop_start_template, get_var_func);
|
||||||
|
|
||||||
// gen code for creating and executing statement
|
// gen code for creating and executing statement
|
||||||
// - bind parameters
|
// - bind parameters
|
||||||
|
|
@ -40,16 +51,20 @@ void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result) const
|
void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result, QString structname) const
|
||||||
{
|
{
|
||||||
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
||||||
|
|
||||||
QString struct_name = "TODO";
|
|
||||||
QString field_format = templ->m_fieldTemplate;
|
QString field_format = templ->m_fieldTemplate;
|
||||||
int field_indent_levels = templ->m_fieldIndentation;
|
int field_indent_levels = templ->m_fieldIndentation;
|
||||||
QString field_indent_string = m_configuration->indentationConfig()->getIndentString(field_indent_levels);
|
QString field_indent_string = m_configuration->indentationConfig()->getIndentString(field_indent_levels);
|
||||||
|
|
||||||
|
auto struct_callback = [&] (QTextStream &out, QString var) {
|
||||||
|
if (var == "structname") out << structname;
|
||||||
|
};
|
||||||
// Make struct start
|
// Make struct start
|
||||||
q << QString(templ->m_startTemplate).arg(struct_name);
|
//q << QString(templ->m_startTemplate).arg(struct_name);
|
||||||
|
FormatToStream(q, templ->m_startTemplate, struct_callback);
|
||||||
// Process fields
|
// Process fields
|
||||||
for (int column = 0; column < result.cols(); ++column) {
|
for (int column = 0; column < result.cols(); ++column) {
|
||||||
QString res_col_name = result.getColName(column);
|
QString res_col_name = result.getColName(column);
|
||||||
|
|
@ -71,7 +86,9 @@ void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result
|
||||||
// - null pointer (useful for languages where this has no cost, other cases boolean flags will be more performant)
|
// - null pointer (useful for languages where this has no cost, other cases boolean flags will be more performant)
|
||||||
}
|
}
|
||||||
// Finish struct
|
// Finish struct
|
||||||
q << QString(templ->m_endTemplate).arg(struct_name);
|
|
||||||
|
//q << QString(templ->m_endTemplate).arg(struct_name);
|
||||||
|
FormatToStream(q, templ->m_endTemplate, struct_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CodeBuilder::columnNameToVariableName(QString column_name) const
|
QString CodeBuilder::columnNameToVariableName(QString column_name) const
|
||||||
|
|
@ -88,6 +105,22 @@ void CodeBuilder::genFieldDeclaration(QTextStream &q, const QString &format, con
|
||||||
{
|
{
|
||||||
QString field_name = columnNameToVariableName(column_name);
|
QString field_name = columnNameToVariableName(column_name);
|
||||||
QString type_name = getTypeName(column_type);
|
QString type_name = getTypeName(column_type);
|
||||||
q << QString(format).arg(field_name).arg(type_name);
|
//q << QString(format).arg(field_name).arg(type_name);
|
||||||
|
FormatToStream(q, format, [&] (QTextStream &out, QString var) {
|
||||||
|
if (var == "typename") out << type_name;
|
||||||
|
else if (var == "varname") out << field_name;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodeBuilder::ColumnDataList CodeBuilder::createColumnDataList(const Pgsql::Result &result)
|
||||||
|
{
|
||||||
|
ColumnDataList list;
|
||||||
|
list.reserve(static_cast<size_t>(result.cols()));
|
||||||
|
for (int column = 0; column < result.cols(); ++column) {
|
||||||
|
Oid type_oid = result.type(column);
|
||||||
|
QString column_name = result.getColName(column);
|
||||||
|
QString field_name = columnNameToVariableName(column_name);
|
||||||
|
list.push_back({type_oid, column_name, field_name});
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,19 @@
|
||||||
|
|
||||||
#include "Pgsql_declare.h"
|
#include "Pgsql_declare.h"
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class LanguageConfig;
|
class LanguageConfig;
|
||||||
class QTextStream;
|
class QTextStream;
|
||||||
|
|
||||||
class CodeBuilder {
|
class CodeBuilder {
|
||||||
public:
|
public:
|
||||||
void GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result);
|
void setLanguageConfig(std::shared_ptr<const LanguageConfig> config){
|
||||||
void GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result) const;
|
m_configuration = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result, QString structname);
|
||||||
|
void GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result, QString structname) const;
|
||||||
|
|
||||||
// Generating code for performing query and going through the result
|
// Generating code for performing query and going through the result
|
||||||
// - Code for executing the query
|
// - Code for executing the query
|
||||||
|
|
@ -20,9 +25,21 @@ public:
|
||||||
QString columnNameToVariableName(QString column_name) const;
|
QString columnNameToVariableName(QString column_name) const;
|
||||||
QString getTypeName(Oid dbtype) const;
|
QString getTypeName(Oid dbtype) const;
|
||||||
private:
|
private:
|
||||||
|
class ColumnData {
|
||||||
|
public:
|
||||||
|
Oid oid;
|
||||||
|
QString columnName;
|
||||||
|
QString varName; ///< either field of the struct or in loop local var name
|
||||||
|
};
|
||||||
|
using ColumnDataList = std::vector<ColumnData>;
|
||||||
|
|
||||||
std::shared_ptr<const LanguageConfig> m_configuration;
|
std::shared_ptr<const LanguageConfig> m_configuration;
|
||||||
|
|
||||||
|
|
||||||
|
void GenFieldAssignments(QTextStream &q, const Pgsql::Result &result);
|
||||||
void genFieldDeclaration(QTextStream &q, const QString &format, const QString &column_name, Oid column_type) const;
|
void genFieldDeclaration(QTextStream &q, const QString &format, const QString &column_name, Oid column_type) const;
|
||||||
|
|
||||||
|
ColumnDataList createColumnDataList(const Pgsql::Result &result);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODEBUILDER_H
|
#endif // CODEBUILDER_H
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
#include "DefaultConfigs.h"
|
#include "DefaultConfigs.h"
|
||||||
|
#include "IndentationConfig.h"
|
||||||
#include "LanguageConfig.h"
|
#include "LanguageConfig.h"
|
||||||
|
#include "NameManglingRules.h"
|
||||||
|
#include "StructureTemplate.h"
|
||||||
#include "TypeMappings.h"
|
#include "TypeMappings.h"
|
||||||
#include "Pgsql_oids.h"
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
using namespace Pgsql;
|
using namespace Pgsql;
|
||||||
|
|
||||||
TypeMappings GetDefaultCppTypeMappings()
|
std::shared_ptr<const TypeMappings> GetDefaultCppTypeMappings()
|
||||||
{
|
{
|
||||||
TypeMappings result = {
|
auto tm = std::make_shared<TypeMappings>();
|
||||||
|
*tm = {
|
||||||
{ bool_oid, "bool" },
|
{ bool_oid, "bool" },
|
||||||
{ char_oid, "char" },
|
{ char_oid, "char" },
|
||||||
{ name_oid, "std::string" },
|
{ name_oid, "std::string" },
|
||||||
|
|
@ -19,13 +23,27 @@ TypeMappings GetDefaultCppTypeMappings()
|
||||||
{ float4_oid, "float" },
|
{ float4_oid, "float" },
|
||||||
{ float8_oid, "double" }
|
{ float8_oid, "double" }
|
||||||
};
|
};
|
||||||
return result;
|
tm->setDefaultStringType("std::string");
|
||||||
|
tm->setDefaultContainerType("std::vector<%1>");
|
||||||
|
return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<LanguageConfig> buildDefaultCppLanguageConfig()
|
std::shared_ptr<LanguageConfig> buildDefaultCppLanguageConfig()
|
||||||
{
|
{
|
||||||
return std::make_shared<LanguageConfig>();
|
auto config = std::make_shared<LanguageConfig>();
|
||||||
|
config->setTypeMappings(GetDefaultCppTypeMappings());
|
||||||
|
config->setNameManglingRules(std::make_shared<NameManglingRules>());
|
||||||
|
|
||||||
|
auto st_templ = std::make_shared<StructureTemplate>();
|
||||||
|
st_templ->m_startTemplate = "class /%structname%/ {\npublic:\n";
|
||||||
|
st_templ->m_endTemplate = "};\n"; // };
|
||||||
|
st_templ->m_fieldTemplate = "/%typename%/ /%varname%/;";
|
||||||
|
//st_templ->m_fieldSeparator;
|
||||||
|
config->setStructureTemplate(st_templ);
|
||||||
|
config->setIndentationConfig(std::make_shared<IndentationConfig>());
|
||||||
|
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const LanguageConfig> getDefaultCppLanguageConfig()
|
std::shared_ptr<const LanguageConfig> getDefaultCppLanguageConfig()
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,11 @@ public:
|
||||||
QString columnNameToFieldName(const QString& column_name) const;
|
QString columnNameToFieldName(const QString& column_name) const;
|
||||||
QString getTypeName(Oid dbtype) const;
|
QString getTypeName(Oid dbtype) const;
|
||||||
|
|
||||||
|
void setNameManglingRules(std::shared_ptr<const NameManglingRules> name_mangling_rules)
|
||||||
|
{
|
||||||
|
m_varNaming = name_mangling_rules;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<const TypeMappings> typeMappings() const { return m_typeMappings; }
|
std::shared_ptr<const TypeMappings> typeMappings() const { return m_typeMappings; }
|
||||||
void setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings)
|
void setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings)
|
||||||
{
|
{
|
||||||
|
|
@ -29,10 +34,20 @@ public:
|
||||||
return m_structureTemplate;
|
return m_structureTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStructureTemplate(std::shared_ptr<const StructureTemplate> structure_template)
|
||||||
|
{
|
||||||
|
m_structureTemplate = structure_template;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<const IndentationConfig> indentationConfig() const
|
std::shared_ptr<const IndentationConfig> indentationConfig() const
|
||||||
{
|
{
|
||||||
return m_indentationConfig;
|
return m_indentationConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setIndentationConfig(std::shared_ptr<const IndentationConfig> indentation_config)
|
||||||
|
{
|
||||||
|
m_indentationConfig = indentation_config;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
/** Default template for declaring a variable of the correct type.
|
/** Default template for declaring a variable of the correct type.
|
||||||
* exmaple: "{$type} {$varname};"
|
* exmaple: "{$type} {$varname};"
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ SOURCES += main.cpp \
|
||||||
tst_PasswordManager.cpp \
|
tst_PasswordManager.cpp \
|
||||||
tst_ParamJson.cpp \
|
tst_ParamJson.cpp \
|
||||||
tst_CodeBuilder.cpp \
|
tst_CodeBuilder.cpp \
|
||||||
tst_NameManglingRules.cpp
|
tst_NameManglingRules.cpp \
|
||||||
|
tst_TypeMappings.cpp
|
||||||
|
|
||||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore
|
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore
|
||||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue