/** * * @file db_test.cc * @author 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 * * Drogon database test program * */ #define DROGON_TEST_MAIN #include #include #include #include #include #include #include #include #include #include #include #include "mysql/Users.h" #include "postgresql/Users.h" #include "sqlite3/Users.h" using namespace std::chrono_literals; using namespace drogon::orm; void expFunction(const DrogonDbException &e) { } #if USE_POSTGRESQL DbClientPtr postgreClient; DROGON_TEST(PostgreTest) { auto &clientPtr = postgreClient; // Prepare the test environment *clientPtr << "DROP TABLE IF EXISTS USERS" >> [TEST_CTX](const Result &r) { SUCCESS(); clientPtr->execSqlAsync( "select 1 as result", [TEST_CTX](const drogon::orm::Result &r) { MANDATE(r.size() == 1); }, expFunction); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - Prepare the test environment(0) what():" + std::string(e.base().what())); }; *clientPtr << "CREATE TABLE users \ (\ user_id character varying(32),\ user_name character varying(64),\ password character varying(64),\ org_name character varying(20),\ signature character varying(50),\ avatar_id character varying(32),\ id serial PRIMARY KEY,\ salt character varying(20),\ admin boolean DEFAULT false,\ CONSTRAINT user_id_org UNIQUE(user_id, org_name)\ )" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - Prepare the test environment(1) what():" + std::string(e.base().what())); }; /// Test1:DbClient streaming-type interface /// 1.1 insert,non-blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *" << "pg" << "postgresql" << "123" << "default" >> [TEST_CTX](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; MANDATE(r[0]["id"].as() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(0) what():" + std::string(e.base().what())); }; /// 1.2 insert,blocking *clientPtr << "insert into users (user_id,user_name,admin,password,org_name) " "values($1,$2,$3,$4,$5) returning *" << "pg1" << "postgresql1" << drogon::orm::DefaultValue{} << "123" << "default" << Mode::Blocking >> [TEST_CTX](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; MANDATE(r[0]["id"].as() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(1) what():" + std::string(e.base().what())); }; /// 1.3 query,no-blocking *clientPtr << "select * from users where 1 = 1" << Mode::NonBlocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(2) what():" + std::string(e.base().what())); }; /// 1.4 query,blocking *clientPtr << "select * from users where 1 = 1" << Mode::Blocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(3) what():" + std::string(e.base().what())); }; /// 1.5 query,blocking int count = 0; *clientPtr << "select user_name, user_id, id from users where 1 = 1" << Mode::Blocking >> [&count, TEST_CTX](bool isNull, const std::string &name, std::string &&user_id, int id) { if (!isNull) ++count; else { MANDATE(count == 2); } } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(4) what():" + std::string(e.base().what())); }; /// 1.6 query, parameter binding *clientPtr << "select * from users where id = $1" << 1 >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(5) what():" + std::string(e.base().what())); }; /// 1.7 query, parameter binding *clientPtr << "select * from users where user_id = $1 and user_name = $2" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(6) what():" + std::string(e.base().what())); }; /// 1.8 delete *clientPtr << "delete from users where user_id = $1 and user_name = $2" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(7) what():" + std::string(e.base().what())); }; /// 1.9 update *clientPtr << "update users set user_id = $1, user_name = $2 where user_id " "= $3 and user_name = $4" << "pg1" << "postgresql1" << "pg" << "postgresql" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(8) what():" + std::string(e.base().what())); }; /// 1.10 clean up *clientPtr << "truncate table users restart identity" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient streaming-type interface(9) what():" + std::string(e.base().what())); }; /// Test asynchronous method /// 2.1 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values($1,$2,$3,$4) returning *", [TEST_CTX](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; MANDATE(r[0]["id"].as() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); }, "pg", "postgresql", "123", "default"); /// 2.2 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values($1,$2,$3,$4)", [TEST_CTX](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "123", "default"); /// 2.3 query clientPtr->execSqlAsync( "select * from users where 1 = 1", [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 2.2 query, parameter binding clientPtr->execSqlAsync( "select * from users where id = $1", [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); }, 1); /// 2.3 query, parameter binding clientPtr->execSqlAsync( "select * from users where user_id = $1 and user_name = $2", [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(4) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.4 delete clientPtr->execSqlAsync( "delete from users where user_id = $1 and user_name = $2", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(5) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.5 update clientPtr->execSqlAsync( "update users set user_id = $1, user_name = $2 where user_id " "= $3 and user_name = $4", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(6) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "pg", "postgresql"); /// 2.6 clean up clientPtr->execSqlAsync( "truncate table users restart identity", [TEST_CTX](const Result &r) { SUCCESS(); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(7) what():" + std::string(e.base().what())); }); /// Test synchronous method /// 3.1 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *", "pg", "postgresql", "123", "default"); MANDATE(r[0]["id"].as() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); } /// 3.2 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4)", "pg1", "postgresql1", "123", "default"); MANDATE(r.affectedRows() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); } /// 3.3 query try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name=$2", "pg1", "postgresql1"); MANDATE(r.size() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); } /// 3.4 query for none try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name=$2", "pg111", "postgresql1"); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); } /// 3.5 bad sql try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name='1234'", "pg111", "postgresql1"); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { SUCCESS(); } /// 3.6 clean up try { auto r = clientPtr->execSqlSync("truncate table users restart identity"); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient asynchronous interface(5) what():" + std::string(e.base().what())); } /// Test future interface /// 4.1 insert auto f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *", "pg", "postgresql", "123", "default"); try { auto r = f.get(); MANDATE(r[0]["id"].as() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient future interface(0) what():" + std::string(e.base().what())); } /// 4.2 insert f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4)", "pg1", "postgresql1", "123", "default"); try { auto r = f.get(); MANDATE(r.affectedRows() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient future interface(1) what():" + std::string(e.base().what())); } /// 4.3 query f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name=$2", "pg1", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient future interface(2) what():" + std::string(e.base().what())); } /// 4.4 query for none f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name=$2", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient future interface(3) what():" + std::string(e.base().what())); } /// 4.5 bad sql f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name='12'", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { SUCCESS(); } /// 4.6 clean up f = clientPtr->execSqlAsyncFuture("truncate table users restart identity"); try { auto r = f.get(); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient future interface(5) what():" + std::string(e.base().what())); } /// 5 Test Result and Row exception throwing // 5.1 query for none and try to access try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name=$2", "pg111", "postgresql1"); r.at(0); FAULT("postgresql - Result throwing exceptions(0)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.2 insert one just for setup try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *", "pg", "postgresql", "123", "default"); MANDATE(r[0]["id"].as() == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - Row throwing exceptions(0) what():" + std::string(e.base().what())); } // 5.3 try to access nonexistent column by name try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row["imaginary_column"]; FAULT("postgresql - Row throwing exceptions(1)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.4 try to access nonexistent column by index try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row.at(420); FAULT("postgresql - Row throwing exceptions(2)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.5 cleanup try { auto r = clientPtr->execSqlSync("truncate table users restart identity"); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("postgresql - Row throwing exceptions(3) what():" + std::string(e.base().what())); } /// Test ORM mapper /// 6.1 insert, noneblocking using namespace drogon_model::postgres; drogon::orm::Mapper mapper(clientPtr); Users user; user.setUserId("pg"); user.setUserName("postgres"); user.setPassword("123"); user.setOrgName("default"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - ORM mapper asynchronous interface(0) what():" + std::string(e.base().what())); }); /// 6.1.5 insert future user.setUserId("pg_future"); auto fu = mapper.insertFuture(user); try { auto u = fu.get(); SUCCESS(); } catch (const DrogonDbException &e) { FAULT( "postgresql - ORM mapper asynchronous future interface(0) what():" + std::string(e.base().what())); } /// 6.2 insert user.setUserId("pg1"); user.setUserName("postgres1"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 3); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - ORM mapper asynchronous interface(1) what():" + std::string(e.base().what())); }); /// 6.3 select where in mapper.findBy( Criteria(Users::Cols::_id, CompareOperator::In, std::vector{2, 200}), [TEST_CTX](std::vector users) { MANDATE(users.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - ORM mapper asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 6.3.5 count mapper.count( drogon::orm::Criteria(Users::Cols::_id, CompareOperator::EQ, 2020), [TEST_CTX](const size_t c) { MANDATE(c == 0); }, [TEST_CTX](const DrogonDbException &e) { FAULT("postgresql - ORM mapper asynchronous interface(3) what():" + std::string(e.base().what())); }); /// 6.4 find by primary key. blocking try { auto user = mapper.findByPrimaryKey(2); SUCCESS(); Users newUser; newUser.setId(user.getValueOfId()); newUser.setSalt("xxx"); auto c = mapper.update(newUser); MANDATE(c == 1); } catch (const DrogonDbException &e) { FAULT("postgresql - ORM mapper synchronous interface(0) what():" + std::string(e.base().what())); } #ifdef __cpp_impl_coroutine auto coro_test = [clientPtr, TEST_CTX]() -> drogon::Task<> { /// 7 Test coroutines. /// This is by no means comprehensive. But coroutine API is esentially a /// wrapper arround callbacks. The purpose is to test the interface /// works 7.1 Basic queries try { auto result = co_await clientPtr->execSqlCoro("select * from users;"); MANDATE(result.size() != 0); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient coroutine interface(0) what():" + std::string(e.base().what())); } /// 7.2 Parameter binding try { auto result = co_await clientPtr->execSqlCoro( "select * from users where 1=$1;", 1); MANDATE(result.size() != 0); } catch (const DrogonDbException &e) { FAULT("postgresql - DbClient coroutine interface(1) what():" + std::string(e.base().what())); } /// 7.3 CoroMapper try { CoroMapper mapper(clientPtr); auto user = co_await mapper.findByPrimaryKey(2); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("postgresql - ORM mapper coroutine interface(0) what():" + std::string(e.base().what())); } try { CoroMapper mapper(clientPtr); auto user = co_await mapper.findByPrimaryKey(314); FAULT("postgresql - ORM mapper coroutine interface(1)"); } catch (const DrogonDbException &e) { SUCCESS(); } try { CoroMapper mapper(clientPtr); auto users = co_await mapper.findAll(); auto count = co_await mapper.count(); MANDATE(users.size() == count); } catch (const DrogonDbException &e) { SUCCESS(); } /// 7.4 Transactions try { auto trans = co_await clientPtr->newTransactionCoro(); auto result = co_await trans->execSqlCoro("select * from users where 1=$1;", 1); MANDATE(result.size() != 0); } catch (const DrogonDbException &e) { FAULT( "postgresql - DbClient coroutine transaction interface(0) " "what():" + std::string(e.base().what())); } }; drogon::sync_wait(coro_test()); #endif } #endif #if USE_MYSQL DbClientPtr mysqlClient; DROGON_TEST(MySQLTest) { auto &clientPtr = mysqlClient; REQUIRE(clientPtr != nullptr); // Prepare the test environment *clientPtr << "CREATE DATABASE IF NOT EXISTS drogonTestMysql" >> [TEST_CTX](const Result &r) { SUCCESS(); clientPtr->execSqlAsync( "select 1 as result", [TEST_CTX](const drogon::orm::Result &r) { MANDATE(r.size() == 1); }, expFunction); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - Prepare the test environment(0) what():" + std::string(e.base().what())); }; *clientPtr << "USE drogonTestMysql" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - Prepare the test environment(0) what():" + std::string(e.base().what())); }; // mysql is case sensitive *clientPtr << "DROP TABLE IF EXISTS users" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - Prepare the test environment(1) what():" + std::string(e.base().what())); }; *clientPtr << "CREATE TABLE users \ (\ id int(11) auto_increment PRIMARY KEY,\ user_id varchar(32),\ user_name varchar(64),\ password varchar(64),\ org_name varchar(20),\ signature varchar(50),\ avatar_id varchar(32),\ salt character varying(20),\ admin boolean DEFAULT false,\ CONSTRAINT user_id_org UNIQUE(user_id, org_name)\ )" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - Prepare the test environment(2) what():" + std::string(e.base().what())); }; /// Test1:DbClient streaming-type interface /// 1.1 insert,non-blocking *clientPtr << "insert into users (user_id,user_name,password,org_name,admin) " "values(?,?,?,?,?)" << "pg" << "postgresql" << "123" << "default" << drogon::orm::DefaultValue{} >> [TEST_CTX](const Result &r) { MANDATE(r.insertId() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(0) what():" + std::string(e.base().what())); }; /// 1.2 insert,blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)" << "pg1" << "postgresql1" << "123" << "default" << Mode::Blocking >> [TEST_CTX](const Result &r) { MANDATE(r.insertId() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(1) what():" + std::string(e.base().what())); }; /// 1.3 query,no-blocking *clientPtr << "select * from users where 1 = 1" << Mode::NonBlocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(2) what():" + std::string(e.base().what())); }; /// 1.4 query,blocking *clientPtr << "select * from users where 1 = 1" << Mode::Blocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(3) what():" + std::string(e.base().what())); }; /// 1.5 query,blocking int count = 0; *clientPtr << "select user_name, user_id, id from users where 1 = 1" << Mode::Blocking >> [&count, TEST_CTX](bool isNull, const std::string &name, std::string &&user_id, int id) { if (!isNull) ++count; else { MANDATE(count == 2); } } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(4) what():" + std::string(e.base().what())); }; /// 1.6 query, parameter binding *clientPtr << "select * from users where id = ?" << 1 >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(5) what():" + std::string(e.base().what())); }; /// 1.7 query, parameter binding *clientPtr << "select * from users where user_id = ? and user_name = ?" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(6) what():" + std::string(e.base().what())); }; /// 1.8 delete *clientPtr << "delete from users where user_id = ? and user_name = ?" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(7) what():" + std::string(e.base().what())); }; /// 1.9 update *clientPtr << "update users set user_id = ?, user_name = ? where user_id " "= ? and user_name = ?" << "pg1" << "postgresql1" << "pg" << "postgresql" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(8) what():" + std::string(e.base().what())); }; /// 1.10 truncate *clientPtr << "truncate table users" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient streaming-type interface(9) what():" + std::string(e.base().what())); }; /// Test asynchronous method /// 2.1 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values(?,?,?,?)", [TEST_CTX](const Result &r) { MANDATE(r.insertId() != 0); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); }, "pg", "postgresql", "123", "default"); /// 2.2 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values(?,?,?,?)", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "123", "default"); /// 2.3 query clientPtr->execSqlAsync( "select * from users where 1 = 1", [TEST_CTX](const Result &r) { MANDATE(r.size() == 2); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 2.2 query, parameter binding clientPtr->execSqlAsync( "select * from users where id = ?", [TEST_CTX](const Result &r) { // std::cout << r.size() << "\n"; MANDATE(r.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); }, 1); /// 2.3 query, parameter binding clientPtr->execSqlAsync( "select * from users where user_id = ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(4) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.4 delete clientPtr->execSqlAsync( "delete from users where user_id = ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(5) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.5 update clientPtr->execSqlAsync( "update users set user_id = ?, user_name = ? where user_id " "= ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(6) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "pg", "postgresql"); /// 2.6 truncate clientPtr->execSqlAsync( "truncate table users", [TEST_CTX](const Result &r) { SUCCESS(); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(7) what():" + std::string(e.base().what())); }); /// Test synchronous method /// 3.1 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg", "postgresql", "123", "default"); // std::cout << r.insertId(); MANDATE(r.insertId() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); } /// 3.2 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg1", "postgresql1", "123", "default"); MANDATE(r.affectedRows() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); } /// 3.3 query try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg1", "postgresql1"); MANDATE(r.size() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); } /// 3.4 query for none try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); } /// 3.5 bad sql try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name='1234'", "pg111", "postgresql1"); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { SUCCESS(); } /// 3.6 truncate try { auto r = clientPtr->execSqlSync("truncate table users"); SUCCESS(); } catch (const DrogonDbException &e) { SUCCESS(); } /// Test future interface /// 4.1 insert auto f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?) ", "pg", "postgresql", "123", "default"); try { auto r = f.get(); MANDATE(r.insertId() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient future interface(0) what():" + std::string(e.base().what())); } /// 4.2 insert f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg1", "postgresql1", "123", "default"); try { auto r = f.get(); MANDATE(r.affectedRows() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient future interface(1) what():" + std::string(e.base().what())); } /// 4.3 query f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name=?", "pg1", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient future interface(2) what():" + std::string(e.base().what())); } /// 4.4 query for none f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient future interface(3) what():" + std::string(e.base().what())); } /// 4.5 bad sql f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name='12'", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0); } catch (const DrogonDbException &e) { SUCCESS(); } /// 4.6 truncate f = clientPtr->execSqlAsyncFuture("truncate table users"); try { auto r = f.get(); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient future interface(5) what():" + std::string(e.base().what())); } /// 5 Test Result and Row exception throwing // 5.1 query for none and try to access try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); r.at(0); FAULT("mysql - Result throwing exceptions(0)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.2 insert one just for setup try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg", "postgresql", "123", "default"); MANDATE(r.insertId() == 1); } catch (const DrogonDbException &e) { FAULT("mysql - Row throwing exceptions(0) what():" + std::string(e.base().what())); } // 5.3 try to access nonexistent column by name try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row["imaginary_column"]; FAULT("mysql - Row throwing exceptions(1)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.4 try to access nonexistent column by index try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row.at(420); FAULT("mysql - Row throwing exceptions(2)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.5 cleanup try { auto r = clientPtr->execSqlSync("truncate table users"); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("mysql - Row throwing exceptions(3) what():" + std::string(e.base().what())); } /// Test ORM mapper /// 6.1 insert, noneblocking using namespace drogon_model::drogonTestMysql; drogon::orm::Mapper mapper(clientPtr); Users user; user.setUserId("pg"); user.setUserName("postgres"); user.setPassword("123"); user.setOrgName("default"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - ORM mapper asynchronous interface(0) what():" + std::string(e.base().what())); }); /// 6.1.5 count mapper.count( drogon::orm::Criteria(Users::Cols::_id, CompareOperator::EQ, 1), [TEST_CTX](const size_t c) { MANDATE(c == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - ORM mapper asynchronous interface(1) what():" + std::string(e.base().what())); }); /// 6.2 insert user.setUserId("pg1"); user.setUserName("postgres1"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 2); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - ORM mapper asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 6.3 select where in mapper.findBy( Criteria(Users::Cols::_id, CompareOperator::In, std::vector{2, 200}), [TEST_CTX](std::vector users) { MANDATE(users.size() == 1); }, [TEST_CTX](const DrogonDbException &e) { FAULT("mysql - ORM mapper asynchronous interface(3) what():" + std::string(e.base().what())); }); /// 6.4 find by primary key. blocking try { auto user = mapper.findByPrimaryKey(1); SUCCESS(); Users newUser; newUser.setId(user.getValueOfId()); newUser.setSalt("xxx"); auto c = mapper.update(newUser); MANDATE(c == 1); } catch (const DrogonDbException &e) { FAULT("mysql - ORM mapper synchronous interface(0) what():" + std::string(e.base().what())); } #ifdef __cpp_impl_coroutine auto coro_test = [clientPtr, TEST_CTX]() -> drogon::Task<> { /// 7 Test coroutines. /// This is by no means comprehensive. But coroutine API is esentially a /// wrapper arround callbacks. The purpose is to test the interface /// works 7.1 Basic queries try { auto result = co_await clientPtr->execSqlCoro("select * from users;"); MANDATE(result.size() != 0); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient coroutine interface(0) what():" + std::string(e.base().what())); } /// 7.2 Parameter binding try { auto result = co_await clientPtr->execSqlCoro( "select * from users where 1=?;", 1); MANDATE(result.size() != 0); } catch (const DrogonDbException &e) { FAULT("mysql - DbClient coroutine interface(1) what():" + std::string(e.base().what())); } }; drogon::sync_wait(coro_test()); #endif } #endif #if USE_SQLITE3 DbClientPtr sqlite3Client; DROGON_TEST(SQLite3Test) { auto &clientPtr = sqlite3Client; REQUIRE(clientPtr != nullptr); // Prepare the test environment *clientPtr << "DROP TABLE IF EXISTS users" >> [TEST_CTX](const Result &r) { SUCCESS(); clientPtr->execSqlAsync( "select 1 as result", [TEST_CTX](const drogon::orm::Result &r) { MANDATE(r.size() == 1); }, expFunction); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - Prepare the test environment(0): what():" + std::string(e.base().what())); }; *clientPtr << "CREATE TABLE users \ (\ id INTEGER PRIMARY KEY autoincrement,\ user_id varchar(32),\ user_name varchar(64),\ password varchar(64),\ org_name varchar(20),\ signature varchar(50),\ avatar_id varchar(32),\ salt character varchar(20),\ admin boolean DEFAULT false,\ CONSTRAINT user_id_org UNIQUE(user_id, org_name)\ )" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - Prepare the test environment(1) what():" + std::string(e.base().what())); }; /// Test1:DbClient streaming-type interface /// 1.1 insert,non-blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)" << "pg" << "postgresql" << "123" << "default" >> [TEST_CTX](const Result &r) { MANDATE(r.insertId() == 1ULL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(0) what():" + std::string(e.base().what())); }; /// 1.2 insert,blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)" << "pg1" << "postgresql1" << "123" << "default" << Mode::Blocking >> [TEST_CTX](const Result &r) { MANDATE(r.insertId() == 2ULL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(1) what():" + std::string(e.base().what())); }; /// 1.3 query,no-blocking *clientPtr << "select * from users where 1 = 1" << Mode::NonBlocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(2) what():" + std::string(e.base().what())); }; /// 1.4 query,blocking *clientPtr << "select * from users where 1 = 1" << Mode::Blocking >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 2UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(3) what():" + std::string(e.base().what())); }; /// 1.5 query,blocking int count = 0; *clientPtr << "select user_name, user_id, id from users where 1 = 1" << Mode::Blocking >> [&count, TEST_CTX](bool isNull, const std::string &name, std::string &&user_id, int id) { if (!isNull) ++count; else { MANDATE(count == 2); } } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(4) what():" + std::string(e.base().what())); }; /// 1.6 query, parameter binding *clientPtr << "select * from users where id = ?" << 1 >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(5) what():" + std::string(e.base().what())); }; /// 1.7 query, parameter binding *clientPtr << "select * from users where user_id = ? and user_name = ?" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.size() == 1UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(6) what():" + std::string(e.base().what())); }; /// 1.8 delete *clientPtr << "delete from users where user_id = ? and user_name = ?" << "pg1" << "postgresql1" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(7) what():" + std::string(e.base().what())); }; /// 1.9 update *clientPtr << "update users set user_id = ?, user_name = ? where user_id " "= ? and user_name = ?" << "pg1" << "postgresql1" << "pg" << "postgresql" >> [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1UL); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(8) what():" + std::string(e.base().what())); }; /// 1.10 clean up *clientPtr << "delete from users" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(9.1) what():" + std::string(e.base().what())); }; *clientPtr << "UPDATE sqlite_sequence SET seq = 0" >> [TEST_CTX](const Result &r) { SUCCESS(); } >> [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient streaming-type interface(9.2) what():" + std::string(e.base().what())); }; /// Test asynchronous method /// 2.1 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values(?,?,?,?)", [TEST_CTX](const Result &r) { MANDATE(r.insertId() == 1ULL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); }, "pg", "postgresql", "123", "default"); /// 2.2 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values(?,?,?,?)", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "123", "default"); /// 2.3 query clientPtr->execSqlAsync( "select * from users where 1 = 1", [TEST_CTX](const Result &r) { MANDATE(r.size() == 2UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 2.2 query, parameter binding clientPtr->execSqlAsync( "select * from users where id = ?", [TEST_CTX](const Result &r) { MANDATE(r.size() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); }, 1); /// 2.3 query, parameter binding clientPtr->execSqlAsync( "select * from users where user_id = ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.size() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(4) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.4 delete clientPtr->execSqlAsync( "delete from users where user_id = ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(5) what():" + std::string(e.base().what())); }, "pg1", "postgresql1"); /// 2.5 update clientPtr->execSqlAsync( "update users set user_id = ?, user_name = ? where user_id " "= ? and user_name = ?", [TEST_CTX](const Result &r) { MANDATE(r.affectedRows() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(6) what():" + std::string(e.base().what())); }, "pg1", "postgresql1", "pg", "postgresql"); /// 2.6 clean up clientPtr->execSqlAsync( "delete from users", [TEST_CTX](const Result &r) { SUCCESS(); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(7.1) what():" + std::string(e.base().what())); }); clientPtr->execSqlAsync( "UPDATE sqlite_sequence SET seq = 0", [TEST_CTX](const Result &r) { SUCCESS(); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(7.2) what():" + std::string(e.base().what())); }); /// Test synchronous method /// 3.1 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg", "postgresql", "123", "default"); MANDATE(r.insertId() == 1ULL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(0) what():" + std::string(e.base().what())); } /// 3.2 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg1", "postgresql1", "123", "default"); MANDATE(r.affectedRows() == 1UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(1) what():" + std::string(e.base().what())); } /// 3.3 query try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg1", "postgresql1"); MANDATE(r.size() == 1UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(2) what():" + std::string(e.base().what())); } /// 3.4 query for none try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); MANDATE(r.size() == 0UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient asynchronous interface(3) what():" + std::string(e.base().what())); } /// 3.5 bad sql try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name='1234'", "pg111", "postgresql1"); MANDATE(r.size() == 0UL); } catch (const DrogonDbException &e) { SUCCESS(); } /// 3.6 clean up try { auto r = clientPtr->execSqlSync("delete from users"); SUCCESS(); } catch (const DrogonDbException &e) { SUCCESS(); } try { auto r = clientPtr->execSqlSync("UPDATE sqlite_sequence SET seq = 0"); SUCCESS(); } catch (const DrogonDbException &e) { SUCCESS(); } /// Test future interface /// 4.1 insert auto f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?) ", "pg", "postgresql", "123", "default"); try { auto r = f.get(); MANDATE(r.insertId() == 1ULL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(0) what():" + std::string(e.base().what())); } /// 4.2 insert f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg1", "postgresql1", "123", "default"); try { auto r = f.get(); MANDATE(r.affectedRows() == 1UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(1) what():" + std::string(e.base().what())); } /// 4.3 query f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name=?", "pg1", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 1UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(2) what():" + std::string(e.base().what())); } /// 4.4 query for none f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(3) what():" + std::string(e.base().what())); } /// 4.5 bad sql f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=? and user_name='12'", "pg111", "postgresql1"); try { auto r = f.get(); MANDATE(r.size() == 0UL); } catch (const DrogonDbException &e) { SUCCESS(); } /// 4.6 clean up f = clientPtr->execSqlAsyncFuture("delete from users"); try { auto r = f.get(); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(5.1) what():" + std::string(e.base().what())); } f = clientPtr->execSqlAsyncFuture("UPDATE sqlite_sequence SET seq = 0"); try { auto r = f.get(); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient future interface(5.2) what():" + std::string(e.base().what())); } /// 5 Test Result and Row exception throwing // 5.1 query for none and try to access try { auto r = clientPtr->execSqlSync( "select * from users where user_id=? and user_name=?", "pg111", "postgresql1"); r.at(0); FAULT("sqlite3 - Result throwing exceptions(0)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.2 insert one just for setup try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values(?,?,?,?)", "pg", "postgresql", "123", "default"); MANDATE(r.insertId() == 1ULL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - Row throwing exceptions(0) what():" + std::string(e.base().what())); } // 5.3 try to access nonexistent column by name try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row["imaginary_column"]; FAULT("sqlite3 - Row throwing exceptions(1)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.4 try to access nonexistent column by index try { auto r = clientPtr->execSqlSync("select * from users"); auto row = r.at(0); row.at(420); FAULT("sqlite3 - Row throwing exceptions(2)"); } catch (const DrogonDbException &e) { SUCCESS(); } // 5.5 cleanup try { auto r = clientPtr->execSqlSync("delete from users"); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - Row throwing exceptions(3) what():" + std::string(e.base().what())); } try { auto r = clientPtr->execSqlSync("UPDATE sqlite_sequence SET seq = 0"); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - Row throwing exceptions(3) what():" + std::string(e.base().what())); } /// Test ORM mapper TODO /// 5.1 insert, noneblocking using namespace drogon_model::sqlite3; drogon::orm::Mapper mapper(clientPtr); Users user; user.setUserId("pg"); user.setUserName("postgres"); user.setPassword("123"); user.setOrgName("default"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - ORM mapper asynchronous interface(0) what():" + std::string(e.base().what())); }); /// 5.2 insert user.setUserId("pg1"); user.setUserName("postgres1"); mapper.insert( user, [TEST_CTX](Users ret) { MANDATE(ret.getPrimaryKey() == 2UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - ORM mapper asynchronous interface(1) what():" + std::string(e.base().what())); }); /// 5.3 select where in mapper.findBy( Criteria(Users::Cols::_id, CompareOperator::In, std::vector{2, 200}), [TEST_CTX](std::vector users) { MANDATE(users.size() == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - ORM mapper asynchronous interface(2) what():" + std::string(e.base().what())); }); /// 5.3.5 count mapper.count( drogon::orm::Criteria(Users::Cols::_id, CompareOperator::EQ, 2), [TEST_CTX](const size_t c) { MANDATE(c == 1UL); }, [TEST_CTX](const DrogonDbException &e) { FAULT("sqlite3 - ORM mapper asynchronous interface(3) what():" + std::string(e.base().what())); }); /// 5.4 find by primary key. blocking try { auto user = mapper.findByPrimaryKey(1); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - ORM mapper synchronous interface(0) what():" + std::string(e.base().what())); } #ifdef __cpp_impl_coroutine auto coro_test = [clientPtr, TEST_CTX]() -> drogon::Task<> { /// 7 Test coroutines. /// This is by no means comprehensive. But coroutine API is esentially a /// wrapper arround callbacks. The purpose is to test the interface /// works 7.1 Basic queries try { auto result = co_await clientPtr->execSqlCoro("select * from users;"); MANDATE(result.size() != 0UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient coroutine interface(0) what():" + std::string(e.base().what())); } /// 7.2 Parameter binding try { auto result = co_await clientPtr->execSqlCoro( "select * from users where 1=?;", 1); MANDATE(result.size() != 0UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - DbClient coroutine interface(1) what():" + std::string(e.base().what())); } /// 7.3 ORM CoroMapper try { auto mapper = CoroMapper(clientPtr); auto user = co_await mapper.findOne( Criteria(Users::Cols::_id, CompareOperator::EQ, 1)); SUCCESS(); } catch (const DrogonDbException &e) { FAULT("sqlite3 - CoroMapper coroutine interface(0) what():" + std::string(e.base().what())); } try { auto mapper = CoroMapper(clientPtr); auto users = co_await mapper.findBy( Criteria(Users::Cols::_id, CompareOperator::EQ, 1)); MANDATE(users.size() == 1UL); } catch (const DrogonDbException &e) { FAULT("sqlite3 - CoroMapper coroutine interface(1) what():" + std::string(e.base().what())); } try { auto mapper = CoroMapper(clientPtr); auto n = co_await mapper.deleteByPrimaryKey(1); MANDATE(n == 1); } catch (const DrogonDbException &e) { FAULT("sqlite3 - CoroMapper coroutine interface(2) what():" + std::string(e.base().what())); } co_await drogon::sleepCoro( trantor::EventLoop::getEventLoopOfCurrentThread(), 1.0s); }; drogon::sync_wait(coro_test()); #endif } #endif using namespace drogon; int main(int argc, char **argv) { trantor::Logger::setLogLevel(trantor::Logger::LogLevel::kDebug); #if USE_MYSQL mysqlClient = DbClient::newMysqlClient( "host=localhost port=3306 user=root client_encoding=utf8mb4", 1); #endif #if USE_POSTGRESQL postgreClient = DbClient::newPgClient( "host=127.0.0.1 port=5432 dbname=postgres user=postgres password=12345 " "client_encoding=utf8", 1); #endif #if USE_SQLITE3 sqlite3Client = DbClient::newSqlite3Client("filename=:memory:", 1); #endif int testStatus = test::run(argc, argv); return testStatus; }