570 lines
18 KiB
Plaintext
570 lines
18 KiB
Plaintext
<%inc#include "create_model.h"
|
|
using namespace drogon_ctl;
|
|
%>
|
|
/**
|
|
*
|
|
* [[className]].h
|
|
* DO NOT EDIT. This file is generated by drogon_ctl
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
#include <drogon/orm/Result.h>
|
|
#include <drogon/orm/Row.h>
|
|
#include <drogon/orm/Field.h>
|
|
#include <drogon/orm/SqlBinder.h>
|
|
#include <drogon/orm/Mapper.h>
|
|
#include <drogon/orm/BaseBuilder.h>
|
|
#ifdef __cpp_impl_coroutine
|
|
#include <drogon/orm/CoroMapper.h>
|
|
#endif
|
|
#include <trantor/utils/Date.h>
|
|
#include <trantor/utils/Logger.h>
|
|
#include <json/json.h>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <tuple>
|
|
#include <stdint.h>
|
|
#include <iostream>
|
|
|
|
namespace drogon
|
|
{
|
|
namespace orm
|
|
{
|
|
class DbClient;
|
|
using DbClientPtr = std::shared_ptr<DbClient>;
|
|
}
|
|
}
|
|
namespace drogon_model
|
|
{
|
|
namespace [[dbName]]
|
|
{
|
|
<%c++
|
|
auto &schema=@@.get<std::string>("schema");
|
|
if(!schema.empty())
|
|
{
|
|
$$<<"namespace "<<schema<<"\n";
|
|
$$<<"{\n";
|
|
}
|
|
std::vector<std::string> relationshipClassNames;
|
|
auto &relationships=@@.get<std::vector<Relationship>>("relationships");
|
|
for(auto &relationship : relationships)
|
|
{
|
|
auto &name = relationship.targetTableName();
|
|
auto relationshipClassName = nameTransform(name, true);
|
|
relationshipClassNames.push_back(relationshipClassName);
|
|
if(relationship.type() == Relationship::Type::ManyToMany)
|
|
{
|
|
auto &pivotTableName = relationship.pivotTable().tableName();
|
|
auto pivotTableClassName = nameTransform(pivotTableName, true);
|
|
relationshipClassNames.push_back(pivotTableClassName);
|
|
}
|
|
}
|
|
std::sort(relationshipClassNames.begin(), relationshipClassNames.end());
|
|
relationshipClassNames.erase(std::unique(relationshipClassNames.begin(), relationshipClassNames.end()), relationshipClassNames.end());
|
|
for(std::string &relationshipClassName : relationshipClassNames)
|
|
{
|
|
%>
|
|
class {%relationshipClassName%};
|
|
<%c++
|
|
}
|
|
%>
|
|
|
|
class [[className]]
|
|
{
|
|
public:
|
|
struct Cols
|
|
{
|
|
<%c++
|
|
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|
for(size_t i=0;i<cols.size();i++)
|
|
{
|
|
$$<<" static const std::string _"<<cols[i].colName_<<";\n";
|
|
}
|
|
%>
|
|
};
|
|
|
|
const static int primaryKeyNumber;
|
|
const static std::string tableName;
|
|
const static bool hasPrimaryKey;
|
|
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
|
const static std::string primaryKeyName;
|
|
<%c++if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
|
using PrimaryKeyType = [[primaryKeyType]];
|
|
const PrimaryKeyType &getPrimaryKey() const;
|
|
<%c++}else{%>
|
|
using PrimaryKeyType = void;
|
|
int getPrimaryKey() const { assert(false); return 0; }
|
|
<%c++}%>
|
|
<%c++}else{
|
|
auto pkTypes=@@.get<std::vector<std::string>>("primaryKeyType");
|
|
std::string typelist;
|
|
for(size_t i=0;i<pkTypes.size();i++)
|
|
{
|
|
typelist += pkTypes[i];
|
|
if(i<(pkTypes.size()-1))
|
|
typelist += ",";
|
|
}
|
|
%>
|
|
const static std::vector<std::string> primaryKeyName;
|
|
using PrimaryKeyType = std::tuple<{%typelist%}>;//<%c++
|
|
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
|
for(size_t i=0;i<pkName.size();i++)
|
|
{
|
|
$$<<pkName[i];
|
|
if(i<(pkName.size()-1))
|
|
$$<<",";
|
|
}
|
|
%>
|
|
|
|
PrimaryKeyType getPrimaryKey() const;
|
|
<%c++}%>
|
|
|
|
/**
|
|
* @brief constructor
|
|
* @param r One row of records in the SQL query result.
|
|
* @param indexOffset Set the offset to -1 to access all columns by column names,
|
|
* otherwise access all columns by offsets.
|
|
* @note If the SQL is not a style of 'select * from table_name ...' (select all
|
|
* columns by an asterisk), please set the offset to -1.
|
|
*/
|
|
explicit [[className]](const drogon::orm::Row &r, const ssize_t indexOffset = 0) noexcept;
|
|
|
|
/**
|
|
* @brief constructor
|
|
* @param pJson The json object to construct a new instance.
|
|
*/
|
|
explicit [[className]](const Json::Value &pJson) noexcept(false);
|
|
|
|
/**
|
|
* @brief constructor
|
|
* @param pJson The json object to construct a new instance.
|
|
* @param pMasqueradingVector The aliases of table columns.
|
|
*/
|
|
[[className]](const Json::Value &pJson, const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
|
|
|
[[className]]() = default;
|
|
|
|
void updateByJson(const Json::Value &pJson) noexcept(false);
|
|
void updateByMasqueradedJson(const Json::Value &pJson,
|
|
const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
|
static bool validateJsonForCreation(const Json::Value &pJson, std::string &err);
|
|
static bool validateMasqueradedJsonForCreation(const Json::Value &,
|
|
const std::vector<std::string> &pMasqueradingVector,
|
|
std::string &err);
|
|
static bool validateJsonForUpdate(const Json::Value &pJson, std::string &err);
|
|
static bool validateMasqueradedJsonForUpdate(const Json::Value &,
|
|
const std::vector<std::string> &pMasqueradingVector,
|
|
std::string &err);
|
|
static bool validJsonOfField(size_t index,
|
|
const std::string &fieldName,
|
|
const Json::Value &pJson,
|
|
std::string &err,
|
|
bool isForCreation);
|
|
|
|
<%c++
|
|
for(const auto &col:cols)
|
|
{
|
|
$$<<" /** For column "<<col.colName_<<" */\n";
|
|
if(!col.colType_.empty())
|
|
{
|
|
$$<<" ///Get the value of the column "<<col.colName_<<", returns the default value if the column is null\n";
|
|
$$<<" const "<<col.colType_<<" &getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
|
if(col.colType_=="std::vector<char>")
|
|
{
|
|
$$<<" ///Return the column value by std::string with binary data\n";
|
|
$$<<" std::string getValueOf"<<col.colTypeName_<<"AsString() const noexcept;\n";
|
|
}
|
|
$$<<" ///Return a shared_ptr object pointing to the column const value, or an empty shared_ptr object if the column is null\n";
|
|
$$<<" const std::shared_ptr<"<<col.colType_<<"> &get"<<col.colTypeName_<<"() const noexcept;\n";
|
|
|
|
$$<<" ///Set the value of the column "<<col.colName_<<"\n";
|
|
$$<<" void set"<<col.colTypeName_<<"(const "<<col.colType_<<" &p"<<col.colTypeName_<<") noexcept;\n";
|
|
if(col.colType_=="std::string")
|
|
$$<<" void set"<<col.colTypeName_<<"("<<col.colType_<<" &&p"<<col.colTypeName_<<") noexcept;\n";
|
|
if(col.colType_=="std::vector<char>")
|
|
{
|
|
$$<<" void set"<<col.colTypeName_<<"(const std::string &p"<<col.colTypeName_<<") noexcept;\n";
|
|
}
|
|
if(!col.notNull_)
|
|
{
|
|
$$<<" void set"<<col.colTypeName_<<"ToNull() noexcept;\n";
|
|
}
|
|
|
|
}
|
|
else
|
|
$$<<" //FIXME!!"<<" getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
|
$$<<"\n";
|
|
}
|
|
%>
|
|
|
|
static size_t getColumnNumber() noexcept { return {% cols.size() %}; }
|
|
static const std::string &getColumnName(size_t index) noexcept(false);
|
|
|
|
Json::Value toJson() const;
|
|
Json::Value toMasqueradedJson(const std::vector<std::string> &pMasqueradingVector) const;
|
|
/// Relationship interfaces
|
|
<%c++
|
|
for(auto &relationship : relationships)
|
|
{
|
|
if(relationship.targetKey().empty() || relationship.originalKey().empty())
|
|
{
|
|
continue;
|
|
}
|
|
auto &name=relationship.targetTableName();
|
|
auto relationshipClassName=nameTransform(name, true);
|
|
auto relationshipValName=nameTransform(name, false);
|
|
auto alias=relationship.targetTableAlias();
|
|
auto aliasValName=nameTransform(alias, false);
|
|
if(relationship.type() == Relationship::Type::HasOne)
|
|
{
|
|
if(!alias.empty())
|
|
{
|
|
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
{
|
|
alias[0] += ('A' - 'a');
|
|
}
|
|
std::string alind(alias.length(), ' ');
|
|
%>
|
|
{%relationshipClassName%} get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
else
|
|
{
|
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
|
%>
|
|
{%relationshipClassName%} get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%relationshipClassInde%} const std::function<void({%relationshipClassName%})> &rcb,
|
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
}
|
|
else if(relationship.type() == Relationship::Type::HasMany)
|
|
{
|
|
if(!alias.empty())
|
|
{
|
|
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
{
|
|
alias[0] += ('A' - 'a');
|
|
}
|
|
std::string alind(alias.length(), ' ');
|
|
%>
|
|
std::vector<{%relationshipClassName%}> get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
else
|
|
{
|
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
|
%>
|
|
std::vector<{%relationshipClassName%}> get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%relationshipClassInde%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
}
|
|
else if(relationship.type() == Relationship::Type::ManyToMany)
|
|
{
|
|
auto &pivotTableName=relationship.pivotTable().tableName();
|
|
auto pivotTableClassName=nameTransform(pivotTableName, true);
|
|
if(!alias.empty())
|
|
{
|
|
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
{
|
|
alias[0] += ('A' - 'a');
|
|
}
|
|
std::string alind(alias.length(), ' ');
|
|
%>
|
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
else
|
|
{
|
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
|
%>
|
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
|
{%relationshipClassInde%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
|
<%c++
|
|
}
|
|
}
|
|
}
|
|
%>
|
|
private:
|
|
friend drogon::orm::Mapper<[[className]]>;
|
|
friend drogon::orm::BaseBuilder<[[className]], true, true>;
|
|
friend drogon::orm::BaseBuilder<[[className]], true, false>;
|
|
friend drogon::orm::BaseBuilder<[[className]], false, true>;
|
|
friend drogon::orm::BaseBuilder<[[className]], false, false>;
|
|
#ifdef __cpp_impl_coroutine
|
|
friend drogon::orm::CoroMapper<[[className]]>;
|
|
#endif
|
|
static const std::vector<std::string> &insertColumns() noexcept;
|
|
void outputArgs(drogon::orm::internal::SqlBinder &binder) const;
|
|
const std::vector<std::string> updateColumns() const;
|
|
void updateArgs(drogon::orm::internal::SqlBinder &binder) const;
|
|
///For mysql or sqlite3
|
|
void updateId(const uint64_t id);
|
|
<%c++
|
|
for(auto col:cols)
|
|
{
|
|
if(!col.colType_.empty())
|
|
$$<<" std::shared_ptr<"<<col.colType_<<"> "<<col.colValName_<<"_;\n";
|
|
}
|
|
%>
|
|
struct MetaData
|
|
{
|
|
const std::string colName_;
|
|
const std::string colType_;
|
|
const std::string colDatabaseType_;
|
|
const ssize_t colLength_;
|
|
const bool isAutoVal_;
|
|
const bool isPrimaryKey_;
|
|
const bool notNull_;
|
|
};
|
|
static const std::vector<MetaData> metaData_;
|
|
bool dirtyFlag_[{%cols.size()%}]={ false };
|
|
public:
|
|
static const std::string &sqlForFindingByPrimaryKey()
|
|
{
|
|
<%c++
|
|
auto rdbms=@@.get<std::string>("rdbms");
|
|
if(@@.get<int>("hasPrimaryKey")<=1){
|
|
if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
|
static const std::string sql="select * from " + tableName + " where [[primaryKeyName]] = {%(rdbms=="postgresql"?"$1":"?")%}";
|
|
<%c++}else{%>
|
|
static const std::string sql="";
|
|
<%c++}%>
|
|
<%c++}else{
|
|
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
|
%>
|
|
static const std::string sql="select * from " + tableName + " where <%c++
|
|
for(size_t i=0;i<pkName.size();i++)
|
|
{
|
|
if(rdbms=="postgresql")
|
|
{
|
|
$$<<pkName[i]<<" = $"<<i+1;
|
|
}
|
|
else
|
|
{
|
|
$$<<pkName[i]<<" = ?";
|
|
}
|
|
if(i<(pkName.size()-1))
|
|
$$<<" and ";
|
|
}
|
|
$$<<"\";\n";
|
|
}
|
|
%>
|
|
return sql;
|
|
}
|
|
|
|
static const std::string &sqlForDeletingByPrimaryKey()
|
|
{
|
|
<%c++
|
|
if(@@.get<int>("hasPrimaryKey")<=1){
|
|
if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
|
static const std::string sql="delete from " + tableName + " where [[primaryKeyName]] = {%(rdbms=="postgresql"?"$1":"?")%}";
|
|
<%c++}else{%>
|
|
static const std::string sql="";
|
|
<%c++}%>
|
|
<%c++}else{
|
|
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
|
%>
|
|
static const std::string sql="delete from " + tableName + " where <%c++
|
|
for(size_t i=0;i<pkName.size();i++)
|
|
{
|
|
if(rdbms=="postgresql")
|
|
{
|
|
$$<<pkName[i]<<" = $"<<i+1;
|
|
}
|
|
else
|
|
{
|
|
$$<<pkName[i]<<" = ?";
|
|
}
|
|
if(i<(pkName.size()-1))
|
|
$$<<" and ";
|
|
}
|
|
$$<<"\";\n";
|
|
}
|
|
%>
|
|
return sql;
|
|
}
|
|
std::string sqlForInserting(bool &needSelection) const
|
|
{
|
|
std::string sql="insert into " + tableName + " (";
|
|
size_t parametersCount = 0;
|
|
needSelection = false;
|
|
<%c++
|
|
bool selFlag=false;
|
|
for(size_t i=0;i<cols.size();i++)
|
|
{
|
|
if(cols[i].isAutoVal_)
|
|
{
|
|
if(@@.get<std::string>("rdbms")=="sqlite3")
|
|
{
|
|
continue;
|
|
}
|
|
if(@@.get<int>("hasPrimaryKey")>0)
|
|
{
|
|
selFlag = true;
|
|
}
|
|
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
|
$$<<" ++parametersCount;\n";
|
|
continue;
|
|
}
|
|
if(cols[i].colType_.empty())
|
|
continue;
|
|
if(cols[i].hasDefaultVal_)
|
|
{
|
|
if(@@.get<std::string>("rdbms")!="sqlite3")
|
|
{
|
|
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
|
$$<<" ++parametersCount;\n";
|
|
}
|
|
else
|
|
{
|
|
%>
|
|
if(dirtyFlag_[{%i%}])
|
|
{
|
|
sql += "{%cols[i].colName_%},";
|
|
++parametersCount;
|
|
}
|
|
<%c++
|
|
}
|
|
if(@@.get<int>("hasPrimaryKey")>0||@@.get<std::string>("rdbms")=="postgresql")
|
|
{
|
|
%>
|
|
if(!dirtyFlag_[{%i%}])
|
|
{
|
|
needSelection=true;
|
|
}
|
|
<%c++
|
|
}
|
|
}
|
|
else
|
|
{
|
|
%>
|
|
if(dirtyFlag_[{%i%}])
|
|
{
|
|
sql += "{%cols[i].colName_%},";
|
|
++parametersCount;
|
|
}
|
|
<%c++
|
|
}
|
|
}
|
|
if(selFlag)
|
|
{
|
|
$$<<" needSelection=true;\n";
|
|
}
|
|
%>
|
|
if(parametersCount > 0)
|
|
{
|
|
sql[sql.length()-1]=')';
|
|
sql += " values (";
|
|
}
|
|
else
|
|
sql += ") values (";
|
|
|
|
<%c++
|
|
if(@@.get<std::string>("rdbms")=="postgresql")
|
|
{
|
|
%>
|
|
int placeholder=1;
|
|
char placeholderStr[64];
|
|
size_t n=0;
|
|
<%c++
|
|
}
|
|
for(size_t i=0;i<cols.size();i++)
|
|
{
|
|
if(cols[i].isAutoVal_)
|
|
{
|
|
if(@@.get<std::string>("rdbms")!="sqlite3")
|
|
{
|
|
%>
|
|
sql +="default,";
|
|
<%c++
|
|
}
|
|
continue;
|
|
}
|
|
if(cols[i].colType_.empty())
|
|
continue;
|
|
%>
|
|
if(dirtyFlag_[{%i%}])
|
|
{
|
|
<%c++
|
|
if(@@.get<std::string>("rdbms")=="postgresql")
|
|
{
|
|
%>
|
|
n = snprintf(placeholderStr,sizeof(placeholderStr),"$%d,",placeholder++);
|
|
sql.append(placeholderStr, n);
|
|
<%c++
|
|
}else
|
|
{
|
|
%>
|
|
sql.append("?,");
|
|
|
|
<%c++
|
|
}
|
|
%>
|
|
}
|
|
<%c++
|
|
if(cols[i].hasDefaultVal_&&@@.get<std::string>("rdbms")!="sqlite3")
|
|
{
|
|
%>
|
|
else
|
|
{
|
|
sql +="default,";
|
|
}
|
|
<%c++
|
|
}
|
|
}
|
|
%>
|
|
if(parametersCount > 0)
|
|
{
|
|
sql.resize(sql.length() - 1);
|
|
}
|
|
<%c++
|
|
if(rdbms=="postgresql")
|
|
{
|
|
%>
|
|
if(needSelection)
|
|
{
|
|
sql.append(") returning *");
|
|
}
|
|
else
|
|
{
|
|
sql.append(1, ')');
|
|
}
|
|
<%c++
|
|
}
|
|
else
|
|
{
|
|
$$<<" sql.append(1, ')');\n";
|
|
}
|
|
%>
|
|
LOG_TRACE << sql;
|
|
return sql;
|
|
}
|
|
};
|
|
<%c++
|
|
if(!schema.empty())
|
|
{
|
|
$$<<"} // namespace "<<schema<<"\n";
|
|
}
|
|
%>
|
|
} // namespace [[dbName]]
|
|
} // namespace drogon_model
|