[core] Enforce foreign key constraints in the offline database
This commit is contained in:
@@ -39,11 +39,16 @@ OfflineDatabase::~OfflineDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
void OfflineDatabase::connect(int flags) {
|
||||
db = std::make_unique<Database>(path.c_str(), flags);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
db->exec("PRAGMA foreign_keys = ON");
|
||||
}
|
||||
|
||||
void OfflineDatabase::ensureSchema() {
|
||||
if (path != ":memory:") {
|
||||
try {
|
||||
db = std::make_unique<Database>(path.c_str(), ReadWrite);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
connect(ReadWrite);
|
||||
|
||||
{
|
||||
auto userVersionStmt = db->prepare("PRAGMA user_version");
|
||||
@@ -57,24 +62,20 @@ void OfflineDatabase::ensureSchema() {
|
||||
}
|
||||
|
||||
removeExisting();
|
||||
db = std::make_unique<Database>(path.c_str(), ReadWrite | Create);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
connect(ReadWrite | Create);
|
||||
} catch (mapbox::sqlite::Exception& ex) {
|
||||
if (ex.code == SQLITE_CANTOPEN) {
|
||||
db = std::make_unique<Database>(path.c_str(), ReadWrite | Create);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
connect(ReadWrite | Create);
|
||||
} else if (ex.code == SQLITE_NOTADB) {
|
||||
removeExisting();
|
||||
db = std::make_unique<Database>(path.c_str(), ReadWrite | Create);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
connect(ReadWrite | Create);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "offline_schema.cpp.include"
|
||||
|
||||
db = std::make_unique<Database>(path.c_str(), ReadWrite | Create);
|
||||
db->setBusyTimeout(Milliseconds::max());
|
||||
connect(ReadWrite | Create);
|
||||
db->exec(schema);
|
||||
db->exec("PRAGMA user_version = " + util::toString(schemaVersion));
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
OfflineRegionStatus getRegionCompletedStatus(int64_t regionID);
|
||||
|
||||
private:
|
||||
void connect(int flags);
|
||||
void ensureSchema();
|
||||
void removeExisting();
|
||||
|
||||
|
||||
@@ -33,12 +33,12 @@ static const char * schema =
|
||||
" description BLOB\n"
|
||||
");\n"
|
||||
"CREATE TABLE region_resources (\n"
|
||||
" region_id INTEGER NOT NULL REFERENCES regions(id),\n"
|
||||
" region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE,\n"
|
||||
" resource_id INTEGER NOT NULL REFERENCES resources(id),\n"
|
||||
" UNIQUE (region_id, resource_id)\n"
|
||||
");\n"
|
||||
"CREATE TABLE region_tiles (\n"
|
||||
" region_id INTEGER NOT NULL REFERENCES regions(id),\n"
|
||||
" region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE,\n"
|
||||
" tile_id INTEGER NOT NULL REFERENCES tiles(id),\n"
|
||||
" UNIQUE (region_id, tile_id)\n"
|
||||
");\n"
|
||||
|
||||
@@ -36,13 +36,13 @@ CREATE TABLE regions (
|
||||
);
|
||||
|
||||
CREATE TABLE region_resources (
|
||||
region_id INTEGER NOT NULL REFERENCES regions(id),
|
||||
region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE,
|
||||
resource_id INTEGER NOT NULL REFERENCES resources(id),
|
||||
UNIQUE (region_id, resource_id)
|
||||
);
|
||||
|
||||
CREATE TABLE region_tiles (
|
||||
region_id INTEGER NOT NULL REFERENCES regions(id),
|
||||
region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE,
|
||||
tile_id INTEGER NOT NULL REFERENCES tiles(id),
|
||||
UNIQUE (region_id, tile_id)
|
||||
);
|
||||
|
||||
@@ -461,7 +461,15 @@ TEST(OfflineDatabase, DeleteRegion) {
|
||||
OfflineDatabase db(":memory:");
|
||||
OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
|
||||
OfflineRegionMetadata metadata {{ 1, 2, 3 }};
|
||||
db.deleteRegion(db.createRegion(definition, metadata));
|
||||
OfflineRegion region = db.createRegion(definition, metadata);
|
||||
|
||||
Response response;
|
||||
response.noContent = true;
|
||||
|
||||
db.putRegionResource(region.getID(), Resource::style("http://example.com/"), response);
|
||||
db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0), response);
|
||||
|
||||
db.deleteRegion(std::move(region));
|
||||
|
||||
ASSERT_EQ(0, db.listRegions().size());
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ public:
|
||||
OfflineDatabase db { ":memory:" };
|
||||
std::size_t size = 0;
|
||||
|
||||
OfflineRegion createRegion() {
|
||||
OfflineRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0 };
|
||||
OfflineRegionMetadata metadata;
|
||||
return db.createRegion(definition, metadata);
|
||||
}
|
||||
|
||||
Response response(const std::string& path) {
|
||||
Response result;
|
||||
result.data = std::make_shared<std::string>(util::read_file("test/fixtures/"s + path));
|
||||
@@ -47,8 +53,9 @@ public:
|
||||
|
||||
TEST(OfflineDownload, NoSubresources) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -76,8 +83,9 @@ TEST(OfflineDownload, NoSubresources) {
|
||||
|
||||
TEST(OfflineDownload, InlineSource) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -115,8 +123,9 @@ TEST(OfflineDownload, InlineSource) {
|
||||
|
||||
TEST(OfflineDownload, GeoJSONSource) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -149,8 +158,9 @@ TEST(OfflineDownload, GeoJSONSource) {
|
||||
|
||||
TEST(OfflineDownload, Activate) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -214,8 +224,9 @@ TEST(OfflineDownload, Activate) {
|
||||
|
||||
TEST(OfflineDownload, GetStatusNoResources) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
OfflineRegionStatus status = download.getStatus();
|
||||
@@ -230,8 +241,9 @@ TEST(OfflineDownload, GetStatusNoResources) {
|
||||
|
||||
TEST(OfflineDownload, GetStatusStyleComplete) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -251,8 +263,9 @@ TEST(OfflineDownload, GetStatusStyleComplete) {
|
||||
|
||||
TEST(OfflineDownload, GetStatusStyleAndSourceComplete) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -276,8 +289,9 @@ TEST(OfflineDownload, GetStatusStyleAndSourceComplete) {
|
||||
|
||||
TEST(OfflineDownload, RequestError) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
@@ -303,8 +317,9 @@ TEST(OfflineDownload, RequestError) {
|
||||
|
||||
TEST(OfflineDownload, RequestErrorsAreRetried) {
|
||||
OfflineTest test;
|
||||
OfflineRegion region = test.createRegion();
|
||||
OfflineDownload download(
|
||||
1,
|
||||
region.getID(),
|
||||
OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
|
||||
test.db, test.fileSource);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user