diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 06:13:02 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 06:13:02 +0000 |
commit | 36adc76235fb0a38e7042bc751f988b71627e2a0 (patch) | |
tree | fc83b3f4e0afeb3932c8d200f5493f0a8d6c4619 /sca-cpp/trunk/components/sqldb | |
parent | 86b1de85536e93c59a25702a5a2d3e384202ffd2 (diff) |
Changes to get successful C++11 based build. Code cleanup, dependency upgrades, and const + inline optimizations in components, samples, and app hosting server.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1420007 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r-- | sca-cpp/trunk/components/sqldb/Makefile.am | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/components/sqldb/client-test.cpp | 71 | ||||
-rw-r--r-- | sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp | 20 | ||||
-rw-r--r-- | sca-cpp/trunk/components/sqldb/pgsql-test.cpp | 33 | ||||
-rw-r--r-- | sca-cpp/trunk/components/sqldb/pgsql.hpp | 204 | ||||
-rw-r--r-- | sca-cpp/trunk/components/sqldb/sqldb.cpp | 65 |
6 files changed, 240 insertions, 157 deletions
diff --git a/sca-cpp/trunk/components/sqldb/Makefile.am b/sca-cpp/trunk/components/sqldb/Makefile.am index 9ce5f26713..988383b4f1 100644 --- a/sca-cpp/trunk/components/sqldb/Makefile.am +++ b/sca-cpp/trunk/components/sqldb/Makefile.am @@ -48,10 +48,10 @@ pgsql_standby_test_SOURCES = pgsql-standby-test.cpp pgsql_standby_test_LDFLAGS = -L${PGSQL_LIB} -R${PGSQL_LIB} -lpq client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = sqldb-test standby-test server-test noinst_PROGRAMS = pgsql-test pgsql-standby-test client-test -TESTS = sqldb-test standby-test server-test +TESTS = sqldb-test server-test endif diff --git a/sca-cpp/trunk/components/sqldb/client-test.cpp b/sca-cpp/trunk/components/sqldb/client-test.cpp index 0cbcb57363..c9fbb7d5bb 100644 --- a/sca-cpp/trunk/components/sqldb/client-test.cpp +++ b/sca-cpp/trunk/components/sqldb/client-test.cpp @@ -38,15 +38,15 @@ namespace sqldb { const string uri("http://localhost:8090/sqldb"); -bool testSqlDb() { - http::CURLSession cs("", "", "", "", 0); - - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const list<value> a = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testSqlDb() { + const http::CURLSession cs("", "", "", "", 0); + + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list<value> a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable<value> id = http::post(a, uri, cs); @@ -59,18 +59,18 @@ bool testSqlDb() { assert(content(val) == a); } - const list<value> j = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$3.55"))); - const list<value> b = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list<value> j = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$3.55"))); + const list<value> b = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + j); { const failable<value> r = http::put(b, uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable<value> val = http::get(uri + p, cs); @@ -80,7 +80,7 @@ bool testSqlDb() { { const failable<value> r = http::del(uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable<value> val = http::get(uri + p, cs); @@ -90,35 +90,26 @@ bool testSqlDb() { return true; } -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable<value> val = http::get(uri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$4.55"))); - const list<value> a = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testGetPerf() { + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$4.55"))); + const list<value> a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable<value> id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); - const lambda<bool()> gl = getLoop(p, a, cs); + const blambda gl = [p, a, cs]() -> const bool { + const failable<value> val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + return true; + }; cout << "Sqldb get test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp index 2cd25f874a..5d73b0d877 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp +++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp @@ -32,7 +32,7 @@ namespace tuscany { namespace pgsql { -bool testPGSql() { +const bool testPGSql() { PGSql wpg("host=localhost port=6432 dbname=db", "test"); PGSql rpg("host=localhost port=6433 dbname=db", "test"); const value k = mklist<value>("a"); @@ -50,25 +50,17 @@ bool testPGSql() { return true; } -struct getLoop { - const value k; - PGSql& pg; - getLoop(const value& k, PGSql& pg) : k(k), pg(pg) { - } - const bool operator()() const { - assert((get(k, pg)) == value(string("CCC"))); - return true; - } -}; - -bool testGetPerf() { +const bool testGetPerf() { const value k = mklist<value>("c"); PGSql wpg("host=localhost port=6432 dbname=db", "test"); PGSql rpg("host=localhost port=6433 dbname=db", "test"); assert(hasContent(post(k, string("CCC"), wpg))); sleep(1); - const lambda<bool()> gl = getLoop(k, rpg); + const blambda gl = [k, rpg]() -> const bool { + assert((get(k, rpg)) == value(string("CCC"))); + return true; + }; cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp index d10ab5f4c2..5d7bb98cd8 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp +++ b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp @@ -32,37 +32,38 @@ namespace tuscany { namespace pgsql { -bool testPGSql() { +const bool testPGSql() { PGSql pg("host=localhost port=6432 dbname=db", "test"); const value k = mklist<value>("a"); + const value lk = mklist<value>(mklist<value>("like", "%"), mklist<value>("limit", "2")); + const value rx = mklist<value>(mklist<value>("regex", "a"), mklist<value>("limit", "2")); + const value ts = mklist<value>(mklist<value>("textsearch", "AAA"), mklist<value>("limit", "2")); + const value rxts = mklist<value>(mklist<value>("regex", "a"), mklist<value>("textsearch", "AAA"), mklist<value>("limit", "2")); assert(hasContent(post(k, string("AAA"), pg))); - assert((get(k, pg)) == value(string("AAA"))); + assert(content(get(k, pg)) == value(string("AAA"))); + assert(cadr<value>(car<value>(content(get(lk, pg)))) == value(string("AAA"))); + assert(cadr<value>(car<value>(content(get(rx, pg)))) == value(string("AAA"))); + assert(cadr<value>(car<value>(content(get(ts, pg)))) == value(string("AAA"))); + assert(cadr<value>(car<value>(content(get(rxts, pg)))) == value(string("AAA"))); + assert(hasContent(put(k, string("aaa"), pg))); - assert((get(k, pg)) == value(string("aaa"))); + assert(content(get(k, pg)) == value(string("aaa"))); assert(hasContent(del(k, pg))); assert(!hasContent(get(k, pg))); return true; } -struct getLoop { - const value k; - PGSql& pg; - getLoop(const value& k, PGSql& pg) : k(k), pg(pg) { - } - const bool operator()() const { - assert((get(k, pg)) == value(string("CCC"))); - return true; - } -}; - -bool testGetPerf() { +const bool testGetPerf() { const value k = mklist<value>("c"); PGSql pg("host=localhost port=6432 dbname=db", "test"); assert(hasContent(post(k, string("CCC"), pg))); - const lambda<bool()> gl = getLoop(k, pg); + const blambda gl = [k, pg]() -> const bool { + assert(content(get(k, pg)) == value(string("CCC"))); + return true; + }; cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/sqldb/pgsql.hpp b/sca-cpp/trunk/components/sqldb/pgsql.hpp index 581cd943e6..620aec4105 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql.hpp +++ b/sca-cpp/trunk/components/sqldb/pgsql.hpp @@ -40,7 +40,7 @@ namespace pgsql { /** * Return and clear a Postgres result failure. */ -const string pgfailure(PGresult* r, PGconn* conn) { +const string pgfailure(PGresult* const r, PGconn* const conn) { const string re = PQresultErrorMessage(r); PQclear(r); if (length(re) != 0) @@ -68,11 +68,12 @@ public: mkfailure<bool>(string("Couldn't connect to postgresql database: ") + PQerrorMessage(conn)); return; } + debug(conn, "pgsql::pgsql::conn"); // Find the name of the first column in the target table // Assume that's the key we need to use string ks = string("select a.attname from pg_attribute a, pg_class c where a.attrelid = c.relfilenode and c.relname = '") + table + string("' and a.attnum in (1, 2) order by a.attnum;"); - PGresult* kr = PQexec(conn, c_str(ks)); + PGresult* const kr = PQexec(conn, c_str(ks)); if (PQresultStatus(kr) != PGRES_TUPLES_OK) { mkfailure<bool>(string("Couldn't execute postgresql column select statement: ") + pgfailure(kr, conn)); return; @@ -82,25 +83,16 @@ public: mkfailure<bool>(string("Couldn't find postgresql table key and value column names")); return; } - kname = PQgetvalue(kr, 0, 0); - vname = PQgetvalue(kr, 1, 0); + kname = c_str(string(PQgetvalue(kr, 0, 0))); + vname = c_str(string(PQgetvalue(kr, 1, 0))); PQclear(kr); } - PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table) { + PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table), kname(c.kname), vname(c.vname) { debug("pgsql::pgsql::copy"); } - const PGSql& operator=(const PGSql& c) { - debug("pgsql::pgsql::operator="); - if(this == &c) - return *this; - owner = false; - conn = c.conn; - conninfo = c.conninfo; - table = c.table; - return *this; - } + PGSql& operator=(const PGSql& c) = delete; ~PGSql() { debug("pgsql::~pgsql"); @@ -108,16 +100,17 @@ public: return; if (conn == NULL) return; + debug(conn, "pgsql::~pgsql::conn"); PQfinish(conn); } private: - bool owner; + const bool owner; PGconn *conn; - string conninfo; - string table; - string kname; - string vname; + const string conninfo; + const string table; + const char* kname; + const char* vname; friend const failable<bool> setup(const PGSql& pgsql); friend const failable<bool> post(const value& key, const value& val, const PGSql& pgsql); @@ -133,7 +126,7 @@ const failable<bool> setup(const PGSql& pgsql) { debug("pgsql::setup"); if (PQstatus(pgsql.conn) == CONNECTION_OK) return true; - debug("pgsql::setup::reset"); + debug(pgsql.conn, "pgsql::setup::reset::conn"); PQreset(pgsql.conn); if (PQstatus(pgsql.conn) != CONNECTION_OK) return mkfailure<bool>(string("Couldn't reconnect to postgresql database: ") + PQerrorMessage(pgsql.conn)); @@ -150,10 +143,10 @@ const failable<bool> post(const value& key, const value& val, const PGSql& pgsql debug(pgsql.table, "pgsql::post::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); - const char* params[2] = { c_str(ks), c_str(vs) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); + const char* const params[2] = { c_str(ks), c_str(vs) }; + PGresult* const r = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); if (PQresultStatus(r) != PGRES_COMMAND_OK) return mkfailure<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); PQclear(r); @@ -172,10 +165,10 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql) debug(pgsql.table, "pgsql::put::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); - const char* params[2] = { c_str(ks), c_str(vs) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("update ") + pgsql.table + string(" set ") + pgsql.vname + string(" = $2 where ") + pgsql.kname + string(" = $1;")), 2, NULL, params, NULL, NULL, 0); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); + const char* const params[2] = { c_str(ks), c_str(vs) }; + PGresult* const r = PQexecParams(pgsql.conn, c_str(string("update ") + pgsql.table + string(" set ") + pgsql.vname + string(" = $2 where ") + pgsql.kname + string(" = $1;")), 2, NULL, params, NULL, NULL, 0); if (PQresultStatus(r) != PGRES_COMMAND_OK) return mkfailure<bool>(string("Couldn't execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); const string t = PQcmdTuples(r); @@ -186,7 +179,7 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql) } PQclear(r); - PGresult* pr = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); + PGresult* const pr = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); if (PQresultStatus(pr) != PGRES_COMMAND_OK) return mkfailure<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn)); PQclear(pr); @@ -196,7 +189,58 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql) } /** - * Get an item from the database. + * Convert a key to an item id. + */ +const list<value> keyid(const list<value>& key) { + if (isNil(key)) + return nilListValue; + if (isList(car(key))) + return keyid(cdr(key)); + return cons<value>(car(key), keyid(cdr(key))); +} + +/** + * Convert a key to an param name / value assoc. + */ +const list<list<value> > keyparams(const list<value>& key) { + if (isNil(key)) + return nilListValue; + if (!isList(car(key))) + return keyparams(cdr(key)); + return cons<list<value> >((list<value>)car(key), keyparams(cdr(key))); +} + +/** + * Convert a get result to a list of items. + */ +const list<value> getitems(PGresult* const r, const int i, const int n) { + if (i == n) + return nilListValue; + const value key(content(scheme::readValue(string(PQgetvalue(r, i, 0))))); + const value val(content(scheme::readValue(string(PQgetvalue(r, i, 1))))); + return cons<value>(mklist<value>(key, val), getitems(r, i + 1, n)); +} + +/** + * Parse a text search query and translate single quotes to spaces and double + * quotes to single quotes. + */ +ostringstream& tsparse(ostringstream& os, const char* const c) { + if (!*c) + return os; + os << (*c == '\''? ' ' : *c == '"'? '\'' : *c); + return tsparse(os, c + 1); +} +const string tstranslate(const string& ts) { + ostringstream os; + tsparse(os, c_str(ts)); + return str(os); +} + +/** + * Get one item or a collection of items from the database. + * The key is a simple value or a list of simple values plus optional name / value + * pairs to specify regex, like, textsearch limit and offset clause */ const failable<value> get(const value& key, const PGSql& pgsql) { debug(key, "pgsql::get::key"); @@ -204,21 +248,99 @@ const failable<value> get(const value& key, const PGSql& pgsql) { debug(pgsql.table, "pgsql::get::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const char* params[1] = { c_str(ks) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("select * from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0); + // Get item and id and get parameters from the key + const bool lk = isList(key); + const list<list<value> > kparams = lk? keyparams(key) : list<list<value> >(); + const list<value> regex = assoc<value>("regex", kparams); + const list<value> like = assoc<value>("like", kparams); + const list<value> textsearch = assoc<value>("textsearch", kparams); + const list<value> limit = assoc<value>("limit", kparams); + const list<value> offset = assoc<value>("offset", kparams); + const list<value> id = lk? keyid(key) : nilListValue; + const list<value> atable = assoc<value>("table", kparams); + const string table = isNil(atable)? pgsql.table : (string)cadr(atable); + const list<value> akname = assoc<value>("kcolumn", kparams); + const string kname = isNil(akname)? pgsql.kname : (string)cadr(akname); + const list<value> avname = assoc<value>("vcolumn", kparams); + const string vname = isNil(avname)? pgsql.vname : (string)cadr(avname); + + // Build the SQL query + const char* sqlparams[5]; + int p = 0; + int w = 0; + ostringstream sqlos; + sqlos << "select data.*"; + if (!isNil(textsearch)) { + // Text search, setup result ranking + sqlos << ", ts_rank_cd(to_tsvector(data." << vname << "), tsquery, 32) as rank"; + } + sqlos << " from " << table << " data"; + if (!isNil(textsearch)) { + // Text search, define the query + const string ts = tstranslate((string)cadr(textsearch)); + sqlparams[p++] = c_str(ts); + sqlos << ", plainto_tsquery($" << p << ") tsquery"; + } + if (!lk || !isNil(id)) { + // Query of the form key = id + sqlparams[p++] = c_str(write(content(scheme::writeValue(lk? (value)id : key)))); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " = $" << p; + w++; + } + if (!isNil(regex)) { + // Query of the form key ~ param + sqlparams[p++] = c_str((string)cadr(regex)); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " ~ $" << p; + w++; + } + if (!isNil(like)) { + // Query of the form key like param + sqlparams[p++] = c_str((string)cadr(like)); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " like $" << p; + w++; + } + if (!isNil(textsearch)) { + // Text search, apply the query + sqlos << (w == 0? " where" : " and"); + sqlos << " tsquery @@ to_tsvector(data." << vname << ") order by rank desc"; + w++; + } + if (!isNil(offset)) { + // Result pagination offset + sqlos << " offset " << atoi(c_str((string)cadr(offset))); + } + // Result limit count + const int l = isNil(limit)? 1 : atoi(c_str((string)cadr(limit))); + sqlos << " limit " << l << ";"; + + // Execute the query + const string sqls = str(sqlos); + debug(sqls, "pgsql::get::sqls"); + PGresult* r = PQexecParams(pgsql.conn, c_str(sqls), p, NULL, sqlparams, NULL, NULL, 0); if (PQresultStatus(r) != PGRES_TUPLES_OK) return mkfailure<value>(string("Couldn't execute select postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); - if (PQntuples(r) < 1) { + const int n = PQntuples(r); + if (n < 1) { PQclear(r); ostringstream os; os << "Couldn't get postgresql entry: " << key; return mkfailure<value>(str(os), 404, false); } - const char* data = PQgetvalue(r, 0, 1); - const value val(scheme::readValue(string(data))); - PQclear(r); + // Return a collection of key / item pairs + if (l != 1) { + const list<value> lval = getitems(r, 0, n); + PQclear(r); + debug(lval, "pgsql::get::result"); + return (value)lval; + } + + // Return a single item + const value val(content(scheme::readValue(string(PQgetvalue(r, 0, 1))))); + PQclear(r); debug(val, "pgsql::get::result"); return val; } @@ -232,9 +354,9 @@ const failable<bool> del(const value& key, const PGSql& pgsql) { debug(pgsql.table, "pgsql::delete::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const char* params[1] = { c_str(ks) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("delete from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0); + const string ks(write(content(scheme::writeValue(key)))); + const char* const params[1] = { c_str(ks) }; + PGresult* const r = PQexecParams(pgsql.conn, c_str(string("delete from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0); if (PQresultStatus(r) != PGRES_COMMAND_OK) return mkfailure<bool>(string("Couldn't execute delete postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); PQclear(r); diff --git a/sca-cpp/trunk/components/sqldb/sqldb.cpp b/sca-cpp/trunk/components/sqldb/sqldb.cpp index 9925897693..1288dd553b 100644 --- a/sca-cpp/trunk/components/sqldb/sqldb.cpp +++ b/sca-cpp/trunk/components/sqldb/sqldb.cpp @@ -38,14 +38,14 @@ namespace sqldb { /** * Get an item from the database. */ -const failable<value> get(const list<value>& params, pgsql::PGSql& pg) { +const failable<value> get(const list<value>& params, const pgsql::PGSql& pg) { return pgsql::get(car(params), pg); } /** * Post an item to the database. */ -const failable<value> post(const list<value>& params, pgsql::PGSql& pg) { +const failable<value> post(const list<value>& params, const pgsql::PGSql& pg) { const value id = append<value>(car(params), mklist(mkuuid())); const failable<bool> val = pgsql::post(id, cadr(params), pg); if (!hasContent(val)) @@ -56,7 +56,7 @@ const failable<value> post(const list<value>& params, pgsql::PGSql& pg) { /** * Put an item into the database. */ -const failable<value> put(const list<value>& params, pgsql::PGSql& pg) { +const failable<value> put(const list<value>& params, const pgsql::PGSql& pg) { const failable<bool> val = pgsql::put(car(params), cadr(params), pg); if (!hasContent(val)) return mkfailure<value>(val); @@ -66,7 +66,7 @@ const failable<value> put(const list<value>& params, pgsql::PGSql& pg) { /** * Delete an item from the database. */ -const failable<value> del(const list<value>& params, pgsql::PGSql& pg) { +const failable<value> del(const list<value>& params, const pgsql::PGSql& pg) { const failable<bool> val = pgsql::del(car(params), pg); if (!hasContent(val)) return mkfailure<value>(val); @@ -74,14 +74,23 @@ const failable<value> del(const list<value>& params, pgsql::PGSql& pg) { } /** - * Component implementation lambda function. + * Start the component. */ -class applySqldb { -public: - applySqldb(const perthread_ptr<pgsql::PGSql>& pg) : pg(pg) { - } +const failable<value> start(const list<value>& params) { + // Connect to the configured database and table + debug("sqldb::start"); + const gc_pool cp(gc_current_pool()); + const value conninfo = ((lvvlambda)car(params))(nilListValue); + const value table = ((lvvlambda)cadr(params))(nilListValue); + const lambda<const gc_ptr<pgsql::PGSql>()> newPGSql = [conninfo, table, cp]() -> const gc_ptr<pgsql::PGSql> { + debug("sqldb::newPGSql"); + const gc_scoped_pool sp(pool(cp)); + return new (gc_new<pgsql::PGSql>()) pgsql::PGSql(conninfo, table); + }; + const perthread_ptr<pgsql::PGSql> pg = *(new (gc_new<perthread_ptr<pgsql::PGSql> >()) perthread_ptr<pgsql::PGSql>(newPGSql)); - const value operator()(const list<value>& params) const { + // Return the component implementation lambda function + const lvvlambda applySqldb = [pg](const list<value>& params) -> const value { const value func(car(params)); if (func == "get") return get(cdr(params), *pg); @@ -92,40 +101,8 @@ public: if (func == "delete") return del(cdr(params), *pg); return mkfailure<value>(); - } - -private: - const perthread_ptr<pgsql::PGSql> pg; -}; - -/** - * Lambda function that creates a new database connection. - */ -class newPGSql { -public: - newPGSql(const string& conninfo, const string& table) : conninfo(conninfo), table(table) { - } - - const gc_ptr<pgsql::PGSql> operator()() const { - return new (gc_new<pgsql::PGSql>()) pgsql::PGSql(conninfo, table); - } - -private: - const string conninfo; - const string table; -}; - -/** - * Start the component. - */ -const failable<value> start(unused const list<value>& params) { - // Connect to the configured database and table - const value conninfo = ((lambda<value(const list<value>&)>)car(params))(list<value>()); - const value table = ((lambda<value(const list<value>&)>)cadr(params))(list<value>()); - const perthread_ptr<pgsql::PGSql> pg(lambda<gc_ptr<pgsql::PGSql>()>(newPGSql(conninfo, table))); - - // Return the component implementation lambda function - return value(lambda<value(const list<value>&)>(applySqldb(pg))); + }; + return value(applySqldb); } } |