[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Monotone-devel] [PATCH] New typesafe VA_ARGS replacement for database w
From: |
Vinzenz 'evilissimo' Feenstra |
Subject: |
[Monotone-devel] [PATCH] New typesafe VA_ARGS replacement for database with operator % style |
Date: |
Tue, 24 Jan 2006 03:04:48 +0100 |
User-agent: |
Thunderbird 1.5 (Windows/20051201) |
Hi,
How promised here is the operator% style VA_ARGS replacement
implementation diff.
BR
evilissimo
#
# old_revision [e6426b2ef1d68cc432f4e296395f80063813949a]
#
# add_file "query_args.hh"
# content [7492927fb5ee7ed019834339d5c0da9abbe6f617]
#
# patch "AUTHORS"
# from [388b6818cd6ab44a800bbb8778680f1e97971e8b]
# to [be2883d201fdd61b63582334f52312a640e012a1]
#
# patch "ChangeLog"
# from [34243b3f9e9e57de7c7e222d20620b97edb1bbc3]
# to [906222e82dfcf7dc96b8974dbbd30957a25a673e]
#
# patch "database.cc"
# from [0f90adb5a765051661760d886a200529e8fd4b42]
# to [7c8ffbc884c70171f77d2da367aef46ab8d1d478]
#
# 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 <address@hidden>
+// 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 <string>
+#include <vector>
+
+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<query_args_param> args;
+ std::string sql_cmd;
+};
+
+#endif //__QUERY_ARGS_HH__
============================================================
--- AUTHORS 388b6818cd6ab44a800bbb8778680f1e97971e8b
+++ AUTHORS be2883d201fdd61b63582334f52312a640e012a1
@@ -71,8 +71,8 @@
Marcel van der Boom <address@hidden>
Roland McGrath <address@hidden>
Daniel Carosone <address@hidden>
+ Vinzenz Feenstra <address@hidden>
-
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 34243b3f9e9e57de7c7e222d20620b97edb1bbc3
+++ ChangeLog 906222e82dfcf7dc96b8974dbbd30957a25a673e
@@ -1,3 +1,10 @@
+2006-01-24 Vinzenz Feenstra <address@hidden>
+ * 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 Timothy Brownawell <address@hidden>
* tests/t_database_check_normalized.at: update included database to
============================================================
--- database.cc 0f90adb5a765051661760d886a200529e8fd4b42
+++ database.cc 7c8ffbc884c70171f77d2da367aef46ab8d1d478
@@ -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 <address@hidden>
+// copyright (C) 2006 vinzenz feenstra <address@hidden>
// all rights reserved.
// licensed to the public under the terms of the GNU GPL (>= 2)
// see the file COPYING for details
+
#include <algorithm>
#include <deque>
#include <fstream>
@@ -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<sqlite3*> 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<char const*>(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<sqlite3*> 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"
@@ -430,7 +481,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)
{
@@ -564,34 +615,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;
@@ -599,44 +634,45 @@
res.clear();
res.resize(0);
- map<string, statement>::iterator i = statement_cache.find(query);
+ map<string, statement>::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);
@@ -644,7 +680,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());
}
@@ -658,7 +696,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);
}
@@ -676,7 +714,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
@@ -694,9 +732,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
@@ -712,7 +750,7 @@
database::commit_transaction()
{
if (transaction_level == 1)
- execute("COMMIT");
+ execute(query_args("COMMIT"));
transaction_level--;
}
@@ -720,7 +758,7 @@
database::rollback_transaction()
{
if (transaction_level == 1)
- execute("ROLLBACK");
+ execute(query_args("ROLLBACK"));
transaction_level--;
}
@@ -731,7 +769,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;
}
@@ -743,7 +781,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;
}
@@ -752,7 +790,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<unsigned long>(res[0][0]);
}
@@ -763,7 +801,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<unsigned long>(res[0][0]);
}
@@ -772,7 +810,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)
{
@@ -787,7 +825,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<gzip<data> > rdata(res[0][0]);
@@ -811,8 +849,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<gzip<delta> > del_packed = res[0][0];
unpack(del_packed, del);
@@ -835,7 +874,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<id> const & ident,
@@ -851,7 +892,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);
@@ -1024,7 +1068,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);
@@ -1108,7 +1153,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
@@ -1165,7 +1210,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<id> old_id(res[i][0]);
@@ -1188,7 +1234,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<id>(res[0][0]);
get_version(newer_id, newer_data, data_table, delta_table);
@@ -1201,7 +1248,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
{
@@ -1211,7 +1258,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();
@@ -1249,8 +1296,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;
}
@@ -1260,8 +1308,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<id>(res[0][0]));
}
@@ -1272,7 +1321,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]),
@@ -1349,7 +1398,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])));
@@ -1363,8 +1412,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]));
}
@@ -1376,8 +1425,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]));
}
@@ -1407,8 +1456,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<gzip<data> > rdat_packed;
rdat_packed = base64<gzip<data> >(res[0][0]);
@@ -1506,16 +1555,16 @@
base64<gzip<data> > 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);
@@ -1540,16 +1589,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.
@@ -1569,9 +1618,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<id> roster_id;
@@ -1581,13 +1635,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)
@@ -1603,10 +1658,10 @@
base64<cert_value> 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.
@@ -1616,8 +1671,8 @@
base64<cert_value> 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
@@ -1631,11 +1686,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]);
@@ -1647,7 +1702,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]);
}
@@ -1663,8 +1718,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;
@@ -1676,8 +1731,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;
@@ -1691,8 +1746,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];
}
@@ -1703,8 +1758,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];
}
@@ -1717,15 +1772,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
@@ -1742,12 +1799,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;
}
@@ -1761,13 +1819,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
@@ -1829,7 +1887,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);
}
@@ -1844,7 +1902,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);
}
@@ -1858,7 +1916,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);
}
@@ -1874,8 +1932,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);
}
@@ -1890,8 +1950,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);
}
@@ -1908,10 +1970,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);
}
@@ -1934,8 +1997,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());
@@ -2017,10 +2080,10 @@
results res;
vector<cert> 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<id>(res[i][0]));
@@ -2033,10 +2096,10 @@
results res;
vector<cert> 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<cert>(certs[0]);
@@ -2048,10 +2111,10 @@
results res;
vector<cert> 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);
}
@@ -2089,8 +2152,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]));
@@ -2107,8 +2170,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]));
@@ -2116,8 +2179,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]));
@@ -2133,8 +2196,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])));
@@ -2264,7 +2327,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<data> row_encoded(res[i][0]);
@@ -2374,7 +2437,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)
@@ -2396,7 +2459,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<cert_value> encoded(idx(*i, 0));
@@ -2414,9 +2477,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<cert_value> encoded(idx(idx(res, 0), 0));
decode_base64(encoded, branch);
@@ -2428,8 +2491,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;
}
@@ -2442,8 +2505,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
@@ -2451,7 +2516,8 @@
{
base64<cert_value> 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
@@ -2461,7 +2527,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));
@@ -2504,10 +2570,10 @@
encode_base64(key.second, name_encoded);
base64<var_value> 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
@@ -2515,8 +2581,9 @@
{
base64<var_name> 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
@@ -2527,7 +2594,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<data> row_encoded(res[i][0]);
@@ -2549,8 +2616,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<id>(res[0][0]);
}
@@ -2616,9 +2684,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))
@@ -2705,7 +2773,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<revision_id> a_ancs, b_ancs;
@@ -2734,22 +2802,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<string>(n).c_str());
+ execute (query_args("INSERT INTO next_roster_node_number VALUES(?)")
+ % text(lexical_cast<string>(n)));
}
else
{
I(res.size() == 1);
n = lexical_cast<node_id>(res[0][0]);
++n;
- execute ("UPDATE next_roster_node_number SET node = ?",
- lexical_cast<string>(n).c_str());
+ execute (query_args("UPDATE next_roster_node_number SET node = ?")
+ % text(lexical_cast<string>(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 <address@hidden>
+// copyright (C) 2006 vinzenz feenstra <address@hidden>
// 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<std::string> > 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<id> const & ident,
std::string const & table);