monotone-devel
[Top][All Lists]
Advanced

[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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]