summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/sqldbm.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-04-22 20:31:54 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-04-22 20:31:54 +0000
commit8548e1273bf068feeeed283e9ae90ca826fd0efa (patch)
tree1ca4b3c73d85ae973e70b9a47567483c57963c25 /crawl-ref/source/sqldbm.cc
parentfac344b62ebbf48e7b1d2a7b5f0bcdd3608bd4a7 (diff)
downloadcrawl-ref-8548e1273bf068feeeed283e9ae90ca826fd0efa.tar.gz
crawl-ref-8548e1273bf068feeeed283e9ae90ca826fd0efa.zip
Fixed trunk build for DOS and Windows. DOS and Windows builds use a SQLite db,
with a dbm-like wrapper so database.cc builds unchanged. Added SQLite to the source tree. Only DOS and Windows builds use it at the moment, but it can be added to Unix builds easily (and will be added automatically if a suitable db.h or ndbm.h is not found). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1342 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/sqldbm.cc')
-rw-r--r--crawl-ref/source/sqldbm.cc279
1 files changed, 279 insertions, 0 deletions
diff --git a/crawl-ref/source/sqldbm.cc b/crawl-ref/source/sqldbm.cc
new file mode 100644
index 0000000000..f3cba77100
--- /dev/null
+++ b/crawl-ref/source/sqldbm.cc
@@ -0,0 +1,279 @@
+/*
+ * File: sqldbm.c
+ * Summary: dbm wrapper for SQLite
+ * Written by: Darshan Shaligram
+ */
+
+#include "AppHdr.h"
+#include "sqldbm.h"
+#include "stuff.h"
+#include <cstring>
+
+#ifdef USE_SQLITE_DBM
+
+SQL_DBM::SQL_DBM(const std::string &dbname, bool do_open)
+ : error(), errc(SQLITE_OK), db(NULL), s_insert(NULL),
+ s_query(NULL), dbfile(dbname)
+{
+ if (do_open && !dbfile.empty())
+ open();
+}
+
+SQL_DBM::~SQL_DBM()
+{
+ close();
+}
+
+int SQL_DBM::ec(int err)
+{
+ if (err == SQLITE_OK)
+ error.clear();
+ else if (db)
+ error = sqlite3_errmsg(db);
+ else
+ error = "Unknown error";
+
+ return (errc = err);
+}
+
+bool SQL_DBM::is_open() const
+{
+ return !!db;
+}
+
+int SQL_DBM::open(const std::string &s)
+{
+ close();
+
+ if (!s.empty())
+ dbfile = s;
+
+ if (!dbfile.empty())
+ {
+ if (dbfile.find(".db") != dbfile.length() - 3)
+ dbfile += ".db";
+
+ if (ec( sqlite3_open(dbfile.c_str(), &db) ) != SQLITE_OK)
+ {
+ std::string saveerr = error;
+ int serrc = errc;
+ close();
+ error = saveerr;
+ errc = serrc;
+ return (errc);
+ }
+
+ init_schema();
+ }
+ else
+ error = "No filename!";
+
+ return (errc);
+}
+
+int SQL_DBM::init_schema()
+{
+ int err = ec(sqlite3_exec(
+ db,
+ "CREATE TABLE dbm (key STRING UNIQUE PRIMARY KEY,"
+ " value STRING);",
+ NULL,
+ NULL,
+ NULL));
+
+ // Turn off auto-commit
+ sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
+ return (err);
+}
+
+void SQL_DBM::close()
+{
+ if (db)
+ {
+ sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
+ finalise_query(&s_insert);
+ finalise_query(&s_query);
+ sqlite3_close(db);
+ db = NULL;
+ }
+}
+
+int SQL_DBM::insert(const std::string &key, const std::string &value)
+{
+ if (init_insert() != SQLITE_OK)
+ return (errc);
+
+ ec(sqlite3_bind_text(s_insert, 1, key.c_str(), -1, SQLITE_STATIC));
+ if (errc != SQLITE_OK)
+ return (errc);
+ ec(sqlite3_bind_text(s_insert, 2, value.c_str(), -1, SQLITE_STATIC));
+ if (errc != SQLITE_OK)
+ return (errc);
+
+ ec(sqlite3_step(s_insert));
+ sqlite3_reset(s_insert);
+
+ return (errc);
+}
+
+int SQL_DBM::init_insert()
+{
+ return s_insert? SQLITE_OK :
+ prepare_query(&s_insert, "INSERT INTO dbm VALUES (?, ?)");
+}
+
+std::string SQL_DBM::query(const std::string &key)
+{
+ if (init_query() != SQLITE_OK)
+ return ("");
+
+ if (ec(sqlite3_bind_text(s_query, 1, key.c_str(), -1, SQLITE_TRANSIENT))
+ != SQLITE_OK)
+ {
+ return ("");
+ }
+
+ int err = SQLITE_OK;
+ std::string res;
+ while ((err = ec(sqlite3_step(s_query))) == SQLITE_ROW)
+ res = (const char *) sqlite3_column_text(s_query, 0);
+
+ sqlite3_reset(s_query);
+
+ return (res);
+}
+
+int SQL_DBM::init_query()
+{
+ return s_query? SQLITE_OK :
+ prepare_query(&s_query, "SELECT value FROM dbm WHERE key = ?");
+}
+
+int SQL_DBM::finalise_query(sqlite3_stmt **q)
+{
+ if (!*q)
+ return (SQLITE_OK);
+
+ sqlite3_reset(*q);
+ int ret = ec(sqlite3_finalize(*q));
+ *q = NULL;
+
+ return (ret);
+}
+
+int SQL_DBM::prepare_query(sqlite3_stmt **q, const char *sql)
+{
+ if (*q)
+ finalise_query(q);
+
+ const char *query_tail;
+ return ec(sqlite3_prepare_v2(db, sql, -1, q, &query_tail));
+}
+
+////////////////////////////////////////////////////////////////////////
+
+sql_datum::sql_datum() : dptr(NULL), dsize(0), need_free(false)
+{
+}
+
+sql_datum::sql_datum(const std::string &s) : dptr(NULL), dsize(s.length()),
+ need_free(false)
+{
+ if ((dptr = new char [dsize]))
+ {
+ strcpy(dptr, s.c_str());
+ need_free = true;
+ }
+}
+
+sql_datum::sql_datum(const sql_datum &dat) : dptr(NULL), dsize(0), need_free(false)
+{
+ init_from(dat);
+}
+
+sql_datum::~sql_datum()
+{
+ reset();
+}
+
+sql_datum &sql_datum::operator = (const sql_datum &d)
+{
+ if (&d != this)
+ {
+ reset();
+ init_from(d);
+ }
+ return (*this);
+}
+
+void sql_datum::reset()
+{
+ if (need_free)
+ delete [] dptr;
+
+ dptr = NULL;
+ dsize = 0;
+}
+
+void sql_datum::init_from(const sql_datum &d)
+{
+ dsize = d.dsize;
+ need_free = false;
+ if (d.need_free)
+ {
+ if ((dptr = new char [dsize]))
+ {
+ if (dsize)
+ memcpy(dptr, d.dptr, dsize);
+ need_free = true;
+ }
+ }
+ else
+ {
+ need_free = false;
+ dptr = d.dptr;
+ }
+}
+
+std::string sql_datum::to_str() const
+{
+ return std::string(dptr, dsize);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+SQL_DBM *dbm_open(const char *filename, int, int)
+{
+ SQL_DBM *n = new SQL_DBM(filename, true);
+ if (!n->is_open())
+ {
+ delete n;
+ return (NULL);
+ }
+
+ return (n);
+}
+
+int dbm_close(SQL_DBM *db)
+{
+ delete db;
+ return (0);
+}
+
+sql_datum dbm_fetch(SQL_DBM *db, const sql_datum &key)
+{
+ std::string ans = db->query(std::string(key.dptr, key.dsize));
+ return sql_datum(ans);
+}
+
+int dbm_store(SQL_DBM *db, const sql_datum &key, const sql_datum &value, int)
+{
+ int err = db->insert(key.to_str(), value.to_str());
+ if (err == SQLITE_DONE || err == SQLITE_CONSTRAINT)
+ err = SQLITE_OK;
+ else
+ end(1, false, "%d: %s", db->errc, db->error.c_str());
+ return (err);
+}
+
+#endif