From 91ff64de200bd8a6eecb487d472f7d70fb5f5546 Mon Sep 17 00:00:00 2001 From: Max Gabrielsson Date: Fri, 6 Sep 2024 14:24:11 +0200 Subject: [PATCH 1/3] check for future geometry versions, add test for future compatability --- .../spatial/core/geometry/geometry_processor.hpp | 9 +++++++-- .../spatial/core/geometry/geometry_properties.hpp | 14 ++++++++++++++ .../spatial/core/geometry/geometry_type.hpp | 13 +++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/spatial/include/spatial/core/geometry/geometry_processor.hpp b/spatial/include/spatial/core/geometry/geometry_processor.hpp index 3567bcae..c70b763c 100644 --- a/spatial/include/spatial/core/geometry/geometry_processor.hpp +++ b/spatial/include/spatial/core/geometry/geometry_processor.hpp @@ -220,8 +220,13 @@ class GeometryProcessor { public: RESULT Process(const geometry_t &geom, ARGS... args) { - has_z = geom.GetProperties().HasZ(); - has_m = geom.GetProperties().HasM(); + const auto props = geom.GetProperties(); + + // Check the version + props.CheckVersion(); + + has_z = props.HasZ(); + has_m = props.HasM(); nesting_level = 0; current_type = geom.GetType(); parent_type = GeometryType::POINT; diff --git a/spatial/include/spatial/core/geometry/geometry_properties.hpp b/spatial/include/spatial/core/geometry/geometry_properties.hpp index 49e71e9c..a3d042c9 100644 --- a/spatial/include/spatial/core/geometry/geometry_properties.hpp +++ b/spatial/include/spatial/core/geometry/geometry_properties.hpp @@ -5,6 +5,8 @@ namespace spatial { namespace core { +static constexpr const uint8_t GEOMETRY_VERSION = 0; + struct GeometryProperties { private: static constexpr const uint8_t Z = 0x01; @@ -14,6 +16,8 @@ struct GeometryProperties { // static constexpr const uint8_t EMPTY = 0x08; // static constexpr const uint8_t GEODETIC = 0x10; // static constexpr const uint8_t SOLID = 0x20; + static constexpr const uint8_t VERSION_1 = 0x40; + static constexpr const uint8_t VERSION_0 = 0x80; uint8_t flags = 0; public: @@ -24,6 +28,16 @@ struct GeometryProperties { SetM(has_m); } + inline void CheckVersion() const { + const auto v0 = (flags & VERSION_0); + const auto v1 = (flags & VERSION_1); + if ((v1 | v0) != GEOMETRY_VERSION) { + throw NotImplementedException( + "This geometry seems to be written with a newer version of the DuckDB spatial library that is not " + "compatible with this version. Please upgrade your DuckDB installation."); + } + } + inline bool HasZ() const { return (flags & Z) != 0; } diff --git a/spatial/include/spatial/core/geometry/geometry_type.hpp b/spatial/include/spatial/core/geometry/geometry_type.hpp index 58fc0339..2a13c629 100644 --- a/spatial/include/spatial/core/geometry/geometry_type.hpp +++ b/spatial/include/spatial/core/geometry/geometry_type.hpp @@ -83,13 +83,15 @@ class geometry_t { } GeometryType GetType() const { + // return the type return Load(const_data_ptr_cast(data.GetPrefix())); } + GeometryProperties GetProperties() const { - return Load(const_data_ptr_cast(data.GetPrefix() + 1)); - } - uint16_t GetHash() const { - return Load(const_data_ptr_cast(data.GetPrefix() + 2)); + const auto props = Load(const_data_ptr_cast(data.GetPrefix() + 1)); + // Check the version + props.CheckVersion(); + return props; } bool TryGetCachedBounds(Box2D &bbox) const { @@ -101,6 +103,9 @@ class geometry_t { auto hash = cursor.Read(); (void)hash; + // Check the version + properties.CheckVersion(); + if (properties.HasBBox()) { cursor.Skip(4); // skip padding From 505e3b4b7d4c362174d7ae962f76c18f57231937 Mon Sep 17 00:00:00 2001 From: Max Gabrielsson Date: Fri, 6 Sep 2024 14:25:21 +0200 Subject: [PATCH 2/3] add test --- test/sql/geometry/geometry_version.test | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/sql/geometry/geometry_version.test diff --git a/test/sql/geometry/geometry_version.test b/test/sql/geometry/geometry_version.test new file mode 100644 index 00000000..0cf2652e --- /dev/null +++ b/test/sql/geometry/geometry_version.test @@ -0,0 +1,27 @@ +# Query a database with geometry types created in duckdb v1.0.0 +require spatial + +statement ok +attach 'test/data/duckdb_v1_0_0.db' as db; + +statement ok +use db + +query IIII rowsort +SELECT st_geometrytype(geom), st_astext(geom), st_isvalid(geom), st_area(geom) FROM types; +---- +GEOMETRYCOLLECTION GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (0 0, 1 1)) true 0.0 +GEOMETRYCOLLECTION GEOMETRYCOLLECTION EMPTY true 0.0 +LINESTRING LINESTRING (0 0, 1 1) true 0.0 +LINESTRING LINESTRING EMPTY true 0.0 +MULTILINESTRING MULTILINESTRING ((0 0, 1 1), (2 2, 3 3)) true 0.0 +MULTILINESTRING MULTILINESTRING EMPTY true 0.0 +MULTIPOINT MULTIPOINT (0 0, 1 1) true 0.0 +MULTIPOINT MULTIPOINT EMPTY true 0.0 +MULTIPOLYGON MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((2 2, 3 2, 3 3, 2 3, 2 2))) true 2.0 +MULTIPOLYGON MULTIPOLYGON EMPTY true 0.0 +POINT POINT (0 0) true 0.0 +POINT POINT EMPTY true 0.0 +POLYGON POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) true 1.0 +POLYGON POLYGON EMPTY true 0.0 + From a190f7c9e60141496a4eee137a77e377bb083d77 Mon Sep 17 00:00:00 2001 From: Max Gabrielsson Date: Fri, 6 Sep 2024 14:49:41 +0200 Subject: [PATCH 3/3] add the db --- test/data/duckdb_v1_0_0.db | Bin 0 -> 536576 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/data/duckdb_v1_0_0.db diff --git a/test/data/duckdb_v1_0_0.db b/test/data/duckdb_v1_0_0.db new file mode 100644 index 0000000000000000000000000000000000000000..268b47026a1c1a1454bbed2ebe4901b0ca7c456f GIT binary patch literal 536576 zcmeI(zi(Sb902gM>qMR+#sVutr^-d*M;G!06e>}Kgkb21QahAfRU}&IXU}8ZqAjBBKQU+wc_x#Srj-LQkL2>mt<#Ko5cklb|eVoKP+j;o&7oOdJ z>Rjjf*PnZ-O8>6hyl{SSe$YPm!sz1DPYwnV5sz zDDUC(CcU#4y%an6QA)e%PMUq{|1kA8n@<9Kozgd{b2t4IXXKK%^RbPulf0jkbQhA; zbLwv~EnY|XkNN9Y6SnH~(-$FbpS^tb%9RD(Cl*F0IB5BAi4(ly%GA}$=zRyjxbF-n zlwf>9d8H+=<^t6z`IEHfjBB<0=6QIn)@-o^)>vS?#%q7@mtM9Q<+-rlV#IzVHVl7z zpRr%R3+XM!2mj~69kvRTUzOzvyG z|LF&p&!luK>O*nDAZitL9QC89{Z2|}qwYn0H|noZ??wH-8~v#H+|6E0Tqxu1$gsT` zv6xbqIOSN$v2y&_!E_WkayhE=ZK9=Dg0zsxA((k{o# zxHW&(%xKzv%eXC`X7kIsOWSL?-yAOYn%mW-+|SYWl6Te2Z`!i1epN14+B2myyTJ7E zjfcLzeh#mCd>7;Mb>#DMDQ&kUf4R5fFgsWG|C#ZYn zI#b^qT4k{+wv@<_009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly MK!5-N0;fjcFPeeov;Y7A literal 0 HcmV?d00001