commit 737efda8f1f79b06c4775761789d2fe9c6a39e57
parent 11a7af9b3bdd6af816333819165fa1b28b913993
Author: cfillion <cfillion@users.noreply.github.com>
Date: Fri, 12 Aug 2016 15:28:46 -0400
registry: accept databases written by compatible newer versions of ReaPack
Diffstat:
5 files changed, 78 insertions(+), 29 deletions(-)
diff --git a/src/database.cpp b/src/database.cpp
@@ -19,6 +19,7 @@
#include "errors.hpp"
+#include <cinttypes>
#include <sqlite3.h>
using namespace std;
@@ -67,22 +68,31 @@ reapack_error Database::lastError() const
return reapack_error(sqlite3_errmsg(m_db));
}
-int Database::lastInsertId() const
+int64_t Database::lastInsertId() const
{
- return (int)sqlite3_last_insert_rowid(m_db);
+ return sqlite3_last_insert_rowid(m_db);
}
-int Database::version() const
+auto Database::version() const -> Version
{
- int version = 0;
+ int32_t version = 0;
Statement stmt("PRAGMA user_version", this);
stmt.exec([&] {
- version = stmt.intColumn(0);
+ version = static_cast<int32_t>(stmt.intColumn(0));
return false;
});
- return version;
+ return {static_cast<int16_t>(version >> 16), static_cast<int16_t>(version)};
+}
+
+void Database::setVersion(const Version &version)
+{
+ int32_t value = version.minor | (int32_t)version.major << 16;
+
+ char sql[255] = {};
+ sprintf(sql, "PRAGMA user_version = %" PRId32, value);
+ exec(sql);
}
int Database::errorCode() const
@@ -121,9 +131,9 @@ void Statement::bind(const int index, const string &text)
throw m_db->lastError();
}
-void Statement::bind(const int index, const int integer)
+void Statement::bind(const int index, const int64_t integer)
{
- if(sqlite3_bind_int(m_stmt, index, integer))
+ if(sqlite3_bind_int64(m_stmt, index, integer))
throw m_db->lastError();
}
@@ -151,9 +161,9 @@ void Statement::exec(const ExecCallback &callback)
}
}
-int Statement::intColumn(const int index) const
+int64_t Statement::intColumn(const int index) const
{
- return sqlite3_column_int(m_stmt, index);
+ return sqlite3_column_int64(m_stmt, index);
}
string Statement::stringColumn(const int index) const
diff --git a/src/database.hpp b/src/database.hpp
@@ -18,6 +18,7 @@
#ifndef REAPACK_DATABASE_HPP
#define REAPACK_DATABASE_HPP
+#include <cstdint>
#include <functional>
#include <string>
#include <vector>
@@ -31,13 +32,16 @@ class Statement;
class Database {
public:
+ struct Version { int16_t major; int16_t minor; };
+
Database(const std::string &filename = std::string());
~Database();
Statement *prepare(const char *sql);
void exec(const char *sql);
- int lastInsertId() const;
- int version() const;
+ int64_t lastInsertId() const;
+ Version version() const;
+ void setVersion(const Version &);
int errorCode() const;
void begin();
void commit();
@@ -56,11 +60,11 @@ public:
typedef std::function<bool (void)> ExecCallback;
void bind(int index, const std::string &text);
- void bind(int index, int integer);
+ void bind(int index, int64_t integer);
void exec();
void exec(const ExecCallback &);
- int intColumn(int index) const;
+ int64_t intColumn(int index) const;
bool boolColumn(int index) const { return intColumn(index) != 0; }
std::string stringColumn(int index) const;
diff --git a/src/registry.cpp b/src/registry.cpp
@@ -74,10 +74,12 @@ Registry::Registry(const Path &path)
void Registry::migrate()
{
+ const Database::Version &version = m_db.version();
+
m_db.begin();
+ m_db.setVersion({0, 4});
- switch(m_db.version()) {
- case 0:
+ if(!version.major && !version.minor) {
// new database!
m_db.exec(
"CREATE TABLE entries ("
@@ -102,22 +104,26 @@ void Registry::migrate()
" FOREIGN KEY(entry) REFERENCES entries(id)"
");"
);
+ }
+
+ switch(version.major) {
+ case 0:
+ // current major schema version
break;
+ default:
+ throw reapack_error(
+ "The package registry was created by a newer version of ReaPack");
+ }
+
+ switch(version.minor) {
case 1:
m_db.exec("ALTER TABLE entries ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0;");
case 2:
m_db.exec("ALTER TABLE files ADD COLUMN type INTEGER NOT NULL DEFAULT 0;");
case 3:
m_db.exec("ALTER TABLE entries ADD COLUMN desc TEXT NOT NULL DEFAULT '';");
- case 4:
- // schema is up to date
- break;
- default:
- throw reapack_error(
- "The package registry was created by a newer version of ReaPack");
}
- m_db.exec("PRAGMA user_version = 4");
m_db.commit();
}
@@ -136,7 +142,7 @@ auto Registry::push(const Version *ver, vector<Path> *conflicts) -> Entry
m_clearFiles->bind(3, pkg->name());
m_clearFiles->exec();
- int entryId = getEntry(ver->package()).id;
+ auto entryId = getEntry(ver->package()).id;
// register or update package and version
if(entryId) {
diff --git a/src/registry.hpp b/src/registry.hpp
@@ -33,7 +33,7 @@ class Version;
class Registry {
public:
struct Entry {
- int id;
+ int64_t id;
std::string remote;
std::string category;
std::string package;
diff --git a/test/database.cpp b/test/database.cpp
@@ -95,12 +95,18 @@ TEST_CASE("bind values and clear", M) {
}
}
-TEST_CASE("version", M) {
+TEST_CASE("database version", M) {
Database db;
- REQUIRE(db.version() == 0);
+ REQUIRE(db.version().major == 0);
+ REQUIRE(db.version().minor == 0);
- db.exec("PRAGMA user_version = 1");
- REQUIRE(db.version() == 1);
+ db.setVersion({0, 1});
+ REQUIRE(db.version().major == 0);
+ REQUIRE(db.version().minor == 1);
+
+ db.setVersion({32767, 32767});
+ REQUIRE(db.version().major == 32767);
+ REQUIRE(db.version().minor == 32767);
}
TEST_CASE("foreign keys", M) {
@@ -161,6 +167,29 @@ TEST_CASE("bind temporary strings", M) {
REQUIRE(got == "hello");
}
+TEST_CASE("get integers from sqlite", M) {
+ Database db;
+ db.exec("CREATE TABLE a(test INTEGER NOT NULL)");
+
+ Statement *insert = db.prepare("INSERT INTO a VALUES(?)");
+
+ insert->bind(1, 2147483647);
+ insert->exec();
+ insert->bind(1, 4294967295);
+ insert->exec();
+
+ vector<sqlite3_int64> signedVals;
+ Statement *select = db.prepare("SELECT test FROM a");
+ select->exec([&] {
+ signedVals.push_back(select->intColumn(0));
+ return true;
+ });
+
+ CHECK(signedVals.size() == 2);
+ REQUIRE(signedVals[0] == 2147483647);
+ REQUIRE(signedVals[1] == 4294967295);
+}
+
TEST_CASE("sqlite error code", M) {
Database db;
db.exec("CREATE TABLE a(b INTEGER UNIQUE); INSERT INTO a VALUES(1)");