Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cardinality estimation, replacement scans, misc fixes and breaking changes to GEOMETRY format. #124

Merged
merged 8 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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