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:
eelke 2018-09-18 11:53:19 +02:00
parent daf9536bed
commit f5145f36ed
19 changed files with 380 additions and 32 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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()

View file

@ -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};"