#
#
# add_file "query_args.hh"
# content [7492927fb5ee7ed019834339d5c0da9abbe6f617]
#
# patch "AUTHORS"
# from [388b6818cd6ab44a800bbb8778680f1e97971e8b]
# to [be2883d201fdd61b63582334f52312a640e012a1]
#
# patch "ChangeLog"
# from [6769db3a8e03f10e9536f529fb425c86a5ee309f]
# to [4714a67c78c948868a09ed8add6e3a610eaa70a1]
#
# patch "database.cc"
# from [6cf553977563b3bdfe1a469a9e1587723988fa6d]
# to [e4f0c515bff3ad55a7880aeb3c8eeeb2686348a3]
#
# patch "database.hh"
# from [65e7daaaa720624144572538ee668d33d1a0385e]
# to [8aac44bf6fb3bdb0477933e06a915671cb448029]
#
============================================================
--- query_args.hh 7492927fb5ee7ed019834339d5c0da9abbe6f617
+++ query_args.hh 7492927fb5ee7ed019834339d5c0da9abbe6f617
@@ -0,0 +1,41 @@
+// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
+// copyright (C) 2006 vinzenz feenstra
+// all rights reserved.
+// licensed to the public under the terms of the GNU GPL (>= 2)
+// see the file COPYING for details
+#ifndef __QUERY_ARGS_HH__
+#define __QUERY_ARGS_HH__
+
+#include
+#include
+
+struct query_args_param
+{
+ enum arg_type{ text, blob };
+ arg_type type;
+ std::string data;
+ size_t size;
+};
+
+struct query_args
+{
+ query_args(char const * cmd)
+ : sql_cmd(cmd)
+ {}
+
+ query_args(std::string const & cmd)
+ : sql_cmd(cmd)
+ {}
+
+ query_args & operator%(query_args_param const & qap)
+ {
+ args.push_back(qap);
+ return *this;
+ }
+
+ std::vector args;
+ std::string sql_cmd;
+};
+
+#endif //__QUERY_ARGS_HH__
============================================================
--- AUTHORS 388b6818cd6ab44a800bbb8778680f1e97971e8b
+++ AUTHORS be2883d201fdd61b63582334f52312a640e012a1
@@ -71,8 +71,8 @@
Marcel van der Boom
Roland McGrath
Daniel Carosone
+ Vinzenz Feenstra
-
Several people have also contributed to the translation of monotone
into non-English languages; their work is available in the po/
subdirectory. Contributors include:
============================================================
--- ChangeLog 6769db3a8e03f10e9536f529fb425c86a5ee309f
+++ ChangeLog 4714a67c78c948868a09ed8add6e3a610eaa70a1
@@ -1,3 +1,11 @@
+2006-01-24 Vinzenz Feenstra
+
+ * query_args.hh: Introduced struct query_args and struct
+ query_args_param. Used to typesafe arguments for database::execute
+ and database::fetch
+ * database.cc/.hh: Adjusted database to the new fetch and execute
+ argument style via operator% which is more typesafe.
+
2006-01-23 Nathaniel Smith
* database.cc (assert_sqlite3_ok): Improve the hint message given
============================================================
--- database.cc 6cf553977563b3bdfe1a469a9e1587723988fa6d
+++ database.cc e4f0c515bff3ad55a7880aeb3c8eeeb2686348a3
@@ -1,9 +1,12 @@
-// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*-
+// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
// copyright (C) 2002, 2003 graydon hoare
+// copyright (C) 2006 vinzenz feenstra
// all rights reserved.
// licensed to the public under the terms of the GNU GPL (>= 2)
// see the file COPYING for details
+
#include
#include
#include
@@ -35,12 +38,13 @@
#include "xdelta.hh"
#include "epoch.hh"
+#include "query_args.hh"
+
// defined in schema.sql, converted to header:
#include "schema.h"
// defined in views.sql, converted to header:
#include "views.h"
-
// this file defines a public, typed interface to the database.
// the database class encapsulates all knowledge about sqlite,
// the schema, and all SQL statements used to access the schema.
@@ -56,10 +60,57 @@
int const any_rows = -1;
int const any_cols = -1;
-namespace
+namespace
{
- // track all open databases for close_all_databases() handler
- set sql_contexts;
+ query_args_param
+ text(std::string const & txt)
+ {
+ query_args_param q = {
+ query_args_param::text,
+ txt,
+ txt.size()
+ };
+ return q;
+ }
+
+ query_args_param
+ text(char const * txt)
+ {
+ query_args_param q = {
+ query_args_param::text,
+ std::string(txt),
+ strlen(txt)
+ };
+ return q;
+ }
+
+ query_args_param
+ blob(void const * data,
+ size_t const size)
+ {
+ char const * ptr = reinterpret_cast(data);
+ query_args_param q = {
+ query_args_param::blob,
+ std::string(ptr,ptr+size),
+ size
+ };
+ return q;
+ }
+
+ query_args_param
+ blob(char const * data,
+ size_t const size)
+ {
+ query_args_param q = {
+ query_args_param::blob,
+ std::string(data,data+size),
+ size
+ };
+ return q;
+ }
+
+ // track all open databases for close_all_databases() handler
+ set sql_contexts;
}
extern "C" {
@@ -101,14 +152,14 @@
string revisions_query = "SELECT 1 FROM revisions LIMIT 1";
string rosters_query = "SELECT 1 FROM rosters LIMIT 1";
- fetch(res_revisions, one_col, any_rows, revisions_query.c_str());
+ fetch(res_revisions, one_col, any_rows, query_args(revisions_query));
if (res_revisions.size() > 0)
{
// they have revisions, so they can't be _ancient_, but they still might
// not have rosters
results res_rosters;
- fetch(res_rosters, one_col, any_rows, rosters_query.c_str());
+ fetch(res_rosters, one_col, any_rows, query_args(rosters_query));
N(res_rosters.size() != 0,
F("database %s contains revisions but no rosters\n"
"if you are a project leader or doing local testing:\n"
@@ -127,7 +178,7 @@
// init; commit; db kill_rev_locally", and then upgrading to a
// rosterified monotone.)
results res_manifests;
- fetch(res_manifests, one_col, any_rows, manifests_query.c_str());
+ fetch(res_manifests, one_col, any_rows, query_args(manifests_query));
N(res_manifests.size() == 0,
F("database %s contains manifests but no revisions\n"
"this is a very old database; it needs to be upgraded\n"
@@ -431,7 +482,7 @@
database::debug(string const & sql, ostream & out)
{
results res;
- fetch(res, any_cols, any_rows, sql.c_str());
+ fetch(res, any_cols, any_rows, query_args(sql));
out << "'" << sql << "' -> " << res.size() << " rows\n" << endl;
for (size_t i = 0; i < res.size(); ++i)
{
@@ -565,34 +616,18 @@
}
void
-database::execute(char const * query, ...)
+database::execute(query_args const & query)
{
results res;
- va_list args;
- va_start(args, query);
- fetch(res, 0, 0, query, args);
- va_end(args);
+ fetch(res, 0, 0, query );
}
void
database::fetch(results & res,
int const want_cols,
int const want_rows,
- char const * query, ...)
+ query_args const & query)
{
- va_list args;
- va_start(args, query);
- fetch(res, want_cols, want_rows, query, args);
- va_end(args);
-}
-
-void
-database::fetch(results & res,
- int const want_cols,
- int const want_rows,
- char const * query,
- va_list args)
-{
int nrow;
int ncol;
int rescode;
@@ -600,44 +635,45 @@
res.clear();
res.resize(0);
- map::iterator i = statement_cache.find(query);
+ map::iterator i = statement_cache.find(query.sql_cmd);
if (i == statement_cache.end())
{
- statement_cache.insert(make_pair(query, statement()));
- i = statement_cache.find(query);
+ statement_cache.insert(make_pair(query.sql_cmd, statement()));
+ i = statement_cache.find(query.sql_cmd);
I(i != statement_cache.end());
const char * tail;
- sqlite3_prepare(sql(), query, -1, i->second.stmt.paddr(), &tail);
+ sqlite3_prepare(sql(), query.sql_cmd.c_str(), -1, i->second.stmt.paddr(), &tail);
assert_sqlite3_ok(sql());
- L(FL("prepared statement %s\n") % query);
+ L(FL("prepared statement %s\n") % query.sql_cmd);
// no support for multiple statements here
E(*tail == 0,
- F("multiple statements in query: %s\n") % query);
+ F("multiple statements in query: %s\n") % query.sql_cmd);
}
ncol = sqlite3_column_count(i->second.stmt());
E(want_cols == any_cols || want_cols == ncol,
- F("wanted %d columns got %d in query: %s\n") % want_cols % ncol % query);
+ F("wanted %d columns got %d in query: %s\n") % want_cols % ncol % query.sql_cmd);
// bind parameters for this execution
int params = sqlite3_bind_parameter_count(i->second.stmt());
+ // Ensure that not to less or to much parameters are given
+ I( params == int(query.args.size()));
+
// profiling finds this logging to be quite expensive
if (global_sanity.debug)
- L(FL("binding %d parameters for %s\n") % params % query);
+ L(FL("binding %d parameters for %s\n") % params % query.sql_cmd);
for (int param = 1; param <= params; param++)
{
- char *value = va_arg(args, char *);
-
// profiling finds this logging to be quite expensive
if (global_sanity.debug)
{
- string log = string(value);
+ string log = query.args[param-1].data;
if (log.size() > constants::log_line_sz)
log = log.substr(0, constants::log_line_sz);
@@ -645,7 +681,9 @@
L(FL("binding %d with value '%s'\n") % param % log);
}
- sqlite3_bind_text(i->second.stmt(), param, value, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(i->second.stmt(), param ,
+ query.args[param-1].data.c_str(),
+ -1, SQLITE_TRANSIENT);
assert_sqlite3_ok(sql());
}
@@ -659,7 +697,7 @@
for (int col = 0; col < ncol; col++)
{
const char * value = sqlite3_column_text_s(i->second.stmt(), col);
- E(value, F("null result in query: %s\n") % query);
+ E(value, F("null result in query: %s\n") % query.sql_cmd);
row.push_back(value);
//L(FL("row %d col %d value='%s'\n") % nrow % col % value);
}
@@ -677,7 +715,7 @@
i->second.count++;
E(want_rows == any_rows || want_rows == nrow,
- F("wanted %d rows got %s in query: %s\n") % want_rows % nrow % query);
+ F("wanted %d rows got %s in query: %s\n") % want_rows % nrow % query.sql_cmd);
}
// general application-level logic
@@ -695,9 +733,9 @@
if (transaction_level == 0)
{
if (exclusive)
- execute("BEGIN EXCLUSIVE");
+ execute(query_args("BEGIN EXCLUSIVE"));
else
- execute("BEGIN DEFERRED");
+ execute(query_args("BEGIN DEFERRED"));
transaction_exclusive = exclusive;
}
else
@@ -713,7 +751,7 @@
database::commit_transaction()
{
if (transaction_level == 1)
- execute("COMMIT");
+ execute(query_args("COMMIT"));
transaction_level--;
}
@@ -721,7 +759,7 @@
database::rollback_transaction()
{
if (transaction_level == 1)
- execute("ROLLBACK");
+ execute(query_args("ROLLBACK"));
transaction_level--;
}
@@ -732,7 +770,7 @@
{
results res;
string query = "SELECT id FROM " + table + " WHERE id = ?";
- fetch(res, one_col, any_rows, query.c_str(), ident().c_str());
+ fetch(res, one_col, any_rows, query_args(query) % text(ident()));
I((res.size() == 1) || (res.size() == 0));
return res.size() == 1;
}
@@ -744,7 +782,7 @@
{
results res;
string query = "SELECT id FROM " + table + " WHERE id = ?";
- fetch(res, one_col, any_rows, query.c_str(), ident().c_str());
+ fetch(res, one_col, any_rows, query_args(query) % text(ident()));
return res.size() > 0;
}
@@ -753,7 +791,7 @@
{
results res;
string query = "SELECT COUNT(*) FROM " + table;
- fetch(res, one_col, one_row, query.c_str());
+ fetch(res, one_col, one_row, query_args(query));
return lexical_cast(res[0][0]);
}
@@ -764,7 +802,7 @@
// COALESCE is required since SUM({empty set}) is NULL.
// the sqlite docs for SUM suggest this as a workaround
string query = "SELECT COALESCE(SUM(LENGTH(" + concatenated_columns + ")), 0) FROM " + table;
- fetch(res, one_col, one_row, query.c_str());
+ fetch(res, one_col, one_row, query_args(query));
return lexical_cast(res[0][0]);
}
@@ -773,7 +811,7 @@
{
results res;
string query = "SELECT id FROM " + table;
- fetch(res, one_col, any_rows, query.c_str());
+ fetch(res, one_col, any_rows, query_args(query));
for (size_t i = 0; i < res.size(); ++i)
{
@@ -788,7 +826,7 @@
{
results res;
string query = "SELECT data FROM " + table + " WHERE id = ?";
- fetch(res, one_col, one_row, query.c_str(), ident().c_str());
+ fetch(res, one_col, one_row, query_args(query) % text(ident()));
// consistency check
base64 > rdata(res[0][0]);
@@ -812,8 +850,9 @@
I(base() != "");
results res;
string query = "SELECT delta FROM " + table + " WHERE id = ? AND base = ?";
- fetch(res, one_col, one_row, query.c_str(),
- ident().c_str(), base().c_str());
+ fetch(res, one_col, one_row, query_args(query)
+ % text(ident())
+ % text(base()));
base64 > del_packed = res[0][0];
unpack(del_packed, del);
@@ -836,7 +875,9 @@
pack(dat, dat_packed);
string insert = "INSERT INTO " + table + " VALUES(?, ?)";
- execute(insert.c_str(),ident().c_str(), dat_packed().c_str());
+ execute(query_args(insert)
+ % text(ident())
+ % text(dat_packed()));
}
void
database::put_delta(hexenc const & ident,
@@ -852,7 +893,10 @@
pack(del, del_packed);
string insert = "INSERT INTO "+table+" VALUES(?, ?, ?)";
- execute(insert.c_str(), ident().c_str(), base().c_str(), del_packed().c_str());
+ execute(query_args(insert)
+ % text(ident())
+ % text(base())
+ % text(del_packed()));
}
// static ticker cache_hits("vcache hits", "h", 1);
@@ -1025,7 +1069,8 @@
// This tip is not a root, so extend the path.
results res;
fetch(res, one_col, any_rows,
- delta_query.c_str(), tip().c_str());
+ query_args(delta_query)
+ % text(tip()));
I(res.size() != 0);
@@ -1109,7 +1154,7 @@
string const & table)
{
string drop = "DELETE FROM " + table + " WHERE id = ?";
- execute(drop.c_str(), ident().c_str());
+ execute(query_args(drop) % text(ident()));
}
void
@@ -1166,7 +1211,8 @@
results res;
string query = "SELECT id FROM " + delta_table + " WHERE base = ?";
fetch(res, one_col, any_rows,
- query.c_str(), target_id().c_str());
+ query_args(query)
+ % text(target_id()));
for (size_t i = 0; i < res.size(); ++i)
{
hexenc old_id(res[i][0]);
@@ -1189,7 +1235,8 @@
results res;
string query = "SELECT base FROM " + delta_table + " WHERE id = ?";
fetch(res, one_col, any_rows,
- query.c_str(), target_id().c_str());
+ query_args(query)
+ % text(target_id()));
I(res.size() > 0);
newer_id = hexenc(res[0][0]);
get_version(newer_id, newer_data, data_table, delta_table);
@@ -1202,7 +1249,7 @@
}
}
string query = "DELETE from " + delta_table + " WHERE id = ?";
- execute(query.c_str(), target_id().c_str());
+ execute(query_args(query) % text(target_id()));
}
else
{
@@ -1212,7 +1259,7 @@
i != older.end(); ++i)
put(i->first, i->second, data_table);
string query = "DELETE from " + data_table + " WHERE id = ?";
- execute(query.c_str(), target_id().c_str());
+ execute(query_args(query) % text(target_id()));
}
guard.commit();
@@ -1250,8 +1297,9 @@
{
results res;
string query = ("SELECT roster_id FROM revision_roster WHERE rev_id = ? ");
- fetch(res, one_col, any_rows, query.c_str(),
- rev_id.inner()().c_str());
+ fetch(res, one_col, any_rows,
+ query_args(query.c_str())
+ % text(rev_id.inner()()));
I((res.size() == 1) || (res.size() == 0));
return res.size() == 1;
}
@@ -1261,8 +1309,9 @@
{
results res;
string query = ("SELECT roster_id FROM revision_roster WHERE rev_id = ? ");
- fetch(res, one_col, any_rows, query.c_str(),
- rev_id.inner()().c_str());
+ fetch(res, one_col, any_rows,
+ query_args(query)
+ % text(rev_id.inner()()));
I((res.size() == 1) || (res.size() == 0));
return (res.size() == 1) && roster_version_exists(hexenc(res[0][0]));
}
@@ -1273,7 +1322,7 @@
links.clear();
results res;
string query = ("SELECT rev_id, roster_id FROM revision_roster");
- fetch(res, 2, any_rows, query.c_str());
+ fetch(res, 2, any_rows, query_args(query));
for (size_t i = 0; i < res.size(); ++i)
{
links.insert(make_pair(revision_id(res[i][0]),
@@ -1350,7 +1399,7 @@
results res;
graph.clear();
fetch(res, 2, any_rows,
- "SELECT parent,child FROM revision_ancestry");
+ query_args("SELECT parent,child FROM revision_ancestry"));
for (size_t i = 0; i < res.size(); ++i)
graph.insert(std::make_pair(revision_id(res[i][0]),
revision_id(res[i][1])));
@@ -1364,8 +1413,8 @@
results res;
parents.clear();
fetch(res, one_col, any_rows,
- "SELECT parent FROM revision_ancestry WHERE child = ?",
- id.inner()().c_str());
+ query_args("SELECT parent FROM revision_ancestry WHERE child = ?")
+ % text(id.inner()()));
for (size_t i = 0; i < res.size(); ++i)
parents.insert(revision_id(res[i][0]));
}
@@ -1377,8 +1426,8 @@
results res;
children.clear();
fetch(res, one_col, any_rows,
- "SELECT child FROM revision_ancestry WHERE parent = ?",
- id.inner()().c_str());
+ query_args("SELECT child FROM revision_ancestry WHERE parent = ?")
+ % text(id.inner()()));
for (size_t i = 0; i < res.size(); ++i)
children.insert(revision_id(res[i][0]));
}
@@ -1408,8 +1457,8 @@
I(!null_id(id));
results res;
fetch(res, one_col, one_row,
- "SELECT data FROM revisions WHERE id = ?",
- id.inner()().c_str());
+ query_args("SELECT data FROM revisions WHERE id = ?")
+ % text(id.inner()()));
base64 > rdat_packed;
rdat_packed = base64 >(res[0][0]);
@@ -1507,16 +1556,16 @@
base64 > d_packed;
pack(d.inner(), d_packed);
- execute("INSERT INTO revisions VALUES(?, ?)",
- new_id.inner()().c_str(),
- d_packed().c_str());
+ execute(query_args("INSERT INTO revisions VALUES(?, ?)")
+ % text(new_id.inner()())
+ % text(d_packed()));
for (edge_map::const_iterator e = rev.edges.begin();
e != rev.edges.end(); ++e)
{
- execute("INSERT INTO revision_ancestry VALUES(?, ?)",
- edge_old_revision(e).inner()().c_str(),
- new_id.inner()().c_str());
+ execute(query_args("INSERT INTO revision_ancestry VALUES(?, ?)")
+ % text(edge_old_revision(e).inner()())
+ % text(new_id.inner()()));
}
deltify_revision(new_id);
@@ -1541,16 +1590,16 @@
void
database::delete_existing_revs_and_certs()
{
- execute("DELETE FROM revisions");
- execute("DELETE FROM revision_ancestry");
- execute("DELETE FROM revision_certs");
+ execute(query_args("DELETE FROM revisions"));
+ execute(query_args("DELETE FROM revision_ancestry"));
+ execute(query_args("DELETE FROM revision_certs"));
}
void
database::delete_existing_manifests()
{
- execute("DELETE FROM manifests");
- execute("DELETE FROM manifest_deltas");
+ execute(query_args("DELETE FROM manifests"));
+ execute(query_args("DELETE FROM manifest_deltas"));
}
/// Deletes one revision from the local database.
@@ -1570,9 +1619,14 @@
L(FL("Killing revision %s locally\n") % rid);
// Kill the certs, ancestry, and rev itself.
- execute("DELETE from revision_certs WHERE id = ?",rid.inner()().c_str());
- execute("DELETE from revision_ancestry WHERE child = ?", rid.inner()().c_str());
- execute("DELETE from revisions WHERE id = ?",rid.inner()().c_str());
+ execute(query_args("DELETE from revision_certs WHERE id = ?")
+ % text(rid.inner()()));
+
+ execute(query_args("DELETE from revision_ancestry WHERE child = ?")
+ % text(rid.inner()()));
+
+ execute(query_args("DELETE from revisions WHERE id = ?")
+ % text(rid.inner()()));
// Find the associated roster and count the number of links to it
hexenc roster_id;
@@ -1582,13 +1636,14 @@
results res;
string query = ("SELECT rev_id, roster_id FROM revision_roster "
"WHERE roster_id = ?");
- fetch(res, 2, any_rows, query.c_str(), roster_id().c_str());
+ fetch(res, 2, any_rows, query_args(query) % text(roster_id()));
I(res.size() > 0);
link_count = res.size();
}
// Delete our link.
- execute("DELETE from revision_roster WHERE rev_id = ?", rid.inner()().c_str());
+ execute(query_args("DELETE from revision_roster WHERE rev_id = ?")
+ % text(rid.inner()()));
// If that was the last link to the roster, kill the roster too.
if (link_count == 1)
@@ -1604,10 +1659,10 @@
base64 encoded;
encode_base64(branch, encoded);
L(FL("Deleting all references to branch %s\n") % branch);
- execute("DELETE FROM revision_certs WHERE name='branch' AND value =?",
- encoded().c_str());
- execute("DELETE FROM branch_epochs WHERE branch=?",
- encoded().c_str());
+ execute(query_args("DELETE FROM revision_certs WHERE name='branch' AND value =?")
+ % text(encoded()));
+ execute(query_args("DELETE FROM branch_epochs WHERE branch=?")
+ % text(encoded()));
}
/// Deletes all certs referring to a particular tag.
@@ -1617,8 +1672,8 @@
base64 encoded;
encode_base64(tag, encoded);
L(FL("Deleting all references to tag %s\n") % tag);
- execute("DELETE FROM revision_certs WHERE name='tag' AND value =?",
- encoded().c_str());
+ execute(query_args("DELETE FROM revision_certs WHERE name='tag' AND value =?")
+ % text(encoded()));
}
// crypto key management
@@ -1632,11 +1687,11 @@
if (pattern != "")
fetch(res, one_col, any_rows,
- "SELECT id FROM public_keys WHERE id GLOB ?",
- pattern.c_str());
+ query_args("SELECT id FROM public_keys WHERE id GLOB ?")
+ % text(pattern));
else
fetch(res, one_col, any_rows,
- "SELECT id FROM public_keys");
+ query_args("SELECT id FROM public_keys"));
for (size_t i = 0; i < res.size(); ++i)
pubkeys.push_back(res[i][0]);
@@ -1648,7 +1703,7 @@
keys.clear();
results res;
string query = "SELECT id FROM " + table;
- fetch(res, one_col, any_rows, query.c_str());
+ fetch(res, one_col, any_rows, query_args(query));
for (size_t i = 0; i < res.size(); ++i)
keys.push_back(res[i][0]);
}
@@ -1664,8 +1719,8 @@
{
results res;
fetch(res, one_col, any_rows,
- "SELECT id FROM public_keys WHERE hash = ?",
- hash().c_str());
+ query_args("SELECT id FROM public_keys WHERE hash = ?")
+ % text(hash()));
I((res.size() == 1) || (res.size() == 0));
if (res.size() == 1)
return true;
@@ -1677,8 +1732,8 @@
{
results res;
fetch(res, one_col, any_rows,
- "SELECT id FROM public_keys WHERE id = ?",
- id().c_str());
+ query_args("SELECT id FROM public_keys WHERE id = ?")
+ % text(id()));
I((res.size() == 1) || (res.size() == 0));
if (res.size() == 1)
return true;
@@ -1692,8 +1747,8 @@
{
results res;
fetch(res, 2, one_row,
- "SELECT id, keydata FROM public_keys WHERE hash = ?",
- hash().c_str());
+ query_args("SELECT id, keydata FROM public_keys WHERE hash = ?")
+ % text(hash()));
id = res[0][0];
pub_encoded = res[0][1];
}
@@ -1704,8 +1759,8 @@
{
results res;
fetch(res, one_col, one_row,
- "SELECT keydata FROM public_keys WHERE id = ?",
- pub_id().c_str());
+ query_args("SELECT keydata FROM public_keys WHERE id = ?")
+ % text(pub_id()));
pub_encoded = res[0][0];
}
@@ -1718,15 +1773,17 @@
I(!public_key_exists(thash));
E(!public_key_exists(pub_id),
F("another key with name '%s' already exists") % pub_id);
- execute("INSERT INTO public_keys VALUES(?, ?, ?)",
- thash().c_str(), pub_id().c_str(), pub_encoded().c_str());
+ execute(query_args("INSERT INTO public_keys VALUES(?, ?, ?)")
+ % text(thash())
+ % text(pub_id())
+ % text(pub_encoded()));
}
void
database::delete_public_key(rsa_keypair_id const & pub_id)
{
- execute("DELETE FROM public_keys WHERE id = ?",
- pub_id().c_str());
+ execute(query_args("DELETE FROM public_keys WHERE id = ?")
+ % text(pub_id()));
}
// cert management
@@ -1743,12 +1800,13 @@
"AND keypair = ? "
"AND signature = ?";
- fetch(res, 1, any_rows, query.c_str(),
- t.ident().c_str(),
- t.name().c_str(),
- t.value().c_str(),
- t.key().c_str(),
- t.sig().c_str());
+ fetch(res, 1, any_rows,
+ query_args(query)
+ % text(t.ident())
+ % text(t.name())
+ % text(t.value())
+ % text(t.key())
+ % text(t.sig()));
I(res.size() == 0 || res.size() == 1);
return res.size() == 1;
}
@@ -1762,13 +1820,13 @@
string insert = "INSERT INTO " + table + " VALUES(?, ?, ?, ?, ?, ?)";
- execute(insert.c_str(),
- thash().c_str(),
- t.ident().c_str(),
- t.name().c_str(),
- t.value().c_str(),
- t.key().c_str(),
- t.sig().c_str());
+ execute(query_args(insert)
+ % text(thash())
+ % text(t.ident())
+ % text(t.name())
+ % text(t.value())
+ % text(t.key())
+ % text(t.sig()));
}
void
@@ -1830,7 +1888,7 @@
{
results res;
string query = "SELECT id, name, value, keypair, signature FROM " + table;
- fetch(res, 5, any_rows, query.c_str());
+ fetch(res, 5, any_rows, query_args(query));
results_to_certs(res, certs);
}
@@ -1845,7 +1903,7 @@
"SELECT id, name, value, keypair, signature FROM " + table +
" WHERE id = ?";
- fetch(res, 5, any_rows, query.c_str(), ident().c_str());
+ fetch(res, 5, any_rows, query_args(query) % text(ident()));
results_to_certs(res, certs);
}
@@ -1859,7 +1917,7 @@
string query =
"SELECT id, name, value, keypair, signature FROM " + table +
" WHERE name = ?";
- fetch(res, 5, any_rows, query.c_str(), name().c_str());
+ fetch(res, 5, any_rows, query_args(query) % text(name()));
results_to_certs(res, certs);
}
@@ -1875,8 +1933,10 @@
"SELECT id, name, value, keypair, signature FROM " + table +
" WHERE id = ? AND name = ?";
- fetch(res, 5, any_rows, query.c_str(),
- ident().c_str(), name().c_str());
+ fetch(res, 5, any_rows,
+ query_args(query)
+ % text(ident())
+ % text(name()));
results_to_certs(res, certs);
}
@@ -1891,8 +1951,10 @@
"SELECT id, name, value, keypair, signature FROM " + table +
" WHERE name = ? AND value = ?";
- fetch(res, 5, any_rows, query.c_str(),
- name().c_str(), val().c_str());
+ fetch(res, 5, any_rows,
+ query_args(query)
+ % text(name())
+ % text(val()));
results_to_certs(res, certs);
}
@@ -1909,10 +1971,11 @@
"SELECT id, name, value, keypair, signature FROM " + table +
" WHERE id = ? AND name = ? AND value = ?";
- fetch(res, 5, any_rows, query.c_str(),
- ident().c_str(),
- name().c_str(),
- value().c_str());
+ fetch(res, 5, any_rows,
+ query_args(query)
+ % text(ident())
+ % text(name())
+ % text(value()));
results_to_certs(res, certs);
}
@@ -1935,8 +1998,8 @@
{
results res;
fetch(res, 3, any_rows,
- "SELECT hash, id, keypair "
- "FROM 'revision_certs' WHERE name != 'branch'");
+ query_args("SELECT hash, id, keypair "
+ "FROM 'revision_certs' WHERE name != 'branch'"));
idx.clear();
idx.reserve(res.size());
@@ -2018,10 +2081,10 @@
results res;
vector certs;
fetch(res, one_col, any_rows,
- "SELECT hash "
+ query_args("SELECT hash "
"FROM revision_certs "
- "WHERE id = ?",
- ident.inner()().c_str());
+ "WHERE id = ?")
+ % text(ident.inner()()));
ts.clear();
for (size_t i = 0; i < res.size(); ++i)
ts.push_back(hexenc(res[i][0]));
@@ -2034,10 +2097,10 @@
results res;
vector certs;
fetch(res, 5, one_row,
- "SELECT id, name, value, keypair, signature "
+ query_args("SELECT id, name, value, keypair, signature "
"FROM revision_certs "
- "WHERE hash = ?",
- hash().c_str());
+ "WHERE hash = ?")
+ % text(hash()));
results_to_certs(res, certs);
I(certs.size() == 1);
c = revision(certs[0]);
@@ -2049,10 +2112,10 @@
results res;
vector certs;
fetch(res, one_col, any_rows,
- "SELECT id "
+ query_args("SELECT id "
"FROM revision_certs "
- "WHERE hash = ?",
- hash().c_str());
+ "WHERE hash = ?")
+ % text(hash()));
I(res.size() == 0 || res.size() == 1);
return (res.size() == 1);
}
@@ -2090,8 +2153,8 @@
string pattern = partial + "*";
fetch(res, 1, any_rows,
- "SELECT id FROM revisions WHERE id GLOB ?",
- pattern.c_str());
+ query_args("SELECT id FROM revisions WHERE id GLOB ?")
+ % text(pattern));
for (size_t i = 0; i < res.size(); ++i)
completions.insert(revision_id(res[i][0]));
@@ -2108,8 +2171,8 @@
string pattern = partial + "*";
fetch(res, 1, any_rows,
- "SELECT id FROM files WHERE id GLOB ?",
- pattern.c_str());
+ query_args("SELECT id FROM files WHERE id GLOB ?")
+ % text(pattern));
for (size_t i = 0; i < res.size(); ++i)
completions.insert(file_id(res[i][0]));
@@ -2117,8 +2180,8 @@
res.clear();
fetch(res, 1, any_rows,
- "SELECT id FROM file_deltas WHERE id GLOB ?",
- pattern.c_str());
+ query_args("SELECT id FROM file_deltas WHERE id GLOB ?")
+ % text(pattern));
for (size_t i = 0; i < res.size(); ++i)
completions.insert(file_id(res[i][0]));
@@ -2134,8 +2197,8 @@
string pattern = partial + "*";
fetch(res, 2, any_rows,
- "SELECT hash, id FROM public_keys WHERE hash GLOB ?",
- pattern.c_str());
+ query_args("SELECT hash, id FROM public_keys WHERE hash GLOB ?")
+ % text(pattern));
for (size_t i = 0; i < res.size(); ++i)
completions.insert(make_pair(key_id(res[i][0]), utf8(res[i][1])));
@@ -2265,7 +2328,7 @@
string subquery = (boost::format("SELECT DISTINCT value FROM revision_certs WHERE name='%s' and unbase64(value) glob '%s'")
% branch_cert_name % i->second).str();
results res;
- fetch(res, one_col, any_rows, subquery.c_str());
+ fetch(res, one_col, any_rows, query_args(subquery));
for (size_t i = 0; i < res.size(); ++i)
{
base64 row_encoded(res[i][0]);
@@ -2375,7 +2438,7 @@
// std::cerr << query << std::endl; // debug expr
results res;
- fetch(res, one_col, any_rows, query.c_str());
+ fetch(res, one_col, any_rows, query_args(query));
for (size_t i = 0; i < res.size(); ++i)
{
if (ty == selectors::sel_ident)
@@ -2397,7 +2460,7 @@
{
epochs.clear();
results res;
- fetch(res, 2, any_rows, "SELECT branch, epoch FROM branch_epochs");
+ fetch(res, 2, any_rows, query_args("SELECT branch, epoch FROM branch_epochs"));
for (results::const_iterator i = res.begin(); i != res.end(); ++i)
{
base64 encoded(idx(*i, 0));
@@ -2415,9 +2478,9 @@
I(epoch_exists(eid));
results res;
fetch(res, 2, any_rows,
- "SELECT branch, epoch FROM branch_epochs"
- " WHERE hash = ?",
- eid.inner()().c_str());
+ query_args("SELECT branch, epoch FROM branch_epochs"
+ " WHERE hash = ?")
+ % text(eid.inner()()));
I(res.size() == 1);
base64 encoded(idx(idx(res, 0), 0));
decode_base64(encoded, branch);
@@ -2429,8 +2492,8 @@
{
results res;
fetch(res, one_col, any_rows,
- "SELECT hash FROM branch_epochs WHERE hash = ?",
- eid.inner()().c_str());
+ query_args("SELECT hash FROM branch_epochs WHERE hash = ?")
+ % text(eid.inner()()));
I(res.size() == 1 || res.size() == 0);
return res.size() == 1;
}
@@ -2443,8 +2506,10 @@
encode_base64(branch, encoded);
epoch_hash_code(branch, epo, eid);
I(epo.inner()().size() == constants::epochlen);
- execute("INSERT OR REPLACE INTO branch_epochs VALUES(?, ?, ?)",
- eid.inner()().c_str(), encoded().c_str(), epo.inner()().c_str());
+ execute(query_args("INSERT OR REPLACE INTO branch_epochs VALUES(?, ?, ?)")
+ % text(eid.inner()())
+ % text(encoded())
+ % text(epo.inner()()));
}
void
@@ -2452,7 +2517,8 @@
{
base64 encoded;
encode_base64(branch, encoded);
- execute("DELETE FROM branch_epochs WHERE branch = ?", encoded().c_str());
+ execute(query_args("DELETE FROM branch_epochs WHERE branch = ?")
+ % text(encoded()));
}
// vars
@@ -2462,7 +2528,7 @@
{
vars.clear();
results res;
- fetch(res, 3, any_rows, "SELECT domain, name, value FROM db_vars");
+ fetch(res, 3, any_rows, query_args("SELECT domain, name, value FROM db_vars"));
for (results::const_iterator i = res.begin(); i != res.end(); ++i)
{
var_domain domain(idx(*i, 0));
@@ -2505,10 +2571,10 @@
encode_base64(key.second, name_encoded);
base64 value_encoded;
encode_base64(value, value_encoded);
- execute("INSERT OR REPLACE INTO db_vars VALUES(?, ?, ?)",
- key.first().c_str(),
- name_encoded().c_str(),
- value_encoded().c_str());
+ execute(query_args("INSERT OR REPLACE INTO db_vars VALUES(?, ?, ?)")
+ % text(key.first())
+ % text(name_encoded())
+ % text(value_encoded()));
}
void
@@ -2516,8 +2582,9 @@
{
base64 name_encoded;
encode_base64(key.second, name_encoded);
- execute("DELETE FROM db_vars WHERE domain = ? AND name = ?",
- key.first().c_str(), name_encoded().c_str());
+ execute(query_args("DELETE FROM db_vars WHERE domain = ? AND name = ?")
+ % text(key.first())
+ % text(name_encoded()));
}
// branches
@@ -2528,7 +2595,7 @@
results res;
string query="SELECT DISTINCT value FROM revision_certs WHERE name= ?";
string cert_name="branch";
- fetch(res, one_col, any_rows, query.c_str(), cert_name.c_str());
+ fetch(res, one_col, any_rows, query_args(query) % text(cert_name));
for (size_t i = 0; i < res.size(); ++i)
{
base64 row_encoded(res[i][0]);
@@ -2550,8 +2617,9 @@
results res;
string query = ("SELECT roster_id FROM revision_roster WHERE rev_id = ? ");
- fetch(res, one_col, any_rows, query.c_str(),
- rev_id.inner()().c_str());
+ fetch(res, one_col, any_rows,
+ query_args(query)
+ % text(rev_id.inner()()));
I(res.size() == 1);
roster_id = hexenc(res[0][0]);
}
@@ -2617,9 +2685,9 @@
transaction_guard guard(*this);
- execute("INSERT into revision_roster VALUES (?, ?)",
- rev_id.inner()().c_str(),
- new_id().c_str());
+ execute(query_args("INSERT into revision_roster VALUES (?, ?)")
+ % text(rev_id.inner()())
+ % text(new_id()));
if (exists(new_id, data_table)
|| delta_exists(new_id, delta_table))
@@ -2706,7 +2774,7 @@
b_uncommon_ancs.clear();
fetch(res, 2, any_rows,
- "SELECT parent,child FROM revision_ancestry");
+ query_args("SELECT parent,child FROM revision_ancestry"));
set a_ancs, b_ancs;
@@ -2735,22 +2803,22 @@
// We implement this as a fixed db var.
fetch(res, one_col, any_rows,
- "SELECT node FROM next_roster_node_number");
+ query_args("SELECT node FROM next_roster_node_number"));
node_id n;
if (res.empty())
{
n = 1;
- execute ("INSERT INTO next_roster_node_number VALUES(?)",
- lexical_cast(n).c_str());
+ execute (query_args("INSERT INTO next_roster_node_number VALUES(?)")
+ % text(lexical_cast(n)));
}
else
{
I(res.size() == 1);
n = lexical_cast(res[0][0]);
++n;
- execute ("UPDATE next_roster_node_number SET node = ?",
- lexical_cast(n).c_str());
+ execute (query_args("UPDATE next_roster_node_number SET node = ?")
+ % text(lexical_cast(n)));
}
guard.commit();
============================================================
--- database.hh 65e7daaaa720624144572538ee668d33d1a0385e
+++ database.hh 8aac44bf6fb3bdb0477933e06a915671cb448029
@@ -1,10 +1,12 @@
-#ifndef __DATABASE_HH__
-#define __DATABASE_HH__
-
+// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
// copyright (C) 2002, 2003 graydon hoare
+// copyright (C) 2006 vinzenz feenstra
// all rights reserved.
// licensed to the public under the terms of the GNU GPL (>= 2)
// see the file COPYING for details
+#ifndef __DATABASE_HH__
+#define __DATABASE_HH__
struct sqlite3;
struct sqlite3_stmt;
@@ -69,6 +71,7 @@
struct posting;
struct app_state;
struct revision_set;
+struct query_args;
class database
{
@@ -96,18 +99,12 @@
typedef std::vector< std::vector > results;
- void execute(char const * query, ...);
+ void execute(query_args const & query);
void fetch(results & res,
int const want_cols,
int const want_rows,
- char const * query, ...);
-
- void fetch(results & res,
- int const want_cols,
- int const want_rows,
- char const * query,
- va_list args);
+ query_args const & query);
bool exists(hexenc const & ident,
std::string const & table);