Lot of code for generating code. Working on unit tests.
This commit is contained in:
parent
da45929b12
commit
8f4845d4d2
42 changed files with 1089 additions and 267 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "BaseTableModel.h"
|
||||
#include "ResultTableModelUtil.h"
|
||||
#include <QBrush>
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
|
|
@ -10,7 +11,7 @@ QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
|||
Oid oid = getType(index.column());
|
||||
if (role == Qt::DisplayRole) {
|
||||
v = getData(index);
|
||||
if (oid == BOOLOID) {
|
||||
if (oid == bool_oid) {
|
||||
v = FormatBoolForDisplay(v.toBool());
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +19,7 @@ QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
|||
v = (int)GetDefaultAlignmentForType(oid);
|
||||
}
|
||||
else if (role == Qt::ForegroundRole) {
|
||||
if (oid == BOOLOID) {
|
||||
if (oid == bool_oid) {
|
||||
QVariant d = getData(index);
|
||||
if (d.type() == QVariant::Bool) {
|
||||
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;
|
||||
};
|
||||
|
|
@ -140,7 +140,7 @@ int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const
|
|||
|
||||
Oid ColumnTableModel::getType(int /*column*/) const
|
||||
{
|
||||
Oid oid = Pgsql::VARCHAROID;
|
||||
Oid oid = Pgsql::varchar_oid;
|
||||
// switch (column) {
|
||||
// case TypeCol:
|
||||
// case NameCol:
|
||||
|
|
|
|||
|
|
@ -79,12 +79,12 @@ QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, i
|
|||
return v;
|
||||
}
|
||||
|
||||
int ConstraintModel::rowCount(const QModelIndex &parent) const
|
||||
int ConstraintModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_constraints.size();
|
||||
}
|
||||
|
||||
int ConstraintModel::columnCount(const QModelIndex &parent) const
|
||||
int ConstraintModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ int ConstraintModel::columnCount(const QModelIndex &parent) const
|
|||
// return v;
|
||||
//}
|
||||
|
||||
Oid ConstraintModel::getType(int column) const
|
||||
Oid ConstraintModel::getType(int ) const
|
||||
{
|
||||
Oid oid = Pgsql::varchar_oid;
|
||||
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ Oid DatabasesTableModel::getType(int column) const
|
|||
switch (column) {
|
||||
case AllowConnCol:
|
||||
case IsTemplateCol:
|
||||
oid = BOOLOID;
|
||||
oid = bool_oid;
|
||||
break;
|
||||
case ConnLimitCol:
|
||||
oid = INT4OID;
|
||||
oid = int4_oid;
|
||||
break;
|
||||
case AclCol:
|
||||
case CollateCol:
|
||||
|
|
@ -96,7 +96,7 @@ Oid DatabasesTableModel::getType(int column) const
|
|||
case DbaCol:
|
||||
case NameCol:
|
||||
case TablespaceCol:
|
||||
oid = VARCHAROID;
|
||||
oid = varchar_oid;
|
||||
break;
|
||||
default:
|
||||
oid = InvalidOid;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ void IconColumnDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
|||
}
|
||||
}
|
||||
|
||||
QSize IconColumnDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
QSize IconColumnDelegate::sizeHint(const QStyleOptionViewItem &,
|
||||
const QModelIndex &) const
|
||||
{
|
||||
return QSize(16, 16);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ Oid RolesTableModel::getType(int column) const
|
|||
Oid oid;
|
||||
switch (column) {
|
||||
case NameCol:
|
||||
oid = VARCHAROID;
|
||||
oid = varchar_oid;
|
||||
break;
|
||||
|
||||
case ReplicationCol:
|
||||
|
|
@ -91,15 +91,15 @@ Oid RolesTableModel::getType(int column) const
|
|||
case CreateRoleCol:
|
||||
case InheritCol:
|
||||
case SuperCol:
|
||||
oid = BOOLOID;
|
||||
oid = bool_oid;
|
||||
break;
|
||||
|
||||
case ConnlimitCol:
|
||||
oid = INT4OID;
|
||||
oid = int4_oid;
|
||||
break;
|
||||
|
||||
case ValidUntilCol:
|
||||
oid = TIMESTAMPOID;
|
||||
oid = timestamp_oid;
|
||||
break;
|
||||
default:
|
||||
oid = InvalidOid;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ Oid TablesTableModel::getType(int column) const
|
|||
case OptionsCol:
|
||||
// case AclCol:
|
||||
default:
|
||||
oid = Pgsql::VARCHAROID;
|
||||
oid = Pgsql::varchar_oid;
|
||||
}
|
||||
return oid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ SOURCES += main.cpp\
|
|||
ConnectionList.cpp \
|
||||
ProcessStdioWidget.cpp \
|
||||
GlobalIoService.cpp \
|
||||
CodeBuilderConfiguration.cpp \
|
||||
ResultTableModelUtil.cpp \
|
||||
BaseTableModel.cpp \
|
||||
QueryParamListController.cpp \
|
||||
|
|
@ -74,7 +73,7 @@ SOURCES += main.cpp\
|
|||
EditorGutter.cpp \
|
||||
CodeEditor.cpp \
|
||||
PlgPage.cpp \
|
||||
PropertyProxyModel.cpp
|
||||
PropertyProxyModel.cpp
|
||||
|
||||
HEADERS += \
|
||||
QueryResultModel.h \
|
||||
|
|
@ -122,7 +121,7 @@ HEADERS += \
|
|||
PlgPage.h \
|
||||
AbstractCommand.h \
|
||||
PropertyProxyModel.h \
|
||||
CustomDataRole.h
|
||||
CustomDataRole.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
ConnectionManagerWindow.ui \
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ class PgContainer: public IPgContainter {
|
|||
public:
|
||||
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)
|
||||
: m_catalogue(cat)
|
||||
{}
|
||||
|
|
@ -87,6 +89,13 @@ public:
|
|||
|
||||
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:
|
||||
std::weak_ptr<PgDatabaseCatalog> m_catalogue;
|
||||
t_Container m_container;
|
||||
|
|
|
|||
119
pglablib/codebuilder/CodeBuilder.cpp
Normal file
119
pglablib/codebuilder/CodeBuilder.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#include "CodeBuilder.h"
|
||||
#include "Pgsql_Result.h"
|
||||
#include "IndentationConfig.h"
|
||||
#include "LanguageConfig.h"
|
||||
#include "StructureTemplate.h"
|
||||
#include "util.h"
|
||||
#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);
|
||||
}
|
||||
|
||||
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result)
|
||||
{
|
||||
// %1 query string
|
||||
// %2 struct_name
|
||||
// %3 list of field assignments
|
||||
QString exec_query_template = "Pgsql::Result result = conn.query(%1);";
|
||||
|
||||
QString loop_start_template =
|
||||
"Pgsql::Result result = conn.query(/%query_literal%/);"
|
||||
"for (auto row: result) {\n"
|
||||
" Pgsql::Col col(row);\n"
|
||||
" /%struct_type%/ v;\n"
|
||||
"/%assign_fields%/"
|
||||
"}";
|
||||
|
||||
// %field_name%
|
||||
// %column_name%
|
||||
// %column_index%
|
||||
QString assign_result_field_template = "col >> v./%field_name%/";
|
||||
QString query_string_literal = ConvertToMultiLineCString(query);
|
||||
|
||||
// [optional] Gen declaration of result structure
|
||||
GenReturnStructDefinition(q, result);
|
||||
|
||||
// assume we have connection? What name???
|
||||
|
||||
// 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 Pgsql::Result &result) const
|
||||
{
|
||||
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
||||
|
||||
QString struct_name = "TODO";
|
||||
QString field_format = templ->m_fieldTemplate;
|
||||
int field_indent_levels = templ->m_fieldIndentation;
|
||||
QString field_indent_string = m_configuration->indentationConfig()->getIndentString(field_indent_levels);
|
||||
// Make struct start
|
||||
q << QString(templ->m_startTemplate).arg(struct_name);
|
||||
// Process fields
|
||||
for (int column = 0; column < result.cols(); ++column) {
|
||||
QString res_col_name = result.getColName(column);
|
||||
Oid type_oid = result.type(column);
|
||||
|
||||
q << field_indent_string;
|
||||
genFieldDeclaration(q, field_format, res_col_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)
|
||||
}
|
||||
// Finish struct
|
||||
q << QString(templ->m_endTemplate).arg(struct_name);
|
||||
}
|
||||
|
||||
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::genFieldDeclaration(QTextStream &q, const QString &format, const QString &column_name, Oid column_type) const
|
||||
{
|
||||
QString field_name = columnNameToVariableName(column_name);
|
||||
QString type_name = getTypeName(column_type);
|
||||
q << QString(format).arg(field_name).arg(type_name);
|
||||
}
|
||||
|
||||
28
pglablib/codebuilder/CodeBuilder.h
Normal file
28
pglablib/codebuilder/CodeBuilder.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef CODEBUILDER_H
|
||||
#define CODEBUILDER_H
|
||||
|
||||
#include "Pgsql_declare.h"
|
||||
#include <QString>
|
||||
|
||||
class LanguageConfig;
|
||||
class QTextStream;
|
||||
|
||||
class CodeBuilder {
|
||||
public:
|
||||
void GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result);
|
||||
void GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result) 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 genFieldDeclaration(QTextStream &q, const QString &format, const QString &column_name, Oid column_type) const;
|
||||
};
|
||||
|
||||
#endif // CODEBUILDER_H
|
||||
50
pglablib/codebuilder/DefaultConfigs.cpp
Normal file
50
pglablib/codebuilder/DefaultConfigs.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "DefaultConfigs.h"
|
||||
#include "LanguageConfig.h"
|
||||
#include "TypeMappings.h"
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
TypeMappings GetDefaultCppTypeMappings()
|
||||
{
|
||||
TypeMappings result = {
|
||||
{ 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" }
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<LanguageConfig> buildDefaultCppLanguageConfig()
|
||||
{
|
||||
return std::make_shared<LanguageConfig>();
|
||||
}
|
||||
|
||||
std::shared_ptr<const LanguageConfig> getDefaultCppLanguageConfig()
|
||||
{
|
||||
static auto config = buildDefaultCppLanguageConfig();
|
||||
return config;
|
||||
}
|
||||
|
||||
std::shared_ptr<const LanguageConfig> buildPgLabCppLanguageConfig()
|
||||
{
|
||||
auto cfg = buildDefaultCppLanguageConfig();
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
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
|
||||
15
pglablib/codebuilder/LanguageConfig.cpp
Normal file
15
pglablib/codebuilder/LanguageConfig.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#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);
|
||||
}
|
||||
54
pglablib/codebuilder/LanguageConfig.h
Normal file
54
pglablib/codebuilder/LanguageConfig.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef LANGUAGECONFIG_H
|
||||
#define LANGUAGECONFIG_H
|
||||
|
||||
#include <QString>
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
class NameManglingRules;
|
||||
class TypeMappings;
|
||||
class StructureTemplate;
|
||||
class IndentationConfig;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class LanguageConfig {
|
||||
public:
|
||||
LanguageConfig();
|
||||
|
||||
QString columnNameToFieldName(const QString& column_name) const;
|
||||
QString getTypeName(Oid dbtype) const;
|
||||
|
||||
std::shared_ptr<const TypeMappings> typeMappings() const { return m_typeMappings; }
|
||||
void setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings)
|
||||
{
|
||||
m_typeMappings = type_mappings;
|
||||
}
|
||||
|
||||
std::shared_ptr<const StructureTemplate> structureTemplate() const
|
||||
{
|
||||
return m_structureTemplate;
|
||||
}
|
||||
|
||||
std::shared_ptr<const IndentationConfig> indentationConfig() const
|
||||
{
|
||||
return m_indentationConfig;
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
50
pglablib/codebuilder/NameManglingRules.h
Normal file
50
pglablib/codebuilder/NameManglingRules.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#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 }
|
||||
|
||||
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 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
|
||||
2
pglablib/codebuilder/StructureTemplate.cpp
Normal file
2
pglablib/codebuilder/StructureTemplate.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#include "StructureTemplate.h"
|
||||
|
||||
16
pglablib/codebuilder/StructureTemplate.h
Normal file
16
pglablib/codebuilder/StructureTemplate.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef STRUCTURETEMPLATE_H
|
||||
#define STRUCTURETEMPLATE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class StructureTemplate {
|
||||
public:
|
||||
|
||||
QString m_startTemplate; // class /$structname/ {\npublic:\n
|
||||
QString m_endTemplate; // };
|
||||
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
|
||||
|
|
@ -57,7 +57,14 @@ SOURCES += \
|
|||
PgAmContainer.cpp \
|
||||
PgObject.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
|
||||
|
||||
HEADERS += \
|
||||
Pglablib.h \
|
||||
|
|
@ -92,7 +99,14 @@ HEADERS += \
|
|||
PgAmContainer.h \
|
||||
PgObject.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
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ namespace Pgsql {
|
|||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ Value::operator double() const
|
|||
|
||||
bool Value::isString() const
|
||||
{
|
||||
return m_typ == CHAROID
|
||||
|| m_typ == VARCHAROID
|
||||
|| m_typ == TEXTOID
|
||||
return m_typ == char_oid
|
||||
|| m_typ == varchar_oid
|
||||
|| m_typ == text_oid
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,95 +5,95 @@
|
|||
|
||||
namespace Pgsql {
|
||||
|
||||
const Oid BOOLOID = 16;
|
||||
const Oid BYTEAOID = 17;
|
||||
const Oid CHAROID = 18;
|
||||
const Oid NAMEOID = 19;
|
||||
const Oid INT8OID = 20;
|
||||
const Oid INT2OID = 21;
|
||||
const Oid INT2VECTOROID = 22;
|
||||
const Oid INT4OID = 23;
|
||||
const Oid REGPROCOID = 24;
|
||||
const Oid TEXTOID = 25;
|
||||
const Oid OIDOID = 26;
|
||||
const Oid TIDOID = 27;
|
||||
const Oid XIDOID = 28;
|
||||
const Oid CIDOID = 29;
|
||||
const Oid OIDVECTOROID = 30;
|
||||
const Oid JSONOID = 114;
|
||||
const Oid XMLOID = 142;
|
||||
const Oid PGNODETREEOID = 194;
|
||||
const Oid PGDDLCOMMANDOID = 32;
|
||||
const Oid POINTOID = 600;
|
||||
const Oid LSEGOID = 601;
|
||||
const Oid PATHOID = 602;
|
||||
const Oid BOXOID = 603;
|
||||
const Oid POLYGONOID = 604;
|
||||
const Oid LINEOID = 628;
|
||||
const Oid FLOAT4OID = 700;
|
||||
const Oid FLOAT8OID = 701;
|
||||
const Oid ABSTIMEOID = 702;
|
||||
const Oid RELTIMEOID = 703;
|
||||
const Oid TINTERVALOID = 704;
|
||||
const Oid UNKNOWNOID = 705;
|
||||
const Oid CIRCLEOID = 718;
|
||||
const Oid CASHOID = 790;
|
||||
const Oid MACADDROID = 829;
|
||||
const Oid INETOID = 869;
|
||||
const Oid CIDROID = 650;
|
||||
const Oid INT2ARRAYOID = 1005;
|
||||
const Oid INT4ARRAYOID = 1007;
|
||||
const Oid TEXTARRAYOID = 1009;
|
||||
const Oid OIDARRAYOID = 1028;
|
||||
const Oid FLOAT4ARRAYOID = 1021;
|
||||
const Oid ACLITEMOID = 1033;
|
||||
const Oid CSTRINGARRAYOID = 1263;
|
||||
const Oid BPCHAROID = 1042;
|
||||
const Oid VARCHAROID = 1043;
|
||||
const Oid DATEOID = 1082;
|
||||
const Oid TIMEOID = 1083;
|
||||
const Oid TIMESTAMPOID = 1114;
|
||||
const Oid TIMESTAMPTZOID = 1184;
|
||||
const Oid INTERVALOID = 1186;
|
||||
const Oid TIMETZOID = 1266;
|
||||
const Oid BITOID = 1560;
|
||||
const Oid VARBITOID = 1562;
|
||||
const Oid NUMERICOID = 1700;
|
||||
const Oid REFCURSOROID = 1790;
|
||||
const Oid REGPROCEDUREOID = 2202;
|
||||
const Oid REGOPEROID = 2203;
|
||||
const Oid REGOPERATOROID = 2204;
|
||||
const Oid REGCLASSOID = 2205;
|
||||
const Oid REGTYPEOID = 2206;
|
||||
const Oid REGROLEOID = 4096;
|
||||
const Oid REGNAMESPACEOID = 4089;
|
||||
const Oid REGTYPEARRAYOID = 2211;
|
||||
const Oid UUIDOID = 2950;
|
||||
const Oid LSNOID = 3220;
|
||||
const Oid TSVECTOROID = 3614;
|
||||
const Oid GTSVECTOROID = 3642;
|
||||
const Oid TSQUERYOID = 3615;
|
||||
const Oid REGCONFIGOID = 3734;
|
||||
const Oid REGDICTIONARYOID = 3769;
|
||||
const Oid JSONBOID = 3802;
|
||||
const Oid INT4RANGEOID = 3904;
|
||||
const Oid RECORDOID = 2249;
|
||||
const Oid RECORDARRAYOID = 2287;
|
||||
const Oid CSTRINGOID = 2275;
|
||||
const Oid ANYOID = 2276;
|
||||
const Oid ANYARRAYOID = 2277;
|
||||
const Oid VOIDOID = 2278;
|
||||
const Oid TRIGGEROID = 2279;
|
||||
const Oid EVTTRIGGEROID = 3838;
|
||||
const Oid LANGUAGE_HANDLEROID = 2280;
|
||||
const Oid INTERNALOID = 2281;
|
||||
const Oid OPAQUEOID = 2282;
|
||||
const Oid ANYELEMENTOID = 2283;
|
||||
const Oid ANYNONARRAYOID = 2776;
|
||||
const Oid ANYENUMOID = 3500;
|
||||
const Oid FDW_HANDLEROID = 3115;
|
||||
const Oid TSM_HANDLEROID = 3310;
|
||||
const Oid ANYRANGEOID = 3831;
|
||||
// const Oid BOOLOID = 16;
|
||||
// const Oid BYTEAOID = 17;
|
||||
// const Oid CHAROID = 18;
|
||||
// const Oid NAMEOID = 19;
|
||||
// const Oid INT8OID = 20;
|
||||
// const Oid INT2OID = 21;
|
||||
// const Oid INT2VECTOROID = 22;
|
||||
// const Oid INT4OID = 23;
|
||||
// const Oid REGPROCOID = 24;
|
||||
// const Oid TEXTOID = 25;
|
||||
// const Oid OIDOID = 26;
|
||||
// const Oid TIDOID = 27;
|
||||
// const Oid XIDOID = 28;
|
||||
// const Oid CIDOID = 29;
|
||||
// const Oid OIDVECTOROID = 30;
|
||||
// const Oid JSONOID = 114;
|
||||
// const Oid XMLOID = 142;
|
||||
// const Oid PGNODETREEOID = 194;
|
||||
// const Oid PGDDLCOMMANDOID = 32;
|
||||
// const Oid POINTOID = 600;
|
||||
// const Oid LSEGOID = 601;
|
||||
// const Oid PATHOID = 602;
|
||||
// const Oid BOXOID = 603;
|
||||
// const Oid POLYGONOID = 604;
|
||||
// const Oid LINEOID = 628;
|
||||
// const Oid FLOAT4OID = 700;
|
||||
// const Oid FLOAT8OID = 701;
|
||||
// const Oid ABSTIMEOID = 702;
|
||||
// const Oid RELTIMEOID = 703;
|
||||
// const Oid TINTERVALOID = 704;
|
||||
// const Oid UNKNOWNOID = 705;
|
||||
// const Oid CIRCLEOID = 718;
|
||||
// const Oid CASHOID = 790;
|
||||
// const Oid MACADDROID = 829;
|
||||
// const Oid INETOID = 869;
|
||||
// const Oid CIDROID = 650;
|
||||
// const Oid INT2ARRAYOID = 1005;
|
||||
// const Oid INT4ARRAYOID = 1007;
|
||||
// const Oid TEXTARRAYOID = 1009;
|
||||
// const Oid OIDARRAYOID = 1028;
|
||||
// const Oid FLOAT4ARRAYOID = 1021;
|
||||
// const Oid ACLITEMOID = 1033;
|
||||
// const Oid CSTRINGARRAYOID = 1263;
|
||||
// const Oid BPCHAROID = 1042;
|
||||
// const Oid VARCHAROID = 1043;
|
||||
// const Oid DATEOID = 1082;
|
||||
// const Oid TIMEOID = 1083;
|
||||
// const Oid TIMESTAMPOID = 1114;
|
||||
// const Oid TIMESTAMPTZOID = 1184;
|
||||
// const Oid INTERVALOID = 1186;
|
||||
// const Oid TIMETZOID = 1266;
|
||||
// const Oid BITOID = 1560;
|
||||
// const Oid VARBITOID = 1562;
|
||||
// const Oid NUMERICOID = 1700;
|
||||
// const Oid REFCURSOROID = 1790;
|
||||
// const Oid REGPROCEDUREOID = 2202;
|
||||
// const Oid REGOPEROID = 2203;
|
||||
// const Oid REGOPERATOROID = 2204;
|
||||
// const Oid REGCLASSOID = 2205;
|
||||
// const Oid REGTYPEOID = 2206;
|
||||
// const Oid REGROLEOID = 4096;
|
||||
// const Oid REGNAMESPACEOID = 4089;
|
||||
// const Oid REGTYPEARRAYOID = 2211;
|
||||
// const Oid UUIDOID = 2950;
|
||||
// const Oid LSNOID = 3220;
|
||||
// const Oid TSVECTOROID = 3614;
|
||||
// const Oid GTSVECTOROID = 3642;
|
||||
// const Oid TSQUERYOID = 3615;
|
||||
// const Oid REGCONFIGOID = 3734;
|
||||
// const Oid REGDICTIONARYOID = 3769;
|
||||
// const Oid JSONBOID = 3802;
|
||||
// const Oid INT4RANGEOID = 3904;
|
||||
// const Oid RECORDOID = 2249;
|
||||
// const Oid RECORDARRAYOID = 2287;
|
||||
// const Oid CSTRINGOID = 2275;
|
||||
// const Oid ANYOID = 2276;
|
||||
// const Oid ANYARRAYOID = 2277;
|
||||
// const Oid VOIDOID = 2278;
|
||||
// const Oid TRIGGEROID = 2279;
|
||||
// const Oid EVTTRIGGEROID = 3838;
|
||||
// const Oid LANGUAGE_HANDLEROID = 2280;
|
||||
// const Oid INTERNALOID = 2281;
|
||||
// const Oid OPAQUEOID = 2282;
|
||||
// const Oid ANYELEMENTOID = 2283;
|
||||
// const Oid ANYNONARRAYOID = 2776;
|
||||
// const Oid ANYENUMOID = 3500;
|
||||
// const Oid FDW_HANDLEROID = 3115;
|
||||
// const Oid TSM_HANDLEROID = 3310;
|
||||
// const Oid ANYRANGEOID = 3831;
|
||||
|
||||
|
||||
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(),
|
||||
|
|
@ -173,11 +173,11 @@ Oid Pgsql::ElemOidFromArrayOid(Oid oid)
|
|||
return l.array < r.array;
|
||||
});
|
||||
if (iter == g_ArrayToElem.end())
|
||||
throw std::runtime_error("ElemOidFromArrayOid Oid not found");
|
||||
return InvalidOid;
|
||||
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(),
|
||||
ElemArray{oid, oid},
|
||||
|
|
@ -186,7 +186,6 @@ Oid Pgsql::ArrayOidFromElemOid(Oid oid)
|
|||
return l.elem < r.elem;
|
||||
});
|
||||
if (iter == g_ElemToArray.end())
|
||||
throw std::runtime_error("ElemOidFromArrayOid Oid not found");
|
||||
return InvalidOid;
|
||||
return iter->array;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ namespace Pgsql {
|
|||
constexpr Oid regoperator_oid = 2204;
|
||||
constexpr Oid regclass_oid = 2205;
|
||||
constexpr Oid regtype_oid = 2206;
|
||||
constexpr Oid any_oid = 2276;
|
||||
constexpr Oid uuid_oid = 2950;
|
||||
constexpr Oid txid_snapshot_oid = 2970;
|
||||
constexpr Oid pg_lsn_oid = 3220;
|
||||
|
|
@ -140,8 +141,19 @@ namespace Pgsql {
|
|||
constexpr Oid regnamespace_array_oid = 4090;
|
||||
constexpr Oid regrole_array_oid = 4097;
|
||||
|
||||
Oid ElemOidFromArrayOid(Oid oid);
|
||||
Oid ArrayOidFromElemOid(Oid oid);
|
||||
/** If oid is an array oid then it returns the corresponding element 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>
|
||||
class OidFor {
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ using namespace Pgsql;
|
|||
|
||||
TEST(Pgsql_Value, test_int4)
|
||||
{
|
||||
Pgsql::Value v("1", INT4OID);
|
||||
Pgsql::Value v("1", int4_oid);
|
||||
int i = (int)v;
|
||||
ASSERT_EQ(i, 1);
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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 exp(QDate(2017, 12, 1), QTime(9, 38, 17, 340),
|
||||
Qt::OffsetFromUTC, 2*3600);
|
||||
|
|
@ -35,21 +35,21 @@ TEST(Pgsql_Value, test_QDateTime_2)
|
|||
|
||||
TEST(Pgsql_Value, test_QDate)
|
||||
{
|
||||
Pgsql::Value v("2017-10-22", DATEOID);
|
||||
Pgsql::Value v("2017-10-22", date_oid);
|
||||
QDate d = v;
|
||||
ASSERT_EQ(d, QDate(2017, 10, 22));
|
||||
}
|
||||
|
||||
TEST(Pgsql_Value, test_QTime)
|
||||
{
|
||||
Pgsql::Value v("12:34:56", TIMEOID);
|
||||
Pgsql::Value v("12:34:56", time_oid);
|
||||
QTime t = v;
|
||||
ASSERT_EQ(t, QTime(12, 34, 56));
|
||||
}
|
||||
|
||||
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;
|
||||
ASSERT_EQ(t, QTime(9, 38, 17, 340));
|
||||
}
|
||||
|
|
@ -58,19 +58,19 @@ TEST(Pgsql_Value, test_QTimeMS)
|
|||
|
||||
TEST(Pgsql_Value, isString_int4)
|
||||
{
|
||||
Pgsql::Value v("1", INT4OID);
|
||||
Pgsql::Value v("1", int4_oid);
|
||||
ASSERT_EQ(v.isString(), false);
|
||||
}
|
||||
|
||||
TEST(Pgsql_Value, isString_varchar)
|
||||
{
|
||||
Pgsql::Value v("1", VARCHAROID);
|
||||
Pgsql::Value v("1", varchar_oid);
|
||||
ASSERT_EQ(v.isString(), true);
|
||||
}
|
||||
|
||||
TEST(Pgsql_Value, getAsVector_Ints)
|
||||
{
|
||||
Pgsql::Value v("1 2", ANYOID);
|
||||
Pgsql::Value v("1 2", any_oid);
|
||||
std::vector<int> r;
|
||||
v.getAsVector<int>(std::back_inserter(r));
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ TEST(Pgsql_Value, getAsVector_Ints)
|
|||
|
||||
TEST(Pgsql_Value, getAsArray_Ints)
|
||||
{
|
||||
Pgsql::Value v("{1,2}", TEXTARRAYOID);
|
||||
Pgsql::Value v("{1,2}", text_array_oid);
|
||||
std::vector<int> r;
|
||||
v.getAsArray<int>(std::back_inserter(r));
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ TEST(Pgsql_Value, getAsArray_Ints)
|
|||
|
||||
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;
|
||||
v.getAsArray<QDateTime>(std::inserter(r, r.end()));
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ TEST(Pgsql_Value, getAsArray_QDateTime)
|
|||
|
||||
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;
|
||||
try {
|
||||
v.getAsArray<int>(std::back_inserter(r));
|
||||
|
|
@ -117,7 +117,7 @@ TEST(Pgsql_Value, getAsArray_throws_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;
|
||||
try {
|
||||
v.getAsArray<int>(std::back_inserter(r), -1);
|
||||
|
|
@ -132,7 +132,7 @@ TEST(Pgsql_Value, getAsArray_default_on_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;
|
||||
try {
|
||||
v.getAsArray<int>(std::back_inserter(r), NullHandling::Ignore);
|
||||
|
|
@ -146,7 +146,7 @@ TEST(Pgsql_Value, getAsArray_ignore_NULL)
|
|||
|
||||
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;
|
||||
try {
|
||||
v.getAsArrayOfOptional<int>(std::back_inserter(r));
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
include(gtest_dependency.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
CONFIG += console c++14
|
||||
CONFIG += console c++17
|
||||
CONFIG -= app_bundle
|
||||
CONFIG += thread
|
||||
CONFIG += qt
|
||||
|
||||
QT += core
|
||||
QT += core widgets
|
||||
|
||||
QMAKE_CXXFLAGS += /std:c++17
|
||||
LIBS += -LC:\VSproj\boost32\lib -LC:/PROG/LIB -lws2_32 -llibpq
|
||||
|
||||
HEADERS +=
|
||||
|
||||
|
|
@ -17,7 +20,9 @@ SOURCES += main.cpp \
|
|||
tst_scopeguard.cpp \
|
||||
tst_CsvWriter.cpp \
|
||||
tst_PasswordManager.cpp \
|
||||
tst_ParamJson.cpp
|
||||
tst_ParamJson.cpp \
|
||||
tst_CodeBuilder.cpp \
|
||||
tst_NameManglingRules.cpp
|
||||
|
||||
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
|
||||
|
|
@ -60,3 +65,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(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../pglablib/debug/pglablib.lib
|
||||
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
|
||||
|
|
|
|||
231
tests/pglabtests/tst_CodeBuilder.cpp
Normal file
231
tests/pglabtests/tst_CodeBuilder.cpp
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
#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;
|
||||
|
||||
|
||||
|
||||
// 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, " ");
|
||||
}
|
||||
|
||||
|
||||
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>");
|
||||
}
|
||||
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include "CsvWriter.h"
|
||||
#include <QTextStream>
|
||||
#include <QByteArray>
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <gmock/gmock-matchers.h>
|
||||
#include "ExplainTreeModelItem.h"
|
||||
#include "json/json.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
54
tests/pglabtests/tst_NameManglingRules.cpp
Normal file
54
tests/pglabtests/tst_NameManglingRules.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#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;
|
||||
|
||||
//QString replaceSpaceWith; ///< default is empty string which means remove spaces
|
||||
r.replaceSpaceWith = std::get<0>(p);
|
||||
|
||||
//CollisionHandling CollisionHandling = CollisionHandling::Restrict;
|
||||
//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;
|
||||
};
|
||||
|
||||
|
||||
TEST_P(NameManglingRulesTest, test1)
|
||||
{
|
||||
ASSERT_EQ(rules.replaceSpaceWith, std::get<0>(GetParam()));
|
||||
}
|
||||
|
||||
TEST_P(NameManglingRulesTest, test2)
|
||||
{
|
||||
ASSERT_EQ(rules.camelCase, std::get<2>(GetParam()));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(InstantiationName1,
|
||||
NameManglingRulesTest,
|
||||
::testing::Combine(
|
||||
::testing::Values("", "_", "+"),
|
||||
::testing::Values(NameManglingRules::CaseConversion::AsIs,
|
||||
NameManglingRules::CaseConversion::Lower,
|
||||
NameManglingRules::CaseConversion::Upper),
|
||||
::testing::Bool()
|
||||
));
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include <gmock/gmock-matchers.h>
|
||||
#include "ParamListModel.h"
|
||||
#include "ParamListJson.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include "PasswordManager.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include "SqlLexer.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include "Expected.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include "ScopeGuard.h"
|
||||
#include "PrintTo_Qt.h"
|
||||
|
||||
using namespace testing;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue