Sqlite3 API Wrapper
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Build Status Coverage Status Coverity Scan Build Status

SAW (Sqlite3 API Wrapper)

My heart is full of saw::Row.
-- Sad anonymous

A Z that stands for saw::Row!
-- Illiterate anonymous

Yet another wrapper

Faced with the need to write some code using sqlite3's C API, I've procrastinated the real task at hand by writing a standalone library wrapping it.

The goal of this small library is NOT to hide sqlite3's API; if it aimed to do so, it would be far more complicated than it already is. Its goal is simply to facilitate some common sqlite3 tasks, such as managing database connections and statements. All wrapped structures such as Database and Statement provide access to the raw data that lies beneath.

See below a short example of the clarity it brings to the code. For a more detailed documentation; please see the wiki.


SAW requires NPL to build.

make doc     # generates doxygen documentation
make check   # runs tests and generates code coverage report using lcov and cppcheck
make install # installs to /usr/local

Internal plumbing

This library uses C++11 features and lots of boost code. For instance, database and statement handlers are shared using reference counting shared pointers. Values are implemented using boost::variant and iterators use boost::iterator_facade.

The code has been mostly tested and is currently at >90% of code coverage as reported by lcov.

If, somehow, you end up using it, please let me know what you think!

C API / SAW comparison


int run(const char* name, int score_min)
  sqlite3* db = 0;
  sqlite3_stmt* stmt = 0;

  int res = sqlite3_open("test.db", &db);

  if (res != SQLITE_OK)
    return res;

  res = sqlite3_prepare_v2(db, "create table if not exists results (name text, score int)", &stmt, 0);

  if (res != SQLITE_OK)
    return res;

  res = sqlite3_step(stmt);

  if (res != SQLITE_DONE)
    return 1;


  res = sqlite3_prepare_v2(db, "select score from results where name = ? and score >= ?", &stmt, 0);

  if (res != SQLITE_OK)
    return res;

  res = sqlite3_bind_text(stmt, 1, name, 0, SQLITE_TRANSIENT);

  if (res != SQLITE_OK)
    return res;

  res = sqlite3_bind_int(stmt, 2, score_min);

  if (res != SQLITE_OK)
    return res;

  res = sqlite3_step(stmt);

  while (res != SQLITE_DONE)
    if (res != SQLITE_ROW)
      return res;

    std::cout << "score: " << sqlite3_column_int(stmt, 0) << std::endl;


  return 0;


void run(const char* name, int score_min)
    saw::Database db("test.db");
    saw::Statement stmt;

    db.exec("create table if not exists results (name text, score int)");

    stmt = db.make("select score from results where name = ? and score >= ?");
    stmt[1] = name;
    stmt[2] = score_min;

    for (const saw::Row& row : stmt.result())
      std::cout << "score: " << row[0].as_integer() << std::endl;
  catch (const saw::Exception& e)
    std::cerr << "error: " << e.what() << std::endl;