Gen code for query #78
69 changed files with 1650 additions and 323 deletions
12
common.pri
Normal file
12
common.pri
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
INCLUDEPATH += C:\prog\include C:\prog\include\pgsql C:\VSproj\boost\include\boost-1_68
|
||||||
|
|
||||||
|
LIBS += -LC:\VSproj\boost\lib -LC:/PROG/LIB -lws2_32 -llibpq
|
||||||
|
|
||||||
|
QMAKE_CXXFLAGS += /std:c++17
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
||||||
|
|
@ -8,23 +8,14 @@ QT -= gui
|
||||||
|
|
||||||
TARGET = core
|
TARGET = core
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += staticlib c++14
|
CONFIG += staticlib c++17
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
! include( ../common.pri ) {
|
||||||
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
}
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include \
|
INCLUDEPATH += C:\Prog\include\pgsql
|
||||||
C:\Prog\include\pgsql \
|
|
||||||
C:\VSproj\boost32\include\boost-1_65_1
|
|
||||||
|
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
|
||||||
#LIBS += /LIBPATH:C:\VSproj\boost_1_63_0\stage\lib /LIBPATH:c:\prog\lib\ libpq.lib fmt.lib User32.lib ws2_32.lib
|
|
||||||
|
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
|
||||||
# any feature of Qt which as been marked as deprecated (the exact warnings
|
|
||||||
# depend on your compiler). Please consult the documentation of the
|
|
||||||
# deprecated API in order to know how to port your code away from it.
|
|
||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
|
||||||
|
|
||||||
# You can also make your code fail to compile if you use deprecated APIs.
|
# You can also make your code fail to compile if you use deprecated APIs.
|
||||||
# In order to do so, uncomment the following line.
|
# In order to do so, uncomment the following line.
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ namespace boost
|
||||||
void assertion_failed(char const * expr, char const * function, char const * file, long line)
|
void assertion_failed(char const * expr, char const * function, char const * file, long line)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Assertion failure int " << function << " " << file << ":" << line;
|
out << "Assertion failure int " << function << " " << file << ":" << line << "\n" << expr;
|
||||||
throw std::runtime_error(out.str());
|
throw std::runtime_error(out.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line)
|
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Assertion failure int " << function << " " << file << ":" << line << "\n"<< msg;
|
out << "Assertion failure int " << function << " " << file << ":" << line << "\n" << msg << "\n" << expr;
|
||||||
throw std::runtime_error(out.str());
|
throw std::runtime_error(out.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ QMAKE_CXXFLAGS += /std:c++17
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include \
|
INCLUDEPATH += C:\prog\include \
|
||||||
C:\Prog\include\pgsql \
|
C:\Prog\include\pgsql \
|
||||||
C:\VSproj\boost32\include\boost-1_65_1
|
C:\VSproj\boost32\include
|
||||||
|
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "BaseTableModel.h"
|
#include "BaseTableModel.h"
|
||||||
#include "ResultTableModelUtil.h"
|
#include "ResultTableModelUtil.h"
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
using namespace Pgsql;
|
using namespace Pgsql;
|
||||||
|
|
||||||
|
|
@ -10,7 +11,7 @@ QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
||||||
Oid oid = getType(index.column());
|
Oid oid = getType(index.column());
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
v = getData(index);
|
v = getData(index);
|
||||||
if (oid == BOOLOID) {
|
if (oid == bool_oid) {
|
||||||
v = FormatBoolForDisplay(v.toBool());
|
v = FormatBoolForDisplay(v.toBool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +19,7 @@ QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
||||||
v = (int)GetDefaultAlignmentForType(oid);
|
v = (int)GetDefaultAlignmentForType(oid);
|
||||||
}
|
}
|
||||||
else if (role == Qt::ForegroundRole) {
|
else if (role == Qt::ForegroundRole) {
|
||||||
if (oid == BOOLOID) {
|
if (oid == bool_oid) {
|
||||||
QVariant d = getData(index);
|
QVariant d = getData(index);
|
||||||
if (d.type() == QVariant::Bool) {
|
if (d.type() == QVariant::Bool) {
|
||||||
v = QBrush(GetDefaultBoolColor(d.toBool()));
|
v = QBrush(GetDefaultBoolColor(d.toBool()));
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#include "CodeBuilderConfiguration.h"
|
|
||||||
#include "Pgsql_Result.h"
|
|
||||||
|
|
||||||
|
|
||||||
QString CodeBuilder::GenClassDefinition(const Pgsql::Result &/*result*/) const
|
|
||||||
{
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QStringBuilder>
|
|
||||||
#include <libpq-fe.h>
|
|
||||||
|
|
||||||
namespace Pgsql { class Result; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
class PgAuthId {
|
|
||||||
public:
|
|
||||||
PgAuthId();
|
|
||||||
|
|
||||||
Oid oid = InvalidOid;
|
|
||||||
QString name;
|
|
||||||
bool super;
|
|
||||||
bool inherit;
|
|
||||||
bool createRole;
|
|
||||||
bool createDB;
|
|
||||||
bool canlogin;
|
|
||||||
bool replication;
|
|
||||||
bool bypassRls;
|
|
||||||
int connLimit;
|
|
||||||
QDateTime validUntil;*/
|
|
||||||
|
|
||||||
/** Defines how a database result fieldname should be converted into a variable
|
|
||||||
* name in the target language.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class VarNameManglingRules {
|
|
||||||
public:
|
|
||||||
enum class CollisionHandling {
|
|
||||||
Restrict, ///< An error will be reported and no code generated
|
|
||||||
Fqn, ///< Turn into fully qualified name (table_column)
|
|
||||||
Number ///< A number will be appended to fields that have the same name
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CaseConversion {
|
|
||||||
AsIs,
|
|
||||||
Upper,
|
|
||||||
Lower
|
|
||||||
};
|
|
||||||
|
|
||||||
QString replaceSpaceWith; ///< default is empty string which means remove spaces
|
|
||||||
CollisionHandling CollisionHandling = CollisionHandling::Restrict;
|
|
||||||
CaseConversion caseConversion = CaseConversion::AsIs; ///< overall case conversion rule
|
|
||||||
CaseConversion caseFirstChar = CaseConversion::AsIs; ///< case of the first char
|
|
||||||
bool underscoreToCamel = false; ///< remove underscores and make first char after underscore uppercase
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class LanguageConfig {
|
|
||||||
public:
|
|
||||||
/** Default template for declaring a variable of the correct type.
|
|
||||||
* exmaple: "{$type} {$varname};"
|
|
||||||
*/
|
|
||||||
QString varDeclTemplate;
|
|
||||||
VarNameManglingRules varNaming;
|
|
||||||
|
|
||||||
enum class VariableStrategy {
|
|
||||||
UseLocalVariables,
|
|
||||||
DeclareClass
|
|
||||||
};
|
|
||||||
|
|
||||||
QString classStartTemplate;
|
|
||||||
QString classEndTemplate;
|
|
||||||
QString classFieldTemplate;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* There are some default fallbacks in place
|
|
||||||
* - smallint > integer
|
|
||||||
* - integer > bigint
|
|
||||||
* - int2 > smallint
|
|
||||||
* - int4 > integer
|
|
||||||
* - int8 > bigint
|
|
||||||
*
|
|
||||||
* - float > double
|
|
||||||
* - text > varchar
|
|
||||||
*/
|
|
||||||
class TypeConfig {
|
|
||||||
public:
|
|
||||||
/** The following template allows you to derive the variable name from the result fieldname.
|
|
||||||
*
|
|
||||||
* {$} in the suplied value will be replaced with the name of the result field.
|
|
||||||
*
|
|
||||||
* example: {$}
|
|
||||||
*/
|
|
||||||
QString varNameTemplate;
|
|
||||||
QString typeIdent;
|
|
||||||
QString varDeclTemplate; ///< Overrules the default template in the language config
|
|
||||||
|
|
||||||
// Mapping() = default;
|
|
||||||
// Mapping(Oid oid, QString lang_type_ident)
|
|
||||||
// : db_oid(oid), lang_type(lang_type_ident)
|
|
||||||
// {}
|
|
||||||
//
|
|
||||||
// bool operator < (const Mapping &rhs) const
|
|
||||||
// {
|
|
||||||
// return db_oid < rhs.db_oid;
|
|
||||||
// }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class TypeMappings {
|
|
||||||
public:
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
class CodeBuilderConfiguration {
|
|
||||||
public:
|
|
||||||
};
|
|
||||||
|
|
||||||
class CodeBuilder {
|
|
||||||
public:
|
|
||||||
QString GenClassDefinition(const Pgsql::Result &result) const;
|
|
||||||
};
|
|
||||||
|
|
@ -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(getPglabCppLanguageConfig());
|
||||||
|
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>
|
||||||
|
|
@ -140,7 +140,7 @@ int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const
|
||||||
|
|
||||||
Oid ColumnTableModel::getType(int /*column*/) const
|
Oid ColumnTableModel::getType(int /*column*/) const
|
||||||
{
|
{
|
||||||
Oid oid = Pgsql::VARCHAROID;
|
Oid oid = Pgsql::varchar_oid;
|
||||||
// switch (column) {
|
// switch (column) {
|
||||||
// case TypeCol:
|
// case TypeCol:
|
||||||
// case NameCol:
|
// case NameCol:
|
||||||
|
|
|
||||||
|
|
@ -79,12 +79,12 @@ QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, i
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConstraintModel::rowCount(const QModelIndex &parent) const
|
int ConstraintModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return m_constraints.size();
|
return m_constraints.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConstraintModel::columnCount(const QModelIndex &parent) const
|
int ConstraintModel::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return colCount;
|
return colCount;
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +99,7 @@ int ConstraintModel::columnCount(const QModelIndex &parent) const
|
||||||
// return v;
|
// return v;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
Oid ConstraintModel::getType(int column) const
|
Oid ConstraintModel::getType(int ) const
|
||||||
{
|
{
|
||||||
Oid oid = Pgsql::varchar_oid;
|
Oid oid = Pgsql::varchar_oid;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,10 @@ Oid DatabasesTableModel::getType(int column) const
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case AllowConnCol:
|
case AllowConnCol:
|
||||||
case IsTemplateCol:
|
case IsTemplateCol:
|
||||||
oid = BOOLOID;
|
oid = bool_oid;
|
||||||
break;
|
break;
|
||||||
case ConnLimitCol:
|
case ConnLimitCol:
|
||||||
oid = INT4OID;
|
oid = int4_oid;
|
||||||
break;
|
break;
|
||||||
case AclCol:
|
case AclCol:
|
||||||
case CollateCol:
|
case CollateCol:
|
||||||
|
|
@ -96,7 +96,7 @@ Oid DatabasesTableModel::getType(int column) const
|
||||||
case DbaCol:
|
case DbaCol:
|
||||||
case NameCol:
|
case NameCol:
|
||||||
case TablespaceCol:
|
case TablespaceCol:
|
||||||
oid = VARCHAROID;
|
oid = varchar_oid;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
oid = InvalidOid;
|
oid = InvalidOid;
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ void IconColumnDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize IconColumnDelegate::sizeHint(const QStyleOptionViewItem &option,
|
QSize IconColumnDelegate::sizeHint(const QStyleOptionViewItem &,
|
||||||
const QModelIndex &index) const
|
const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return QSize(16, 16);
|
return QSize(16, 16);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ Oid RolesTableModel::getType(int column) const
|
||||||
Oid oid;
|
Oid oid;
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case NameCol:
|
case NameCol:
|
||||||
oid = VARCHAROID;
|
oid = varchar_oid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReplicationCol:
|
case ReplicationCol:
|
||||||
|
|
@ -91,15 +91,15 @@ Oid RolesTableModel::getType(int column) const
|
||||||
case CreateRoleCol:
|
case CreateRoleCol:
|
||||||
case InheritCol:
|
case InheritCol:
|
||||||
case SuperCol:
|
case SuperCol:
|
||||||
oid = BOOLOID;
|
oid = bool_oid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConnlimitCol:
|
case ConnlimitCol:
|
||||||
oid = INT4OID;
|
oid = int4_oid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValidUntilCol:
|
case ValidUntilCol:
|
||||||
oid = TIMESTAMPOID;
|
oid = timestamp_oid;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
oid = InvalidOid;
|
oid = InvalidOid;
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ Oid TablesTableModel::getType(int column) const
|
||||||
case OptionsCol:
|
case OptionsCol:
|
||||||
// case AclCol:
|
// case AclCol:
|
||||||
default:
|
default:
|
||||||
oid = Pgsql::VARCHAROID;
|
oid = Pgsql::varchar_oid;
|
||||||
}
|
}
|
||||||
return oid;
|
return oid;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
pglab/UserConfiguration.cpp
Normal file
26
pglab/UserConfiguration.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
28
pglab/UserConfiguration.h
Normal file
28
pglab/UserConfiguration.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
||||||
|
|
@ -9,15 +9,18 @@ QT += core gui concurrent
|
||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets sql
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets sql
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
|
||||||
|
|
||||||
TARGET = pglab
|
TARGET = pglab
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include C:\Prog\include\pgsql C:\VSproj\boost32\include\boost-1_65_1
|
! include( ../common.pri ) {
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX _WIN32_WINNT=0x0501
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
}
|
||||||
|
|
||||||
|
INCLUDEPATH += C:\Prog\include\pgsql
|
||||||
|
DEFINES += _WIN32_WINNT=0x0501
|
||||||
#LIBS += -LC:/prog/boost/lib -Lc:/prog/lib libpq.lib fmt.lib User32.lib ws2_32.lib
|
#LIBS += -LC:/prog/boost/lib -Lc:/prog/lib libpq.lib fmt.lib User32.lib ws2_32.lib
|
||||||
LIBS += -LC:\VSproj\boost32\lib -LC:/PROG/LIB -lws2_32 -llibpq
|
#LIBS += -LC:\VSproj\boost32\lib -LC:/PROG/LIB -lws2_32 -llibpq
|
||||||
|
|
||||||
#debug {
|
#debug {
|
||||||
LIBS += c:/prog/lib/botand_imp.lib
|
LIBS += c:/prog/lib/botand_imp.lib
|
||||||
|
|
@ -54,7 +57,6 @@ SOURCES += main.cpp\
|
||||||
ConnectionList.cpp \
|
ConnectionList.cpp \
|
||||||
ProcessStdioWidget.cpp \
|
ProcessStdioWidget.cpp \
|
||||||
GlobalIoService.cpp \
|
GlobalIoService.cpp \
|
||||||
CodeBuilderConfiguration.cpp \
|
|
||||||
ResultTableModelUtil.cpp \
|
ResultTableModelUtil.cpp \
|
||||||
BaseTableModel.cpp \
|
BaseTableModel.cpp \
|
||||||
QueryParamListController.cpp \
|
QueryParamListController.cpp \
|
||||||
|
|
@ -74,7 +76,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 \
|
||||||
|
|
@ -122,7 +126,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 \
|
||||||
|
|
@ -135,7 +141,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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ TEMPLATE = subdirs
|
||||||
|
|
||||||
DEFINES += BOOST_ENABLE_ASSERT_HANDLER
|
DEFINES += BOOST_ENABLE_ASSERT_HANDLER
|
||||||
|
|
||||||
|
|
||||||
SUBDIRS += core \
|
SUBDIRS += core \
|
||||||
ctk \
|
ctk \
|
||||||
pgsql \
|
pgsql \
|
||||||
|
|
@ -15,7 +14,6 @@ pglablib.depends = core pgsql
|
||||||
tests.depends = core pgsql pglablib
|
tests.depends = core pgsql pglablib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
SUBDIRS += tests
|
SUBDIRS += tests
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
pglablib/FormatToStream.cpp
Normal file
29
pglablib/FormatToStream.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "FormatToStream.h"
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
void FormatToStream(QTextStream &stream, QString format, std::function<void(QTextStream &, QString)> field_callback)
|
||||||
|
{
|
||||||
|
// Use static to optimize only once
|
||||||
|
static QRegularExpression cached_find_var_re("(?:[^\\\\]|^)(\\/%([a-zA-Z0-9_-]+)%\\/)", QRegularExpression::OptimizeOnFirstUsageOption);
|
||||||
|
|
||||||
|
int from = 0;
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
while (format.indexOf(cached_find_var_re, from, &match) >= 0) {
|
||||||
|
if (from > 0) {
|
||||||
|
// Because the regex has to check for backslash in front we have the from position
|
||||||
|
// one position before where we actually should continue for the second match and later ie when from > 0
|
||||||
|
// Therefor increase from by 1 to make the substring (midRef) calculation work
|
||||||
|
++from;
|
||||||
|
}
|
||||||
|
// copy code before the var to the stream
|
||||||
|
stream << format.midRef(from, match.capturedStart(1) - from);
|
||||||
|
field_callback(stream, match.captured(2));
|
||||||
|
from = match.capturedEnd()-1; // -1 because it wants to match one character before or start of line to make sure there is no backslash
|
||||||
|
}
|
||||||
|
if (from > 0) {
|
||||||
|
// same reason as at the start of the loop
|
||||||
|
++from;
|
||||||
|
}
|
||||||
|
stream << format.midRef(from);
|
||||||
|
}
|
||||||
17
pglablib/FormatToStream.h
Normal file
17
pglablib/FormatToStream.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef FORMATTOSTREAM_H
|
||||||
|
#define FORMATTOSTREAM_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class QTextStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief FormatToStream replaces /%var%/ variables in a string with the values returned by the callback
|
||||||
|
* @param stream The stream to which to write the result of the formatting operation
|
||||||
|
* @param format The format string containing the vars.
|
||||||
|
* @param field_callback A callable which returns the values for var.
|
||||||
|
*/
|
||||||
|
void FormatToStream(QTextStream &stream, QString format, std::function<void(QTextStream &, QString)> field_callback);
|
||||||
|
|
||||||
|
#endif // FORMATTOSTREAM_H
|
||||||
|
|
@ -24,8 +24,8 @@ PgClass PgClassContainer::loadElem(const Pgsql::Row &row)
|
||||||
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
|
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
|
||||||
>> v.kind >> v.hasoids >> v.ispopulated >> v.frozenxid >> v.minmxid;
|
>> v.kind >> v.hasoids >> v.ispopulated >> v.frozenxid >> v.minmxid;
|
||||||
|
|
||||||
col.getAsArray<QString>(std::back_inserter(v.acl), Pgsql::NullHandling::Ignore);
|
col.getAsArray<QString>(std::back_inserter(v.acl), QString());
|
||||||
col.getAsArray<QString>(std::back_inserter(v.options), Pgsql::NullHandling::Ignore);
|
col.getAsArray<QString>(std::back_inserter(v.options), QString());
|
||||||
|
|
||||||
auto cat = m_catalogue.lock();
|
auto cat = m_catalogue.lock();
|
||||||
auto ns = cat->namespaces()->getByKey(v.relnamespace);
|
auto ns = cat->namespaces()->getByKey(v.relnamespace);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ class PgContainer: public IPgContainter {
|
||||||
public:
|
public:
|
||||||
using t_Container = std::vector<T>; ///< Do not assume it will stay a vector only expect bidirectional access
|
using t_Container = std::vector<T>; ///< Do not assume it will stay a vector only expect bidirectional access
|
||||||
|
|
||||||
|
PgContainer() = default;
|
||||||
|
|
||||||
explicit PgContainer(std::weak_ptr<PgDatabaseCatalog> cat)
|
explicit PgContainer(std::weak_ptr<PgDatabaseCatalog> cat)
|
||||||
: m_catalogue(cat)
|
: m_catalogue(cat)
|
||||||
{}
|
{}
|
||||||
|
|
@ -87,6 +89,13 @@ public:
|
||||||
|
|
||||||
std::sort(m_container.begin(), m_container.end());
|
std::sort(m_container.begin(), m_container.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Meant for mocking during testing
|
||||||
|
void add(const T &elem)
|
||||||
|
{
|
||||||
|
m_container.push_back(elem);
|
||||||
|
std::sort(m_container.begin(), m_container.end());
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
std::weak_ptr<PgDatabaseCatalog> m_catalogue;
|
std::weak_ptr<PgDatabaseCatalog> m_catalogue;
|
||||||
t_Container m_container;
|
t_Container m_container;
|
||||||
|
|
|
||||||
118
pglablib/codebuilder/CodeBuilder.cpp
Normal file
118
pglablib/codebuilder/CodeBuilder.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
#include "CodeBuilder.h"
|
||||||
|
#include "FormatToStream.h"
|
||||||
|
#include "Pgsql_Result.h"
|
||||||
|
#include "IndentationConfig.h"
|
||||||
|
#include "LanguageConfig.h"
|
||||||
|
#include "ResultLoopTemplate.h"
|
||||||
|
#include "StructureTemplate.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result, QString structname)
|
||||||
|
{
|
||||||
|
QString loop_template = m_configuration->resultLoopTemplate()->m_loopTemplate;;
|
||||||
|
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 == "queryliteral") out << query;
|
||||||
|
else if (var == "assignfields") genFieldRetrieval(out, columnData);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// [optional] Gen declaration of result structure
|
||||||
|
GenReturnStructDefinition(q, columnData, structname);
|
||||||
|
|
||||||
|
// assume we have connection? What name???
|
||||||
|
FormatToStream(q, loop_template, get_var_func);
|
||||||
|
|
||||||
|
// gen code for creating and executing statement
|
||||||
|
// - bind parameters
|
||||||
|
|
||||||
|
// Gen code for iterating through result and filling the result struct/or local variables
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const ColumnDataList &columns, QString structname) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
||||||
|
|
||||||
|
auto struct_callback = [&] (QTextStream &out, QString var) {
|
||||||
|
if (var == "structname") out << structname;
|
||||||
|
else if (var == "structfields") genStructFields(out, columns);
|
||||||
|
};
|
||||||
|
|
||||||
|
FormatToStream(q, templ->m_structTemplate, struct_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBuilder::genStructFields(QTextStream &q, const ColumnDataList &columns) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
||||||
|
QString field_format = templ->m_fieldTemplate;
|
||||||
|
const int field_indent_levels = templ->m_fieldIndentation;
|
||||||
|
QString field_indent_string = m_configuration->indentationConfig()->getIndentString(field_indent_levels);
|
||||||
|
|
||||||
|
for (auto col : columns) {
|
||||||
|
QString field_name = col.varName;
|
||||||
|
Oid type_oid = col.oid;
|
||||||
|
q << field_indent_string;
|
||||||
|
genFieldDeclaration(q, field_format, field_name, type_oid);
|
||||||
|
q << "\n";
|
||||||
|
// Unfortunatly there is no easy reliable way to determine if a column can contain null values
|
||||||
|
// For simple result columns we can have a look at the original column and if that has a NOT NULL constraint
|
||||||
|
// then we can assume NOT NULL for the result if there are no LEFT/RIGHT JOINS or other constructs that can introduce NULL
|
||||||
|
// values
|
||||||
|
|
||||||
|
// Any way at generation time we might want to be able to specify the null handle
|
||||||
|
// - exception/error return
|
||||||
|
// - magic value
|
||||||
|
// - boost::optional
|
||||||
|
// - boolean flags
|
||||||
|
// - null pointer (useful for languages where this has no cost, other cases boolean flags will be more performant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CodeBuilder::columnNameToVariableName(QString column_name) const
|
||||||
|
{
|
||||||
|
return m_configuration->columnNameToFieldName(column_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CodeBuilder::getTypeName(Oid dbtype) const
|
||||||
|
{
|
||||||
|
return m_configuration->getTypeName(dbtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBuilder::genFieldRetrieval(QTextStream &q, const ColumnDataList &columns) const
|
||||||
|
{
|
||||||
|
QString assign_result_field_template = m_configuration->resultLoopTemplate()->m_retrieveValueTemplate;
|
||||||
|
for (auto col : columns) {
|
||||||
|
FormatToStream(q, assign_result_field_template, [&col] (QTextStream &out, QString var) {
|
||||||
|
if (var == "varname") out << col.varName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBuilder::genFieldDeclaration(QTextStream &q, const QString &format, const QString &field_name, Oid column_type) const
|
||||||
|
{
|
||||||
|
QString type_name = getTypeName(column_type);
|
||||||
|
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) const
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
47
pglablib/codebuilder/CodeBuilder.h
Normal file
47
pglablib/codebuilder/CodeBuilder.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef CODEBUILDER_H
|
||||||
|
#define CODEBUILDER_H
|
||||||
|
|
||||||
|
#include "Pgsql_declare.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class LanguageConfig;
|
||||||
|
class QTextStream;
|
||||||
|
|
||||||
|
class CodeBuilder {
|
||||||
|
public:
|
||||||
|
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>;
|
||||||
|
|
||||||
|
ColumnDataList createColumnDataList(const Pgsql::Result &result) const;
|
||||||
|
|
||||||
|
void setLanguageConfig(std::shared_ptr<const LanguageConfig> config){
|
||||||
|
m_configuration = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result, QString structname);
|
||||||
|
void GenReturnStructDefinition(QTextStream &q, const ColumnDataList &columns, QString structname) const;
|
||||||
|
|
||||||
|
// Generating code for performing query and going through the result
|
||||||
|
// - Code for executing the query
|
||||||
|
// - Code for looping the result
|
||||||
|
// - Code for processing a single row
|
||||||
|
// - Declaration of struct for holding single row result
|
||||||
|
QString columnNameToVariableName(QString column_name) const;
|
||||||
|
QString getTypeName(Oid dbtype) const;
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<const LanguageConfig> m_configuration;
|
||||||
|
|
||||||
|
void genStructFields(QTextStream &q, const ColumnDataList &columns) const;
|
||||||
|
void genFieldRetrieval(QTextStream &q, const ColumnDataList &columns) const;
|
||||||
|
void genFieldDeclaration(QTextStream &q, const QString &format, const QString &field_name, Oid column_type) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CODEBUILDER_H
|
||||||
86
pglablib/codebuilder/DefaultConfigs.cpp
Normal file
86
pglablib/codebuilder/DefaultConfigs.cpp
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include "DefaultConfigs.h"
|
||||||
|
#include "IndentationConfig.h"
|
||||||
|
#include "LanguageConfig.h"
|
||||||
|
#include "NameManglingRules.h"
|
||||||
|
#include "ResultLoopTemplate.h"
|
||||||
|
#include "StructureTemplate.h"
|
||||||
|
#include "TypeMappings.h"
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
using namespace Pgsql;
|
||||||
|
|
||||||
|
std::shared_ptr<const TypeMappings> GetPglabCppTypeMappings()
|
||||||
|
{
|
||||||
|
auto tm = std::make_shared<TypeMappings>();
|
||||||
|
*tm = {
|
||||||
|
{ bool_oid, "bool" },
|
||||||
|
{ char_oid, "char" },
|
||||||
|
{ name_oid, "std::string" },
|
||||||
|
{ int8_oid, "int64_t" },
|
||||||
|
{ int2_oid, "int16_t" },
|
||||||
|
{ int4_oid, "int32_t" },
|
||||||
|
{ text_oid, "std::string" },
|
||||||
|
{ oid_oid, "Oid" },
|
||||||
|
{ float4_oid, "float" },
|
||||||
|
{ float8_oid, "double" }
|
||||||
|
};
|
||||||
|
tm->setDefaultStringType("std::string");
|
||||||
|
tm->setDefaultContainerType("std::vector<%1>");
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<StructureTemplate> buildPglabStructureTemplate()
|
||||||
|
{
|
||||||
|
auto t = std::make_shared<StructureTemplate>();
|
||||||
|
t->m_structTemplate =
|
||||||
|
R"__(class /%structname%/ {
|
||||||
|
public:
|
||||||
|
/%structfields%/
|
||||||
|
};
|
||||||
|
using /%structname%/Lst = std::vector</%structname%/>;
|
||||||
|
)__";
|
||||||
|
|
||||||
|
t->m_fieldTemplate = "/%typename%/ /%varname%/;";
|
||||||
|
//st_templ->m_fieldSeparator;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ResultLoopTemplate> buildPglabResultLoopTemplate()
|
||||||
|
{
|
||||||
|
auto t = std::make_shared<ResultLoopTemplate>();
|
||||||
|
t->m_loopTemplate =
|
||||||
|
R"__(Pgsql::Result result = conn.query(/%queryliteral%/);
|
||||||
|
/%structname%/Lst lst;
|
||||||
|
for (auto row: result) {
|
||||||
|
Pgsql::Col col(row);
|
||||||
|
/%structname%/ v;
|
||||||
|
col
|
||||||
|
/%assignfields%/;
|
||||||
|
lst.push_back(v);
|
||||||
|
}
|
||||||
|
)__";
|
||||||
|
t->m_retrieveValueTemplate = " >> v./%varname%/";
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LanguageConfig> buildPglabCppLanguageConfig()
|
||||||
|
{
|
||||||
|
auto config = std::make_shared<LanguageConfig>();
|
||||||
|
config->setTypeMappings(GetPglabCppTypeMappings());
|
||||||
|
config->setNameManglingRules(std::make_shared<NameManglingRules>());
|
||||||
|
config->setStructureTemplate(buildPglabStructureTemplate());
|
||||||
|
config->setIndentationConfig(std::make_shared<IndentationConfig>());
|
||||||
|
config->setResultLoopTemplate(buildPglabResultLoopTemplate());
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<const LanguageConfig> getPglabCppLanguageConfig()
|
||||||
|
{
|
||||||
|
static auto config = buildPglabCppLanguageConfig();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
11
pglablib/codebuilder/DefaultConfigs.h
Normal file
11
pglablib/codebuilder/DefaultConfigs.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef DEFAULTCONFIGS_H
|
||||||
|
#define DEFAULTCONFIGS_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class LanguageConfig;
|
||||||
|
|
||||||
|
//std::shared_ptr<const LanguageConfig> getDefaultCppLanguageConfig();
|
||||||
|
std::shared_ptr<const LanguageConfig> getPglabCppLanguageConfig();
|
||||||
|
|
||||||
|
#endif // DEFAULTCONFIGS_H
|
||||||
27
pglablib/codebuilder/IndentationConfig.cpp
Normal file
27
pglablib/codebuilder/IndentationConfig.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "IndentationConfig.h"
|
||||||
|
|
||||||
|
IndentationConfig::IndentationConfig() = default;
|
||||||
|
|
||||||
|
IndentationConfig::IndentationConfig(int tab_size, int indentation_size, bool use_tabs)
|
||||||
|
: m_tabSize(tab_size)
|
||||||
|
, m_indentationSize(indentation_size)
|
||||||
|
, m_useTabs(use_tabs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** Returns a string with the right amount of tabs and spaces for the
|
||||||
|
* requested indentation level.
|
||||||
|
*/
|
||||||
|
QString IndentationConfig::getIndentString(int level) const
|
||||||
|
{
|
||||||
|
int spaces = level * m_indentationSize;
|
||||||
|
int tabs = 0;
|
||||||
|
if (m_useTabs) {
|
||||||
|
tabs = spaces / m_tabSize;
|
||||||
|
spaces -= tabs * m_tabSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tabs > 0)
|
||||||
|
return QString(tabs, '\t') + QString(spaces, ' ');
|
||||||
|
else
|
||||||
|
return QString(spaces, ' ');
|
||||||
|
}
|
||||||
23
pglablib/codebuilder/IndentationConfig.h
Normal file
23
pglablib/codebuilder/IndentationConfig.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef INDENTATIONCONFIG_H
|
||||||
|
#define INDENTATIONCONFIG_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class IndentationConfig {
|
||||||
|
public:
|
||||||
|
IndentationConfig();
|
||||||
|
IndentationConfig(int tab_size, int indentation_size, bool use_tabs);
|
||||||
|
|
||||||
|
/** Returns a string with the right amount of tabs and spaces for the
|
||||||
|
* requested indentation level.
|
||||||
|
*/
|
||||||
|
QString getIndentString(int level) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_tabSize = 8; ///< the size of a tab
|
||||||
|
int m_indentationSize = 4; ///< Number of positions per level to indent
|
||||||
|
bool m_useTabs = true; ///< Use tabs as much as possible instead of spaces when indenting
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // INDENTATIONCONFIG_H
|
||||||
60
pglablib/codebuilder/LanguageConfig.cpp
Normal file
60
pglablib/codebuilder/LanguageConfig.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include "LanguageConfig.h"
|
||||||
|
#include "NameManglingRules.h"
|
||||||
|
#include "TypeMappings.h"
|
||||||
|
|
||||||
|
LanguageConfig::LanguageConfig() = default;
|
||||||
|
|
||||||
|
QString LanguageConfig::columnNameToFieldName(const QString& column_name) const
|
||||||
|
{
|
||||||
|
return m_varNaming->transform(column_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LanguageConfig::getTypeName(Oid dbtype) const
|
||||||
|
{
|
||||||
|
return m_typeMappings->getTypeForOid(dbtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageConfig::setNameManglingRules(std::shared_ptr<const NameManglingRules> name_mangling_rules)
|
||||||
|
{
|
||||||
|
m_varNaming = name_mangling_rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const TypeMappings> LanguageConfig::typeMappings() const
|
||||||
|
{
|
||||||
|
return m_typeMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageConfig::setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings)
|
||||||
|
{
|
||||||
|
m_typeMappings = type_mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const StructureTemplate> LanguageConfig::structureTemplate() const
|
||||||
|
{
|
||||||
|
return m_structureTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageConfig::setStructureTemplate(std::shared_ptr<const StructureTemplate> structure_template)
|
||||||
|
{
|
||||||
|
m_structureTemplate = structure_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const IndentationConfig> LanguageConfig::indentationConfig() const
|
||||||
|
{
|
||||||
|
return m_indentationConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageConfig::setIndentationConfig(std::shared_ptr<const IndentationConfig> indentation_config)
|
||||||
|
{
|
||||||
|
m_indentationConfig = indentation_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const ResultLoopTemplate> LanguageConfig::resultLoopTemplate() const
|
||||||
|
{
|
||||||
|
return m_resultLoopTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageConfig::setResultLoopTemplate(std::shared_ptr<const ResultLoopTemplate> result_loop_template)
|
||||||
|
{
|
||||||
|
m_resultLoopTemplate = result_loop_template;
|
||||||
|
}
|
||||||
48
pglablib/codebuilder/LanguageConfig.h
Normal file
48
pglablib/codebuilder/LanguageConfig.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef LANGUAGECONFIG_H
|
||||||
|
#define LANGUAGECONFIG_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
class NameManglingRules;
|
||||||
|
class TypeMappings;
|
||||||
|
class StructureTemplate;
|
||||||
|
class IndentationConfig;
|
||||||
|
class ResultLoopTemplate;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class LanguageConfig {
|
||||||
|
public:
|
||||||
|
LanguageConfig();
|
||||||
|
|
||||||
|
QString columnNameToFieldName(const QString& column_name) const;
|
||||||
|
QString getTypeName(Oid dbtype) const;
|
||||||
|
|
||||||
|
void setNameManglingRules(std::shared_ptr<const NameManglingRules> name_mangling_rules);
|
||||||
|
std::shared_ptr<const TypeMappings> typeMappings() const;
|
||||||
|
void setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings);
|
||||||
|
std::shared_ptr<const StructureTemplate> structureTemplate() const;
|
||||||
|
void setStructureTemplate(std::shared_ptr<const StructureTemplate> structure_template);
|
||||||
|
std::shared_ptr<const IndentationConfig> indentationConfig() const;
|
||||||
|
void setIndentationConfig(std::shared_ptr<const IndentationConfig> indentation_config);
|
||||||
|
std::shared_ptr<const ResultLoopTemplate> resultLoopTemplate() const;
|
||||||
|
void setResultLoopTemplate(std::shared_ptr<const ResultLoopTemplate> result_loop_template);
|
||||||
|
private:
|
||||||
|
/** Default template for declaring a variable of the correct type.
|
||||||
|
* exmaple: "{$type} {$varname};"
|
||||||
|
*/
|
||||||
|
//QString varDeclTemplate;
|
||||||
|
std::shared_ptr<const NameManglingRules> m_varNaming;
|
||||||
|
std::shared_ptr<const TypeMappings> m_typeMappings;
|
||||||
|
std::shared_ptr<const StructureTemplate> m_structureTemplate;
|
||||||
|
std::shared_ptr<const IndentationConfig> m_indentationConfig;
|
||||||
|
std::shared_ptr<const ResultLoopTemplate> m_resultLoopTemplate;
|
||||||
|
|
||||||
|
enum class VariableStrategy {
|
||||||
|
UseLocalVariables,
|
||||||
|
DeclareClass
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LANGUAGECONFIG_H
|
||||||
32
pglablib/codebuilder/NameManglingRules.cpp
Normal file
32
pglablib/codebuilder/NameManglingRules.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "NameManglingRules.h"
|
||||||
|
|
||||||
|
void NameManglingRules::apply(const ReplaceRule &rule, QString &in) const
|
||||||
|
{
|
||||||
|
int from = 0;
|
||||||
|
int pos;
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
while ((pos = in.indexOf(rule.pattern, from, &match)) >= 0) {
|
||||||
|
int len = match.capturedLength();
|
||||||
|
in.replace(pos, len, rule.replace);
|
||||||
|
from = pos + rule.replace.size();
|
||||||
|
if (rule.nextToUpper)
|
||||||
|
in[from] = in[from].toUpper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NameManglingRules::transform(const QString &input) const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
if (caseConversion == CaseConversion::Lower)
|
||||||
|
result = input.toLower();
|
||||||
|
else if (caseConversion == CaseConversion::Upper)
|
||||||
|
result = input.toUpper();
|
||||||
|
else
|
||||||
|
result = input;
|
||||||
|
|
||||||
|
for (auto rule : replaceRules) {
|
||||||
|
apply(rule, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
49
pglablib/codebuilder/NameManglingRules.h
Normal file
49
pglablib/codebuilder/NameManglingRules.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef NAMEMANGLINGRULES_H
|
||||||
|
#define NAMEMANGLINGRULES_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** Defines how a database result fieldname should be converted into a variable
|
||||||
|
* name in the target language.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class NameManglingRules {
|
||||||
|
public:
|
||||||
|
enum class CollisionHandling {
|
||||||
|
Restrict, ///< An error will be reported and no code generated
|
||||||
|
Fqn, ///< Turn into fully qualified name (table_column)
|
||||||
|
Number ///< A number will be appended to fields that have the same name
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CaseConversion {
|
||||||
|
AsIs,
|
||||||
|
Upper,
|
||||||
|
Lower
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReplaceRule {
|
||||||
|
public:
|
||||||
|
QRegularExpression pattern;
|
||||||
|
QString replace;
|
||||||
|
bool nextToUpper = false;
|
||||||
|
};
|
||||||
|
using ReplaceRules = std::vector<ReplaceRule>;
|
||||||
|
|
||||||
|
ReplaceRules replaceRules;
|
||||||
|
// { {"[ -_]", QRegularExpression::OptimizeOnFirstUsageOption }, "", true }
|
||||||
|
|
||||||
|
//CollisionHandling CollisionHandling = CollisionHandling::Restrict;
|
||||||
|
CaseConversion caseConversion = CaseConversion::AsIs; ///< overall case conversion rule
|
||||||
|
//CaseConversion caseFirstChar = CaseConversion::AsIs; ///< case of the first char
|
||||||
|
// bool camelCase = false; ///< removes underscores and make first char after underscore uppercase
|
||||||
|
|
||||||
|
void apply(const ReplaceRule &rule, QString &in) const;
|
||||||
|
|
||||||
|
QString transform(const QString &input) const;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAMEMANGLINGRULES_H
|
||||||
26
pglablib/codebuilder/ResultLoopTemplate.h
Normal file
26
pglablib/codebuilder/ResultLoopTemplate.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef RESULTLOOPTEMPLATE_H
|
||||||
|
#define RESULTLOOPTEMPLATE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class ResultLoopTemplate {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief m_loopTemplate
|
||||||
|
*
|
||||||
|
* Excepted template fields
|
||||||
|
* - structname: The typename of the struct/class
|
||||||
|
* - queryliteral: The query
|
||||||
|
* - assignfields: Replaced with the field assignment
|
||||||
|
*/
|
||||||
|
QString m_loopTemplate;
|
||||||
|
/**
|
||||||
|
* @brief m_retrieveValueTemplate
|
||||||
|
*
|
||||||
|
* Excepted template fields
|
||||||
|
* - varname: the name of the field of the struct or normal variable
|
||||||
|
*/
|
||||||
|
QString m_retrieveValueTemplate;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RESULTLOOPTEMPLATE_H
|
||||||
2
pglablib/codebuilder/StructureTemplate.cpp
Normal file
2
pglablib/codebuilder/StructureTemplate.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "StructureTemplate.h"
|
||||||
|
|
||||||
17
pglablib/codebuilder/StructureTemplate.h
Normal file
17
pglablib/codebuilder/StructureTemplate.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef STRUCTURETEMPLATE_H
|
||||||
|
#define STRUCTURETEMPLATE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class StructureTemplate {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// QString m_startTemplate; // class /$structname/ {\npublic:\n
|
||||||
|
// QString m_endTemplate; // };
|
||||||
|
QString m_structTemplate;
|
||||||
|
QString m_fieldTemplate; // /$typename/ /$varname/;
|
||||||
|
QString m_fieldSeparator; // use when you need something between fields but not after the last field
|
||||||
|
int m_fieldIndentation = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STRUCTURETEMPLATE_H
|
||||||
133
pglablib/codebuilder/TypeMappings.cpp
Normal file
133
pglablib/codebuilder/TypeMappings.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include "TypeMappings.h"
|
||||||
|
#include "PgTypeContainer.h"
|
||||||
|
|
||||||
|
//namespace {
|
||||||
|
// using Fallbacks = std::unordered_map<Oid, Oid>;
|
||||||
|
|
||||||
|
// Fallbacks fallbacks = {
|
||||||
|
// { oid_text, oid_varchar },
|
||||||
|
// { }
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
|
TypeMappings::TypeMappings() = default;
|
||||||
|
|
||||||
|
TypeMappings::TypeMappings(std::initializer_list<Mapping> mappings)
|
||||||
|
{
|
||||||
|
m_typeMap.insert(mappings.begin(), mappings.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TypeMappings::getTypeForOid(Oid oid) const
|
||||||
|
{
|
||||||
|
// TODO use the catalog to determine if someting is an array or vector type.
|
||||||
|
// If it is lookup its element type and use the std container
|
||||||
|
auto res = m_typeMap.find(oid);
|
||||||
|
if (res != m_typeMap.end()) {
|
||||||
|
return res->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_types) {
|
||||||
|
PgType type = m_types->getByKey(oid);
|
||||||
|
if (type.oid != InvalidOid && type.elem != InvalidOid) {
|
||||||
|
res = m_typeMap.find(type.elem);
|
||||||
|
QString type_string;
|
||||||
|
if (res == m_typeMap.end()) {
|
||||||
|
type_string = m_defaultStringType;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
type_string = res->second;
|
||||||
|
}
|
||||||
|
return QString(m_defaultContainerType).arg(type_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_defaultStringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeMappings::setTypes(std::shared_ptr<const PgTypeContainer> types)
|
||||||
|
{
|
||||||
|
m_types = types;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeMappings::setDefaultStringType(QString str)
|
||||||
|
{
|
||||||
|
m_defaultStringType = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeMappings::setDefaultContainerType(QString str)
|
||||||
|
{
|
||||||
|
m_defaultContainerType = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeMappings::set(Oid oid, QString type)
|
||||||
|
{
|
||||||
|
m_typeMap.insert_or_assign(oid, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//constexpr Oid bool_oid = 16;
|
||||||
|
//constexpr Oid bytea_oid = 17;
|
||||||
|
//constexpr Oid char_oid = 18;
|
||||||
|
//constexpr Oid name_oid = 19;
|
||||||
|
//constexpr Oid int8_oid = 20;
|
||||||
|
//constexpr Oid int2_oid = 21;
|
||||||
|
//constexpr Oid int4_oid = 23;
|
||||||
|
//constexpr Oid regproc_oid = 24;
|
||||||
|
//constexpr Oid text_oid = 25;
|
||||||
|
//constexpr Oid oid_oid = 26;
|
||||||
|
//constexpr Oid tid_oid = 27;
|
||||||
|
//constexpr Oid xid_oid = 28;
|
||||||
|
//constexpr Oid cid_oid = 29;
|
||||||
|
//constexpr Oid json_oid = 114;
|
||||||
|
//constexpr Oid xml_oid = 142;
|
||||||
|
//constexpr Oid point_oid = 600;
|
||||||
|
//constexpr Oid lseg_oid = 601;
|
||||||
|
//constexpr Oid path_oid = 602;
|
||||||
|
//constexpr Oid box_oid = 603;
|
||||||
|
//constexpr Oid polygon_oid = 604;
|
||||||
|
//constexpr Oid line_oid = 628;
|
||||||
|
//constexpr Oid cidr_oid = 650;
|
||||||
|
//constexpr Oid float4_oid = 700;
|
||||||
|
//constexpr Oid float8_oid = 701;
|
||||||
|
//constexpr Oid abstime_oid = 702;
|
||||||
|
//constexpr Oid reltime_oid = 703;
|
||||||
|
//constexpr Oid tinterval_oid = 704;
|
||||||
|
//constexpr Oid circle_oid = 718;
|
||||||
|
//constexpr Oid money_oid = 790;
|
||||||
|
//constexpr Oid macaddr_oid = 829;
|
||||||
|
//constexpr Oid inet_oid = 869;
|
||||||
|
//constexpr Oid aclitem_oid = 1033;
|
||||||
|
//constexpr Oid bpchar_oid = 1042;
|
||||||
|
//constexpr Oid varchar_oid = 1043;
|
||||||
|
//constexpr Oid date_oid = 1082;
|
||||||
|
//constexpr Oid time_oid = 1083;
|
||||||
|
//constexpr Oid timestamp_oid = 1114;
|
||||||
|
//constexpr Oid timestamptz_oid = 1184;
|
||||||
|
//constexpr Oid interval_oid = 1186;
|
||||||
|
//constexpr Oid timetz_oid = 1266;
|
||||||
|
//constexpr Oid bit_oid = 1560;
|
||||||
|
//constexpr Oid varbit_oid = 1562;
|
||||||
|
//constexpr Oid numeric_oid = 1700;
|
||||||
|
//constexpr Oid refcursor_oid = 1790;
|
||||||
|
//constexpr Oid regprocedure_oid = 2202;
|
||||||
|
//constexpr Oid regoper_oid = 2203;
|
||||||
|
//constexpr Oid regoperator_oid = 2204;
|
||||||
|
//constexpr Oid regclass_oid = 2205;
|
||||||
|
//constexpr Oid regtype_oid = 2206;
|
||||||
|
//constexpr Oid uuid_oid = 2950;
|
||||||
|
//constexpr Oid txid_snapshot_oid = 2970;
|
||||||
|
//constexpr Oid pg_lsn_oid = 3220;
|
||||||
|
//constexpr Oid tsvector_oid = 3614;
|
||||||
|
//constexpr Oid tsquery_oid = 3615;
|
||||||
|
//constexpr Oid gtsvector_oid = 3642;
|
||||||
|
//constexpr Oid regconfig_oid = 3734;
|
||||||
|
//constexpr Oid regdictionary_oid = 3769;
|
||||||
|
//constexpr Oid jsonb_oid = 3802;
|
||||||
|
//constexpr Oid int4range_oid = 3904;
|
||||||
|
//constexpr Oid numrange_oid = 3906;
|
||||||
|
//constexpr Oid tsrange_oid = 3908;
|
||||||
|
//constexpr Oid tstzrange_oid = 3910;
|
||||||
|
//constexpr Oid daterange_oid = 3912;
|
||||||
|
//constexpr Oid int8range_oid = 3926;
|
||||||
|
//constexpr Oid regnamespace_oid = 4089;
|
||||||
|
//constexpr Oid regrole_oid = 4096;
|
||||||
46
pglablib/codebuilder/TypeMappings.h
Normal file
46
pglablib/codebuilder/TypeMappings.h
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef TYPEMAPPINGS_H
|
||||||
|
#define TYPEMAPPINGS_H
|
||||||
|
|
||||||
|
#include <Pgsql_declare.h>
|
||||||
|
#include <QString>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class PgTypeContainer;
|
||||||
|
|
||||||
|
class TypeMappings {
|
||||||
|
public:
|
||||||
|
using TypeMap = std::unordered_map<Oid, QString>;
|
||||||
|
using Mapping = std::pair<Oid, QString>;
|
||||||
|
|
||||||
|
TypeMappings();
|
||||||
|
|
||||||
|
TypeMappings(std::initializer_list<Mapping> mappings);
|
||||||
|
|
||||||
|
QString getTypeForOid(Oid oid) const;
|
||||||
|
|
||||||
|
const TypeMap& typeMap() const { return m_typeMap; }
|
||||||
|
|
||||||
|
QString defaultStringType() const { return m_defaultStringType; }
|
||||||
|
|
||||||
|
void setTypes(std::shared_ptr<const PgTypeContainer> types);
|
||||||
|
|
||||||
|
void setDefaultStringType(QString str);
|
||||||
|
|
||||||
|
void setDefaultContainerType(QString str);
|
||||||
|
|
||||||
|
void set(Oid oid, QString type);
|
||||||
|
/** Removing a type from the mapping will reeastablish its default mapping
|
||||||
|
* which in most cases is the default string type for the language.
|
||||||
|
*/
|
||||||
|
void remove(Oid oid);
|
||||||
|
private:
|
||||||
|
|
||||||
|
TypeMap m_typeMap;
|
||||||
|
QString m_defaultStringType;
|
||||||
|
QString m_defaultContainerType; ///< This string should contain a format variable where the element type should go
|
||||||
|
|
||||||
|
std::shared_ptr<const PgTypeContainer> m_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TYPEMAPPINGS_H
|
||||||
|
|
@ -10,15 +10,11 @@ TARGET = pglablib
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += staticlib
|
CONFIG += staticlib
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
! include( ../common.pri ) {
|
||||||
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
}
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
INCLUDEPATH += C:\Prog\include\pgsql
|
||||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
|
||||||
# depend on your compiler). Please consult the documentation of the
|
|
||||||
# deprecated API in order to know how to port your code away from it.
|
|
||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include C:\Prog\include\pgsql C:\VSproj\boost32\include\boost-1_65_1
|
|
||||||
|
|
||||||
# You can also make your code fail to compile if you use deprecated APIs.
|
# You can also make your code fail to compile if you use deprecated APIs.
|
||||||
# In order to do so, uncomment the following line.
|
# In order to do so, uncomment the following line.
|
||||||
|
|
@ -57,7 +53,15 @@ SOURCES += \
|
||||||
PgAmContainer.cpp \
|
PgAmContainer.cpp \
|
||||||
PgObject.cpp \
|
PgObject.cpp \
|
||||||
PgTablespace.cpp \
|
PgTablespace.cpp \
|
||||||
PgTablespaceContainer.cpp
|
PgTablespaceContainer.cpp \
|
||||||
|
codebuilder/LanguageConfig.cpp \
|
||||||
|
codebuilder/CodeBuilder.cpp \
|
||||||
|
codebuilder/NameManglingRules.cpp \
|
||||||
|
codebuilder/DefaultConfigs.cpp \
|
||||||
|
codebuilder/TypeMappings.cpp \
|
||||||
|
codebuilder/IndentationConfig.cpp \
|
||||||
|
codebuilder/StructureTemplate.cpp \
|
||||||
|
FormatToStream.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Pglablib.h \
|
Pglablib.h \
|
||||||
|
|
@ -92,7 +96,16 @@ HEADERS += \
|
||||||
PgAmContainer.h \
|
PgAmContainer.h \
|
||||||
PgObject.h \
|
PgObject.h \
|
||||||
PgTablespace.h \
|
PgTablespace.h \
|
||||||
PgTablespaceContainer.h
|
PgTablespaceContainer.h \
|
||||||
|
codebuilder/LanguageConfig.h \
|
||||||
|
codebuilder/CodeBuilder.h \
|
||||||
|
codebuilder/NameManglingRules.h \
|
||||||
|
codebuilder/DefaultConfigs.h \
|
||||||
|
codebuilder/TypeMappings.h \
|
||||||
|
codebuilder/IndentationConfig.h \
|
||||||
|
codebuilder/StructureTemplate.h \
|
||||||
|
FormatToStream.h \
|
||||||
|
codebuilder/ResultLoopTemplate.h
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
target.path = /usr/lib
|
target.path = /usr/lib
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,14 @@ namespace Pgsql {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename I>
|
template <typename E, typename I>
|
||||||
void getAsArray(I insert_iter, const E &value_for_nulls) const
|
Col& getAsArray(I insert_iter, const E &value_for_nulls)
|
||||||
{
|
{
|
||||||
nextValue().getAsArray<E, I>(insert_iter, value_for_nulls);
|
nextValue().getAsArray<E, I>(insert_iter, value_for_nulls);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename I>
|
template <typename E, typename I>
|
||||||
void getAsArrayOfOptional(I insert_iter) const
|
Col& getAsArrayOfOptional(I insert_iter)
|
||||||
{
|
{
|
||||||
nextValue().getAsArrayOfOptional<E, I>(insert_iter);
|
nextValue().getAsArrayOfOptional<E, I>(insert_iter);
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -50,6 +50,12 @@ namespace Pgsql {
|
||||||
int col = -1;
|
int col = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Col& operator>>(Col &c, std::vector<T> &s)
|
||||||
|
{
|
||||||
|
return c.getAsArray<T>(std::back_inserter(s));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Col& operator>>(Col &c, T &s)
|
Col& operator>>(Col &c, T &s)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Pgsql {
|
||||||
*
|
*
|
||||||
* The class takes ownership of data and will try to delete[] it.
|
* The class takes ownership of data and will try to delete[] it.
|
||||||
*/
|
*/
|
||||||
Param addText(const char *data, Oid oid=VARCHAROID);
|
Param addText(const char *data, Oid oid=varchar_oid);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Pgsql
|
} // end namespace Pgsql
|
||||||
|
|
|
||||||
|
|
@ -103,9 +103,9 @@ Value::operator double() const
|
||||||
|
|
||||||
bool Value::isString() const
|
bool Value::isString() const
|
||||||
{
|
{
|
||||||
return m_typ == CHAROID
|
return m_typ == char_oid
|
||||||
|| m_typ == VARCHAROID
|
|| m_typ == varchar_oid
|
||||||
|| m_typ == TEXTOID
|
|| m_typ == text_oid
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
||||||
|
|
@ -47,7 +48,7 @@ namespace Pgsql {
|
||||||
{
|
{
|
||||||
if (m_val == nullptr) {
|
if (m_val == nullptr) {
|
||||||
if (nullhandling == NullHandling::Throw)
|
if (nullhandling == NullHandling::Throw)
|
||||||
throw std::runtime_error("Unexpected NULL value in array");
|
throw std::runtime_error("Unexpected NULL value for array");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
|
|
@ -76,6 +77,8 @@ namespace Pgsql {
|
||||||
template <typename E, typename I>
|
template <typename E, typename I>
|
||||||
void getAsArray(I insert_iter, const E &value_for_nulls) const
|
void getAsArray(I insert_iter, const E &value_for_nulls) const
|
||||||
{
|
{
|
||||||
|
if (m_val == nullptr) return;
|
||||||
|
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
ArrayParser parser(m_val);
|
ArrayParser parser(m_val);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
@ -149,10 +152,24 @@ namespace Pgsql {
|
||||||
Oid m_typ;
|
Oid m_typ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void operator<<(boost::optional<T> &s, const Value &v)
|
||||||
|
{
|
||||||
|
if (v.null())
|
||||||
|
s = boost::optional<T>();
|
||||||
|
else
|
||||||
|
*s << v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void operator<<(std::vector<T> &s, const Value &v)
|
||||||
|
{
|
||||||
|
v.getAsArray(std::back_inserter(s));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator<<(T &s, const Value &v)
|
void operator<<(T &s, const Value &v)
|
||||||
{
|
{
|
||||||
//s = static_cast<T>(v);
|
|
||||||
s = v.operator T();
|
s = v.operator T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,95 +5,95 @@
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
||||||
const Oid BOOLOID = 16;
|
// const Oid BOOLOID = 16;
|
||||||
const Oid BYTEAOID = 17;
|
// const Oid BYTEAOID = 17;
|
||||||
const Oid CHAROID = 18;
|
// const Oid CHAROID = 18;
|
||||||
const Oid NAMEOID = 19;
|
// const Oid NAMEOID = 19;
|
||||||
const Oid INT8OID = 20;
|
// const Oid INT8OID = 20;
|
||||||
const Oid INT2OID = 21;
|
// const Oid INT2OID = 21;
|
||||||
const Oid INT2VECTOROID = 22;
|
// const Oid INT2VECTOROID = 22;
|
||||||
const Oid INT4OID = 23;
|
// const Oid INT4OID = 23;
|
||||||
const Oid REGPROCOID = 24;
|
// const Oid REGPROCOID = 24;
|
||||||
const Oid TEXTOID = 25;
|
// const Oid TEXTOID = 25;
|
||||||
const Oid OIDOID = 26;
|
// const Oid OIDOID = 26;
|
||||||
const Oid TIDOID = 27;
|
// const Oid TIDOID = 27;
|
||||||
const Oid XIDOID = 28;
|
// const Oid XIDOID = 28;
|
||||||
const Oid CIDOID = 29;
|
// const Oid CIDOID = 29;
|
||||||
const Oid OIDVECTOROID = 30;
|
// const Oid OIDVECTOROID = 30;
|
||||||
const Oid JSONOID = 114;
|
// const Oid JSONOID = 114;
|
||||||
const Oid XMLOID = 142;
|
// const Oid XMLOID = 142;
|
||||||
const Oid PGNODETREEOID = 194;
|
// const Oid PGNODETREEOID = 194;
|
||||||
const Oid PGDDLCOMMANDOID = 32;
|
// const Oid PGDDLCOMMANDOID = 32;
|
||||||
const Oid POINTOID = 600;
|
// const Oid POINTOID = 600;
|
||||||
const Oid LSEGOID = 601;
|
// const Oid LSEGOID = 601;
|
||||||
const Oid PATHOID = 602;
|
// const Oid PATHOID = 602;
|
||||||
const Oid BOXOID = 603;
|
// const Oid BOXOID = 603;
|
||||||
const Oid POLYGONOID = 604;
|
// const Oid POLYGONOID = 604;
|
||||||
const Oid LINEOID = 628;
|
// const Oid LINEOID = 628;
|
||||||
const Oid FLOAT4OID = 700;
|
// const Oid FLOAT4OID = 700;
|
||||||
const Oid FLOAT8OID = 701;
|
// const Oid FLOAT8OID = 701;
|
||||||
const Oid ABSTIMEOID = 702;
|
// const Oid ABSTIMEOID = 702;
|
||||||
const Oid RELTIMEOID = 703;
|
// const Oid RELTIMEOID = 703;
|
||||||
const Oid TINTERVALOID = 704;
|
// const Oid TINTERVALOID = 704;
|
||||||
const Oid UNKNOWNOID = 705;
|
// const Oid UNKNOWNOID = 705;
|
||||||
const Oid CIRCLEOID = 718;
|
// const Oid CIRCLEOID = 718;
|
||||||
const Oid CASHOID = 790;
|
// const Oid CASHOID = 790;
|
||||||
const Oid MACADDROID = 829;
|
// const Oid MACADDROID = 829;
|
||||||
const Oid INETOID = 869;
|
// const Oid INETOID = 869;
|
||||||
const Oid CIDROID = 650;
|
// const Oid CIDROID = 650;
|
||||||
const Oid INT2ARRAYOID = 1005;
|
// const Oid INT2ARRAYOID = 1005;
|
||||||
const Oid INT4ARRAYOID = 1007;
|
// const Oid INT4ARRAYOID = 1007;
|
||||||
const Oid TEXTARRAYOID = 1009;
|
// const Oid TEXTARRAYOID = 1009;
|
||||||
const Oid OIDARRAYOID = 1028;
|
// const Oid OIDARRAYOID = 1028;
|
||||||
const Oid FLOAT4ARRAYOID = 1021;
|
// const Oid FLOAT4ARRAYOID = 1021;
|
||||||
const Oid ACLITEMOID = 1033;
|
// const Oid ACLITEMOID = 1033;
|
||||||
const Oid CSTRINGARRAYOID = 1263;
|
// const Oid CSTRINGARRAYOID = 1263;
|
||||||
const Oid BPCHAROID = 1042;
|
// const Oid BPCHAROID = 1042;
|
||||||
const Oid VARCHAROID = 1043;
|
// const Oid VARCHAROID = 1043;
|
||||||
const Oid DATEOID = 1082;
|
// const Oid DATEOID = 1082;
|
||||||
const Oid TIMEOID = 1083;
|
// const Oid TIMEOID = 1083;
|
||||||
const Oid TIMESTAMPOID = 1114;
|
// const Oid TIMESTAMPOID = 1114;
|
||||||
const Oid TIMESTAMPTZOID = 1184;
|
// const Oid TIMESTAMPTZOID = 1184;
|
||||||
const Oid INTERVALOID = 1186;
|
// const Oid INTERVALOID = 1186;
|
||||||
const Oid TIMETZOID = 1266;
|
// const Oid TIMETZOID = 1266;
|
||||||
const Oid BITOID = 1560;
|
// const Oid BITOID = 1560;
|
||||||
const Oid VARBITOID = 1562;
|
// const Oid VARBITOID = 1562;
|
||||||
const Oid NUMERICOID = 1700;
|
// const Oid NUMERICOID = 1700;
|
||||||
const Oid REFCURSOROID = 1790;
|
// const Oid REFCURSOROID = 1790;
|
||||||
const Oid REGPROCEDUREOID = 2202;
|
// const Oid REGPROCEDUREOID = 2202;
|
||||||
const Oid REGOPEROID = 2203;
|
// const Oid REGOPEROID = 2203;
|
||||||
const Oid REGOPERATOROID = 2204;
|
// const Oid REGOPERATOROID = 2204;
|
||||||
const Oid REGCLASSOID = 2205;
|
// const Oid REGCLASSOID = 2205;
|
||||||
const Oid REGTYPEOID = 2206;
|
// const Oid REGTYPEOID = 2206;
|
||||||
const Oid REGROLEOID = 4096;
|
// const Oid REGROLEOID = 4096;
|
||||||
const Oid REGNAMESPACEOID = 4089;
|
// const Oid REGNAMESPACEOID = 4089;
|
||||||
const Oid REGTYPEARRAYOID = 2211;
|
// const Oid REGTYPEARRAYOID = 2211;
|
||||||
const Oid UUIDOID = 2950;
|
// const Oid UUIDOID = 2950;
|
||||||
const Oid LSNOID = 3220;
|
// const Oid LSNOID = 3220;
|
||||||
const Oid TSVECTOROID = 3614;
|
// const Oid TSVECTOROID = 3614;
|
||||||
const Oid GTSVECTOROID = 3642;
|
// const Oid GTSVECTOROID = 3642;
|
||||||
const Oid TSQUERYOID = 3615;
|
// const Oid TSQUERYOID = 3615;
|
||||||
const Oid REGCONFIGOID = 3734;
|
// const Oid REGCONFIGOID = 3734;
|
||||||
const Oid REGDICTIONARYOID = 3769;
|
// const Oid REGDICTIONARYOID = 3769;
|
||||||
const Oid JSONBOID = 3802;
|
// const Oid JSONBOID = 3802;
|
||||||
const Oid INT4RANGEOID = 3904;
|
// const Oid INT4RANGEOID = 3904;
|
||||||
const Oid RECORDOID = 2249;
|
// const Oid RECORDOID = 2249;
|
||||||
const Oid RECORDARRAYOID = 2287;
|
// const Oid RECORDARRAYOID = 2287;
|
||||||
const Oid CSTRINGOID = 2275;
|
// const Oid CSTRINGOID = 2275;
|
||||||
const Oid ANYOID = 2276;
|
// const Oid ANYOID = 2276;
|
||||||
const Oid ANYARRAYOID = 2277;
|
// const Oid ANYARRAYOID = 2277;
|
||||||
const Oid VOIDOID = 2278;
|
// const Oid VOIDOID = 2278;
|
||||||
const Oid TRIGGEROID = 2279;
|
// const Oid TRIGGEROID = 2279;
|
||||||
const Oid EVTTRIGGEROID = 3838;
|
// const Oid EVTTRIGGEROID = 3838;
|
||||||
const Oid LANGUAGE_HANDLEROID = 2280;
|
// const Oid LANGUAGE_HANDLEROID = 2280;
|
||||||
const Oid INTERNALOID = 2281;
|
// const Oid INTERNALOID = 2281;
|
||||||
const Oid OPAQUEOID = 2282;
|
// const Oid OPAQUEOID = 2282;
|
||||||
const Oid ANYELEMENTOID = 2283;
|
// const Oid ANYELEMENTOID = 2283;
|
||||||
const Oid ANYNONARRAYOID = 2776;
|
// const Oid ANYNONARRAYOID = 2776;
|
||||||
const Oid ANYENUMOID = 3500;
|
// const Oid ANYENUMOID = 3500;
|
||||||
const Oid FDW_HANDLEROID = 3115;
|
// const Oid FDW_HANDLEROID = 3115;
|
||||||
const Oid TSM_HANDLEROID = 3310;
|
// const Oid TSM_HANDLEROID = 3310;
|
||||||
const Oid ANYRANGEOID = 3831;
|
// const Oid ANYRANGEOID = 3831;
|
||||||
|
|
||||||
|
|
||||||
class Params;
|
class Params;
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Oid Pgsql::ElemOidFromArrayOid(Oid oid)
|
Oid Pgsql::ElemOidFromArrayOid(Oid oid) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
auto iter = std::lower_bound(g_ArrayToElem.begin(), g_ArrayToElem.end(),
|
auto iter = std::lower_bound(g_ArrayToElem.begin(), g_ArrayToElem.end(),
|
||||||
|
|
@ -173,11 +173,11 @@ Oid Pgsql::ElemOidFromArrayOid(Oid oid)
|
||||||
return l.array < r.array;
|
return l.array < r.array;
|
||||||
});
|
});
|
||||||
if (iter == g_ArrayToElem.end())
|
if (iter == g_ArrayToElem.end())
|
||||||
throw std::runtime_error("ElemOidFromArrayOid Oid not found");
|
return InvalidOid;
|
||||||
return iter->elem;
|
return iter->elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
Oid Pgsql::ArrayOidFromElemOid(Oid oid)
|
Oid Pgsql::ArrayOidFromElemOid(Oid oid) noexcept
|
||||||
{
|
{
|
||||||
auto iter = std::lower_bound(g_ElemToArray.begin(), g_ElemToArray.end(),
|
auto iter = std::lower_bound(g_ElemToArray.begin(), g_ElemToArray.end(),
|
||||||
ElemArray{oid, oid},
|
ElemArray{oid, oid},
|
||||||
|
|
@ -186,7 +186,6 @@ Oid Pgsql::ArrayOidFromElemOid(Oid oid)
|
||||||
return l.elem < r.elem;
|
return l.elem < r.elem;
|
||||||
});
|
});
|
||||||
if (iter == g_ElemToArray.end())
|
if (iter == g_ElemToArray.end())
|
||||||
throw std::runtime_error("ElemOidFromArrayOid Oid not found");
|
return InvalidOid;
|
||||||
return iter->array;
|
return iter->array;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ namespace Pgsql {
|
||||||
constexpr Oid regoperator_oid = 2204;
|
constexpr Oid regoperator_oid = 2204;
|
||||||
constexpr Oid regclass_oid = 2205;
|
constexpr Oid regclass_oid = 2205;
|
||||||
constexpr Oid regtype_oid = 2206;
|
constexpr Oid regtype_oid = 2206;
|
||||||
|
constexpr Oid any_oid = 2276;
|
||||||
constexpr Oid uuid_oid = 2950;
|
constexpr Oid uuid_oid = 2950;
|
||||||
constexpr Oid txid_snapshot_oid = 2970;
|
constexpr Oid txid_snapshot_oid = 2970;
|
||||||
constexpr Oid pg_lsn_oid = 3220;
|
constexpr Oid pg_lsn_oid = 3220;
|
||||||
|
|
@ -140,8 +141,19 @@ namespace Pgsql {
|
||||||
constexpr Oid regnamespace_array_oid = 4090;
|
constexpr Oid regnamespace_array_oid = 4090;
|
||||||
constexpr Oid regrole_array_oid = 4097;
|
constexpr Oid regrole_array_oid = 4097;
|
||||||
|
|
||||||
Oid ElemOidFromArrayOid(Oid oid);
|
/** If oid is an array oid then it returns the corresponding element oid.
|
||||||
Oid ArrayOidFromElemOid(Oid oid);
|
* It oid is not an array the functions returns InvalidOid.
|
||||||
|
* This function only works for the predefined postgresql types.
|
||||||
|
* If you need it to work for user defined types then use the system catalogue.
|
||||||
|
*/
|
||||||
|
Oid ElemOidFromArrayOid(Oid oid) noexcept;
|
||||||
|
/** If oid is a non array oid then it returns the corresponding array oid.
|
||||||
|
* It oid is a array oid or oid is unknown it returns InvalidOid.
|
||||||
|
* This function only works for the predefined postgresql types.
|
||||||
|
* If you need it to work for user defined types then use the system catalogue.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Oid ArrayOidFromElemOid(Oid oid) noexcept;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class OidFor {
|
class OidFor {
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,10 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets sql
|
||||||
TARGET = pgsql
|
TARGET = pgsql
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include \
|
! include( ../common.pri ) {
|
||||||
C:\Prog\include\pgsql \
|
error( "Couldn't find the common.pri file!" )
|
||||||
C:\VSproj\boost32\include\boost-1_65_1
|
}
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
|
||||||
|
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
|
||||||
#LIBS += -LC:/prog/boost/lib -Lc:/prog/lib libpq.lib fmt.lib User32.lib ws2_32.lib
|
#LIBS += -LC:/prog/boost/lib -Lc:/prog/lib libpq.lib fmt.lib User32.lib ws2_32.lib
|
||||||
LIBS += -LC:/PROG/LIB -lws2_32 -llibpq
|
LIBS += -LC:/PROG/LIB -lws2_32 -llibpq
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
|
! include( ../../common.pri ) {
|
||||||
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
}
|
||||||
include(gtest_dependency.pri)
|
include(gtest_dependency.pri)
|
||||||
|
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += console c++11
|
CONFIG += console c++17
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
CONFIG += thread
|
CONFIG += thread
|
||||||
CONFIG += qt
|
CONFIG += qt
|
||||||
|
|
||||||
QT += core
|
QT += core
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
INCLUDEPATH += C:\Prog\include\pgsql
|
||||||
|
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include C:\Prog\include\pgsql
|
|
||||||
|
|
||||||
HEADERS +=
|
HEADERS +=
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ using namespace Pgsql;
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_int4)
|
TEST(Pgsql_Value, test_int4)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("1", INT4OID);
|
Pgsql::Value v("1", int4_oid);
|
||||||
int i = (int)v;
|
int i = (int)v;
|
||||||
ASSERT_EQ(i, 1);
|
ASSERT_EQ(i, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_QDateTime)
|
TEST(Pgsql_Value, test_QDateTime)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("2017-10-22 12:34:56", TIMESTAMPTZOID);
|
Pgsql::Value v("2017-10-22 12:34:56", timestamptz_oid);
|
||||||
QDateTime dt = (QDateTime)v;
|
QDateTime dt = (QDateTime)v;
|
||||||
ASSERT_EQ(dt, QDateTime(QDate(2017, 10, 22), QTime(12, 34, 56)));
|
ASSERT_EQ(dt, QDateTime(QDate(2017, 10, 22), QTime(12, 34, 56)));
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ TEST(Pgsql_Value, test_QDateTime)
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_QDateTime_2)
|
TEST(Pgsql_Value, test_QDateTime_2)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("2017-12-01 09:38:17.339817+02", TIMESTAMPTZOID);
|
Pgsql::Value v("2017-12-01 09:38:17.339817+02", timestamptz_oid);
|
||||||
QDateTime dt = (QDateTime)v;
|
QDateTime dt = (QDateTime)v;
|
||||||
QDateTime exp(QDate(2017, 12, 1), QTime(9, 38, 17, 340),
|
QDateTime exp(QDate(2017, 12, 1), QTime(9, 38, 17, 340),
|
||||||
Qt::OffsetFromUTC, 2*3600);
|
Qt::OffsetFromUTC, 2*3600);
|
||||||
|
|
@ -35,21 +35,21 @@ TEST(Pgsql_Value, test_QDateTime_2)
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_QDate)
|
TEST(Pgsql_Value, test_QDate)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("2017-10-22", DATEOID);
|
Pgsql::Value v("2017-10-22", date_oid);
|
||||||
QDate d = v;
|
QDate d = v;
|
||||||
ASSERT_EQ(d, QDate(2017, 10, 22));
|
ASSERT_EQ(d, QDate(2017, 10, 22));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_QTime)
|
TEST(Pgsql_Value, test_QTime)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("12:34:56", TIMEOID);
|
Pgsql::Value v("12:34:56", time_oid);
|
||||||
QTime t = v;
|
QTime t = v;
|
||||||
ASSERT_EQ(t, QTime(12, 34, 56));
|
ASSERT_EQ(t, QTime(12, 34, 56));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pgsql_Value, test_QTimeMS)
|
TEST(Pgsql_Value, test_QTimeMS)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("09:38:17.339817+02", TIMETZOID);
|
Pgsql::Value v("09:38:17.339817+02", timetz_oid);
|
||||||
QTime t = v;
|
QTime t = v;
|
||||||
ASSERT_EQ(t, QTime(9, 38, 17, 340));
|
ASSERT_EQ(t, QTime(9, 38, 17, 340));
|
||||||
}
|
}
|
||||||
|
|
@ -58,19 +58,19 @@ TEST(Pgsql_Value, test_QTimeMS)
|
||||||
|
|
||||||
TEST(Pgsql_Value, isString_int4)
|
TEST(Pgsql_Value, isString_int4)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("1", INT4OID);
|
Pgsql::Value v("1", int4_oid);
|
||||||
ASSERT_EQ(v.isString(), false);
|
ASSERT_EQ(v.isString(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pgsql_Value, isString_varchar)
|
TEST(Pgsql_Value, isString_varchar)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("1", VARCHAROID);
|
Pgsql::Value v("1", varchar_oid);
|
||||||
ASSERT_EQ(v.isString(), true);
|
ASSERT_EQ(v.isString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsVector_Ints)
|
TEST(Pgsql_Value, getAsVector_Ints)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("1 2", ANYOID);
|
Pgsql::Value v("1 2", any_oid);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
v.getAsVector<int>(std::back_inserter(r));
|
v.getAsVector<int>(std::back_inserter(r));
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ TEST(Pgsql_Value, getAsVector_Ints)
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArray_Ints)
|
TEST(Pgsql_Value, getAsArray_Ints)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,2}", text_array_oid);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
v.getAsArray<int>(std::back_inserter(r));
|
v.getAsArray<int>(std::back_inserter(r));
|
||||||
|
|
||||||
|
|
@ -92,9 +92,10 @@ TEST(Pgsql_Value, getAsArray_Ints)
|
||||||
ASSERT_EQ(r[1], 2);
|
ASSERT_EQ(r[1], 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArray_QDateTime)
|
TEST(Pgsql_Value, getAsArray_QDateTime)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{\"2017-12-11 10:11:22\",\"2017-12-13 12:00:11\"}", TEXTARRAYOID);
|
Pgsql::Value v("{\"2017-12-11 10:11:22\",\"2017-12-13 12:00:11\"}", text_array_oid);
|
||||||
std::set<QDateTime> r;
|
std::set<QDateTime> r;
|
||||||
v.getAsArray<QDateTime>(std::inserter(r, r.end()));
|
v.getAsArray<QDateTime>(std::inserter(r, r.end()));
|
||||||
|
|
||||||
|
|
@ -103,7 +104,7 @@ TEST(Pgsql_Value, getAsArray_QDateTime)
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArray_throws_on_NULL)
|
TEST(Pgsql_Value, getAsArray_throws_on_NULL)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,NULL,2}", text_array_oid);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
try {
|
try {
|
||||||
v.getAsArray<int>(std::back_inserter(r));
|
v.getAsArray<int>(std::back_inserter(r));
|
||||||
|
|
@ -117,7 +118,7 @@ TEST(Pgsql_Value, getAsArray_throws_on_NULL)
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArray_default_on_NULL)
|
TEST(Pgsql_Value, getAsArray_default_on_NULL)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,NULL,2}", text_array_oid);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
try {
|
try {
|
||||||
v.getAsArray<int>(std::back_inserter(r), -1);
|
v.getAsArray<int>(std::back_inserter(r), -1);
|
||||||
|
|
@ -132,7 +133,7 @@ TEST(Pgsql_Value, getAsArray_default_on_NULL)
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArray_ignore_NULL)
|
TEST(Pgsql_Value, getAsArray_ignore_NULL)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,NULL,2}", text_array_oid);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
try {
|
try {
|
||||||
v.getAsArray<int>(std::back_inserter(r), NullHandling::Ignore);
|
v.getAsArray<int>(std::back_inserter(r), NullHandling::Ignore);
|
||||||
|
|
@ -146,7 +147,7 @@ TEST(Pgsql_Value, getAsArray_ignore_NULL)
|
||||||
|
|
||||||
TEST(Pgsql_Value, getAsArrayOptional)
|
TEST(Pgsql_Value, getAsArrayOptional)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,NULL,2}", text_array_oid);
|
||||||
std::vector<std::optional<int>> r;
|
std::vector<std::optional<int>> r;
|
||||||
try {
|
try {
|
||||||
v.getAsArrayOfOptional<int>(std::back_inserter(r));
|
v.getAsArrayOfOptional<int>(std::back_inserter(r));
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,19 @@
|
||||||
include(gtest_dependency.pri)
|
include(gtest_dependency.pri)
|
||||||
|
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += console c++14
|
CONFIG += console c++17
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
CONFIG += thread
|
CONFIG += thread
|
||||||
CONFIG += qt
|
CONFIG += qt
|
||||||
|
|
||||||
QT += core
|
QT += core widgets
|
||||||
|
|
||||||
|
QMAKE_CXXFLAGS += /std:c++17
|
||||||
|
|
||||||
|
! include( ../../common.pri ) {
|
||||||
|
error( "Couldn't find the common.pri file!" )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HEADERS +=
|
HEADERS +=
|
||||||
|
|
||||||
|
|
@ -17,14 +24,17 @@ SOURCES += main.cpp \
|
||||||
tst_scopeguard.cpp \
|
tst_scopeguard.cpp \
|
||||||
tst_CsvWriter.cpp \
|
tst_CsvWriter.cpp \
|
||||||
tst_PasswordManager.cpp \
|
tst_PasswordManager.cpp \
|
||||||
tst_ParamJson.cpp
|
tst_ParamJson.cpp \
|
||||||
|
tst_CodeBuilder.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
|
||||||
|
|
||||||
INCLUDEPATH += C:\prog\include \
|
INCLUDEPATH += C:\prog\include \
|
||||||
C:\Prog\include\pgsql \
|
C:\Prog\include\pgsql \
|
||||||
C:\VSproj\boost32\include\boost-1_65_1
|
C:\VSproj\boost32\include
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/../../core
|
INCLUDEPATH += $$PWD/../../core
|
||||||
DEPENDPATH += $$PWD/../../core
|
DEPENDPATH += $$PWD/../../core
|
||||||
|
|
@ -60,3 +70,16 @@ else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../p
|
||||||
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/release/pglablib.lib
|
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/release/pglablib.lib
|
||||||
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/debug/pglablib.lib
|
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/debug/pglablib.lib
|
||||||
else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/libpglablib.a
|
else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/libpglablib.a
|
||||||
|
|
||||||
|
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/release/ -lmygtestutils
|
||||||
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../mygtestutils/debug/ -lmygtestutils
|
||||||
|
else:unix:!macx: LIBS += -L$$OUT_PWD/../mygtestutils/ -lmygtestutils
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../mygtestutils
|
||||||
|
DEPENDPATH += $$PWD/../mygtestutils
|
||||||
|
|
||||||
|
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/libmygtestutils.a
|
||||||
|
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/libmygtestutils.a
|
||||||
|
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/release/mygtestutils.lib
|
||||||
|
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/debug/mygtestutils.lib
|
||||||
|
else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../mygtestutils/libmygtestutils.a
|
||||||
|
|
|
||||||
172
tests/pglabtests/tst_CodeBuilder.cpp
Normal file
172
tests/pglabtests/tst_CodeBuilder.cpp
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include "PgType.h"
|
||||||
|
#include "PgTypeContainer.h"
|
||||||
|
#include "codebuilder/IndentationConfig.h"
|
||||||
|
#include "codebuilder/TypeMappings.h"
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Test to verify my understanding of the documentation
|
||||||
|
TEST(QRegularExpression, doIUnderstandItCorrectly)
|
||||||
|
{
|
||||||
|
QString text("abcdefghi");
|
||||||
|
QRegularExpression re("c(def)g");
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
int pos = text.indexOf(re, 0, &match);
|
||||||
|
|
||||||
|
ASSERT_THAT(pos, Eq(2));
|
||||||
|
ASSERT_THAT(match.capturedStart(), Eq(2));
|
||||||
|
ASSERT_THAT(match.capturedEnd(), Eq(7));
|
||||||
|
ASSERT_THAT(match.capturedStart(1), Eq(3));
|
||||||
|
ASSERT_THAT(match.capturedEnd(1), Eq(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QRegularExpression, doIUnderstandItCorrectly2)
|
||||||
|
{
|
||||||
|
QString text("abc/%def%/ghi");
|
||||||
|
QRegularExpression re("(?:[^\\\\]|^)(\\/%([a-zA-Z0-9_-]+)%\\/)");
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
int pos = text.indexOf(re, 0, &match);
|
||||||
|
|
||||||
|
ASSERT_THAT(pos, Eq(2));
|
||||||
|
ASSERT_THAT(match.capturedStart(1), Eq(3));
|
||||||
|
ASSERT_THAT(match.capturedLength(1), Eq(7));
|
||||||
|
ASSERT_THAT(match.capturedStart(2), Eq(5));
|
||||||
|
ASSERT_THAT(match.capturedLength(2), Eq(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
void FormatToStream(QTextStream &stream, QString format, std::function<void(QTextStream &, QString)> field_callback);
|
||||||
|
|
||||||
|
TEST(FormatToStream, EmptyFormat)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "", nullptr);
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_THAT(result, Eq(QString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatToStream, OnlyVar)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "/%var%/",
|
||||||
|
[](QTextStream &stream, QString varname)
|
||||||
|
{
|
||||||
|
if (varname == "var")
|
||||||
|
stream << "abc";
|
||||||
|
});
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_EQ(result, QString("abc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatToStream, StartWithVar)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "/%var%/def",
|
||||||
|
[](QTextStream &stream, QString varname)
|
||||||
|
{
|
||||||
|
if (varname == "var")
|
||||||
|
stream << "abc";
|
||||||
|
});
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_EQ(result, QString("abcdef"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatToStream, EndWithVar)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "def/%var%/",
|
||||||
|
[](QTextStream &stream, QString varname)
|
||||||
|
{
|
||||||
|
if (varname == "var")
|
||||||
|
stream << "abc";
|
||||||
|
});
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_EQ(result, QString("defabc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatToStream, TwoVarsTogether)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "/%var1%//%var2%/",
|
||||||
|
[](QTextStream &stream, QString varname)
|
||||||
|
{
|
||||||
|
if (varname == "var1")
|
||||||
|
stream << "abc";
|
||||||
|
else if (varname == "var2")
|
||||||
|
stream << "def";
|
||||||
|
});
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_EQ(result, QString("abcdef"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatToStream, TwoVarsWithTextInBetween)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream stream(&result);
|
||||||
|
FormatToStream(stream, "1/%var1%/2/%var2%/3",
|
||||||
|
[](QTextStream &stream, QString varname)
|
||||||
|
{
|
||||||
|
if (varname == "var1")
|
||||||
|
stream << "abc";
|
||||||
|
else if (varname == "var2")
|
||||||
|
stream << "def";
|
||||||
|
});
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
ASSERT_EQ(result, QString("1abc2def3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(IndentationConfig, tab8indent4true_level1)
|
||||||
|
{
|
||||||
|
IndentationConfig icfg(8, 4, true);
|
||||||
|
QString result = icfg.getIndentString(1);
|
||||||
|
ASSERT_EQ(result, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IndentationConfig, tab8indent4true_level2)
|
||||||
|
{
|
||||||
|
IndentationConfig icfg(8, 4, true);
|
||||||
|
QString result = icfg.getIndentString(2);
|
||||||
|
ASSERT_EQ(result, "\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IndentationConfig, tab8indent4true_level3)
|
||||||
|
{
|
||||||
|
IndentationConfig icfg(8, 4, true);
|
||||||
|
QString result = icfg.getIndentString(3);
|
||||||
|
ASSERT_EQ(result, "\t ");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IndentationConfig, tab8indent4false_level1)
|
||||||
|
{
|
||||||
|
IndentationConfig icfg(8, 4, false);
|
||||||
|
QString result = icfg.getIndentString(1);
|
||||||
|
ASSERT_EQ(result, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IndentationConfig, tab8indent4false_level2)
|
||||||
|
{
|
||||||
|
IndentationConfig icfg(8, 4, false);
|
||||||
|
QString result = icfg.getIndentString(2);
|
||||||
|
ASSERT_EQ(result, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "CsvWriter.h"
|
#include "CsvWriter.h"
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "ExplainTreeModelItem.h"
|
#include "ExplainTreeModelItem.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
81
tests/pglabtests/tst_NameManglingRules.cpp
Normal file
81
tests/pglabtests/tst_NameManglingRules.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
#include "codebuilder/NameManglingRules.h"
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
class NameManglingRulesTest : public ::testing::Test, public ::testing::WithParamInterface<
|
||||||
|
std::tuple<QString, NameManglingRules::CaseConversion, bool> > {
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void SetUp() override
|
||||||
|
{
|
||||||
|
NameManglingRules r;
|
||||||
|
|
||||||
|
// auto p = GetParam();
|
||||||
|
// //ReplaceRules replaceRules;
|
||||||
|
// // { {"[ -_]", QRegularExpression::OptimizeOnFirstUsageOption }, "", true }
|
||||||
|
// // r.replaceRules;
|
||||||
|
|
||||||
|
// //CaseConversion caseConversion = CaseConversion::AsIs; ///< overall case conversion rule
|
||||||
|
// r.caseConversion = std::get<1>(p);
|
||||||
|
// //CaseConversion caseFirstChar = CaseConversion::AsIs; ///< case of the first char
|
||||||
|
// //r.camelCase = std::get<2>(p); ///< removes underscores and make first char after underscore uppercase
|
||||||
|
// rules = r;
|
||||||
|
}
|
||||||
|
NameManglingRules rules;
|
||||||
|
};
|
||||||
|
|
||||||
|
// First a few test to test some basic things
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(NameManglingRulesTest, caseConversionAsIs)
|
||||||
|
{
|
||||||
|
QString input = "Ab";
|
||||||
|
QString expected = input;
|
||||||
|
|
||||||
|
NameManglingRules rules;
|
||||||
|
rules.caseConversion = NameManglingRules::CaseConversion::AsIs;
|
||||||
|
QString result = rules.transform(input);
|
||||||
|
|
||||||
|
ASSERT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NameManglingRulesTest, caseConversionLower)
|
||||||
|
{
|
||||||
|
QString input = "Ab";
|
||||||
|
QString expected = "ab";
|
||||||
|
|
||||||
|
NameManglingRules rules;
|
||||||
|
rules.caseConversion = NameManglingRules::CaseConversion::Lower;
|
||||||
|
QString result = rules.transform(input);
|
||||||
|
|
||||||
|
ASSERT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NameManglingRulesTest, caseConversionUpper)
|
||||||
|
{
|
||||||
|
QString input = "Ab";
|
||||||
|
QString expected = "AB";
|
||||||
|
|
||||||
|
NameManglingRules rules;
|
||||||
|
rules.caseConversion = NameManglingRules::CaseConversion::Upper;
|
||||||
|
QString result = rules.transform(input);
|
||||||
|
|
||||||
|
ASSERT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NameManglingRulesTest, replace)
|
||||||
|
{
|
||||||
|
QString input = "abc-def ghi";
|
||||||
|
QString expected = "abc_Def_Ghi";
|
||||||
|
|
||||||
|
NameManglingRules rules;
|
||||||
|
rules.replaceRules.push_back({QRegularExpression("[- ]"), "_", true});
|
||||||
|
QString result = rules.transform(input);
|
||||||
|
|
||||||
|
ASSERT_EQ(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "ParamListModel.h"
|
#include "ParamListModel.h"
|
||||||
#include "ParamListJson.h"
|
#include "ParamListJson.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "PasswordManager.h"
|
#include "PasswordManager.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "SqlLexer.h"
|
#include "SqlLexer.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
@ -53,7 +54,7 @@ TEST(SqlLexer, lexer_comma_handling)
|
||||||
lexer.nextBasicToken(startpos, length, tokentype, out);
|
lexer.nextBasicToken(startpos, length, tokentype, out);
|
||||||
ASSERT_THAT(startpos, Eq(3));
|
ASSERT_THAT(startpos, Eq(3));
|
||||||
ASSERT_THAT(length, Eq(1));
|
ASSERT_THAT(length, Eq(1));
|
||||||
ASSERT_THAT(tokentype, Eq(BasicTokenType::Self));
|
ASSERT_THAT(tokentype, Eq(BasicTokenType::Comma));
|
||||||
ASSERT_THAT(out, Eq(QString(",")));
|
ASSERT_THAT(out, Eq(QString(",")));
|
||||||
|
|
||||||
lexer.nextBasicToken(startpos, length, tokentype, out);
|
lexer.nextBasicToken(startpos, length, tokentype, out);
|
||||||
|
|
|
||||||
71
tests/pglabtests/tst_TypeMappings.cpp
Normal file
71
tests/pglabtests/tst_TypeMappings.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
//#include <QRegularExpression>
|
||||||
|
#include "PgType.h"
|
||||||
|
#include "PgTypeContainer.h"
|
||||||
|
//#include "PrintTo_Qt.h"
|
||||||
|
//#include "codebuilder/IndentationConfig.h"
|
||||||
|
#include "codebuilder/TypeMappings.h"
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
|
||||||
|
class TypeMappingsTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
def_str_type = "std::string";
|
||||||
|
int4str = "int";
|
||||||
|
int8str = "long long";
|
||||||
|
tm = TypeMappings( {
|
||||||
|
{ Pgsql::int4_oid, int4str },
|
||||||
|
{ Pgsql::int8_oid, int8str }
|
||||||
|
});
|
||||||
|
tm.setDefaultStringType(def_str_type);
|
||||||
|
tm.setDefaultContainerType("std::vector<%1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// void TearDown() override {}
|
||||||
|
|
||||||
|
QString def_str_type;
|
||||||
|
QString int4str;
|
||||||
|
QString int8str;
|
||||||
|
TypeMappings tm;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(TypeMappingsTest, defStringType)
|
||||||
|
{
|
||||||
|
QString result = tm.getTypeForOid(Pgsql::float4_oid);
|
||||||
|
ASSERT_EQ(result, def_str_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TypeMappingsTest, int4Type)
|
||||||
|
{
|
||||||
|
QString result = tm.getTypeForOid(Pgsql::int4_oid);
|
||||||
|
ASSERT_EQ(result, int4str);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TypeMappingsTest, int4overideType)
|
||||||
|
{
|
||||||
|
tm.set(Pgsql::int4_oid, "QString");
|
||||||
|
QString result = tm.getTypeForOid(Pgsql::int4_oid);
|
||||||
|
ASSERT_EQ(result, "QString");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need catalogue for the next test
|
||||||
|
// Maybe we should mock this !?
|
||||||
|
TEST_F(TypeMappingsTest, int4arrayType)
|
||||||
|
{
|
||||||
|
auto types= std::make_shared<PgTypeContainer>();
|
||||||
|
PgType int4arr;
|
||||||
|
int4arr.oid = Pgsql::int4_array_oid;
|
||||||
|
int4arr.elem = Pgsql::int4_oid;
|
||||||
|
types->add(int4arr);
|
||||||
|
|
||||||
|
tm.setTypes(types);
|
||||||
|
|
||||||
|
QString result = tm.getTypeForOid(Pgsql::int4_array_oid);
|
||||||
|
ASSERT_EQ(result, "std::vector<int>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "Expected.h"
|
#include "Expected.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock-matchers.h>
|
#include <gmock/gmock-matchers.h>
|
||||||
#include "ScopeGuard.h"
|
#include "ScopeGuard.h"
|
||||||
|
#include "PrintTo_Qt.h"
|
||||||
|
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue