diff --git a/hdr/collectors.h b/hdr/collectors.h new file mode 100644 index 00000000..0a1bf152 --- /dev/null +++ b/hdr/collectors.h @@ -0,0 +1,82 @@ + +#ifndef SQLITE_COLLECTORS_H +#define SQLITE_COLLECTORS_H + +#include + +#if __cplusplus > 201402 +#define CPP14_SUPPORTED +#endif + +#ifdef CPP14_SUPPORTED +#define __COLLECTOR_RETURN_TYPE auto +#define __COLLECTOR_CTOR_OF_T(T,X) {X} +#else +#define __COLLECTOR_RETURN_TYPE std::function +#define __COLLECTOR_CTOR_OF_T(T,X) T(X) +#endif + +template +struct collect +{ + template class C> + inline static + __COLLECTOR_RETURN_TYPE + to(C &container) + { + return [&container](const Args&... args) + { + container.push_back(__COLLECTOR_CTOR_OF_T(T,args...)); + }; + } + + template class C> + inline static + __COLLECTOR_RETURN_TYPE + to(C> &container) + { + return [&container](const Args&... args) + { + container.push_back(std::make_shared(args...)); + }; + } + + template class C, typename T > + struct as + { + friend C operator>>(sqlite::database_binder& db_binder, as) + { + C container; + db_binder>>to(container); + return container; + } + + friend C operator>>(sqlite::database_binder&& db_binder, as) + { + return db_binder>>as(); + } + }; + + template + struct as + { + friend std::shared_ptr operator>>(sqlite::database_binder& db_binder, as) + { + std::shared_ptr objP; + db_binder>>[&objP](Args... args) + { + objP = std::make_shared(args...); + }; + return objP; + } + + friend std::shared_ptr operator>>(sqlite::database_binder&& db_binder, as whatever) + { + return db_binder>>whatever; + } + + }; +}; + + +#endif diff --git a/tests/collector.cc b/tests/collector.cc new file mode 100644 index 00000000..62e9281e --- /dev/null +++ b/tests/collector.cc @@ -0,0 +1,88 @@ + +#include "collectors.h" +#include +#include + +using namespace std; +using namespace sqlite; + +struct user +{ + int id; + string name; + + user(int _id, string _name):id(_id),name(_name) + { + clog<<"object created : "<<*this<<"\n"; + } + + friend std::ostream& operator <<(std::ostream& out, const user& a) + { + out<<"<"<"; + return out; + } +}; + + +database init_db() +{ + database db(":memory:"); + db << "CREATE TABLE tbl (id integer, name string);"; + db << "INSERT INTO tbl VALUES (?, ?);" << 1 << "hello"; + db << "INSERT INTO tbl VALUES (?, ?);" << 2 << "world"; + + return db; +} + + +void test_single_user(database &db) +{ + auto may_be_user = db<<"SELECT * FROM tbl WHERE id = 1 ;" + >> collect::as(); + assert(may_be_user); + assert(may_be_user->name == "hello"); +} + +void test_multiple_user(database &db) +{ + auto all_users = db<<"SELECT * FROM tbl ;" + >> collect::as(); + assert(not all_users.empty()); + assert(any_of(all_users.begin(), all_users.end(), [](user u) + { + return u.name == "hello"; + })); +} + +void test_multiple_usernames(database &db) +{ + auto names = db<<"SELECT name FROM tbl ORDER BY id DESC;" + >> collect::as(); + assert(not names.empty()); + assert(names[0] == "world"); + assert(names[1] == "hello"); +} + +void test_append_results_to_container(database &db) +{ + list ids = {-1,0,11}; + + db<<"SELECT id FROM tbl ;" + >>collect::to(ids); + + list expected = { -1,0,11, 1, 2}; + assert(ids == expected); +} + +int main() +{ + database db=init_db(); + + test_single_user(db); + test_multiple_user(db); + test_multiple_usernames(db); + + test_append_results_to_container(db); + + return 0; +}