pgLab/pglablib/codebuilder/CodeBuilder.cpp
2018-09-17 15:43:26 +02:00

93 lines
3.1 KiB
C++

#include "CodeBuilder.h"
#include "Pgsql_Result.h"
#include "IndentationConfig.h"
#include "LanguageConfig.h"
#include "StructureTemplate.h"
#include "util.h"
#include <QTextStream>
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);
}