<%inc#include "create_model.h" using namespace drogon_ctl; %> /** * * [[className]].cc * DO NOT EDIT. This file is generated by drogon_ctl * */ #include "[[className]].h" <%c++ auto &relationships=@@.get>("relationships"); auto rdbms=@@.get("rdbms"); for(auto &relationship : relationships) { if(relationship.type() == Relationship::Type::HasOne || relationship.type() == Relationship::Type::HasMany || relationship.type() == Relationship::Type::ManyToMany) { auto &name=relationship.targetTableName(); auto relationshipClassName=nameTransform(name, true); auto originalClassName=nameTransform(relationship.originalTableName(),true); if(relationshipClassName!=originalClassName) { %> #include "{%relationshipClassName%}.h" <%c++ } } if(relationship.type() == Relationship::Type::ManyToMany) { auto &pivotTableName=relationship.pivotTable().tableName(); auto pivotTableClassName=nameTransform(pivotTableName, true); %> #include "{%pivotTableClassName%}.h" <%c++ } } %> #include #include <%c++ const auto &cols=@@.get>("columns"); auto className=@@.get("className"); std::string indentStr(@@.get("className").length(), ' '); %> using namespace drogon; using namespace drogon_model::[[dbName]]<%c++ auto &schema=@@.get("schema"); if(!schema.empty()) { $$<<"::"< <%c++for(auto col:cols){ %> const std::string [[className]]::Cols::_{%col.colName_%} = "{%col.colName_%}"; <%c++ }%> <%c++if(@@.get("hasPrimaryKey")<=1){%> const std::string [[className]]::primaryKeyName = "[[primaryKeyName]]"; <%c++}else{%> const std::vector [[className]]::primaryKeyName = {<%c++ auto pkName=@@.get>("primaryKeyName"); for(size_t i=0;i}; <%c++}%> <%c++ if(@@.get("hasPrimaryKey")>0){%> const bool [[className]]::hasPrimaryKey = true; <%c++ }else{%> const bool [[className]]::hasPrimaryKey = false; <%c++}%> const std::string [[className]]::tableName = "<%c++ if(!schema.empty()) { $$<[[tableName]]"; const std::vector [[className]]::metaData_={ <%c++for(size_t i=0;i }; const std::string &[[className]]::getColumnName(size_t index) noexcept(false) { assert(index < metaData_.size()); return metaData_[index].colName_; } [[className]]::[[className]](const Row &r, const ssize_t indexOffset) noexcept { if(indexOffset < 0) { <%c++ for(size_t i = 0; i if(!r["{%col.colName_%}"].isNull()) { <%c++ if(col.colDatabaseType_=="date") { $$<<" auto daysStr = r[\""<();\n"; $$<<" struct tm stm;\n"; $$<<" memset(&stm,0,sizeof(stm));\n"; $$<<" strptime(daysStr.c_str(),\"%Y-%m-%d\",&stm);\n"; $$<<" time_t t = mktime(&stm);\n"; // $$<<" "<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" auto timeStr = r[\""<();\n"; $$<<" struct tm stm;\n"; $$<<" memset(&stm,0,sizeof(stm));\n"; $$<<" auto p = strptime(timeStr.c_str(),\"%Y-%m-%d %H:%M:%S\",&stm);\n"; $$<<" time_t t = mktime(&stm);\n"; $$<<" size_t decimalNum = 0;\n"; $$<<" if(*p=='.')\n"; $$<<" {\n"; $$<<" std::string decimals(p+1,&timeStr[timeStr.length()]);\n"; $$<<" while(decimals.length()<6)\n"; $$<<" {\n"; $$<<" decimals += \"0\";\n"; $$<<" }\n"; $$<<" decimalNum = (size_t)atol(decimals.c_str());\n"; $$<<" }\n"; // $$<<" "<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea") { $$<<" auto str = r[\""<();\n"; $$<<" if(str.length()>=2&&\n"; $$<<" str[0]=='\\\\'&&str[1]=='x')\n"; $$<<" {\n"; $$<<" "<>(drogon::utils::hexToBinaryVector(str.data()+2,str.length()-2));\n"; $$<<" }\n"; $$<<" }\n"; continue; } %> {%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r["{%col.colName_%}"].as<{%col.colType_%}>()); } <%c++} %> } else { size_t offset = (size_t)indexOffset; if(offset + {%cols.size()%} > r.size()) { LOG_FATAL << "Invalid SQL result for this model"; return; } size_t index; <%c++ for(size_t i = 0; i index = offset + {%i%}; if(!r[index].isNull()) { <%c++ if(col.colDatabaseType_=="date") { $$<<" auto daysStr = r[index].as();\n"; $$<<" struct tm stm;\n"; $$<<" memset(&stm,0,sizeof(stm));\n"; $$<<" strptime(daysStr.c_str(),\"%Y-%m-%d\",&stm);\n"; $$<<" time_t t = mktime(&stm);\n"; // $$<<" "<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" auto timeStr = r[index].as();\n"; $$<<" struct tm stm;\n"; $$<<" memset(&stm,0,sizeof(stm));\n"; $$<<" auto p = strptime(timeStr.c_str(),\"%Y-%m-%d %H:%M:%S\",&stm);\n"; $$<<" time_t t = mktime(&stm);\n"; $$<<" size_t decimalNum = 0;\n"; $$<<" if(*p=='.')\n"; $$<<" {\n"; $$<<" std::string decimals(p+1,&timeStr[timeStr.length()]);\n"; $$<<" while(decimals.length()<6)\n"; $$<<" {\n"; $$<<" decimals += \"0\";\n"; $$<<" }\n"; $$<<" decimalNum = (size_t)atol(decimals.c_str());\n"; $$<<" }\n"; // $$<<" "<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea") { $$<<" auto str = r[index].as();\n"; $$<<" if(str.length()>=2&&\n"; $$<<" str[0]=='\\\\'&&str[1]=='x')\n"; $$<<" {\n"; $$<<" "<>(drogon::utils::hexToBinaryVector(str.data()+2,str.length()-2));\n"; $$<<" }\n"; $$<<" }\n"; continue; } %> {%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r[index].as<{%col.colType_%}>()); } <%c++}%> } } [[className]]::[[className]](const Json::Value &pJson, const std::vector &pMasqueradingVector) noexcept(false) { if(pMasqueradingVector.size() != {%cols.size()%}) { LOG_ERROR << "Bad masquerading vector"; return; } <%c++ for(size_t i=0; i if(!pMasqueradingVector[{%i%}].empty() && pJson.isMember(pMasqueradingVector[{%i%}])) { dirtyFlag_[{%i%}] = true; <%c++ if(col.colType_ == "std::string") { $$<<" if(!pJson[pMasqueradingVector["<(pJson[pMasqueradingVector["<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" if(!pJson[pMasqueradingVector["<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos) { $$<<" if(!pJson[pMasqueradingVector["<>(drogon::utils::base64DecodeToVector(str));\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short") { $$<<" if(!pJson[pMasqueradingVector["<(("<(("<(pJson[pMasqueradingVector["<(pJson[pMasqueradingVector["<(pJson[pMasqueradingVector["< } <%c++ } %> } [[className]]::[[className]](const Json::Value &pJson) noexcept(false) { <%c++ for(size_t i=0;i if(pJson.isMember("{%col.colName_%}")) { dirtyFlag_[{%i%}]=true; <%c++ if(col.colType_ == "std::string") { $$<<" if(!pJson[\""<(pJson[\""<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" if(!pJson[\""<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos) { $$<<" if(!pJson[\""<>(drogon::utils::base64DecodeToVector(str));\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short") { $$<<" if(!pJson[\""<(("<(("<(pJson[\""<(pJson[\""<(pJson[\""< } <%c++ } %> } void [[className]]::updateByMasqueradedJson(const Json::Value &pJson, const std::vector &pMasqueradingVector) noexcept(false) { if(pMasqueradingVector.size() != {%cols.size()%}) { LOG_ERROR << "Bad masquerading vector"; return; } <%c++ for(size_t i=0;i if(!pMasqueradingVector[{%i%}].empty() && pJson.isMember(pMasqueradingVector[{%i%}])) { <%c++ if(!col.isAutoVal_ && !col.isPrimaryKey_) { $$<<" dirtyFlag_["<(pJson[pMasqueradingVector["<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" if(!pJson[pMasqueradingVector["<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos) { $$<<" if(!pJson[pMasqueradingVector["<>(drogon::utils::base64DecodeToVector(str));\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short") { $$<<" if(!pJson[pMasqueradingVector["<(("<(("<(pJson[pMasqueradingVector["<(pJson[pMasqueradingVector["<(pJson[pMasqueradingVector["< } <%c++ } %> } void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false) { <%c++ for(size_t i=0;i if(pJson.isMember("{%col.colName_%}")) { <%c++ if(!col.isAutoVal_ && !col.isPrimaryKey_) { $$<<" dirtyFlag_["<(pJson[\""<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos) { $$<<" if(!pJson[\""<(::trantor::Date(946656000000000).after(daysNum*86400));\n"; $$<<" "<(t*1000000+decimalNum);\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos) { $$<<" if(!pJson[\""<>(drogon::utils::base64DecodeToVector(str));\n"; $$<<" }\n"; $$<<" }\n"; continue; } else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short") { $$<<" if(!pJson[\""<(("<(("<(pJson[\""<(pJson[\""<(pJson[\""< } <%c++ } %> } <%c++ for(size_t i=0;i") { $$<<"std::string "<data(),"<size());\n"; $$<<" return defaultValue;\n"; $$<<"}\n"; } $$<<"const std::shared_ptr<"< &"<(p"<(p"<(std::move(p"<") { $$<<"void "<>(p"<("hasPrimaryKey")==1) { $$<<"const typename "<("rdbms")=="postgresql"||@@.get("hasPrimaryKey")!=1) { $$<<"void "<("rdbms")=="mysql"||@@.get("rdbms")=="sqlite3") { auto primaryKeyTypeString=@@.get("primaryKeyType"); $$<<"void "<(static_cast<"<(id));\n"; } else { $$<<" "<(id);\n"; } break; } } $$<<"}\n"; } if(@@.get("hasPrimaryKey")>1) { $$<<"typename "<("hasPrimaryKey")) $$<<","; } } $$<<");\n"; $$<<"}\n"; } %> const std::vector &[[className]]::insertColumns() noexcept { static const std::vector inCols={ <%c++for(size_t i=0;i }; return inCols; } void [[className]]::outputArgs(drogon::orm::internal::SqlBinder &binder) const { <%c++for(size_t i = 0; i < cols.size(); ++i){ auto &col = cols[i]; if(!col.isAutoVal_&&!col.colType_.empty()) { %> if(dirtyFlag_[{%i%}]) { if(get{%col.colTypeName_%}()) { binder << getValueOf{%col.colTypeName_%}(); } else { binder << nullptr; } } <%c++ } } %> } const std::vector [[className]]::updateColumns() const { std::vector ret; <%c++ for(size_t i=0;i if(dirtyFlag_[{%i%}]) { ret.push_back(getColumnName({%i%})); } <%c++ } %> return ret; } void [[className]]::updateArgs(drogon::orm::internal::SqlBinder &binder) const { <%c++ for(size_t i=0;i if(dirtyFlag_[{%i%}]) { if(get{%col.colTypeName_%}()) { binder << getValueOf{%col.colTypeName_%}(); } else { binder << nullptr; } } <%c++ } %> } Json::Value [[className]]::toJson() const { Json::Value ret; <%c++for(auto col:cols){%> if(get{%col.colTypeName_%}()) { <%c++if(col.colDatabaseType_=="date"){%> ret["{%col.colName_%}"]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos){%> ret["{%col.colName_%}"]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_=="bytea"||col.colDatabaseType_.find("blob")!=std::string::npos){%> ret["{%col.colName_%}"]=drogon::utils::base64Encode((const unsigned char *)get{%col.colTypeName_%}()->data(),get{%col.colTypeName_%}()->size()); <%c++}else if(col.colType_=="int64_t"){%> ret["{%col.colName_%}"]=(Json::Int64)getValueOf{%col.colTypeName_%}(); <%c++}else if(col.colType_=="uint64_t"){%> ret["{%col.colName_%}"]=(Json::UInt64)getValueOf{%col.colTypeName_%}(); <%c++}else{%> ret["{%col.colName_%}"]=getValueOf{%col.colTypeName_%}(); <%c++}%> } else { ret["{%col.colName_%}"]=Json::Value(); } <%c++ }%> return ret; } Json::Value [[className]]::toMasqueradedJson( const std::vector &pMasqueradingVector) const { Json::Value ret; if(pMasqueradingVector.size() == {%cols.size()%}) { <%c++for(size_t i = 0; i < cols.size(); ++i){ auto &col = cols[i]; %> if(!pMasqueradingVector[{%i%}].empty()) { if(get{%col.colTypeName_%}()) { <%c++if(col.colDatabaseType_=="date"){%> ret[pMasqueradingVector[{%i%}]]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos){%> ret[pMasqueradingVector[{%i%}]]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_=="bytea"||col.colDatabaseType_.find("blob")!=std::string::npos){%> ret[pMasqueradingVector[{%i%}]]=drogon::utils::base64Encode((const unsigned char *)get{%col.colTypeName_%}()->data(),get{%col.colTypeName_%}()->size()); <%c++}else if(col.colType_=="int64_t"){%> ret[pMasqueradingVector[{%i%}]]=(Json::Int64)getValueOf{%col.colTypeName_%}(); <%c++}else if(col.colType_=="uint64_t"){%> ret[pMasqueradingVector[{%i%}]]=(Json::UInt64)getValueOf{%col.colTypeName_%}(); <%c++}else{%> ret[pMasqueradingVector[{%i%}]]=getValueOf{%col.colTypeName_%}(); <%c++}%> } else { ret[pMasqueradingVector[{%i%}]]=Json::Value(); } } <%c++ }%> return ret; } LOG_ERROR << "Masquerade failed"; <%c++for(auto col:cols){%> if(get{%col.colTypeName_%}()) { <%c++if(col.colDatabaseType_=="date"){%> ret["{%col.colName_%}"]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos){%> ret["{%col.colName_%}"]=get{%col.colTypeName_%}()->toDbStringLocal(); <%c++}else if(col.colDatabaseType_=="bytea"||col.colDatabaseType_.find("blob")!=std::string::npos){%> ret["{%col.colName_%}"]=drogon::utils::base64Encode((const unsigned char *)get{%col.colTypeName_%}()->data(),get{%col.colTypeName_%}()->size()); <%c++}else if(col.colType_=="int64_t"){%> ret["{%col.colName_%}"]=(Json::Int64)getValueOf{%col.colTypeName_%}(); <%c++}else if(col.colType_=="uint64_t"){%> ret["{%col.colName_%}"]=(Json::UInt64)getValueOf{%col.colTypeName_%}(); <%c++}else{%> ret["{%col.colName_%}"]=getValueOf{%col.colTypeName_%}(); <%c++}%> } else { ret["{%col.colName_%}"]=Json::Value(); } <%c++ }%> return ret; } bool [[className]]::validateJsonForCreation(const Json::Value &pJson, std::string &err) { <%c++ for(size_t i=0;i if(pJson.isMember("{%col.colName_%}")) { if(!validJsonOfField({%i%}, "{%col.colName_%}", pJson["{%col.colName_%}"], err, true)) return false; } <%c++if(col.notNull_ && !col.isAutoVal_ && !col.hasDefaultVal_){%> else { err="The {%col.colName_%} column cannot be null"; return false; } <%c++} }%> return true; } bool [[className]]::validateMasqueradedJsonForCreation(const Json::Value &pJson, {%indentStr%} const std::vector &pMasqueradingVector, {%indentStr%} std::string &err) { if(pMasqueradingVector.size() != {%cols.size()%}) { err = "Bad masquerading vector"; return false; } <%c++ for(size_t i=0;i if(!pMasqueradingVector[{%i%}].empty()) { if(pJson.isMember(pMasqueradingVector[{%i%}])) { if(!validJsonOfField({%i%}, pMasqueradingVector[{%i%}], pJson[pMasqueradingVector[{%i%}]], err, true)) return false; } <%c++if(col.notNull_ && !col.isAutoVal_ && !col.hasDefaultVal_){%> else { err="The " + pMasqueradingVector[{%i%}] + " column cannot be null"; return false; } <%c++}%> } <%c++}%> return true; } bool [[className]]::validateJsonForUpdate(const Json::Value &pJson, std::string &err) { <%c++ for(size_t i=0;i if(pJson.isMember("{%col.colName_%}")) { if(!validJsonOfField({%i%}, "{%col.colName_%}", pJson["{%col.colName_%}"], err, false)) return false; } <%c++ if(col.isPrimaryKey_) { %> else { err = "The value of primary key must be set in the json object for update"; return false; } <%c++ } }%> return true; } bool [[className]]::validateMasqueradedJsonForUpdate(const Json::Value &pJson, {%indentStr%} const std::vector &pMasqueradingVector, {%indentStr%} std::string &err) { if(pMasqueradingVector.size() != {%cols.size()%}) { err = "Bad masquerading vector"; return false; } <%c++ for(size_t i=0;i if(!pMasqueradingVector[{%i%}].empty() && pJson.isMember(pMasqueradingVector[{%i%}])) { if(!validJsonOfField({%i%}, pMasqueradingVector[{%i%}], pJson[pMasqueradingVector[{%i%}]], err, false)) return false; } <%c++ if(col.isPrimaryKey_) { %> else { err = "The value of primary key must be set in the json object for update"; return false; } <%c++ } }%> return true; } bool [[className]]::validJsonOfField(size_t index, {%indentStr%} const std::string &fieldName, {%indentStr%} const Json::Value &pJson, {%indentStr%} std::string &err, {%indentStr%} bool isForCreation) { switch(index) { <%c++ for(size_t i=0;i case {%i%}: <%c++if(col.notNull_){%> if(pJson.isNull()) { err="The " + fieldName + " column cannot be null"; return false; } <%c++} if(col.isAutoVal_) { if(col.isPrimaryKey_) { %> if(isForCreation) { err="The automatic primary key cannot be set"; return false; } <%c++ }else { %> if(isForCreation) { err="The automatic primary key cannot be set"; return false; } else { err="The automatic primary key cannot be update"; return false; } <%c++ } } if(!col.notNull_){%> if(pJson.isNull()) { return true; } <%c++} if(col.colType_ == "uint64_t") { %> if(!pJson.isUInt64()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else if(col.colType_ == "int64_t") { %> if(!pJson.isInt64()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else if(col.colType_.find("uint") == 0) { %> if(!pJson.isUInt()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else if(col.colType_.find("int") == 0) { %> if(!pJson.isInt()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else if(col.colType_ == "float" || col.colType_ == "double") { %> if(!pJson.isNumeric()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else if(col.colType_ == "bool") { %> if(!pJson.isBool()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ } else { %> if(!pJson.isString()) { err="Type error in the "+fieldName+" field"; return false; } <%c++ if(col.colType_ == "std::string" && col.colLength_>0) { %> // asString().length() creates a string object, is there any better way to validate the length? if(pJson.isString() && pJson.asString().length() > {%col.colLength_%}) { err="String length exceeds limit for the " + fieldName + " field (the maximum value is {%col.colLength_%})"; return false; } <%c++ } } %> break; <%c++ }%> default: err="Internal error in the server"; return false; break; } return true; } <%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(), ' '); %> void [[className]]::get{%alias%}(const DbClientPtr &clientPtr, {%indentStr%} {%alind%} const std::function &rcb, {%indentStr%} {%alind%} const ExceptionCallback &ecb) const <%c++ } else { std::string relationshipClassInde(relationshipClassName.length(), ' '); %> void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr, {%indentStr%} {%relationshipClassInde%} const std::function &rcb, {%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const <%c++ } %> { const static std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++ if(rdbms=="postgresql") { $$<<"$1"; } else { $$<<"?"; }%>"; *clientPtr << sql << *{%nameTransform(relationship.originalKey(), false)%}_ >> [rcb = std::move(rcb), ecb](const Result &r){ if (r.size() == 0) { ecb(UnexpectedRows("0 rows found")); } else if (r.size() > 1) { ecb(UnexpectedRows("Found more than one row")); } else { rcb({%relationshipClassName%}(r[0])); } } >> ecb; } <%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(), ' '); %> void [[className]]::get{%alias%}(const DbClientPtr &clientPtr, {%indentStr%} {%alind%} const std::function)> &rcb, {%indentStr%} {%alind%} const ExceptionCallback &ecb) const <%c++ } else { std::string relationshipClassInde(relationshipClassName.length(), ' '); %> void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr, {%indentStr%} {%relationshipClassInde%} const std::function)> &rcb, {%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const <%c++ } %> { const static std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++ if(rdbms=="postgresql") { $$<<"$1"; } else { $$<<"?"; }%>"; *clientPtr << sql << *{%nameTransform(relationship.originalKey(), false)%}_ >> [rcb = std::move(rcb)](const Result &r){ std::vector<{%relationshipClassName%}> ret; ret.reserve(ret.size()); for (auto const &row : r) { ret.emplace_back({%relationshipClassName%}(row)); } rcb(ret); } >> ecb; } <%c++ } else if(relationship.type() == Relationship::Type::ManyToMany) { auto &pivotTableName=relationship.pivotTable().tableName(); auto pivotTableClassName=nameTransform(pivotTableName, true); auto &pivotOriginalKey=relationship.pivotTable().originalKey(); auto &pivotTargetKey=relationship.pivotTable().targetKey(); if(!alias.empty()) { if(alias[0] <= 'z' && alias[0] >= 'a') { alias[0] += ('A' - 'a'); } std::string alind(alias.length(), ' '); %> void [[className]]::get{%alias%}(const DbClientPtr &clientPtr, {%indentStr%} {%alind%} const std::function>)> &rcb, {%indentStr%} {%alind%} const ExceptionCallback &ecb) const <%c++ } else { std::string relationshipClassInde(relationshipClassName.length(), ' '); %> void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr, {%indentStr%} {%relationshipClassInde%} const std::function>)> &rcb, {%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const <%c++ } %> { const static std::string sql = "select * from {%name%},{%pivotTableName%} where {%pivotTableName%}.{%pivotOriginalKey%} = <%c++ if(rdbms=="postgresql") { $$<<"$1"; } else { $$<<"?"; }%> and {%pivotTableName%}.{%pivotTargetKey%} = {%name%}.{%relationship.targetKey()%}"; *clientPtr << sql << *{%nameTransform(relationship.originalKey(), false)%}_ >> [rcb = std::move(rcb)](const Result &r){ std::vector> ret; ret.reserve(ret.size()); for (auto const &row : r) { ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>( {%relationshipClassName%}(row),{%pivotTableClassName%}(row,{%relationshipClassName%}::getColumnNumber()))); } rcb(ret); } >> ecb; } <%c++ } } %>