<%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++
std::vector<std::string> relationshipClassNames;
auto &relationships=@@.get<std::vector<Relationship>>("relationships");
auto rdbms=@@.get<std::string>("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)
        {
            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)
{
%>
#include "{%relationshipClassName%}.h"
<%c++
}
%>
#include <drogon/utils/Utilities.h>
<%c++
auto &convertMethods=@@.get<std::vector<ConvertMethod>>("convertMethods");
for(auto convertMethod : convertMethods ) {
    for(auto i : convertMethod.includeFiles()) { %>
<%c++ $$<<"#include "<<i<<"\n";%>
<%c++
	} //for
} //for
%>
#include <string>
<%c++
    const auto &cols=@@.get<std::vector<ColumnInfo>>("columns");
    auto className=@@.get<std::string>("className");
    std::string indentStr(@@.get<std::string>("className").length(), ' ');
%>

using namespace drogon;
using namespace drogon::orm;
using namespace drogon_model::[[dbName]]<%c++
auto &schema=@@.get<std::string>("schema");
if(!schema.empty())
{
    $$<<"::"<<schema<<";\n";
}
else
{
    $$<<";\n";
}
%>

<%c++for(auto col:cols){
%>
const std::string [[className]]::Cols::_{%col.colName_%} = "{%escapeIdentifier(col.colName_, rdbms)%}";
<%c++
}%>
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
const std::string [[className]]::primaryKeyName = "[[primaryKeyName]]";
<%c++}else{%>
const std::vector<std::string> [[className]]::primaryKeyName = {<%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))
        $$<<",";
}
%>};
<%c++}%>
<%c++ if(@@.get<int>("hasPrimaryKey")>0){%>
const bool [[className]]::hasPrimaryKey = true;
<%c++ }else{%>
const bool [[className]]::hasPrimaryKey = false;
<%c++}%>
const std::string [[className]]::tableName = "<%c++
if(!schema.empty())
{
    $$<<schema<<".";
}
%>{%escapeIdentifier(@@.get<std::string>("tableName"), rdbms)%}";

const std::vector<typename [[className]]::MetaData> [[className]]::metaData_={
<%c++for(size_t i=0;i<cols.size();i++){
    auto &col=cols[i];
$$<<"{\""<<col.colName_<<"\",\""<<col.colType_<<"\",\""<<col.colDatabaseType_<<"\","<<col.colLength_<<","<<col.isAutoVal_<<","<<col.isPrimaryKey_<<","<<col.notNull_<<"}";
if(i<(cols.size()-1))
$$<<",\n";
else
$$<<"\n";
}%>
};
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 <cols.size(); ++i)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
        if(!r["{%col.colName_%}"].isNull())
        {
<%c++
            if(col.colDatabaseType_=="date")
            {
                $$<<"            auto daysStr = r[\""<<col.colName_<<"\"].as<std::string>();\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";
//                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "" ) {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"            auto timeStr = r[\""<<col.colName_<<"\"].as<std::string>();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea")
            {
                $$<<"            auto str = r[\""<<col.colName_<<"\"].as<std::string_view>();\n";
                $$<<"            if(str.length()>=2&&\n";
                $$<<"                str[0]=='\\\\'&&str[1]=='x')\n";
                $$<<"            {\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::hexToBinaryVector(str.data()+2,str.length()-2));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                continue;
            }
%>
            {%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r["{%col.colName_%}"].as<{%col.colType_%}>());
<%c++
            auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
            if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
            } //endif %>
        }
<%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 <cols.size(); ++i)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
        index = offset + {%i%};
        if(!r[index].isNull())
        {
<%c++
            if(col.colDatabaseType_=="date")
            {
                $$<<"            auto daysStr = r[index].as<std::string>();\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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"            auto timeStr = r[index].as<std::string>();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea")
            {
                $$<<"            auto str = r[index].as<std::string_view>();\n";
                $$<<"            if(str.length()>=2&&\n";
                $$<<"                str[0]=='\\\\'&&str[1]=='x')\n";
                $$<<"            {\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::hexToBinaryVector(str.data()+2,str.length()-2));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                    $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                continue;
            }
%>
            {%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r[index].as<{%col.colType_%}>());
<%c++
            auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
            if (convertMethod != convertMethods.end() && convertMethod->methodAfterDbRead() != "") {
                $$<<"            "<< convertMethod->methodAfterDbRead() << "(" << col.colValName_ << "_);\n";
            } //endif %>
        }
<%c++}%>
    }

}

