wip: codegenerator, basic widget present for showing the generated code and specifying
parameters. Some code is also generated but it is not complete yet. minimum still required - field assignments - properly format and escape the query string
This commit is contained in:
parent
daf9536bed
commit
f5145f36ed
19 changed files with 380 additions and 32 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#include "CodeBuilder.h"
|
||||
#include "FormatToStream.h"
|
||||
#include "Pgsql_Result.h"
|
||||
#include "IndentationConfig.h"
|
||||
#include "LanguageConfig.h"
|
||||
|
|
@ -6,31 +7,41 @@
|
|||
#include "util.h"
|
||||
#include <QTextStream>
|
||||
|
||||
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result)
|
||||
void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query, const Pgsql::Result &result, QString structname)
|
||||
{
|
||||
// %1 query string
|
||||
// %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%/"
|
||||
"}";
|
||||
QString loop_start_template = R"__(Pgsql::Result result = conn.query(/%queryliteral%/);
|
||||
for (auto row: result) {
|
||||
Pgsql::Col col(row);
|
||||
/%structname%/ v;
|
||||
/%assignfields%/
|
||||
})__";
|
||||
|
||||
// %field_name%
|
||||
// %column_name%
|
||||
// %column_index%
|
||||
QString assign_result_field_template = "col >> v./%field_name%/";
|
||||
QString assign_result_field_template = "col >> v./%fieldname%/";
|
||||
QString query_string_literal = ConvertToMultiLineCString(query);
|
||||
|
||||
ColumnDataList columnData = createColumnDataList(result);
|
||||
|
||||
auto get_var_func = [&] (QTextStream &out, QString var) {
|
||||
if (var == "structname") out << structname;
|
||||
//else if (var == "assign_fields") GenFieldAssignments(out);
|
||||
else if (var == "queryliteral") out << query;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// [optional] Gen declaration of result structure
|
||||
GenReturnStructDefinition(q, result);
|
||||
GenReturnStructDefinition(q, result, structname);
|
||||
|
||||
// assume we have connection? What name???
|
||||
FormatToStream(q, loop_start_template, get_var_func);
|
||||
|
||||
// gen code for creating and executing statement
|
||||
// - bind parameters
|
||||
|
|
@ -40,16 +51,20 @@ void CodeBuilder::GenCodeForExecutingQuery(QTextStream &q, const QString &query,
|
|||
|
||||
}
|
||||
|
||||
void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result) const
|
||||
void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result &result, QString structname) const
|
||||
{
|
||||
std::shared_ptr<const StructureTemplate> templ = m_configuration->structureTemplate();
|
||||
|
||||
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);
|
||||
|
||||
auto struct_callback = [&] (QTextStream &out, QString var) {
|
||||
if (var == "structname") out << structname;
|
||||
};
|
||||
// Make struct start
|
||||
q << QString(templ->m_startTemplate).arg(struct_name);
|
||||
//q << QString(templ->m_startTemplate).arg(struct_name);
|
||||
FormatToStream(q, templ->m_startTemplate, struct_callback);
|
||||
// Process fields
|
||||
for (int column = 0; column < result.cols(); ++column) {
|
||||
QString res_col_name = result.getColName(column);
|
||||
|
|
@ -71,7 +86,9 @@ void CodeBuilder::GenReturnStructDefinition(QTextStream &q, const Pgsql::Result
|
|||
// - null pointer (useful for languages where this has no cost, other cases boolean flags will be more performant)
|
||||
}
|
||||
// Finish struct
|
||||
q << QString(templ->m_endTemplate).arg(struct_name);
|
||||
|
||||
//q << QString(templ->m_endTemplate).arg(struct_name);
|
||||
FormatToStream(q, templ->m_endTemplate, struct_callback);
|
||||
}
|
||||
|
||||
QString CodeBuilder::columnNameToVariableName(QString column_name) const
|
||||
|
|
@ -88,6 +105,22 @@ void CodeBuilder::genFieldDeclaration(QTextStream &q, const QString &format, con
|
|||
{
|
||||
QString field_name = columnNameToVariableName(column_name);
|
||||
QString type_name = getTypeName(column_type);
|
||||
q << QString(format).arg(field_name).arg(type_name);
|
||||
//q << QString(format).arg(field_name).arg(type_name);
|
||||
FormatToStream(q, format, [&] (QTextStream &out, QString var) {
|
||||
if (var == "typename") out << type_name;
|
||||
else if (var == "varname") out << field_name;
|
||||
});
|
||||
}
|
||||
|
||||
CodeBuilder::ColumnDataList CodeBuilder::createColumnDataList(const Pgsql::Result &result)
|
||||
{
|
||||
ColumnDataList list;
|
||||
list.reserve(static_cast<size_t>(result.cols()));
|
||||
for (int column = 0; column < result.cols(); ++column) {
|
||||
Oid type_oid = result.type(column);
|
||||
QString column_name = result.getColName(column);
|
||||
QString field_name = columnNameToVariableName(column_name);
|
||||
list.push_back({type_oid, column_name, field_name});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,19 @@
|
|||
|
||||
#include "Pgsql_declare.h"
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
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;
|
||||
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 Pgsql::Result &result, QString structname) const;
|
||||
|
||||
// Generating code for performing query and going through the result
|
||||
// - Code for executing the query
|
||||
|
|
@ -20,9 +25,21 @@ public:
|
|||
QString columnNameToVariableName(QString column_name) const;
|
||||
QString getTypeName(Oid dbtype) const;
|
||||
private:
|
||||
class ColumnData {
|
||||
public:
|
||||
Oid oid;
|
||||
QString columnName;
|
||||
QString varName; ///< either field of the struct or in loop local var name
|
||||
};
|
||||
using ColumnDataList = std::vector<ColumnData>;
|
||||
|
||||
std::shared_ptr<const LanguageConfig> m_configuration;
|
||||
|
||||
|
||||
void GenFieldAssignments(QTextStream &q, const Pgsql::Result &result);
|
||||
void genFieldDeclaration(QTextStream &q, const QString &format, const QString &column_name, Oid column_type) const;
|
||||
|
||||
ColumnDataList createColumnDataList(const Pgsql::Result &result);
|
||||
};
|
||||
|
||||
#endif // CODEBUILDER_H
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
#include "DefaultConfigs.h"
|
||||
#include "IndentationConfig.h"
|
||||
#include "LanguageConfig.h"
|
||||
#include "NameManglingRules.h"
|
||||
#include "StructureTemplate.h"
|
||||
#include "TypeMappings.h"
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
TypeMappings GetDefaultCppTypeMappings()
|
||||
std::shared_ptr<const TypeMappings> GetDefaultCppTypeMappings()
|
||||
{
|
||||
TypeMappings result = {
|
||||
auto tm = std::make_shared<TypeMappings>();
|
||||
*tm = {
|
||||
{ bool_oid, "bool" },
|
||||
{ char_oid, "char" },
|
||||
{ name_oid, "std::string" },
|
||||
|
|
@ -19,13 +23,27 @@ TypeMappings GetDefaultCppTypeMappings()
|
|||
{ float4_oid, "float" },
|
||||
{ float8_oid, "double" }
|
||||
};
|
||||
return result;
|
||||
tm->setDefaultStringType("std::string");
|
||||
tm->setDefaultContainerType("std::vector<%1>");
|
||||
return tm;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<LanguageConfig> buildDefaultCppLanguageConfig()
|
||||
{
|
||||
return std::make_shared<LanguageConfig>();
|
||||
auto config = std::make_shared<LanguageConfig>();
|
||||
config->setTypeMappings(GetDefaultCppTypeMappings());
|
||||
config->setNameManglingRules(std::make_shared<NameManglingRules>());
|
||||
|
||||
auto st_templ = std::make_shared<StructureTemplate>();
|
||||
st_templ->m_startTemplate = "class /%structname%/ {\npublic:\n";
|
||||
st_templ->m_endTemplate = "};\n"; // };
|
||||
st_templ->m_fieldTemplate = "/%typename%/ /%varname%/;";
|
||||
//st_templ->m_fieldSeparator;
|
||||
config->setStructureTemplate(st_templ);
|
||||
config->setIndentationConfig(std::make_shared<IndentationConfig>());
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
std::shared_ptr<const LanguageConfig> getDefaultCppLanguageConfig()
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ public:
|
|||
QString columnNameToFieldName(const QString& column_name) const;
|
||||
QString getTypeName(Oid dbtype) const;
|
||||
|
||||
void setNameManglingRules(std::shared_ptr<const NameManglingRules> name_mangling_rules)
|
||||
{
|
||||
m_varNaming = name_mangling_rules;
|
||||
}
|
||||
|
||||
std::shared_ptr<const TypeMappings> typeMappings() const { return m_typeMappings; }
|
||||
void setTypeMappings(std::shared_ptr<const TypeMappings> type_mappings)
|
||||
{
|
||||
|
|
@ -29,10 +34,20 @@ public:
|
|||
return m_structureTemplate;
|
||||
}
|
||||
|
||||
void setStructureTemplate(std::shared_ptr<const StructureTemplate> structure_template)
|
||||
{
|
||||
m_structureTemplate = structure_template;
|
||||
}
|
||||
|
||||
std::shared_ptr<const IndentationConfig> indentationConfig() const
|
||||
{
|
||||
return m_indentationConfig;
|
||||
}
|
||||
|
||||
void setIndentationConfig(std::shared_ptr<const IndentationConfig> indentation_config)
|
||||
{
|
||||
m_indentationConfig = indentation_config;
|
||||
}
|
||||
private:
|
||||
/** Default template for declaring a variable of the correct type.
|
||||
* exmaple: "{$type} {$varname};"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue