mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-12-02 11:47:56 +08:00
Merge pull request #9 from an-tao/with_orm
Add support for the model: You can read and write the postgreSQL database using drogon:: orm::DbClient or drogon::orm::Transaction; You can create a model class using 'drogon_ctl create model ...'; You can read and write models from database using the drogon::orm::Mapper <T> template; Note: Currently only postgreSQL is supported.
This commit is contained in:
commit
c1164d8c42
@ -19,7 +19,7 @@ else()
|
||||
set(CMAKE_CXX_STD_FLAGS c++17)
|
||||
endif()
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/trantor ${PROJECT_SOURCE_DIR}/lib/inc)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/trantor ${PROJECT_SOURCE_DIR}/lib/inc ${PROJECT_SOURCE_DIR}/orm_lib/inc)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules/)
|
||||
#jsoncpp
|
||||
@ -61,6 +61,16 @@ link_libraries(${ZLIB_LIBRARIES})
|
||||
|
||||
message(STATUS "zlib inc path:" ${ZLIB_INCLUDE_DIR})
|
||||
|
||||
#find postgres
|
||||
find_package(PostgreSQL)
|
||||
if(PostgreSQL_FOUND)
|
||||
include_directories(${PostgreSQL_INCLUDE_DIR})
|
||||
message(STATUS "libpq inc path:" ${PostgreSQL_INCLUDE_DIR})
|
||||
link_libraries(${PostgreSQL_LIBRARIES})
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl DIR_SRCS)
|
||||
set(USE_ORM TRUE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
@ -80,6 +90,7 @@ add_subdirectory(examples)
|
||||
add_subdirectory(drogon_ctl)
|
||||
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR}/lib/src DIR_SRCS)
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src DIR_SRCS)
|
||||
|
||||
ADD_LIBRARY(drogon ${DIR_SRCS})
|
||||
|
||||
@ -90,6 +101,13 @@ SET(CONFIG_HEADER "${PROJECT_SOURCE_DIR}/config.h")
|
||||
file(WRITE "${CONFIG_HEADER}" "#pragma once\n")
|
||||
|
||||
file(APPEND "${CONFIG_HEADER}" "#include <trantor/utils/config.h>\n")
|
||||
|
||||
if(PostgreSQL_FOUND)
|
||||
file(APPEND "${CONFIG_HEADER}" "#define USE_POSTGRESQL 1")
|
||||
else()
|
||||
file(APPEND "${CONFIG_HEADER}" "#define USE_POSTGRESQL 0")
|
||||
endif()
|
||||
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
|
||||
if(CMAKE_BUILD_TYPE_LOWER STREQUAL release)
|
||||
file(APPEND "${CONFIG_HEADER}" "\n" "const char compileFlags[]=\"" ${CMAKE_CXX_FLAGS_RELEASE} "\";")
|
||||
@ -113,14 +131,22 @@ EXEC_PROGRAM(${PROJECT_SOURCE_DIR}/update_config.sh ARGS "${CONFIG_HEADER} ${PRO
|
||||
|
||||
if (MAKETEST STREQUAL YES)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
if(PostgreSQL_FOUND)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
SET(CMAKE_INSTALL_PREFIX /usr/local)
|
||||
|
||||
#Installation
|
||||
install(TARGETS drogon DESTINATION lib)
|
||||
|
||||
file(GLOB drogon_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/*.h")
|
||||
install(FILES ${drogon_headers} DESTINATION include/drogon)
|
||||
if(USE_ORM)
|
||||
file(GLOB orm_headers "${CMAKE_CURRENT_SOURCE_DIR}/orm_lib/inc/drogon/orm/*.h")
|
||||
install(FILES ${orm_headers} DESTINATION include/drogon/orm)
|
||||
endif()
|
||||
file(GLOB drogon_util_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/utils/*.h")
|
||||
install(FILES ${drogon_util_headers}
|
||||
DESTINATION include/drogon/utils)
|
||||
|
54
COPYING
Executable file
54
COPYING
Executable file
@ -0,0 +1,54 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 drogon,an-tao
|
||||
https://github.com/an-tao/drogon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
The license for libpqxx is as follows. Source code for several classes, including the
|
||||
Result class, the Row class, the Field class and their iterator classes are taken from
|
||||
libpqxx and modified.
|
||||
|
||||
Copyright (c) 2001-2017 Jeroen T. Vermeulen.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the author, nor the names of other contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -26,6 +26,26 @@
|
||||
"key": ""
|
||||
}
|
||||
],*/
|
||||
"db_clients":[
|
||||
{
|
||||
//name:Name of the client,'default' by default
|
||||
//"name":"",
|
||||
//rdbms:server type, "postgreSQL" by default
|
||||
"rdbms": "postgreSQL",
|
||||
//host:server address,localhost by default
|
||||
"host": "127.0.0.1",
|
||||
//port:server port, 5432 by default
|
||||
"port": 5432,
|
||||
//dbname:Database name
|
||||
"dbname": "test",
|
||||
//user:'postgres' by default
|
||||
"user": "",
|
||||
//passwd:'' by default
|
||||
"passwd": "",
|
||||
//connection_number:1 by default
|
||||
"connection_number":1
|
||||
}
|
||||
],
|
||||
"app": {
|
||||
//threads_num:num of threads,1 by default
|
||||
"threads_num": 16,
|
||||
|
@ -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)
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class CommandHandler : public virtual drogon::DrObjectBase
|
||||
virtual std::string script() { return ""; }
|
||||
virtual std::string detail() { return ""; }
|
||||
virtual ~CommandHandler() {}
|
||||
};
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -49,4 +49,4 @@ void exeCommand(std::vector<std::string> ¶meters)
|
||||
{
|
||||
std::cout << "command error!use help command to get usage!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -32,7 +32,9 @@ std::string create::detail()
|
||||
"drogon_ctl create project <project_name> //"
|
||||
"create a project named project_name\n"
|
||||
"drogon_ctl create filter <class_name> //"
|
||||
"create a filter named class_name\n";
|
||||
"create a filter named class_name\n"
|
||||
"drogon_ctl create model <model_path> //"
|
||||
"create model classes in model_path\n";
|
||||
}
|
||||
|
||||
void create::handleCommand(std::vector<std::string> ¶meters)
|
||||
@ -42,4 +44,4 @@ void create::handleCommand(std::vector<std::string> ¶meters)
|
||||
createObjName = std::string("create_") + createObjName;
|
||||
parameters[0] = createObjName;
|
||||
exeCommand(parameters);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
/**
|
||||
*
|
||||
* @file
|
||||
* @author An Tao
|
||||
* @section LICENSE
|
||||
* create_controller.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
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -49,4 +49,4 @@ void create_filter::handleCommand(std::vector<std::string> ¶meters)
|
||||
auto className = parameters[0];
|
||||
createFilterHeaderFile(className);
|
||||
createFilterSourceFile(className);
|
||||
}
|
||||
}
|
||||
|
@ -31,4 +31,4 @@ class create_filter : public DrObject<create_filter>, public CommandHandler
|
||||
void newViewHeaderFile(std::ofstream &file, const std::string &className);
|
||||
void newViewSourceFile(std::ofstream &file, const std::string &className, std::ifstream &infile);
|
||||
};
|
||||
} // namespace drogon_ctl
|
||||
} // namespace drogon_ctl
|
||||
|
405
drogon_ctl/create_model.cc
Normal file
405
drogon_ctl/create_model.cc
Normal file
@ -0,0 +1,405 @@
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_model.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#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;
|
||||
|
||||
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, const DbClientPtr &client, const std::string &tableName)
|
||||
{
|
||||
auto className = nameTransform(tableName, true);
|
||||
HttpViewData data;
|
||||
data["className"] = className;
|
||||
data["tableName"] = tableName;
|
||||
data["hasPrimaryKey"] = (int)0;
|
||||
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._dbType = "pg";
|
||||
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>();
|
||||
info._colDatabaseType = type;
|
||||
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 if (type == "date")
|
||||
{
|
||||
info._colType = "::trantor::Date";
|
||||
info._colLength = 4;
|
||||
}
|
||||
else if (type.find("timestamp") != std::string::npos)
|
||||
{
|
||||
info._colType = "::trantor::Date";
|
||||
}
|
||||
else
|
||||
{
|
||||
info._colType = "std::string";
|
||||
//FIXME add more type such as hstore,blob...
|
||||
}
|
||||
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);
|
||||
};
|
||||
|
||||
size_t pkNumber = 0;
|
||||
*client << "SELECT \
|
||||
pg_constraint.conname AS pk_name,\
|
||||
pg_constraint.conkey AS pk_vector \
|
||||
FROM pg_constraint \
|
||||
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid \
|
||||
WHERE \
|
||||
pg_class.relname = $1 \
|
||||
AND pg_constraint.contype = 'p'"
|
||||
<< tableName
|
||||
<< Mode::Blocking >>
|
||||
[&](bool isNull, const std::string &pkName, const std::vector<std::shared_ptr<short>> &pk) {
|
||||
if (!isNull)
|
||||
{
|
||||
//std::cout << tableName << " Primary key = " << pk.size() << std::endl;
|
||||
pkNumber = pk.size();
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
data["hasPrimaryKey"] = (int)pkNumber;
|
||||
if (pkNumber == 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["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);
|
||||
};
|
||||
}
|
||||
else if (pkNumber > 1)
|
||||
{
|
||||
std::vector<std::string> pkNames, pkTypes;
|
||||
for (size_t i = 1; i <= pkNumber; i++)
|
||||
{
|
||||
*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 = $2 and pg_constraint.contype='p'"
|
||||
<< (int)i
|
||||
<< tableName
|
||||
<< Mode::Blocking >>
|
||||
[&](bool isNull, std::string colName, const std::string &type) {
|
||||
if (isNull)
|
||||
return;
|
||||
//std::cout << "primary key name=" << colName << std::endl;
|
||||
pkNames.push_back(colName);
|
||||
for (auto &col : cols)
|
||||
{
|
||||
if (col._colName == colName)
|
||||
{
|
||||
col._isPrimaryKey = true;
|
||||
pkTypes.push_back(col._colType);
|
||||
}
|
||||
}
|
||||
} >>
|
||||
[](const DrogonDbException &e) {
|
||||
std::cerr << e.base().what() << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
}
|
||||
data["primaryKeyName"] = pkNames;
|
||||
data["primaryKeyType"] = pkTypes;
|
||||
}
|
||||
|
||||
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, const DbClientPtr &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;
|
||||
}
|
||||
DbClientPtr client = drogon::orm::DbClient::newPgClient(connStr, 1);
|
||||
std::cout << "Connect to server..." << std::endl;
|
||||
std::cout << "Source files in the " << path << " folder will be overwritten, continue(y/n)?\n";
|
||||
auto in = getchar();
|
||||
if (in != 'Y' && in != 'y')
|
||||
{
|
||||
std::cout << "Abort!" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
auto tables = config["tables"];
|
||||
if (!tables || tables.size() == 0)
|
||||
createModelFromPG(path, client);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < (int)tables.size(); i++)
|
||||
{
|
||||
auto tableName = tables[i].asString();
|
||||
std::cout << "table name:" << tableName << std::endl;
|
||||
createModelClassFromPG(path, client, tableName);
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
#if USE_POSTGRESQL
|
||||
std::cout << "Create model" << std::endl;
|
||||
if (parameters.size() == 0)
|
||||
{
|
||||
std::cerr << "Missing Model path name!" << std::endl;
|
||||
}
|
||||
for (auto path : parameters)
|
||||
{
|
||||
createModel(path);
|
||||
}
|
||||
#else
|
||||
std::cout << "No database can be found in your system, please install one first!" << std::endl;
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
62
drogon_ctl/create_model.h
Normal file
62
drogon_ctl/create_model.h
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/config.h>
|
||||
#include <json/json.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/DbClient.h>
|
||||
using namespace drogon::orm;
|
||||
#endif
|
||||
#include <drogon/DrObject.h>
|
||||
#include "CommandHandler.h"
|
||||
#include <string>
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
|
||||
namespace drogon_ctl
|
||||
{
|
||||
|
||||
struct ColumnInfo
|
||||
{
|
||||
std::string _colName;
|
||||
std::string _colValName;
|
||||
std::string _colTypeName;
|
||||
std::string _colType;
|
||||
std::string _colDatabaseType;
|
||||
std::string _dbType;
|
||||
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, const DbClientPtr &client, const std::string &tableName);
|
||||
void createModelFromPG(const std::string &path, const DbClientPtr &client);
|
||||
#endif
|
||||
std::string _dbname;
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -67,6 +67,11 @@ static void newConfigFile(std::ofstream &configFile)
|
||||
auto templ=DrTemplateBase::newTemplate("config");
|
||||
configFile << templ->genText();
|
||||
}
|
||||
static void newModelConfigFile(std::ofstream &configFile)
|
||||
{
|
||||
auto templ = DrTemplateBase::newTemplate("model_json");
|
||||
configFile << templ->genText();
|
||||
}
|
||||
void create_project::createProject(const std::string &projectName)
|
||||
{
|
||||
|
||||
@ -88,6 +93,7 @@ void create_project::createProject(const std::string &projectName)
|
||||
mkdir("controllers", 0755);
|
||||
mkdir("filters", 0755);
|
||||
mkdir("build", 0755);
|
||||
mkdir("models", 0755);
|
||||
mkdir("cmake_modules", 0755);
|
||||
std::ofstream jsonFile("cmake_modules/FindJsoncpp.cmake", std::ofstream::out);
|
||||
newJsonFindFile(jsonFile);
|
||||
@ -98,4 +104,6 @@ void create_project::createProject(const std::string &projectName)
|
||||
newGitIgFile(gitFile);
|
||||
std::ofstream configFile("config.json", std::ofstream::out);
|
||||
newConfigFile(configFile);
|
||||
std::ofstream modelConfigFile("models/model.json", std::ofstream::out);
|
||||
newModelConfigFile(modelConfigFile);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@ -28,4 +28,4 @@ class create_project : public DrObject<create_project>, public CommandHandler
|
||||
std::string _outputPath = ".";
|
||||
void createProject(const std::string &projectName);
|
||||
};
|
||||
} // namespace drogon_ctl
|
||||
} // namespace drogon_ctl
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -32,4 +32,4 @@ class create_view : public DrObject<create_view>, public CommandHandler
|
||||
void newViewHeaderFile(std::ofstream &file, const std::string &className);
|
||||
void newViewSourceFile(std::ofstream &file, const std::string &className, std::ifstream &infile);
|
||||
};
|
||||
} // namespace drogon_ctl
|
||||
} // namespace drogon_ctl
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -60,4 +60,4 @@ void help::handleCommand(std::vector<std::string> ¶meters)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
* this is a drogon lib tool program
|
||||
* run drogon_ctl help to get usage
|
||||
*/
|
||||
@ -36,4 +36,4 @@ int main(int argc, char *argv[])
|
||||
exeCommand(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,18 @@ find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
link_libraries(${ZLIB_LIBRARIES})
|
||||
|
||||
#find postgres
|
||||
find_package(PostgreSQL)
|
||||
if(PostgreSQL_FOUND)
|
||||
include_directories(${PostgreSQL_INCLUDE_DIR})
|
||||
link_libraries(${PostgreSQL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
AUX_SOURCE_DIRECTORY(./ SRC_DIR)
|
||||
AUX_SOURCE_DIRECTORY(controllers CTL_SRC)
|
||||
AUX_SOURCE_DIRECTORY(filters FILTER_SRC)
|
||||
AUX_SOURCE_DIRECTORY(models MODEL_SRC)
|
||||
|
||||
include_directories(/usr/local/include)
|
||||
|
||||
@ -71,4 +80,5 @@ foreach(cspFile ${SCP_LIST})
|
||||
set(VIEWSRC ${VIEWSRC} ${classname}.cc)
|
||||
endforeach()
|
||||
|
||||
add_executable({{ProjectName}} ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_executable({{ProjectName}} ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC} ${MODEL_SRC})
|
||||
|
@ -26,6 +26,27 @@
|
||||
"key": ""
|
||||
}
|
||||
],*/
|
||||
/*
|
||||
"db_clients": [
|
||||
{
|
||||
//name:Name of the client,'default' by default
|
||||
//"name":"",
|
||||
//rdbms:server type, "postgreSQL" by default
|
||||
"rdbms": "postgreSQL",
|
||||
//host:server address,localhost by default
|
||||
"host": "127.0.0.1",
|
||||
//port:server port, 5432 by default
|
||||
"port": 5432,
|
||||
//dbname:Database name
|
||||
"dbname": "test",
|
||||
//user:'postgres' by default
|
||||
"user": "",
|
||||
//passwd:'' by default
|
||||
"passwd": "",
|
||||
//connection_number:1 by default
|
||||
"connection_number": 1
|
||||
}
|
||||
],*/
|
||||
"app": {
|
||||
//threads_num:num of threads,1 by default
|
||||
"threads_num": 16,
|
||||
@ -89,18 +110,23 @@
|
||||
"use_gzip": true,
|
||||
//static_files_cache_time:5 (seconds) by default,the time in which static file response is cached,
|
||||
//0 means cache forever,the negative value means no cache
|
||||
"static_files_cache_time":5,
|
||||
"static_files_cache_time": 5,
|
||||
//simple_controllers_map:Configuring mapping from path to simple controller
|
||||
"simple_controllers_map": [
|
||||
{
|
||||
"path": "/path/name",
|
||||
"controller": "controllerClassName",
|
||||
"http_methods": ["get","post"],
|
||||
"filters": ["FilterClassName"]
|
||||
"http_methods": [
|
||||
"get",
|
||||
"post"
|
||||
],
|
||||
"filters": [
|
||||
"FilterClassName"
|
||||
]
|
||||
}
|
||||
],
|
||||
//idle_connection_timeout: defaults to 60 seconds, the lifetime
|
||||
//of the connection without read or write
|
||||
"idle_connection_timeout":60
|
||||
"idle_connection_timeout": 60
|
||||
}
|
||||
}
|
||||
}
|
272
drogon_ctl/templates/model_cc.csp
Normal file
272
drogon_ctl/templates/model_cc.csp
Normal file
@ -0,0 +1,272 @@
|
||||
/**
|
||||
*
|
||||
* {{className}}.cc
|
||||
* created by drogon_ctl
|
||||
*
|
||||
*/
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
|
||||
#include "{{className}}.h"
|
||||
#include <string>
|
||||
<%c++
|
||||
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
||||
auto className=@@.get<std::string>("className");
|
||||
%>
|
||||
|
||||
using namespace drogon_model::{{dbName}};
|
||||
|
||||
<%c++for(auto col:cols){
|
||||
%>
|
||||
const std::string {{className}}::Cols::<%c++$$<<col._colName;%> = "<%c++$$<<col._colName;%>";
|
||||
<%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)>0){%>
|
||||
const bool {{className}}::hasPrimaryKey = true;
|
||||
<%c++ }else{%>
|
||||
const bool {{className}}::hasPrimaryKey = false;
|
||||
<%c++}%>
|
||||
const std::string {{className}}::tableName = "{{tableName}}";
|
||||
|
||||
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) noexcept
|
||||
{
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(col._colType.empty())
|
||||
continue;
|
||||
%>
|
||||
if(!r["<%c++$$<<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";
|
||||
$$<<" long t = timelocal(&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";
|
||||
$$<<" }\n";
|
||||
continue;
|
||||
}
|
||||
else if(col._colDatabaseType.find("timestamp")!=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";
|
||||
$$<<" size_t t = timelocal(&stm);\n";
|
||||
$$<<" size_t decimalNum = 0;\n";
|
||||
$$<<" if(*p=='.')\n";
|
||||
$$<<" {\n";
|
||||
$$<<" std::string decimals(p+1,&timeStr[timeStr.length()]);\n";
|
||||
$$<<" while(decimals.length()<6)\n";
|
||||
$$<<" {\n";
|
||||
$$<<" decimals += \"0\";\n";
|
||||
$$<<" }\n";
|
||||
$$<<" decimalNum = (size_t)atol(decimals.c_str());\n";
|
||||
$$<<" }\n";
|
||||
// $$<<" _"<<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";
|
||||
$$<<" }\n";
|
||||
continue;
|
||||
}
|
||||
%>
|
||||
_<%c++$$<<col._colValName;%>=std::make_shared<<%c++$$<<col._colType;%>>(r["<%c++$$<<col._colName;%>"].as<<%c++$$<<col._colType;%>>());
|
||||
}
|
||||
<%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 "<<col._colType<<" &defaultValue) const noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" if(_"<<col._colValName<<")\n";
|
||||
$$<<" return *_"<<col._colValName<<";\n";
|
||||
$$<<" return defaultValue;\n";
|
||||
$$<<"}\n";
|
||||
|
||||
$$<<"std::shared_ptr<const "<<col._colType<<"> "<<className<<"::get"<<col._colTypeName<<"() const noexcept\n";
|
||||
$$<<"{\n";
|
||||
$$<<" return _"<<col._colValName<<";\n";
|
||||
$$<<"}\n";
|
||||
|
||||
if(!col._isAutoVal)
|
||||
{
|
||||
$$<<"void "<<className<<"::set"<<col._colTypeName<<"(const "<<col._colType<<" &"<<col._colValName<<") noexcept\n";
|
||||
$$<<"{\n";
|
||||
if(col._colDatabaseType=="date")
|
||||
{
|
||||
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">("<<col._colValName<<".roundDay());\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">("<<col._colValName<<");\n";
|
||||
}
|
||||
$$<<" _dirtyFlag["<<i<<"] = true;\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";
|
||||
$$<<" _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<int>("hasPrimaryKey")>1)
|
||||
{
|
||||
$$<<"typename "<<className<<"::PrimaryKeyType "<<className<<"::getPrimaryKey() const\n";
|
||||
$$<<"{\n";
|
||||
$$<<" return std::make_tuple(";
|
||||
int count=0;
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(col._isPrimaryKey)
|
||||
{
|
||||
count++;
|
||||
$$<<"*_"<<col._colValName;
|
||||
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(auto col:cols){
|
||||
if(!col._isAutoVal&&!col._colType.empty())
|
||||
{
|
||||
%>
|
||||
if(get<%c++$$<<col._colTypeName;%>())
|
||||
{
|
||||
<%c++if(col._colDatabaseType=="date"){%>
|
||||
binder << (int32_t)(getValueOf<%c++$$<<col._colTypeName;%>().microSecondsSinceEpoch()/1000000-946656000)/86400;
|
||||
<%c++}else if(col._colDatabaseType.find("timestamp")!=std::string::npos){%>
|
||||
binder << get<%c++$$<<col._colTypeName;%>()->toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S", true);
|
||||
<%c++}else{%>
|
||||
binder << getValueOf<%c++$$<<col._colTypeName;%>();
|
||||
<%c++}%>
|
||||
}
|
||||
else
|
||||
{
|
||||
binder << nullptr;
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
%>
|
||||
}
|
||||
|
||||
const std::vector<std::string> {{className}}::updateColumns() const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
for(size_t i=0;i<sizeof(_dirtyFlag);i++)
|
||||
{
|
||||
if(_dirtyFlag[i])
|
||||
{
|
||||
ret.push_back(getColumnName(i));
|
||||
}
|
||||
}
|
||||
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[<%c++$$<<i;%>])
|
||||
{
|
||||
if(get<%c++$$<<col._colTypeName;%>())
|
||||
{
|
||||
<%c++if(col._colDatabaseType=="date"){%>
|
||||
binder << (int32_t)(getValueOf<%c++$$<<col._colTypeName;%>().microSecondsSinceEpoch()/1000000-946656000)/86400;
|
||||
<%c++}else if(col._colDatabaseType.find("timestamp")!=std::string::npos){%>
|
||||
binder << get<%c++$$<<col._colTypeName;%>()->toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S", true);
|
||||
<%c++}else{%>
|
||||
binder << getValueOf<%c++$$<<col._colTypeName;%>();
|
||||
<%c++}%>
|
||||
}
|
||||
else
|
||||
{
|
||||
binder << nullptr;
|
||||
}
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
%>
|
||||
}
|
130
drogon_ctl/templates/model_h.csp
Normal file
130
drogon_ctl/templates/model_h.csp
Normal file
@ -0,0 +1,130 @@
|
||||
/**
|
||||
*
|
||||
* {{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 <drogon/orm/SqlBinder.h>
|
||||
#include <trantor/utils/Date.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace drogon::orm;
|
||||
|
||||
namespace drogon_model
|
||||
{
|
||||
namespace {{dbName}}
|
||||
{
|
||||
|
||||
class {{className}}
|
||||
{
|
||||
public:
|
||||
struct Cols
|
||||
{
|
||||
<%c++
|
||||
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
||||
for(size_t i=0;i<cols.size();i++)
|
||||
{
|
||||
$$<<" static const std::string "<<cols[i]._colName<<";\n";
|
||||
}
|
||||
%>
|
||||
};
|
||||
|
||||
const static int primaryKeyNumber;
|
||||
const static std::string tableName;
|
||||
const static bool hasPrimaryKey;
|
||||
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
||||
const static std::string primaryKeyName;
|
||||
<%c++if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
||||
typedef {{primaryKeyType}} PrimaryKeyType;
|
||||
const PrimaryKeyType & getPrimaryKey() const;
|
||||
<%c++}else{%>
|
||||
typedef void PrimaryKeyType;
|
||||
<%c++}%>
|
||||
<%c++}else{
|
||||
auto pkTypes=@@.get<std::vector<std::string>>("primaryKeyType");
|
||||
std::string typelist;
|
||||
for(size_t i=0;i<pkTypes.size();i++)
|
||||
{
|
||||
typelist += pkTypes[i];
|
||||
if(i<(pkTypes.size()-1))
|
||||
typelist += ",";
|
||||
}
|
||||
%>
|
||||
const static std::vector<std::string> primaryKeyName;
|
||||
typedef std::tuple<<%c++$$<<typelist;%>> PrimaryKeyType;//<%c++
|
||||
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
||||
for(size_t i=0;i<pkName.size();i++)
|
||||
{
|
||||
$$<<pkName[i];
|
||||
if(i<(pkName.size()-1))
|
||||
$$<<",";
|
||||
}
|
||||
%>
|
||||
|
||||
PrimaryKeyType getPrimaryKey() const;
|
||||
<%c++}%>
|
||||
{{className}}(const Row &r) noexcept;
|
||||
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
$$<<" //For column "<<col._colName<<"\n";
|
||||
if(!col._colType.empty())
|
||||
{
|
||||
$$<<" const "<<col._colType<<" &getValueOf"<<col._colTypeName<<"(const "<<col._colType<<" &defaultValue="<<col._colType<<"()) const noexcept;\n";
|
||||
$$<<" std::shared_ptr<const "<<col._colType<<"> get"<<col._colTypeName<<"() const noexcept;\n";
|
||||
if(!col._isAutoVal)
|
||||
{
|
||||
$$<<" 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";
|
||||
}
|
||||
%>
|
||||
static const std::string &getColumnName(size_t index) noexcept(false);
|
||||
static const std::vector<std::string> &insertColumns() noexcept;
|
||||
void outputArgs(drogon::orm::internal::SqlBinder &binder) const;
|
||||
|
||||
const std::vector<std::string> updateColumns() const;
|
||||
void updateArgs(drogon::orm::internal::SqlBinder &binder) const;
|
||||
|
||||
private:
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(!col._colType.empty())
|
||||
$$<<" std::shared_ptr<"<<col._colType<<"> _"<<col._colValName<<";\n";
|
||||
}
|
||||
%>
|
||||
struct MetaData
|
||||
{
|
||||
const std::string _colName;
|
||||
const std::string _colType;
|
||||
const std::string _colDatabaseType;
|
||||
const ssize_t _colLength;
|
||||
const bool _isAutoVal;
|
||||
const bool _isPrimaryKey;
|
||||
const bool _notNull;
|
||||
};
|
||||
static const std::vector<MetaData> _metaData;
|
||||
bool _dirtyFlag[<%c++$$<<cols.size();%>]={ false };
|
||||
};
|
||||
|
||||
} // namespace {{dbName}}
|
||||
} // namespace drogon_model
|
13
drogon_ctl/templates/model_json.csp
Normal file
13
drogon_ctl/templates/model_json.csp
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
//rdbms:server type, postgreSQL
|
||||
"rdbms":"postgreSQL",
|
||||
//host:server address,localhost by default;
|
||||
"host":"127.0.0.1",
|
||||
//port:server port, 5432 by default;
|
||||
"port":5432,
|
||||
//dbname:Database name;
|
||||
"dbname":"",
|
||||
"user":"",
|
||||
"passwd":"",
|
||||
"tables":[]
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -32,4 +32,4 @@ void version::handleCommand(std::vector<std::string> ¶meters)
|
||||
std::cout << "version:" << VERSION << std::endl;
|
||||
std::cout << "git commit:" << VERSION_MD5 << std::endl;
|
||||
std::cout << "compile config:" << compileFlags <<" "<< includeDirs << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -16,4 +16,4 @@ void JsonTestController::asyncHandleHttpRequest(const HttpRequestPtr &req, const
|
||||
json["rows"] = array;
|
||||
auto resp = HttpResponse::newHttpJsonResponse(json);
|
||||
callback(resp);
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,4 @@ class JsonTestController : public drogon::HttpSimpleController<JsonTestControlle
|
||||
PATH_LIST_BEGIN
|
||||
PATH_ADD("/json", "drogon::GetFilter", "drogon::LocalHostFilter");
|
||||
PATH_LIST_END
|
||||
};
|
||||
};
|
||||
|
@ -7,4 +7,4 @@ void ListParaCtl::asyncHandleHttpRequest(const HttpRequestPtr &req, const std::f
|
||||
data.insert("parameters", req->getParameters());
|
||||
auto res = drogon::HttpResponse::newHttpViewResponse("ListParaView.csp", data);
|
||||
callback(res);
|
||||
}
|
||||
}
|
||||
|
@ -7,4 +7,4 @@ void TestController::asyncHandleHttpRequest(const HttpRequestPtr &req, const std
|
||||
resp->setBody("<p>Hello, world!</p>");
|
||||
resp->setExpiredTime(0);
|
||||
callback(resp);
|
||||
}
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ void TestViewCtl::asyncHandleHttpRequest(const HttpRequestPtr &req, const std::f
|
||||
data.insert("title", std::string("TestView"));
|
||||
auto res = drogon::HttpResponse::newHttpViewResponse("TestView", data);
|
||||
callback(res);
|
||||
}
|
||||
}
|
||||
|
@ -13,4 +13,4 @@ void WebSocketTest::handleNewConnection(const HttpRequestPtr &,
|
||||
const WebSocketConnectionPtr &)
|
||||
{
|
||||
LOG_TRACE << "new websocket connection!";
|
||||
}
|
||||
}
|
||||
|
@ -28,4 +28,4 @@ void Attachment::upload(const HttpRequestPtr &req,
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(HttpResponse::k200OK);
|
||||
callback(resp);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@ -44,4 +44,4 @@ class Cookie
|
||||
std::string _key;
|
||||
std::string _value;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class DeleteFilter : public HttpFilter<DeleteFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class GetFilter : public HttpFilter<GetFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,13 +8,16 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/config.h>
|
||||
#if USE_POSTGRESQL
|
||||
#include <drogon/orm/DbClient.h>
|
||||
#endif
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <drogon/HttpBinder.h>
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
@ -137,6 +140,17 @@ class HttpAppFramework : public trantor::NonCopyable
|
||||
virtual void setStaticFilesCacheTime(int cacheTime) = 0;
|
||||
virtual int staticFilesCacheTime() const = 0;
|
||||
virtual void setIdleConnectionTimeout(size_t timeout) = 0;
|
||||
#if USE_POSTGRESQL
|
||||
virtual orm::DbClientPtr getDbClient(const std::string &name = "default") = 0;
|
||||
virtual void createDbClient(const std::string &dbType,
|
||||
const std::string &host,
|
||||
const u_short port,
|
||||
const std::string &databaseName,
|
||||
const std::string &userName,
|
||||
const std::string &password,
|
||||
const size_t connectionNum = 1,
|
||||
const std::string &name = "default") = 0;
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual void registerHttpController(const std::string &pathPattern,
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -73,4 +73,4 @@ public:
|
||||
protected:
|
||||
HttpClient() = default;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -37,4 +37,4 @@ class HttpFilter : public DrObject<T>, public HttpFilterBase
|
||||
public:
|
||||
virtual ~HttpFilter() {}
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -70,4 +70,4 @@ class HttpRequest
|
||||
static HttpRequestPtr newHttpRequest();
|
||||
};
|
||||
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class InnerIpFilter : public HttpFilter<InnerIpFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class LocalHostFilter : public HttpFilter<LocalHostFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -7,4 +7,4 @@ class NotFound : public DrTemplate<NotFound>
|
||||
NotFound(){};
|
||||
virtual ~NotFound(){};
|
||||
virtual std::string genText(const HttpViewData &) override;
|
||||
};
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class PostFilter : public HttpFilter<PostFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ class PutFilter : public HttpFilter<PutFilter>
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) override;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -43,4 +43,4 @@ class WebSocketConnection
|
||||
virtual any *getMutableContext() = 0;
|
||||
};
|
||||
typedef std::shared_ptr<WebSocketConnection> WebSocketConnectionPtr;
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -28,4 +28,4 @@
|
||||
#include <drogon/HttpClient.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -216,6 +216,30 @@ static void loadApp(const Json::Value &app)
|
||||
auto kickOffTimeout = app.get("idle_connection_timeout", 60).asUInt64();
|
||||
HttpAppFramework::instance().setIdleConnectionTimeout(kickOffTimeout);
|
||||
}
|
||||
static void loadDbClients(const Json::Value &dbClients)
|
||||
{
|
||||
#if USE_POSTGRESQL
|
||||
if (!dbClients)
|
||||
return;
|
||||
for (auto &client : dbClients)
|
||||
{
|
||||
auto type = client.get("rdbms", "postgreSQL").asString();
|
||||
auto host = client.get("host", "127.0.0.1").asString();
|
||||
auto port = client.get("port", 5432).asUInt();
|
||||
auto dbname = client.get("dbname", "").asString();
|
||||
if (dbname == "")
|
||||
{
|
||||
std::cerr << "Please configure dbname in the configuration file" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto user = client.get("user", "postgres").asString();
|
||||
auto password = client.get("passwd", "").asString();
|
||||
auto connNum = client.get("connection_number", 1).asUInt();
|
||||
auto name = client.get("name", "default").asString();
|
||||
HttpAppFramework::instance().createDbClient(type, host, (u_short)port, dbname, user, password, connNum, name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static void loadListeners(const Json::Value &listeners)
|
||||
{
|
||||
if (!listeners)
|
||||
@ -246,4 +270,5 @@ void ConfigLoader::load()
|
||||
loadApp(_configJsonRoot["app"]);
|
||||
loadSSL(_configJsonRoot["ssl"]);
|
||||
loadListeners(_configJsonRoot["listeners"]);
|
||||
loadDbClients(_configJsonRoot["db_clients"]);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -31,4 +31,4 @@ class ConfigLoader : public trantor::NonCopyable
|
||||
std::string _configFile;
|
||||
Json::Value _configJsonRoot;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -50,4 +50,4 @@ const std::string Cookie::cookieString() const
|
||||
ret.resize(ret.length() - 2); //delete last semicolon
|
||||
ret.append("\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -46,4 +46,4 @@ std::unordered_map<std::string, DrAllocFunc> &DrClassMap::getMap()
|
||||
{
|
||||
static std::unordered_map<std::string, DrAllocFunc> map;
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
@ -360,7 +360,7 @@ void HttpAppFrameworkImpl::run()
|
||||
break;
|
||||
}
|
||||
waitpid(child_pid, &child_status, 0);
|
||||
sleep(5);
|
||||
sleep(1);
|
||||
LOG_INFO << "start new process";
|
||||
}
|
||||
}
|
||||
@ -1215,3 +1215,32 @@ HttpAppFramework &HttpAppFramework::instance()
|
||||
HttpAppFramework::~HttpAppFramework()
|
||||
{
|
||||
}
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
orm::DbClientPtr HttpAppFrameworkImpl::getDbClient(const std::string &name)
|
||||
{
|
||||
return _dbClientsMap[name];
|
||||
}
|
||||
|
||||
void HttpAppFrameworkImpl::createDbClient(const std::string &dbType,
|
||||
const std::string &host,
|
||||
const u_short port,
|
||||
const std::string &databaseName,
|
||||
const std::string &userName,
|
||||
const std::string &password,
|
||||
const size_t connectionNum,
|
||||
const std::string &name)
|
||||
{
|
||||
if (dbType == "postgreSQL")
|
||||
{
|
||||
auto connStr = formattedString("host=%s port=%u dbname=%s user=%s", host.c_str(), port, databaseName.c_str(), userName.c_str());
|
||||
if (!password.empty())
|
||||
{
|
||||
connStr += " password=";
|
||||
connStr += password;
|
||||
}
|
||||
auto client = drogon::orm::DbClient::newPgClient(connStr, connectionNum);
|
||||
_dbClientsMap[name] = client;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@ -85,7 +85,17 @@ class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
}
|
||||
|
||||
trantor::EventLoop *loop();
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
virtual orm::DbClientPtr getDbClient(const std::string &name = "default") override;
|
||||
virtual void createDbClient(const std::string &dbType,
|
||||
const std::string &host,
|
||||
const u_short port,
|
||||
const std::string &databaseName,
|
||||
const std::string &userName,
|
||||
const std::string &password,
|
||||
const size_t connectionNum = 1,
|
||||
const std::string &name = "default") override;
|
||||
#endif
|
||||
private:
|
||||
virtual void registerHttpController(const std::string &pathPattern,
|
||||
const HttpBinderBasePtr &binder,
|
||||
@ -202,5 +212,9 @@ class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
int _staticFilesCacheTime = 5;
|
||||
std::unordered_map<std::string, std::weak_ptr<HttpResponse>> _staticFilesCache;
|
||||
std::mutex _staticFilesCacheMutex;
|
||||
#if USE_POSTGRESQL
|
||||
std::map<std::string, orm::DbClientPtr> _dbClientsMap;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace drogon
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
@ -240,4 +240,4 @@ HttpClientPtr HttpClient::newHttpClient(const std::string &ip, uint16_t port, bo
|
||||
HttpClientPtr HttpClient::newHttpClient(const std::string &hostString)
|
||||
{
|
||||
return std::make_shared<HttpClientImpl>(((HttpAppFrameworkImpl &)(HttpAppFramework::instance())).loop(), hostString);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@ -39,4 +39,4 @@ class HttpClientImpl : public HttpClient, public std::enable_shared_from_this<Ht
|
||||
void onRecvMessage(const trantor::TcpConnectionPtr &, trantor::MsgBuffer *);
|
||||
std::string _domain;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#include <drogon/HttpViewBase.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ void InnerIpFilter::doFilter(const HttpRequestPtr &req,
|
||||
}
|
||||
auto res = drogon::HttpResponse::newNotFoundResponse();
|
||||
fcb(res);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
@ -26,4 +26,4 @@ void LocalHostFilter::doFilter(const HttpRequestPtr &req,
|
||||
}
|
||||
auto res = drogon::HttpResponse::newNotFoundResponse();
|
||||
fcb(res);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@ -38,4 +38,4 @@ class SharedLibManager : public trantor::NonCopyable
|
||||
void *loadLibs(const std::string &sourceFile, void *oldHld);
|
||||
trantor::TimerId _timeId;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -118,4 +118,4 @@ const any &WebSocketConnectionImpl::WebSocketConnectionImpl::getContext() const
|
||||
any *WebSocketConnectionImpl::WebSocketConnectionImpl::getMutableContext()
|
||||
{
|
||||
return &_context;
|
||||
}
|
||||
}
|
||||
|
@ -41,4 +41,4 @@ class WebSocketConnectionImpl : public WebSocketConnection
|
||||
WebSocketControllerBasePtr _ctrlPtr;
|
||||
any _context;
|
||||
};
|
||||
} // namespace drogon
|
||||
} // namespace drogon
|
||||
|
@ -249,4 +249,4 @@ std::string Md5Encode::Encode(std::string src_info)
|
||||
result.append(GetHexStr(param.uc_));
|
||||
result.append(GetHexStr(param.ud_));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -70,4 +70,4 @@ class Md5Encode
|
||||
static const unsigned long long k_ti_num_integer;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
73
orm_lib/inc/drogon/orm/ArrayParser.h
Normal file
73
orm_lib/inc/drogon/orm/ArrayParser.h
Normal file
@ -0,0 +1,73 @@
|
||||
/** Handling of SQL arrays.
|
||||
*
|
||||
* DO NOT INCLUDE THIS FILE DIRECTLY; include drogon/orm/Field.h instead.
|
||||
*
|
||||
* Copyright (c) 2018, Jeroen T. Vermeulen.
|
||||
*
|
||||
* See COPYING for copyright license. If you did not receive a file called
|
||||
* COPYING with this source code, please notify the distributor of this mistake,
|
||||
* or contact the author.
|
||||
*/
|
||||
//Taken from libpqxx and modified
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
namespace orm
|
||||
{
|
||||
/// Low-level array parser.
|
||||
/** Use this to read an array field retrieved from the database.
|
||||
*
|
||||
* Use this only if your client encoding is UTF-8, ASCII, or a single-byte
|
||||
* encoding which is a superset of ASCII.
|
||||
*
|
||||
* The input is a C-style string containing the textual representation of an
|
||||
* array, as returned by the database. The parser reads this representation
|
||||
* on the fly. The string must remain in memory until parsing is done.
|
||||
*
|
||||
* Parse the array by making calls to @c get_next until it returns a
|
||||
* @c juncture of "done". The @c juncture tells you what the parser found in
|
||||
* that step: did the array "nest" to a deeper level, or "un-nest" back up?
|
||||
*/
|
||||
class ArrayParser
|
||||
{
|
||||
public:
|
||||
/// What's the latest thing found in the array?
|
||||
enum juncture
|
||||
{
|
||||
/// Starting a new row.
|
||||
row_start,
|
||||
/// Ending the current row.
|
||||
row_end,
|
||||
/// Found a NULL value.
|
||||
null_value,
|
||||
/// Found a string value.
|
||||
string_value,
|
||||
/// Parsing has completed.
|
||||
done,
|
||||
};
|
||||
|
||||
/// Constructor. You don't need this; use @c field::as_array instead.
|
||||
explicit ArrayParser(const char input[]);
|
||||
|
||||
/// Parse the next step in the array.
|
||||
/** Returns what it found. If the juncture is @c string_value, the string
|
||||
* will contain the value. Otherwise, it will be empty.
|
||||
*
|
||||
* Call this until the @c juncture it returns is @c done.
|
||||
*/
|
||||
std::pair<juncture, std::string> getNext();
|
||||
|
||||
private:
|
||||
/// Current parsing position in the input.
|
||||
const char *m_pos;
|
||||
};
|
||||
|
||||
} // namespace orm
|
||||
} // namespace drogon
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user