[[className]]::[[className]](const Json::Value &pJson, const std::vector<std::string> &pMasqueradingVector) noexcept(false)
{
    if(pMasqueradingVector.size() != {%cols.size()%})
    {
        LOG_ERROR << "Bad masquerading vector";
        return;
    }
<%c++
    for(size_t i=0; i<cols.size(); ++i)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
    if(!pMasqueradingVector[{%i%}].empty() && pJson.isMember(pMasqueradingVector[{%i%}]))
    {
        dirtyFlag_[{%i%}] = true;
<%c++
            if(col.colType_ == "std::string")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::string>(pJson[pMasqueradingVector["<<i<<"]].asString());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif

                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="date")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto daysStr = pJson[pMasqueradingVector["<<i<<"]].asString();\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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto timeStr = pJson[pMasqueradingVector["<<i<<"]].asString();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto str = pJson[pMasqueradingVector["<<i<<"]].asString();\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::base64DecodeToVector(str));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[pMasqueradingVector["<<i<<"]].asUInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("int") == 0 || col.colType_ == "short")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[pMasqueradingVector["<<i<<"]].asInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "float")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<float>(pJson[pMasqueradingVector["<<i<<"]].asFloat());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"     }\n";
                continue;
            }
            else if(col.colType_ == "double")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<double>(pJson[pMasqueradingVector["<<i<<"]].asDouble());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "bool")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<bool>(pJson[pMasqueradingVector["<<i<<"]].asBool());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
%>
        }
<%c++
    }
%>
}

[[className]]::[[className]](const Json::Value &pJson) noexcept(false)
{
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
    if(pJson.isMember("{%col.colName_%}"))
    {
        dirtyFlag_[{%i%}]=true;
<%c++
            if(col.colType_ == "std::string")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::string>(pJson[\""<<col.colName_<<"\"].asString());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="date")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto daysStr = pJson[\""<<col.colName_<<"\"].asString();\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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto timeStr = pJson[\""<<col.colName_<<"\"].asString();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                 $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto str = pJson[\""<<col.colName_<<"\"].asString();\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::base64DecodeToVector(str));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[\""<<col.colName_<<"\"].asUInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("int") == 0 || col.colType_ == "short")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[\""<<col.colName_<<"\"].asInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "float")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<float>(pJson[\""<<col.colName_<<"\"].asFloat());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"     }\n";
                continue;
            }
            else if(col.colType_ == "double")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<double>(pJson[\""<<col.colName_<<"\"].asDouble());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "bool")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<bool>(pJson[\""<<col.colName_<<"\"].asBool());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
%>
    }
<%c++
    }
    %>
}

void [[className]]::updateByMasqueradedJson(const Json::Value &pJson,
                                            const std::vector<std::string> &pMasqueradingVector) noexcept(false)
{
    if(pMasqueradingVector.size() != {%cols.size()%})
    {
        LOG_ERROR << "Bad masquerading vector";
        return;
    }
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
    if(!pMasqueradingVector[{%i%}].empty() && pJson.isMember(pMasqueradingVector[{%i%}]))
    {
<%c++
            if(!col.isAutoVal_ && !col.isPrimaryKey_)
            {
                $$<<"        dirtyFlag_["<<i<<"] = true;\n";
            }
            if(col.colType_ == "std::string")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::string>(pJson[pMasqueradingVector["<<i<<"]].asString());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="date")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto daysStr = pJson[pMasqueradingVector["<<i<<"]].asString();\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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto timeStr = pJson[pMasqueradingVector["<<i<<"]].asString();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto str = pJson[pMasqueradingVector["<<i<<"]].asString();\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::base64DecodeToVector(str));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[pMasqueradingVector["<<i<<"]].asUInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("int") == 0 || col.colType_ == "short")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[pMasqueradingVector["<<i<<"]].asInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "float")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<float>(pJson[pMasqueradingVector["<<i<<"]].asFloat());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "double")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<double>(pJson[pMasqueradingVector["<<i<<"]].asDouble());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "bool")
            {
                $$<<"        if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<bool>(pJson[pMasqueradingVector["<<i<<"]].asBool());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
%>
        }
