Or since in C++ use an unordered_map.  Add your statement pointers to that, and 
delete them from the map when finalized. Then walk through that map on 
destruction to finalize all you haven't cleaned up yourself.

Given the way he's developing I would make a function to do this that 
pre-checks that the statement doesn't already exist in the map to catch errors.

#include <sstream>
#include <unordered_set>
#include "sqlite3.h"

// Compiles with gcc 4.4
//  g++ -std=c++0x -g -o map map.cpp
  
using namespace std;
    
class Statement {
public:
  Statement() {};
  ~Statement();
  bool add(sqlite3_stmt **stmt); // returns true if successful
  bool remove(sqlite3_stmt **stmt); // returns true if succesful
  string errmsg() {
    return serrmsg.str();
  };
  void clear();
private:
  stringstream serrmsg;
  unordered_set<sqlite3_stmt **> statements;
};
    
Statement::~Statement() {
  clear();
}   
  
void Statement::clear() {
  for(unordered_set<sqlite3_stmt **>::iterator it = statements.begin(); 
it!=statements.end(); ++it) {
    cout << "finalize " << *it << endl;
    statements.erase(*it);
  }
} 
    
bool Statement::add(sqlite3_stmt **stmt) {
  serrmsg.str("");
  unordered_set<sqlite3_stmt **>::const_iterator got;
  got = statements.find(stmt);
  if ( got != statements.end()) {
    serrmsg << "stmt already exists";
    return false;
  }
  serrmsg << "OK";
  statements.insert(stmt);
  return true;
}

bool Statement::remove(sqlite3_stmt **stmt) {
  serrmsg.str("");
  unordered_set<sqlite3_stmt **>::const_iterator got;
  got = statements.find(stmt);
  if ( got == statements.end()) {
    serrmsg << "stmt does not exist";
    return false;
  }
  serrmsg << "OK";
  statements.erase(stmt);
  return true;
}

int main() {
  sqlite3_stmt *stmt1,*stmt2,*stmt3;
  Statement st;
  if (!st.add(&stmt1)) { // works
    cerr << "Error#1 putting stmt: " << st.errmsg() << endl;
  }
  if (!st.add(&stmt2)) { // works
    cerr << "Error#1 putting stmt: " << st.errmsg() << endl;
  }
  if (!st.add(&stmt3)) { // works
    cerr << "Error#1 putting stmt: " << st.errmsg() << endl;
  }
  if (!st.add(&stmt1)) { // gives error
    cerr << "Error#2 putting stmt: " << st.errmsg() << endl;
  }
  if (!st.remove(&stmt1)) { // works
    cerr << "Error#3 removing stmt: " << st.errmsg() << endl;
  }
  if (!st.remove(&stmt1)) { // gives error
    cerr << "Error#4 removing stmt: " << st.errmsg() << endl;
  }
}



Michael D. Black
Senior Scientist
Advanced Analytics Directorate
Advanced GEOINT Solutions Operating Unit
Northrop Grumman Information Systems

________________________________________
From: sqlite-users-boun...@sqlite.org [sqlite-users-boun...@sqlite.org] on 
behalf of Roger Binns [rog...@rogerbinns.com]
Sent: Friday, July 27, 2012 5:20 PM
To: General Discussion of SQLite Database
Subject: EXT :Re: [sqlite] C++ - Finalizing my SQLite interface

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 27/07/12 07:22, Arbol One wrote:
> Before calling the destructor, I would like to make sure that all the
> sqlite3_stmt have been 'finalized', is there a function in SQLite that
> that can help me do this, or should I just use 'NULL'?

Your best bet is to use reference counting.  Each statement, backup etc
should add one to the database reference count, and subtract one when
finalized.  Then only call the database destructor once its reference
count reaches zero.

Roger

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)

iEYEARECAAYFAlATFBAACgkQmOOfHg372QTdCQCfS6Y/E3G8lFcI5jDlYFY/l7XC
GkkAoMrxm+adE0WQNsb3kM7hSkWMbTc/
=Lf/f
-----END PGP SIGNATURE-----
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to