aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-10-02 08:29:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-10-02 08:29:06 +0200
commitb3a299fbbd80e69554b37d0ae30cf2c45a98d1a6 (patch)
tree89055429d81c77fd6104fc07fa854f734657a408
parent29b45e1658840b0ce5f67529b46cad5d595433c4 (diff)
Add support for SQLite 3.3.6
That's what is still shipped with RHEL5.
-rw-r--r--m4/libsqlite.m44
-rw-r--r--odb/sqlite/connection.cxx14
-rw-r--r--odb/sqlite/database.hxx9
-rw-r--r--odb/sqlite/statement.cxx110
-rw-r--r--odb/sqlite/statement.hxx6
5 files changed, 136 insertions, 7 deletions
diff --git a/m4/libsqlite.m4 b/m4/libsqlite.m4
index a75062c..4bbe9a1 100644
--- a/m4/libsqlite.m4
+++ b/m4/libsqlite.m4
@@ -24,9 +24,9 @@ int
main ()
{
sqlite3* handle;
- sqlite3_open_v2 ("", &handle, 0, 0);
+ sqlite3_open ("", &handle);
sqlite3_stmt* stmt;
- sqlite3_prepare_v2 (handle, "", 0, &stmt, 0);
+ sqlite3_prepare (handle, "", 0, &stmt, 0);
sqlite3_finalize (stmt);
sqlite3_close (handle);
}
diff --git a/odb/sqlite/connection.cxx b/odb/sqlite/connection.cxx
index f4e7259..188d59f 100644
--- a/odb/sqlite/connection.cxx
+++ b/odb/sqlite/connection.cxx
@@ -51,12 +51,22 @@ namespace odb
f |= SQLITE_OPEN_NOMUTEX;
#endif
- const string& vfs (db.vfs ());
-
sqlite3* h (0);
+
+ // sqlite3_open_v2() was only addedin SQLite 3.5.0.
+ //
+#if SQLITE_VERSION_NUMBER >= 3005000
+ const string& vfs (db.vfs ());
int e (
sqlite3_open_v2 (
n.c_str (), &h, f, (vfs.empty () ? 0 : vfs.c_str ())));
+#else
+ // Readonly opening not supported in SQLite earlier than 3.5.0.
+ //
+ assert ((f & SQLITE_OPEN_READONLY) == 0);
+ int e (sqlite3_open (n.c_str (), &h));
+#endif
+
handle_.reset (h);
if (e != SQLITE_OK)
diff --git a/odb/sqlite/database.hxx b/odb/sqlite/database.hxx
index ee758e5..d2053e5 100644
--- a/odb/sqlite/database.hxx
+++ b/odb/sqlite/database.hxx
@@ -27,6 +27,15 @@
#include <odb/sqlite/details/export.hxx>
+// We use the sqlite3_open_v2() flags in our interface. Define them
+// for SQLite earlier that 3.5.0.
+//
+#if SQLITE_VERSION_NUMBER < 3005000
+# define SQLITE_OPEN_READONLY 0x00000001
+# define SQLITE_OPEN_READWRITE 0x00000002
+# define SQLITE_OPEN_CREATE 0x00000004
+#endif
+
namespace odb
{
namespace sqlite
diff --git a/odb/sqlite/statement.cxx b/odb/sqlite/statement.cxx
index de71e12..a09e467 100644
--- a/odb/sqlite/statement.cxx
+++ b/odb/sqlite/statement.cxx
@@ -43,6 +43,11 @@ namespace odb
{
int e;
sqlite3_stmt* stmt (0);
+
+ // sqlite3_prepare_v2() is only available since SQLite 3.3.9
+ // but is buggy until 3.3.11.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
while ((e = sqlite3_prepare_v2 (conn_.handle (),
text,
static_cast<int> (text_size),
@@ -51,11 +56,23 @@ namespace odb
{
conn_.wait ();
}
+#else
+ e = sqlite3_prepare (conn_.handle (),
+ text,
+ static_cast<int> (text_size),
+ &stmt,
+ 0);
+#endif
if (e != SQLITE_OK)
translate_error (e, conn_);
stmt_.reset (stmt);
+
+#if SQLITE_VERSION_NUMBER < 3005003
+ text_.assign (text, text_size);
+#endif
+
active_ = false;
prev_ = 0;
@@ -73,7 +90,13 @@ namespace odb
const char* statement::
text () const
{
+ // sqlite3_sql() is only available since 3.5.3.
+ //
+#if SQLITE_VERSION_NUMBER >= 3005003
return sqlite3_sql (stmt_);
+#else
+ return text_.c_str ();
+#endif
}
void statement::
@@ -100,7 +123,15 @@ namespace odb
case bind::integer:
{
long long v (*static_cast<long long*> (b.buffer));
- e = sqlite3_bind_int64 (stmt_, j, static_cast<sqlite3_int64> (v));
+ e = sqlite3_bind_int64 (stmt_,
+ j,
+ // Prior to 3.5.0, sqlite3_int64 was called sqlite_int64.
+#if SQLITE_VERSION_NUMBER >= 3005000
+ static_cast<sqlite3_int64> (v)
+#else
+ static_cast<sqlite_int64> (v)
+#endif
+ );
break;
}
case bind::real:
@@ -295,10 +326,42 @@ namespace odb
for (; e == SQLITE_ROW; e = sqlite3_step (stmt_))
r++;
+ // sqlite3_step() will return a detailed error code only if we used
+ // sqlite3_prepare_v2(). Otherwise, sqlite3_reset() returns the
+ // error.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
sqlite3_reset (stmt_);
if (e != SQLITE_DONE)
translate_error (e, conn_);
+#else
+ e = sqlite3_reset (stmt_);
+
+ if (e != SQLITE_OK)
+ {
+ // If the schema has changed, try to re-prepare and re-execute the
+ // statement. That's what newer versions of SQLite do automatically.
+ //
+ if (e == SQLITE_SCHEMA)
+ {
+ sqlite3_stmt* stmt (0);
+ e = sqlite3_prepare (h,
+ text_.c_str (),
+ static_cast<int> (text_.size () + 1),
+ &stmt,
+ 0);
+
+ if (e != SQLITE_OK)
+ translate_error (e, conn_);
+
+ stmt_.reset (stmt);
+ return execute (); // Try again by recursively calling ourselves.
+ }
+ else
+ translate_error (e, conn_);
+ }
+#endif
if (!result_set_)
r = static_cast<unsigned long long> (sqlite3_changes (h));
@@ -393,10 +456,23 @@ namespace odb
if (e != SQLITE_ROW)
{
- reset ();
done_ = true;
+ // sqlite3_step() will return a detailed error code only if we used
+ // sqlite3_prepare_v2(). Otherwise, sqlite3_reset() returns the
+ // error.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
+ reset ();
+
if (e != SQLITE_DONE)
+#else
+ e = sqlite3_reset (stmt_);
+ list_remove ();
+ active_ = false;
+
+ if (e != SQLITE_OK)
+#endif
translate_error (e, conn_);
}
}
@@ -468,9 +544,19 @@ namespace odb
e = sqlite3_step (stmt_);
#endif
+ // sqlite3_step() will return a detailed error code only if we used
+ // sqlite3_prepare_v2(). Otherwise, sqlite3_reset() returns the
+ // error.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
sqlite3_reset (stmt_);
if (e != SQLITE_DONE)
+#else
+ e = sqlite3_reset (stmt_);
+
+ if (e != SQLITE_OK)
+#endif
{
// SQLITE_CONSTRAINT error code covers more than just a duplicate
// primary key. Unfortunately, there is nothing more precise that
@@ -539,9 +625,19 @@ namespace odb
e = sqlite3_step (stmt_);
#endif
+ // sqlite3_step() will return a detailed error code only if we used
+ // sqlite3_prepare_v2(). Otherwise, sqlite3_reset() returns the
+ // error.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
sqlite3_reset (stmt_);
if (e != SQLITE_DONE)
+#else
+ e = sqlite3_reset (stmt_);
+
+ if (e != SQLITE_OK)
+#endif
translate_error (e, conn_);
return static_cast<unsigned long long> (sqlite3_changes (h));
@@ -593,9 +689,19 @@ namespace odb
e = sqlite3_step (stmt_);
#endif
+ // sqlite3_step() will return a detailed error code only if we used
+ // sqlite3_prepare_v2(). Otherwise, sqlite3_reset() returns the
+ // error.
+ //
+#if SQLITE_VERSION_NUMBER >= 3003011
sqlite3_reset (stmt_);
if (e != SQLITE_DONE)
+#else
+ e = sqlite3_reset (stmt_);
+
+ if (e != SQLITE_OK)
+#endif
translate_error (e, conn_);
return static_cast<unsigned long long> (sqlite3_changes (h));
diff --git a/odb/sqlite/statement.hxx b/odb/sqlite/statement.hxx
index eb55e58..ccb4762 100644
--- a/odb/sqlite/statement.hxx
+++ b/odb/sqlite/statement.hxx
@@ -124,6 +124,10 @@ namespace odb
connection_type& conn_;
auto_handle<sqlite3_stmt> stmt_;
+#if SQLITE_VERSION_NUMBER < 3005003
+ std::string text_;
+#endif
+
bool active_;
private:
@@ -132,7 +136,7 @@ namespace odb
// Doubly-linked list of active statements.
//
- private:
+ protected:
void
list_add ()
{