<%c++
    }
    %>
}

void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
{
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
        %>
    if(pJson.isMember("{%col.colName_%}"))
    {
<%c++
            if(!col.isAutoVal_ && !col.isPrimaryKey_)
            {
                $$<<"        dirtyFlag_["<<i<<"] = true;\n";
            }
            if(col.colType_ == "std::string")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::string>(pJson[\""<<col.colName_<<"\"].asString());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="date")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto daysStr = pJson[\""<<col.colName_<<"\"].asString();\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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_.find("timestamp")!=std::string::npos||col.colDatabaseType_.find("datetime")!=std::string::npos)
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto timeStr = pJson[\""<<col.colName_<<"\"].asString();\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";
                $$<<"                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";
 //               $$<<"            "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
                $$<<"                "<<col.colValName_<<"_=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"            }\n";
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            auto str = pJson[\""<<col.colName_<<"\"].asString();\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<std::vector<char>>(drogon::utils::base64DecodeToVector(str));\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[\""<<col.colName_<<"\"].asUInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_.find("int") == 0 || col.colType_ == "short")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<"<<col.colType_<<">(("<<col.colType_<<")pJson[\""<<col.colName_<<"\"].asInt64());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "float")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<float>(pJson[\""<<col.colName_<<"\"].asFloat());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "double")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<double>(pJson[\""<<col.colName_<<"\"].asDouble());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
            else if(col.colType_ == "bool")
            {
                $$<<"        if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
                $$<<"        {\n";
                $$<<"            "<<col.colValName_<<"_=std::make_shared<bool>(pJson[\""<<col.colName_<<"\"].asBool());\n";
                auto convertMethod=std::find_if(convertMethods.begin(),convertMethods.end(),[col](const ConvertMethod& c){ return c.shouldConvert("*", col.colName_); });
                if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
                    $$<<"            "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
                } //endif
                $$<<"        }\n";
                $$<<"    }\n";
                continue;
            }
%>
        }
<%c++
    }
    %>
}

<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(!col.colType_.empty())
        {
            $$<<"const "<<col.colType_<<" &"<<className<<"::getValueOf"<<col.colTypeName_<<"() const noexcept\n";
            $$<<"{\n";
            $$<<"    static const "<<col.colType_<<" defaultValue = "<<col.colType_<<"();\n";
            $$<<"    if("<<col.colValName_<<"_)\n";
            $$<<"        return *"<<col.colValName_<<"_;\n";
            $$<<"    return defaultValue;\n";
            $$<<"}\n";
            if(col.colType_=="std::vector<char>")
            {
                $$<<"std::string "<<className<<"::getValueOf"<<col.colTypeName_<<"AsString() const noexcept\n";
                $$<<"{\n";
                $$<<"    static const std::string defaultValue = std::string();\n";
                $$<<"    if("<<col.colValName_<<"_)\n";
                $$<<"        return std::string("<<col.colValName_<<"_->data(),"<<col.colValName_<<"_->size());\n";
                $$<<"    return defaultValue;\n";
                $$<<"}\n";
            }
            $$<<"const std::shared_ptr<"<<col.colType_<<"> &"<<className<<"::get"<<col.colTypeName_<<"() const noexcept\n";
            $$<<"{\n";
            $$<<"    return "<<col.colValName_<<"_;\n";
            $$<<"}\n";

                $$<<"void "<<className<<"::set"<<col.colTypeName_<<"(const "<<col.colType_<<" &p"<<col.colTypeName_<<") noexcept\n";
                $$<<"{\n";
                if(col.colDatabaseType_=="date")
                {
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<"<<col.colType_<<">(p"<<col.colTypeName_<<".roundDay());\n";
                }
                else
                {
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<"<<col.colType_<<">(p"<<col.colTypeName_<<");\n";
                }
                $$<<"    dirtyFlag_["<<i<<"] = true;\n";
                $$<<"}\n";

                if(col.colType_=="std::string")
                {
                    $$<<"void "<<className<<"::set"<<col.colTypeName_<<"("<<col.colType_<<" &&p"<<col.colTypeName_<<") noexcept\n";
                    $$<<"{\n";
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<"<<col.colType_<<">(std::move(p"<<col.colTypeName_<<"));\n";
                    $$<<"    dirtyFlag_["<<i<<"] = true;\n";
                    $$<<"}\n";
                }

                if(col.colType_=="std::vector<char>")
                {
                    $$<<"void "<<className<<"::set"<<col.colTypeName_<<"(const std::string &p"<<col.colTypeName_<<") noexcept\n";
                    $$<<"{\n";
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<std::vector<char>>(p"<<col.colTypeName_<<".c_str(),p"<<col.colTypeName_<<".c_str()+p"<<col.colTypeName_<<".length());\n";
                    $$<<"    dirtyFlag_["<<i<<"] = true;\n";
                    $$<<"}\n";
                }

                if(!col.notNull_)
                {
                    $$<<"void "<<className<<"::set"<<col.colTypeName_<<"ToNull() noexcept\n";
                    $$<<"{\n";
                    $$<<"    "<<col.colValName_<<"_.reset();\n";
                    $$<<"    dirtyFlag_["<<i<<"] = true;\n";
                    $$<<"}\n";
                }

            if(col.isPrimaryKey_&&@@.get<int>("hasPrimaryKey")==1)
            {
                $$<<"const typename "<<className<<"::PrimaryKeyType & "<<className<<"::getPrimaryKey() const\n";
                $$<<"{\n";
                $$<<"    assert("<<col.colValName_<<"_);\n";
                $$<<"    return *"<<col.colValName_<<"_;\n";
                $$<<"}\n";
            }
        }
        $$<<"\n";
    }
    if(@@.get<std::string>("rdbms")=="postgresql"||@@.get<int>("hasPrimaryKey")!=1)
    {
        $$<<"void "<<className<<"::updateId(const uint64_t id)\n";
        $$<<"{\n";
        $$<<"}\n";
    }
    else if(@@.get<std::string>("rdbms")=="mysql"||@@.get<std::string>("rdbms")=="sqlite3")
    {
        auto primaryKeyTypeString=@@.get<std::string>("primaryKeyType");
        $$<<"void "<<className<<"::updateId(const uint64_t id)\n";
        $$<<"{\n";
        for(auto col:cols)
        {
            if(col.isAutoVal_)
            {
                if(primaryKeyTypeString!="uint64_t")
                {
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<"<<primaryKeyTypeString<<">(static_cast<"<<primaryKeyTypeString<<">(id));\n";
                }
                else
                {
                    $$<<"    "<<col.colValName_<<"_ = std::make_shared<uint64_t>(id);\n";
                }
                break;
            }
        }
        $$<<"}\n";
    }
    if(@@.get<int>("hasPrimaryKey")>1)
    {
        $$<<"typename "<<className<<"::PrimaryKeyType "<<className<<"::getPrimaryKey() const\n";
        $$<<"{\n";
        $$<<"    return std::make_tuple(";
        int count=0;
        auto pkNames=@@.get<std::vector<std::string>>("primaryKeyValNames");
        for(auto pkName:pkNames)
        {
            ++count;
            $$<<"*"<<pkName<<"_";
            if(count<@@.get<int>("hasPrimaryKey"))
                $$<<",";
        }
        $$<<");\n";
        $$<<"}\n";
    }
