From e72e36dde673c8f474edc0934a28205b9f527436 Mon Sep 17 00:00:00 2001 From: Robin Tang Date: Mon, 12 Feb 2024 12:45:27 -0700 Subject: [PATCH] [Postgis] Support Geography (#333) --- lib/cdc/util/geometry.go | 5 ++--- lib/cdc/util/parse.go | 2 +- lib/cdc/util/parse_test.go | 33 +++++++++++++++++++++++++++++++++ lib/debezium/schema.go | 2 +- lib/debezium/types.go | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/cdc/util/geometry.go b/lib/cdc/util/geometry.go index c173aaeba..1f3572374 100644 --- a/lib/cdc/util/geometry.go +++ b/lib/cdc/util/geometry.go @@ -5,9 +5,8 @@ import ( "encoding/json" "fmt" + "github.com/twpayne/go-geom/encoding/ewkb" "github.com/twpayne/go-geom/encoding/geojson" - - "github.com/twpayne/go-geom/encoding/wkb" ) type GeoJSON struct { @@ -81,7 +80,7 @@ func parseGeometry(value interface{}) (string, error) { return "", fmt.Errorf("error decoding base64: %w", err) } - geom, err := wkb.Unmarshal(wkbBytes) + geom, err := ewkb.Unmarshal(wkbBytes) if err != nil { return "", fmt.Errorf("error unmarshalling WKB bytes: %w", err) } diff --git a/lib/cdc/util/parse.go b/lib/cdc/util/parse.go index 1f43ca841..38c2e6d7d 100644 --- a/lib/cdc/util/parse.go +++ b/lib/cdc/util/parse.go @@ -34,7 +34,7 @@ func parseField(field debezium.Field, value interface{}) interface{} { if err == nil { return valString } - case debezium.GeometryType: + case debezium.GeometryType, debezium.GeographyType: geometryString, err := parseGeometry(value) if err == nil { return geometryString diff --git a/lib/cdc/util/parse_test.go b/lib/cdc/util/parse_test.go index b262bbc0b..4ed6e6df6 100644 --- a/lib/cdc/util/parse_test.go +++ b/lib/cdc/util/parse_test.go @@ -90,6 +90,39 @@ func TestParseField(t *testing.T) { expectedValue: "123.45", expectedDecimal: true, }, + { + name: "geometry (no srid)", + field: debezium.Field{ + DebeziumType: string(debezium.GeometryType), + }, + value: map[string]interface{}{ + "srid": nil, + "wkb": "AQEAAAAAAAAAAADwPwAAAAAAABRA", + }, + expectedValue: `{"type":"Feature","geometry":{"type":"Point","coordinates":[1,5]},"properties":null}`, + }, + { + name: "geometry (w/ srid)", + field: debezium.Field{ + DebeziumType: string(debezium.GeometryType), + }, + value: map[string]interface{}{ + "srid": 4326, + "wkb": "AQEAACDmEAAAAAAAAAAA8D8AAAAAAAAYQA==", + }, + expectedValue: `{"type":"Feature","geometry":{"type":"Point","coordinates":[1,6]},"properties":null}`, + }, + { + name: "geography (w/ srid)", + field: debezium.Field{ + DebeziumType: string(debezium.GeographyType), + }, + value: map[string]interface{}{ + "srid": 4326, + "wkb": "AQEAACDmEAAAAAAAAADAXkAAAAAAAIBDwA==", + }, + expectedValue: `{"type":"Feature","geometry":{"type":"Point","coordinates":[123,-39]},"properties":null}`, + }, } for _, testCase := range testCases { diff --git a/lib/debezium/schema.go b/lib/debezium/schema.go index 60cdef2c7..9c0afe47e 100644 --- a/lib/debezium/schema.go +++ b/lib/debezium/schema.go @@ -86,7 +86,7 @@ func (f Field) ToKindDetails() typing.KindDetails { return typing.NewKindDetailsFromTemplate(typing.ETime, ext.DateKindType) case string(Time), string(TimeMicro), string(TimeKafkaConnect), string(TimeWithTimezone): return typing.NewKindDetailsFromTemplate(typing.ETime, ext.TimeKindType) - case string(JSON), string(GeometryPointType), string(GeometryType): + case string(JSON), string(GeometryPointType), string(GeometryType), string(GeographyType): return typing.Struct case string(KafkaDecimalType): scaleAndPrecision, err := f.GetScaleAndPrecision() diff --git a/lib/debezium/types.go b/lib/debezium/types.go index 775586414..3cac80654 100644 --- a/lib/debezium/types.go +++ b/lib/debezium/types.go @@ -36,6 +36,7 @@ const ( // PostGIS data types GeometryPointType SupportedDebeziumType = "io.debezium.data.geometry.Point" GeometryType SupportedDebeziumType = "io.debezium.data.geometry.Geometry" + GeographyType SupportedDebeziumType = "io.debezium.data.geometry.Geography" KafkaDecimalPrecisionKey = "connect.decimal.precision" ) @@ -54,6 +55,7 @@ var typesThatRequireTypeCasting = []SupportedDebeziumType{ JSON, GeometryPointType, GeometryType, + GeographyType, } func RequiresSpecialTypeCasting(typeLabel string) (bool, SupportedDebeziumType) {