diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-02-23 18:02:52 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-02-24 13:38:14 -0800 |
commit | 5cefaeb85716b21f2bbe57165a244844114b8dbe (patch) | |
tree | 33bdf56b0dc6c107e514dd7acb036e7e6e6b1479 | |
parent | 1bdeddab2cbda01117fac756367f76526b14bb9e (diff) | |
download | qtlocation-mapboxgl-5cefaeb85716b21f2bbe57165a244844114b8dbe.tar.gz |
[core] Enforce foreign key constraints in the offline database
-rw-r--r-- | platform/default/mbgl/storage/offline_database.cpp | 21 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_database.hpp | 1 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_schema.cpp.include | 4 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_schema.sql | 4 | ||||
-rw-r--r-- | test/storage/offline_database.cpp | 10 | ||||
-rw-r--r-- | test/storage/offline_download.cpp | 33 |
6 files changed, 49 insertions, 24 deletions
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index aac5e4a54c..983b84a3b4 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -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)); } diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index 1e6666c2aa..f207ab406a 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -50,6 +50,7 @@ public: OfflineRegionStatus getRegionCompletedStatus(int64_t regionID); private: + void connect(int flags); void ensureSchema(); void removeExisting(); diff --git a/platform/default/mbgl/storage/offline_schema.cpp.include b/platform/default/mbgl/storage/offline_schema.cpp.include index 3068dadfe0..a80c7677e6 100644 --- a/platform/default/mbgl/storage/offline_schema.cpp.include +++ b/platform/default/mbgl/storage/offline_schema.cpp.include @@ -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" diff --git a/platform/default/mbgl/storage/offline_schema.sql b/platform/default/mbgl/storage/offline_schema.sql index cba922f3f7..9df8fa6a89 100644 --- a/platform/default/mbgl/storage/offline_schema.sql +++ b/platform/default/mbgl/storage/offline_schema.sql @@ -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) ); diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp index 563c6f31dc..d93945fb40 100644 --- a/test/storage/offline_database.cpp +++ b/test/storage/offline_database.cpp @@ -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()); } diff --git a/test/storage/offline_download.cpp b/test/storage/offline_download.cpp index 33c9c5a95d..73a6f80fcc 100644 --- a/test/storage/offline_download.cpp +++ b/test/storage/offline_download.cpp @@ -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); |