Skip to content

Commit

Permalink
Merge pull request #124 from Maxxen/dev
Browse files Browse the repository at this point in the history
Cardinality estimation, replacement scans, misc fixes and breaking changes to `GEOMETRY` format.
  • Loading branch information
Maxxen authored Sep 10, 2023
2 parents 67f8e34 + 770db15 commit a99134f
Show file tree
Hide file tree
Showing 21 changed files with 694 additions and 416 deletions.
2 changes: 1 addition & 1 deletion duckdb
Submodule duckdb updated 281 files
91 changes: 91 additions & 0 deletions spatial/include/spatial/core/geometry/cursor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma once
#include "spatial/common.hpp"

namespace spatial {

namespace core {

class Cursor {
private:
data_ptr_t start;
data_ptr_t ptr;
data_ptr_t end;

public:
enum class Offset { START, CURRENT, END };

explicit Cursor(data_ptr_t start, data_ptr_t end) : start(start), ptr(start), end(end) {
}

explicit Cursor(string_t blob) : start((data_ptr_t)blob.GetDataUnsafe()), ptr(start), end(start + blob.GetSize()) {
}

data_ptr_t GetPtr() {
return ptr;
}

void SetPtr(data_ptr_t ptr_p) {
if (ptr_p < start || ptr_p > end) {
throw SerializationException("Trying to set ptr outside of buffer");
}
ptr = ptr_p;
}

template <class T>
T Read() {
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
if (ptr + sizeof(T) > end) {
throw SerializationException("Trying to read past end of buffer");
}
auto result = Load<T>(ptr);
ptr += sizeof(T);
return result;
}

template <class T>
void Write(T value) {
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
if (ptr + sizeof(T) > end) {
throw SerializationException("Trying to write past end of buffer");
}
Store<T>(value, ptr);
ptr += sizeof(T);
}

template <class T>
T Peek() {
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
if (ptr + sizeof(T) > end) {
throw SerializationException("Trying to read past end of buffer");
}
return Load<T>(ptr);
}

void Skip(uint32_t bytes) {
if (ptr + bytes > end) {
throw SerializationException("Trying to read past end of buffer");
}
ptr += bytes;
}

void Seek(Offset offset, int32_t bytes) {
switch (offset) {
case Offset::START:
ptr = start + bytes;
break;
case Offset::CURRENT:
ptr += bytes;
break;
case Offset::END:
ptr = end + bytes;
break;
}
if (ptr < start || ptr > end) {
throw SerializationException("Trying to set ptr outside of buffer");
}
}
};

} // namespace core

} // namespace spatial
56 changes: 35 additions & 21 deletions spatial/include/spatial/core/geometry/geometry.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#pragma once

#include "spatial/common.hpp"
#include "spatial/core/geometry/geometry_properties.hpp"
#include "spatial/core/geometry/vertex_vector.hpp"
#include "spatial/core/geometry/cursor.hpp"
#include "spatial/core/geometry/geometry_type.hpp"

