mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-11-29 18:27:43 +08:00
Improve the function of creating models
This commit is contained in:
parent
cae30230c3
commit
0d77fa1490
@ -14,6 +14,7 @@ foreach(cspFile ${SCP_LIST})
|
||||
VERBATIM )
|
||||
set(TEMPL_SRC ${TEMPL_SRC} ${classname}.cc)
|
||||
endforeach()
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_executable(drogon_ctl ${SRC_DIR} ${TEMPL_SRC})
|
||||
add_dependencies(drogon_ctl trantor makeVersion _drogon_ctl)
|
||||
install(TARGETS drogon_ctl DESTINATION bin)
|
||||
|
@ -33,8 +33,8 @@ std::string create::detail()
|
||||
"create a project named project_name\n"
|
||||
"drogon_ctl create filter <class_name> //"
|
||||
"create a filter named class_name\n"
|
||||
"drogon_ctl create dao <dao_path> //"
|
||||
"create DAO classes in dao_path\n";
|
||||
"drogon_ctl create model <model_path> //"
|
||||
"create model classes in model_path\n";
|
||||
}
|
||||
|
||||
void create::handleCommand(std::vector<std::string> ¶meters)
|
||||
|
@ -1,203 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_dao.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_dao.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/PgClient.h>
|
||||
#endif
|
||||
#include <drogon/HttpViewData.h>
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <json/json.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
using namespace drogon::orm;
|
||||
|
||||
std::string nameTransform(const std::string &origName, bool isType)
|
||||
{
|
||||
auto str = origName;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tolower);
|
||||
std::string::size_type startPos = 0;
|
||||
std::string::size_type pos;
|
||||
std::string ret;
|
||||
do
|
||||
{
|
||||
pos = str.find("_", startPos);
|
||||
if (pos != std::string::npos)
|
||||
ret += str.substr(startPos, pos - startPos);
|
||||
else
|
||||
{
|
||||
ret += str.substr(startPos);
|
||||
break;
|
||||
}
|
||||
while (str[pos] == '_')
|
||||
pos++;
|
||||
if (str[pos] >= 'a' && str[pos] <= 'z')
|
||||
str[pos] += ('A' - 'a');
|
||||
startPos = pos;
|
||||
} while (1);
|
||||
if (isType && ret[0] >= 'a' && ret[0] <= 'z')
|
||||
ret[0] += ('A' - 'a');
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
void create_dao::createDAOClassFromPG(const std::string &path, PgClient &client, const std::string &tableName)
|
||||
{
|
||||
auto className = nameTransform(tableName, true);
|
||||
HttpViewData data;
|
||||
data["className"] = className;
|
||||
data["tableName"] = tableName;
|
||||
data["hasPrimaryKey"] = true;
|
||||
data["primaryKeyName"] = "";
|
||||
data["dbName"] = _dbname;
|
||||
std::ofstream headerFile(path + "/" + className + ".h", std::ofstream::out);
|
||||
std::ofstream sourceFile(path + "/" + className + ".cc", std::ofstream::out);
|
||||
auto templ = DrTemplateBase::newTemplate("dao_h.csp");
|
||||
headerFile << templ->genText(data);
|
||||
templ = DrTemplateBase::newTemplate("dao_cc.csp");
|
||||
sourceFile << templ->genText(data);
|
||||
}
|
||||
void create_dao::createDAOFromPG(const std::string &path, PgClient &client)
|
||||
{
|
||||
client << "SELECT a.oid,"
|
||||
"a.relname AS name,"
|
||||
"b.description AS comment "
|
||||
"FROM pg_class a "
|
||||
"LEFT OUTER JOIN pg_description b ON b.objsubid = 0 AND a.oid = b.objoid "
|
||||
"WHERE a.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public') "
|
||||
"AND a.relkind = 'r' ORDER BY a.relname"
|
||||
<< Mode::Blocking >>
|
||||
[&](bool isNull, size_t oid, const std::string &tableName, const std::string &comment) {
|
||||
if (!isNull)
|
||||
{
|
||||
std::cout << "table name:" << tableName << std::endl;
|
||||
createDAOClassFromPG(path, client, tableName);
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
void create_dao::createDAO(const std::string &path, const Json::Value &config)
|
||||
{
|
||||
auto dbType = config.get("rdbms", "No dbms").asString();
|
||||
if (dbType == "postgreSQL")
|
||||
{
|
||||
#if USE_POSTGRESQL
|
||||
std::cout << "postgresql" << std::endl;
|
||||
auto host = config.get("host", "127.0.0.1").asString();
|
||||
auto port = config.get("port", 5432).asUInt();
|
||||
auto dbname = config.get("dbname", "").asString();
|
||||
if (dbname == "")
|
||||
{
|
||||
std::cerr << "Please configure dbname in " << path << "/dao.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
_dbname = dbname;
|
||||
auto user = config.get("user", "").asString();
|
||||
if (user == "")
|
||||
{
|
||||
std::cerr << "Please configure user in " << path << "/dao.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto password = config.get("passwd", "").asString();
|
||||
|
||||
auto connStr = formattedString("host=%s port=%u dbname=%s user=%s", host.c_str(), port, dbname.c_str(), user.c_str());
|
||||
if (!password.empty())
|
||||
{
|
||||
connStr += " password=";
|
||||
connStr += password;
|
||||
}
|
||||
PgClient client(connStr, 1);
|
||||
std::cout << "Connect to server..." << std::endl;
|
||||
sleep(1);
|
||||
createDAOFromPG(path, client);
|
||||
#endif
|
||||
}
|
||||
else if (dbType == "No dbms")
|
||||
{
|
||||
std::cerr << "Please configure DAO in " << path << "/dao.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Does not support " << dbType << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void create_dao::createDAO(const std::string &path)
|
||||
{
|
||||
DIR *dp;
|
||||
if ((dp = opendir(path.c_str())) == NULL)
|
||||
{
|
||||
std::cerr << "No such file or directory : " << path << std::endl;
|
||||
return;
|
||||
}
|
||||
closedir(dp);
|
||||
auto configFile = path + "/dao.json";
|
||||
if (access(configFile.c_str(), 0) != 0)
|
||||
{
|
||||
std::cerr << "Config file " << configFile << " not found!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (access(configFile.c_str(), R_OK) != 0)
|
||||
{
|
||||
std::cerr << "No permission to read config file " << configFile << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::ifstream infile(configFile.c_str(), std::ifstream::in);
|
||||
if (infile)
|
||||
{
|
||||
Json::Value configJsonRoot;
|
||||
try
|
||||
{
|
||||
infile >> configJsonRoot;
|
||||
createDAO(path, configJsonRoot);
|
||||
}
|
||||
catch (const std::exception &exception)
|
||||
{
|
||||
std::cerr << "Configuration file format error! in " << configFile << ":" << std::endl;
|
||||
std::cerr << exception.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_dao::handleCommand(std::vector<std::string> ¶meters)
|
||||
{
|
||||
std::cout << "Create dao" << std::endl;
|
||||
if (parameters.size() == 0)
|
||||
{
|
||||
std::cerr << "Missing DAO path name!" << std::endl;
|
||||
}
|
||||
for (auto path : parameters)
|
||||
{
|
||||
createDAO(path);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_dao.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <json/json.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/PgClient.h>
|
||||
#endif
|
||||
#include <drogon/DrObject.h>
|
||||
#include "CommandHandler.h"
|
||||
#include <string>
|
||||
|
||||
using namespace drogon;
|
||||
using namespace drogon::orm;
|
||||
|
||||
namespace drogon_ctl
|
||||
{
|
||||
class create_dao : public DrObject<create_dao>, public CommandHandler
|
||||
{
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override { return "create DAO classes files"; }
|
||||
|
||||
protected:
|
||||
void createDAO(const std::string &path);
|
||||
void createDAO(const std::string &path, const Json::Value &config);
|
||||
#if USE_POSTGRESQL
|
||||
void createDAOClassFromPG(const std::string &path, PgClient &client, const std::string &tableName);
|
||||
void createDAOFromPG(const std::string &path, PgClient &client);
|
||||
#endif
|
||||
std::string _dbname;
|
||||
};
|
||||
} // namespace drogon_ctl
|
309
drogon_ctl/create_model.cc
Normal file
309
drogon_ctl/create_model.cc
Normal file
@ -0,0 +1,309 @@
|
||||
/**
|
||||
*
|
||||
* create_model.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_model.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/PgClient.h>
|
||||
#endif
|
||||
#include <drogon/HttpViewData.h>
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <json/json.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
using namespace drogon::orm;
|
||||
|
||||
|
||||
std::string nameTransform(const std::string &origName, bool isType)
|
||||
{
|
||||
auto str = origName;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tolower);
|
||||
std::string::size_type startPos = 0;
|
||||
std::string::size_type pos;
|
||||
std::string ret;
|
||||
do
|
||||
{
|
||||
pos = str.find("_", startPos);
|
||||
if (pos != std::string::npos)
|
||||
ret += str.substr(startPos, pos - startPos);
|
||||
else
|
||||
{
|
||||
ret += str.substr(startPos);
|
||||
break;
|
||||
}
|
||||
while (str[pos] == '_')
|
||||
pos++;
|
||||
if (str[pos] >= 'a' && str[pos] <= 'z')
|
||||
str[pos] += ('A' - 'a');
|
||||
startPos = pos;
|
||||
} while (1);
|
||||
if (isType && ret[0] >= 'a' && ret[0] <= 'z')
|
||||
ret[0] += ('A' - 'a');
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
void create_model::createModelClassFromPG(const std::string &path, PgClient &client, const std::string &tableName)
|
||||
{
|
||||
auto className = nameTransform(tableName, true);
|
||||
HttpViewData data;
|
||||
data["className"] = className;
|
||||
data["tableName"] = tableName;
|
||||
data["hasPrimaryKey"] = false;
|
||||
data["primaryKeyName"] = "";
|
||||
data["dbName"] = _dbname;
|
||||
std::vector<ColumnInfo> cols;
|
||||
client << "SELECT * \
|
||||
FROM information_schema.columns \
|
||||
WHERE table_schema = 'public' \
|
||||
AND table_name = $1"
|
||||
<< tableName << Mode::Blocking >>
|
||||
[&](const Result &r) {
|
||||
for (auto row : r)
|
||||
{
|
||||
ColumnInfo info;
|
||||
info._colName = row["column_name"].as<std::string>();
|
||||
info._colTypeName = nameTransform(info._colName, true);
|
||||
info._colValName = nameTransform(info._colName, false);
|
||||
auto isNullAble = row["is_nullable"].as<std::string>();
|
||||
|
||||
info._notNull = isNullAble == "YES" ? false : true;
|
||||
auto type = row["data_type"].as<std::string>();
|
||||
if (type == "smallint")
|
||||
{
|
||||
info._colType = "short";
|
||||
info._colLength = 2;
|
||||
}
|
||||
else if (type == "integer")
|
||||
{
|
||||
info._colType = "int32_t";
|
||||
info._colLength = 4;
|
||||
}
|
||||
else if (type == "bigint" || type == "numeric") //FIXME:Use int64 to represent numeric type?
|
||||
{
|
||||
info._colType = "int64_t";
|
||||
info._colLength = 8;
|
||||
}
|
||||
else if (type == "real")
|
||||
{
|
||||
info._colType = "float";
|
||||
info._colLength = sizeof(float);
|
||||
}
|
||||
else if (type == "double precision")
|
||||
{
|
||||
info._colType = "double";
|
||||
info._colLength = sizeof(double);
|
||||
}
|
||||
else if (type == "character varying")
|
||||
{
|
||||
info._colType = "std::string";
|
||||
if (!row["character_maximum_length"].isNull())
|
||||
info._colLength = row["character_maximum_length"].as<ssize_t>();
|
||||
}
|
||||
else if (type == "boolean")
|
||||
{
|
||||
info._colType = "bool";
|
||||
info._colLength = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//FIXME add more type such as hstore...
|
||||
}
|
||||
auto defaultVal = row["column_default"].as<std::string>();
|
||||
|
||||
if (!defaultVal.empty())
|
||||
{
|
||||
info._hasDefaultVal = true;
|
||||
if (defaultVal.find("nextval(") == 0)
|
||||
{
|
||||
info._isAutoVal = true;
|
||||
}
|
||||
}
|
||||
cols.push_back(std::move(info));
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
|
||||
client << "SELECT \
|
||||
pg_attribute.attname AS colname,\
|
||||
pg_type.typname AS typename,\
|
||||
pg_constraint.contype AS contype \
|
||||
FROM pg_constraint \
|
||||
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid \
|
||||
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid \
|
||||
AND pg_attribute.attnum = pg_constraint.conkey [ 1 ] \
|
||||
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid \
|
||||
WHERE pg_class.relname = $1 and pg_constraint.contype='p'"
|
||||
<< tableName << Mode::Blocking >>
|
||||
[&](bool isNull, std::string colName, const std::string &type) {
|
||||
if (isNull)
|
||||
return;
|
||||
data["hasPrimaryKey"] = true;
|
||||
data["primaryKeyName"] = colName;
|
||||
for (auto &col : cols)
|
||||
{
|
||||
if (col._colName == colName)
|
||||
{
|
||||
col._isPrimaryKey = true;
|
||||
data["primaryKeyType"] = col._colType;
|
||||
}
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
data["columns"] = cols;
|
||||
std::ofstream headerFile(path + "/" + className + ".h", std::ofstream::out);
|
||||
std::ofstream sourceFile(path + "/" + className + ".cc", std::ofstream::out);
|
||||
auto templ = DrTemplateBase::newTemplate("model_h.csp");
|
||||
headerFile << templ->genText(data);
|
||||
templ = DrTemplateBase::newTemplate("model_cc.csp");
|
||||
sourceFile << templ->genText(data);
|
||||
}
|
||||
void create_model::createModelFromPG(const std::string &path, PgClient &client)
|
||||
{
|
||||
client << "SELECT a.oid,"
|
||||
"a.relname AS name,"
|
||||
"b.description AS comment "
|
||||
"FROM pg_class a "
|
||||
"LEFT OUTER JOIN pg_description b ON b.objsubid = 0 AND a.oid = b.objoid "
|
||||
"WHERE a.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public') "
|
||||
"AND a.relkind = 'r' ORDER BY a.relname"
|
||||
<< Mode::Blocking >>
|
||||
[&](bool isNull, size_t oid, const std::string &tableName, const std::string &comment) {
|
||||
if (!isNull)
|
||||
{
|
||||
std::cout << "table name:" << tableName << std::endl;
|
||||
createModelClassFromPG(path, client, tableName);
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
void create_model::createModel(const std::string &path, const Json::Value &config)
|
||||
{
|
||||
auto dbType = config.get("rdbms", "No dbms").asString();
|
||||
if (dbType == "postgreSQL")
|
||||
{
|
||||
#if USE_POSTGRESQL
|
||||
std::cout << "postgresql" << std::endl;
|
||||
auto host = config.get("host", "127.0.0.1").asString();
|
||||
auto port = config.get("port", 5432).asUInt();
|
||||
auto dbname = config.get("dbname", "").asString();
|
||||
if (dbname == "")
|
||||
{
|
||||
std::cerr << "Please configure dbname in " << path << "/model.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
_dbname = dbname;
|
||||
auto user = config.get("user", "").asString();
|
||||
if (user == "")
|
||||
{
|
||||
std::cerr << "Please configure user in " << path << "/model.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto password = config.get("passwd", "").asString();
|
||||
|
||||
auto connStr = formattedString("host=%s port=%u dbname=%s user=%s", host.c_str(), port, dbname.c_str(), user.c_str());
|
||||
if (!password.empty())
|
||||
{
|
||||
connStr += " password=";
|
||||
connStr += password;
|
||||
}
|
||||
PgClient client(connStr, 1);
|
||||
std::cout << "Connect to server..." << std::endl;
|
||||
sleep(1);
|
||||
createModelFromPG(path, client);
|
||||
#endif
|
||||
}
|
||||
else if (dbType == "No dbms")
|
||||
{
|
||||
std::cerr << "Please configure Model in " << path << "/model.json " << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Does not support " << dbType << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void create_model::createModel(const std::string &path)
|
||||
{
|
||||
DIR *dp;
|
||||
if ((dp = opendir(path.c_str())) == NULL)
|
||||
{
|
||||
std::cerr << "No such file or directory : " << path << std::endl;
|
||||
return;
|
||||
}
|
||||
closedir(dp);
|
||||
auto configFile = path + "/model.json";
|
||||
if (access(configFile.c_str(), 0) != 0)
|
||||
{
|
||||
std::cerr << "Config file " << configFile << " not found!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (access(configFile.c_str(), R_OK) != 0)
|
||||
{
|
||||
std::cerr << "No permission to read config file " << configFile << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::ifstream infile(configFile.c_str(), std::ifstream::in);
|
||||
if (infile)
|
||||
{
|
||||
Json::Value configJsonRoot;
|
||||
try
|
||||
{
|
||||
infile >> configJsonRoot;
|
||||
createModel(path, configJsonRoot);
|
||||
}
|
||||
catch (const std::exception &exception)
|
||||
{
|
||||
std::cerr << "Configuration file format error! in " << configFile << ":" << std::endl;
|
||||
std::cerr << exception.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_model::handleCommand(std::vector<std::string> ¶meters)
|
||||
{
|
||||
std::cout << "Create model" << std::endl;
|
||||
if (parameters.size() == 0)
|
||||
{
|
||||
std::cerr << "Missing Model path name!" << std::endl;
|
||||
}
|
||||
for (auto path : parameters)
|
||||
{
|
||||
createModel(path);
|
||||
}
|
||||
}
|
59
drogon_ctl/create_model.h
Normal file
59
drogon_ctl/create_model.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
*
|
||||
* create_model.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <json/json.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/PgClient.h>
|
||||
#endif
|
||||
#include <drogon/DrObject.h>
|
||||
#include "CommandHandler.h"
|
||||
#include <string>
|
||||
|
||||
using namespace drogon;
|
||||
using namespace drogon::orm;
|
||||
|
||||
namespace drogon_ctl
|
||||
{
|
||||
|
||||
struct ColumnInfo
|
||||
{
|
||||
std::string _colName;
|
||||
std::string _colValName;
|
||||
std::string _colTypeName;
|
||||
std::string _colType;
|
||||
ssize_t _colLength = -1;
|
||||
bool _isAutoVal = false;
|
||||
bool _isPrimaryKey = false;
|
||||
bool _notNull = false;
|
||||
bool _hasDefaultVal = false;
|
||||
};
|
||||
|
||||
class create_model : public DrObject<create_model>, public CommandHandler
|
||||
{
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override { return "create Model classes files"; }
|
||||
|
||||
protected:
|
||||
void createModel(const std::string &path);
|
||||
void createModel(const std::string &path, const Json::Value &config);
|
||||
#if USE_POSTGRESQL
|
||||
void createModelClassFromPG(const std::string &path, PgClient &client, const std::string &tableName);
|
||||
void createModelFromPG(const std::string &path, PgClient &client);
|
||||
#endif
|
||||
std::string _dbname;
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* {{className}}.cc
|
||||
* created by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#include "{{className}}.h"
|
||||
|
||||
const std::string User::primaryKeyName = "{{priKeyName}}";
|
||||
<%c++ if(@@.get<bool>("hasPrimaryKey",false)){%>
|
||||
const bool User::hasPrimaryKey = true;
|
||||
<%c++ }else{%>
|
||||
const bool User::hasPrimaryKey = false;
|
||||
<%c++}%>
|
||||
const std::string User::tableName = "{{tableName}}";
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* {{className}}.h
|
||||
* Created by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace drogon_dao
|
||||
{
|
||||
namespace {{dbName}}
|
||||
{
|
||||
class {{className}}
|
||||
{
|
||||
public:
|
||||
const static std::string primaryKeyName;
|
||||
const static bool hasPrimaryKey;
|
||||
const static std::string tableName;
|
||||
|
||||
typedef {{primaryKeyType}} PrimaryKeyType;
|
||||
{{className}}(const Row &r);
|
||||
};
|
||||
} // namespace {{dbName}}
|
||||
} // namespace drogon_dao
|
76
drogon_ctl/templates/model_cc.csp
Normal file
76
drogon_ctl/templates/model_cc.csp
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
*
|
||||
* {{className}}.cc
|
||||
* created by drogon_ctl
|
||||
*
|
||||
*/
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
|
||||
#include "{{className}}.h"
|
||||
#include <string>
|
||||
|
||||
using namespace drogon_model::{{dbname}};
|
||||
const std::string User::primaryKeyName = "{{priKeyName}}";
|
||||
<%c++ if(@@.get<bool>("hasPrimaryKey",false)){%>
|
||||
const bool User::hasPrimaryKey = true;
|
||||
<%c++ }else{%>
|
||||
const bool User::hasPrimaryKey = false;
|
||||
<%c++}%>
|
||||
const std::string User::tableName = "{{tableName}}";
|
||||
<%c++
|
||||
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
||||
auto className=@@.get<std::string>("className");
|
||||
%>
|
||||
{{className}}::{{className}}(const Row &r) noexcept
|
||||
{
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
%>
|
||||
if(!r["<%c++$$<<col._colName;%>"].isNull())
|
||||
{
|
||||
_<%c++$$<<col._colValName;%>=std::make_shared<<%c++$$<<col._colType;%>>(r["<%c++$$<<col._colName;%>"].as<<%c++$$<<col._colType;%>>());
|
||||
}
|
||||
<%c++
|
||||
}%>
|
||||
}
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(!col._colType.empty())
|
||||
{
|
||||
$$<<"const "<<col._colType<<" & "<<className<<"::getValueOf"<<col._colTypeName<<"(const "<<col._colType<<" &default) const noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" if(_"<<col._colValName<<")\n";
|
||||
$$<<" return *_"<<col._colValName<<";\n";
|
||||
$$<<" return default;\n";
|
||||
$$<<"}\n";
|
||||
|
||||
|
||||
|
||||
$$<<"std::shared_ptr<const "<<col._colType<<"> "<<className<<"::get"<<col._colTypeName<<"() const noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" return _"<<col._colValName<<";\n";
|
||||
$$<<"}\n";
|
||||
|
||||
|
||||
$$<<"void "<<className<<"::set"<<col._colTypeName<<"(const "<<col._colType<<" &"<<col._colValName<<") noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">("<<col._colValName<<");\n";
|
||||
$$<<"}\n";
|
||||
|
||||
|
||||
if(col._colType=="std::string")
|
||||
{
|
||||
$$<<"void "<<className<<"::set"<<col._colTypeName<<"("<<col._colType<<" &&"<<col._colValName<<") noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">(std::move("<<col._colValName<<"));\n";
|
||||
$$<<"}\n";
|
||||
}
|
||||
|
||||
}
|
||||
$$<<"\n";
|
||||
}
|
||||
%>
|
61
drogon_ctl/templates/model_h.csp
Normal file
61
drogon_ctl/templates/model_h.csp
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
*
|
||||
* {{className}}.h
|
||||
* Created by drogon_ctl
|
||||
*
|
||||
*/
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
#pragma once
|
||||
#include <drogon/orm/Result.h>
|
||||
#include <drogon/orm/Row.h>
|
||||
#include <drogon/orm/Field.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
using namespace drogon::orm;
|
||||
|
||||
namespace drogon_model
|
||||
{
|
||||
namespace {{dbName}}
|
||||
{
|
||||
|
||||
class {{className}}
|
||||
{
|
||||
public:
|
||||
const static std::string primaryKeyName;
|
||||
const static bool hasPrimaryKey;
|
||||
const static std::string tableName;
|
||||
|
||||
typedef {{primaryKeyType}} PrimaryKeyType;
|
||||
{{className}}(const Row &r) noexcept;
|
||||
<%c++
|
||||
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
||||
for(auto col:cols)
|
||||
{
|
||||
$$<<" //For column "<<col._colName<<"\n";
|
||||
if(!col._colType.empty())
|
||||
{
|
||||
$$<<" const "<<col._colType<<" &getValueOf"<<col._colTypeName<<"(const "<<col._colType<<" &default="<<col._colType<<"()) const noexcept;\n";
|
||||
$$<<" std::shared_ptr<const "<<col._colType<<"> get"<<col._colTypeName<<"() const noexcept;\n";
|
||||
$$<<" void set"<<col._colTypeName<<"(const "<<col._colType<<" &"<<col._colValName<<") noexcept;\n";
|
||||
if(col._colType=="std::string")
|
||||
$$<<" void set"<<col._colTypeName<<"("<<col._colType<<" &&"<<col._colValName<<") noexcept;\n";
|
||||
}
|
||||
else
|
||||
$$<<" //FIXME!!"<<" getValueOf"<<col._colTypeName<<"() const noexcept;\n";
|
||||
$$<<"\n";
|
||||
}
|
||||
%>
|
||||
private:
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(!col._colType.empty())
|
||||
$$<<" std::shared_ptr<"<<col._colType<<"> _"<<col._colValName<<";\n";
|
||||
}
|
||||
%>
|
||||
};
|
||||
|
||||
} // namespace {{dbName}}
|
||||
} // namespace drogon_model
|
@ -455,7 +455,7 @@ inline void Mapper<T>::insert(T &obj) noexcept(false)
|
||||
};
|
||||
binder.exec(); //Maybe throw exception;
|
||||
}
|
||||
assert(r.szie() == 1);
|
||||
assert(r.size() == 1);
|
||||
obj = T(r[0]);
|
||||
}
|
||||
template <typename T>
|
||||
|
@ -32,6 +32,7 @@ int main()
|
||||
drogon::orm::PgClient client("host=127.0.0.1 port=5432 dbname=trantor user=antao", 1);
|
||||
LOG_DEBUG << "start!";
|
||||
sleep(1);
|
||||
//client << "\\d users" >> [](const Result &r) {} >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; };
|
||||
Mapper<User> mapper(client);
|
||||
auto U = mapper.findByPrimaryKey(2);
|
||||
std::cout << "id=" << U._userId << std::endl;
|
||||
|
Loading…
Reference in New Issue
Block a user