%>

const std::vector<std::string> &[[className]]::insertColumns() noexcept
{
    static const std::vector<std::string> inCols={
<%c++for(size_t i=0;i<cols.size();i++){
    auto col=cols[i];
    if(!col.isAutoVal_&&!col.colType_.empty())
    {
        $$<<"        \""<<col.colName_<<"\"";
        if(i<(cols.size()-1))
            $$<<",\n";
        else
            $$<<"\n";
    }
}%>
    };
    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<std::string> [[className]]::updateColumns() const
{
    std::vector<std::string> ret;
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto & col=cols[i];
        if(col.colType_.empty()||col.isAutoVal_)
            continue;
%>
    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<cols.size();i++)
    {
        auto & col=cols[i];
        if(col.colType_.empty()||col.isAutoVal_)
            continue;
%>
    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;
}

std::string [[className]]::toString() const
{
    return toJson().toStyledString();
}

Json::Value [[className]]::toMasqueradedJson(
    const std::vector<std::string> &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<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
    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<std::string> &pMasqueradingVector,
     {%indentStr%}                                     std::string &err)
{
    if(pMasqueradingVector.size() != {%cols.size()%})
    {
        err = "Bad masquerading vector";
        return false;
    }
    try {
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
      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++}%>
    }
    catch(const Json::LogicError &e)
    {
      err = e.what();
      return false;
    }
    return true;
}
bool [[className]]::validateJsonForUpdate(const Json::Value &pJson, std::string &err)
{
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
    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<std::string> &pMasqueradingVector,
     {%indentStr%}                                   std::string &err)
{
    if(pMasqueradingVector.size() != {%cols.size()%})
    {
        err = "Bad masquerading vector";
        return false;
    }
    try {
<%c++
    for(size_t i=0;i<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
      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++
    }
}%>
    }
    catch(const Json::LogicError &e)
    {
      err = e.what();
      return false;
    }
    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<cols.size();i++)
    {
        auto &col = cols[i];
        if(col.colType_.empty())
            continue;
%>
        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 || col.colType_ == "short")
            {
%>
            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)
                {
%>
            if(pJson.isString() && std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}
                .from_bytes(pJson.asCString()).size() > {%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;
    }
    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(!alias.empty())
        {
            if(alias[0] <= 'z' && alias[0] >= 'a')
            {
                alias[0] += ('A' - 'a');
            }
        }
        else
        {
            alias = relationshipClassName;
        }
		std::string alind(alias.length(), ' ');
        if(relationship.type() == Relationship::Type::HasOne)
        {
%>
{%relationshipClassName%} [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
    static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
            if(rdbms=="postgresql")
            {
                $$<<"$1";
            }
            else
            {
                $$<<"?";
            }%>";
    Result r(nullptr);
    {
        auto binder = *clientPtr << sql;
        binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
            [&r](const Result &result) { r = result; };
        binder.exec();
    }
    if (r.size() == 0)
    {
        throw UnexpectedRows("0 rows found");
    }
    else if (r.size() > 1)
    {
        throw UnexpectedRows("Found more than one row");
    }
    return {%relationshipClassName%}(r[0]);
}

void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
     {%indentStr%}     {%alind%} const std::function<void({%relationshipClassName%})> &rcb,
     {%indentStr%}     {%alind%} const ExceptionCallback &ecb) const
{
    static const 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)
        {
%>
std::vector<{%relationshipClassName%}> [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
    static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
            if(rdbms=="postgresql")
            {
                $$<<"$1";
            }
            else
            {
                $$<<"?";
            }%>";
    Result r(nullptr);
    {
        auto binder = *clientPtr << sql;
        binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
            [&r](const Result &result) { r = result; };
        binder.exec();
    }
    std::vector<{%relationshipClassName%}> ret;
    ret.reserve(r.size());
    for (auto const &row : r)
    {
        ret.emplace_back({%relationshipClassName%}(row));
    }
    return ret;
}

void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
     {%indentStr%}     {%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
     {%indentStr%}     {%alind%} const ExceptionCallback &ecb) const
{
    static const 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(r.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();
%>
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
    static const std::string sql = "select * from {%name%},{%pivotTableName%} where {%pivotTableName%}.{%pivotOriginalKey%} = <%c++
            if(rdbms=="postgresql")
            {
                $$<<"$1";
            }
            else
            {
                $$<<"?";
            }%> and {%pivotTableName%}.{%pivotTargetKey%} = {%name%}.{%relationship.targetKey()%}";
    Result r(nullptr);
    {
        auto binder = *clientPtr << sql;
        binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
            [&r](const Result &result) { r = result; };
        binder.exec();
    }
    std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> ret;
    ret.reserve(r.size());
    for (auto const &row : r)
    {
        ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>(
            {%relationshipClassName%}(row),{%pivotTableClassName%}(row,{%relationshipClassName%}::getColumnNumber())));
    }
    return ret;
}

void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
     {%indentStr%}     {%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
     {%indentStr%}     {%alind%} const ExceptionCallback &ecb) const
{
    static const 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<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> ret;
                   ret.reserve(r.size());
                   for (auto const &row : r)
                   {
                       ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>(
                           {%relationshipClassName%}(row),{%pivotTableClassName%}(row,{%relationshipClassName%}::getColumnNumber())));
                   }
                   rcb(ret);
               }
               >> ecb;
}
<%c++
        }
    }
%>