namespace spatial {

Expand Down Expand Up @@ -51,16 +54,6 @@ struct Utils {
struct Geometry;
struct GeometryFactory;

enum class GeometryType : uint8_t {
POINT,
LINESTRING,
POLYGON,
MULTIPOINT,
MULTILINESTRING,
MULTIPOLYGON,
GEOMETRYCOLLECTION
};

class Point {
friend GeometryFactory;
VertexVector vertices;
Expand Down Expand Up @@ -263,6 +256,7 @@ struct Geometry {

private:
GeometryType type;
GeometryProperties properties;
union {
Point point;
LineString linestring;
Expand Down Expand Up @@ -296,6 +290,14 @@ struct Geometry {
return type;
}

inline GeometryProperties &Properties() {
return properties;
}

inline const GeometryProperties &Properties() const {
return properties;
}

inline Point &GetPoint() {
D_ASSERT(type == GeometryType::POINT);
return point;
Expand Down Expand Up @@ -386,29 +388,41 @@ RESULT_TYPE GeometryCollection::Aggregate(AGG agg, RESULT_TYPE zero) const {
return result;
}

struct GeometryPrefix {
uint8_t flags;
class GeometryHeader {
public:
GeometryType type;
GeometryProperties properties;
uint16_t hash;

GeometryPrefix(uint8_t flags, GeometryType type, uint16_t hash) : flags(flags), type(type), hash(hash) {
explicit GeometryHeader() : type(GeometryType::POINT), properties(GeometryProperties()), hash(0) {
}

uint32_t SerializedSize() const {
return sizeof(GeometryPrefix);
explicit GeometryHeader(GeometryType type, GeometryProperties properties, uint16_t hash)
: type(type), properties(properties), hash(hash) {
}

void Serialize(data_ptr_t &dst) const {
Store<uint8_t>(flags, dst);
dst += sizeof(uint8_t);
Store<uint8_t>((uint8_t)type, dst);
Store<GeometryType>(type, dst);
dst += sizeof(GeometryType);
Store<GeometryProperties>(properties, dst);
dst += sizeof(GeometryProperties);
Store<uint16_t>(hash, dst);
dst += sizeof(uint16_t);
}

// Deserialize a GeometryHeader from a string prefix
static GeometryHeader Get(const string_t &blob) {
auto prefix = const_data_ptr_cast(blob.GetPrefix());
auto header = Load<GeometryHeader>(prefix);
return header;
}

// Deserialize a GeometryHeader from a Cursor
static GeometryHeader Deserialize(Cursor &cursor) {
return cursor.Read<GeometryHeader>();
}
};
static_assert(sizeof(GeometryPrefix) == 4, "GeometryPrefix should be 4 bytes");
static_assert(sizeof(GeometryPrefix) == string_t::PREFIX_BYTES, "GeometryPrefix should fit in string_t prefix");
static_assert(sizeof(GeometryHeader) == 4, "GeometryPrefix should be 4 bytes");
static_assert(sizeof(GeometryHeader) == string_t::PREFIX_BYTES, "GeometryPrefix should fit in string_t prefix");
} // namespace core

} // namespace spatial
31 changes: 15 additions & 16 deletions spatial/include/spatial/core/geometry/geometry_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ namespace spatial {

namespace core {

class BinaryReader;
class BinaryWriter;
class Cursor;

struct GeometryFactory {
public:
Expand Down Expand Up @@ -60,13 +59,13 @@ struct GeometryFactory {

private:
// Serialize
void SerializePoint(data_ptr_t &ptr, const Point &point);
void SerializeLineString(data_ptr_t &ptr, const LineString &linestring);
void SerializePolygon(data_ptr_t &ptr, const Polygon &polygon);
void SerializeMultiPoint(data_ptr_t &ptr, const MultiPoint &multipoint);
void SerializeMultiLineString(data_ptr_t &ptr, const MultiLineString &multilinestring);
void SerializeMultiPolygon(data_ptr_t &ptr, const MultiPolygon &multipolygon);
void SerializeGeometryCollection(data_ptr_t &ptr, const GeometryCollection &collection);
void SerializePoint(Cursor &cursor, const Point &point);
void SerializeLineString(Cursor &cursor, const LineString &linestring);
void SerializePolygon(Cursor &cursor, const Polygon &polygon);
void SerializeMultiPoint(Cursor &cursor, const MultiPoint &multipoint);
void SerializeMultiLineString(Cursor &cursor, const MultiLineString &multilinestring);
void SerializeMultiPolygon(Cursor &cursor, const MultiPolygon &multipolygon);
void SerializeGeometryCollection(Cursor &cursor, const GeometryCollection &collection);

// Get Serialize Size
uint32_t GetSerializedSize(const Point &point);
Expand All @@ -79,13 +78,13 @@ struct GeometryFactory {
uint32_t GetSerializedSize(const Geometry &geometry);

// Deserialize
Point DeserializePoint(BinaryReader &reader);
LineString DeserializeLineString(BinaryReader &reader);
Polygon DeserializePolygon(BinaryReader &reader);
MultiPoint DeserializeMultiPoint(BinaryReader &reader);
MultiLineString DeserializeMultiLineString(BinaryReader &reader);
MultiPolygon DeserializeMultiPolygon(BinaryReader &reader);
GeometryCollection DeserializeGeometryCollection(BinaryReader &reader);
Point DeserializePoint(Cursor &reader);
LineString DeserializeLineString(Cursor &reader);
Polygon DeserializePolygon(Cursor &reader);
MultiPoint DeserializeMultiPoint(Cursor &reader);
MultiLineString DeserializeMultiLineString(Cursor &reader);
MultiPolygon DeserializeMultiPolygon(Cursor &reader);
GeometryCollection DeserializeGeometryCollection(Cursor &reader);
};

} // namespace core
Expand Down
57 changes: 57 additions & 0 deletions spatial/include/spatial/core/geometry/geometry_properties.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once
#include "spatial/common.hpp"

namespace spatial {

namespace core {

struct GeometryProperties {
private:
static constexpr const uint8_t Z = 0x01;
static constexpr const uint8_t M = 0x02;
static constexpr const uint8_t BBOX = 0x04;
static constexpr const uint8_t GEODETIC = 0x08;
static constexpr const uint8_t READONLY = 0x10;
static constexpr const uint8_t SOLID = 0x20;
uint8_t flags = 0;

public:
explicit GeometryProperties(uint8_t flags = 0) : flags(flags) {
}

inline bool HasZ() const {
return (flags & Z) != 0;
}
inline bool HasM() const {
return (flags & M) != 0;
}
inline bool HasBBox() const {
return (flags & BBOX) != 0;
}
inline bool IsGeodetic() const {
return (flags & GEODETIC) != 0;
}
inline bool IsReadOnly() const {
return (flags & READONLY) != 0;
}

inline void SetZ(bool value) {
flags = value ? (flags | Z) : (flags & ~Z);
}
inline void SetM(bool value) {
flags = value ? (flags | M) : (flags & ~M);
}
inline void SetBBox(bool value) {
flags = value ? (flags | BBOX) : (flags & ~BBOX);
}
inline void SetGeodetic(bool value) {
flags = value ? (flags | GEODETIC) : (flags & ~GEODETIC);
}
inline void SetReadOnly(bool value) {
flags = value ? (flags | READONLY) : (flags & ~READONLY);
}
};

} // namespace core

} // namespace spatial
20 changes: 20 additions & 0 deletions spatial/include/spatial/core/geometry/geometry_type.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include "spatial/common.hpp"

namespace spatial {

namespace core {

enum class GeometryType : uint8_t {
POINT = 0,
LINESTRING,
POLYGON,
MULTIPOINT,
MULTILINESTRING,
MULTIPOLYGON,
GEOMETRYCOLLECTION
};

} // namespace core

} // namespace spatial
Loading

0 comments on commit a99134f

Please sign in to comment.