Search Shortcut cmd + k | ctrl + k
duck_geoarrow

DuckDB extension for converting GEOMETRY/WKB to and from GeoArrow native encodings, powered by geoarrow-c.

Maintainer(s): am2222

Compatibility Matrix

This table covers all DuckDB releases that have not reached end-of-life, including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.

Platform 1.4.4 1.4.5 1.5.5 1.5.6 2.0.0
Linux AMD64
Linux ARM64
macOS AMD64
macOS ARM64
Windows AMD64
Windows ARM64
WebAssembly

Installing and Loading

INSTALL duck_geoarrow FROM community;
LOAD duck_geoarrow;

Example

INSTALL duck_geoarrow FROM community;
LOAD duck_geoarrow;

-- Read a GeoArrow-encoded GeoParquet file written by geopandas. A geometry column
-- written with encoding="polygon" arrives as STRUCT(x DOUBLE, y DOUBLE)[][].
SELECT county_name, st_geomfromgeoarrow('polygon', geometry) AS geom
FROM read_parquet('county_regions.parquet');

-- Write GEOMETRY back out as a GeoArrow native encoding
COPY (SELECT county_name, st_asgeoarrowpolygon(geom) AS geometry FROM counties)
TO 'counties.parquet';

-- GEOMETRY -> GeoArrow native encoding, one function per geometry type
SELECT st_asgeoarrowpoint('POINT(30 10)'::GEOMETRY);
-- {'x': 30.0, 'y': 10.0}

SELECT st_asgeoarrowpolygon('POLYGON((0 0, 1 0, 1 1, 0 0))'::GEOMETRY);
-- [[{'x': 0.0, 'y': 0.0}, {'x': 1.0, 'y': 0.0}, {'x': 1.0, 'y': 1.0}, {'x': 0.0, 'y': 0.0}]]

-- GeoArrow native encoding -> GEOMETRY; the type name disambiguates colliding shapes
SELECT st_geomfromgeoarrow('linestring', [{'x': 0.0, 'y': 0.0}, {'x': 1.0, 'y': 1.0}]),
       st_geomfromgeoarrow('multipoint', [{'x': 0.0, 'y': 0.0}, {'x': 1.0, 'y': 1.0}]);
-- LINESTRING (0 0, 1 1)  |  MULTIPOINT (0 0, 1 1)

-- Z and M: reading infers them from the value, writing takes them as an argument
SELECT st_geomfromgeoarrow('point', {'x': 1.0, 'y': 2.0, 'z': 3.0});
-- POINT Z (1 2 3)
SELECT st_asgeoarrowpoint('POINT Z (1 2 3)'::GEOMETRY, 'xyz');
-- {'x': 1.0, 'y': 2.0, 'z': 3.0}

-- Flat struct form: one struct per geometry with parallel coordinate arrays
SELECT st_asgeoarrow('POINT(30 10)'::GEOMETRY);
-- {'geometry_type': 1, 'xs': [30.0], 'ys': [10.0], 'ring_offsets': [], 'geom_offsets': []}

SELECT duck_geoarrow_version();

About duck_geoarrow

duck_geoarrow converts between DuckDB GEOMETRY (or WKB BLOB) and the GeoArrow coordinate encodings, powered by the geoarrow-c library.

Two GeoArrow representations are supported:

  • Native encodings: nested lists of separated coordinates (STRUCT(x, y)[][] for a Polygon, and so on). This is what GeoParquet, geoarrow-pyarrow and geopandas produce, so it is the one to reach for when reading or writing files.
  • A flat struct: one struct per geometry holding parallel coordinate and offset arrays (geometry_type, xs, ys, optional zs / ms, ring_offsets, geom_offsets). Convenient for hand-building geometries in SQL.

Both directions support XY, XYZ, XYM and XYZM.

Functions

Function Direction Notes
st_geomfromgeoarrow(type, value) GeoArrow → GEOMETRY Generic: any native encoding, type given as a string
st_geomfromgeoarrow<type>(value) GeoArrow → GEOMETRY One name per geometry type
st_geomfromgeoarrow(struct) GeoArrow → GEOMETRY Flat struct form
st_asgeoarrow<type>(geom[, dims]) GEOMETRY → GeoArrow Native encoding for one geometry type
st_asgeoarrow(geom[, dims]) GEOMETRY → GeoArrow Flat struct form
duck_geoarrow_version() — Extension and geoarrow-c versions

<type> is one of point, linestring, polygon, multipoint, multilinestring or multipolygon. All conversion functions accept either GEOMETRY or a BLOB holding WKB.

Native encodings

Geometry type DuckDB type GEOMETRY → GeoArrow GeoArrow → GEOMETRY
Point STRUCT(x, y) st_asgeoarrowpoint st_geomfromgeoarrowpoint
LineString STRUCT(x, y)[] st_asgeoarrowlinestring st_geomfromgeoarrowlinestring
Polygon STRUCT(x, y)[][] st_asgeoarrowpolygon st_geomfromgeoarrowpolygon
MultiPoint STRUCT(x, y)[] st_asgeoarrowmultipoint st_geomfromgeoarrowmultipoint
MultiLineString STRUCT(x, y)[][] st_asgeoarrowmultilinestring st_geomfromgeoarrowmultilinestring
MultiPolygon STRUCT(x, y)[][][] st_asgeoarrowmultipolygon st_geomfromgeoarrowmultipolygon

These are the separated-coordinate layouts from the GeoArrow specification, so the values interoperate directly with other GeoArrow implementations.

The generic st_geomfromgeoarrow(type, value) exists because the DuckDB types collide: LineString and MultiPoint are both STRUCT(x, y)[], and Polygon and MultiLineString are both STRUCT(x, y)[][]. The type name is resolved at bind time, so an unknown type or a mismatched shape is a binder error rather than a runtime one. Names are case- and separator-insensitive and may carry a z, m or zm suffix.

Z and M dimensions

GeoArrow carries extra ordinates in the coordinate struct (STRUCT(x, y, z), STRUCT(x, y, m), STRUCT(x, y, z, m)), and the flat struct gains matching zs / ms lists. Reading needs no extra argument since the value's type says which ordinates are present. Writing takes the dimensions as an argument (xy, xyz, xym, xyzm) because a SQL function's return type must be fixed before any data is seen; omitting it means xy. Dropping ordinates is allowed, inventing them is not: asking for xyz from a 2D geometry raises an error rather than filling in NaNs.

Notes

  • NULL input produces NULL output. A NULL inside a list (a null ring, say) is read as an empty ring, since the GeoArrow native encoding only carries validity at the top level.
  • GeometryCollection, and the geoarrow.box and interleaved-coordinate encodings, are not supported.

Added Functions

function_name function_type description comment examples
duck_geoarrow_version scalar Returns the version of the duck_geoarrow extension together with the version of the bundled geoarrow-c library. NULL [duck_geoarrow_version()]
st_asgeoarrow scalar Converts a GEOMETRY or WKB BLOB to the flat GeoArrow encoding, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'); dropping ordinates the geometry carries is allowed, asking for ones it does not have is an error. NULL [st_asgeoarrow('LINESTRING ZM (0 0 1 5, 1 1 2 6)'::GEOMETRY, 'xyzm')]
st_asgeoarrow scalar Converts a GEOMETRY or WKB BLOB to the flat GeoArrow encoding: one STRUCT per geometry holding a geometry_type code alongside parallel coordinate (xs, ys) and offset (ring_offsets, geom_offsets) arrays, with XY coordinates. NULL [st_asgeoarrow('POINT(30 10)'::GEOMETRY)]
st_asgeoarrowlinestring scalar Converts a LineString GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)[]), erroring if the input is not a LineString. NULL [st_asgeoarrowlinestring('LINESTRING (0 0, 4 0)'::GEOMETRY)]
st_asgeoarrowlinestring scalar Converts a LineString GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowlinestring('LINESTRING Z (0 0 1, 4 0 2)'::GEOMETRY, 'xyz')]
st_asgeoarrowmultilinestring scalar Converts a MultiLineString GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)[][]), erroring if the input is not a MultiLineString. NULL [st_asgeoarrowmultilinestring('MULTILINESTRING ((0 0, 4 0), (4 4, 8 8))'::GEOMETRY)]
st_asgeoarrowmultilinestring scalar Converts a MultiLineString GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowmultilinestring('MULTILINESTRING Z ((0 0 1, 4 0 2), (4 4 3, 8 8 4))'::GEOMETRY, 'xyz')]
st_asgeoarrowmultipoint scalar Converts a MultiPoint GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)[]), erroring if the input is not a MultiPoint. NULL [st_asgeoarrowmultipoint('MULTIPOINT (0 0, 4 0)'::GEOMETRY)]
st_asgeoarrowmultipoint scalar Converts a MultiPoint GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowmultipoint('MULTIPOINT Z (0 0 1, 4 0 2)'::GEOMETRY, 'xyz')]
st_asgeoarrowmultipolygon scalar Converts a MultiPolygon GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)[][][]), erroring if the input is not a MultiPolygon. NULL [st_asgeoarrowmultipolygon('MULTIPOLYGON (((0 0, 4 0, 4 4, 0 0)))'::GEOMETRY)]
st_asgeoarrowmultipolygon scalar Converts a MultiPolygon GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowmultipolygon('MULTIPOLYGON Z (((0 0 1, 4 0 2, 4 4 3, 0 0 1)))'::GEOMETRY, 'xyz')]
st_asgeoarrowpoint scalar Converts a Point GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)), erroring if the input is not a Point. NULL [st_asgeoarrowpoint('POINT (30 10)'::GEOMETRY)]
st_asgeoarrowpoint scalar Converts a Point GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowpoint('POINT Z (0 0 1)'::GEOMETRY, 'xyz')]
st_asgeoarrowpolygon scalar Converts a Polygon GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type (STRUCT(x DOUBLE, y DOUBLE)[][]), erroring if the input is not a Polygon. NULL [st_asgeoarrowpolygon('POLYGON ((0 0, 4 0, 4 4, 0 0))'::GEOMETRY)]
st_asgeoarrowpolygon scalar Converts a Polygon GEOMETRY or WKB BLOB into the GeoArrow native encoding for that geometry type, writing the ordinates named by dims ('xy', 'xyz', 'xym' or 'xyzm'). NULL [st_asgeoarrowpolygon('POLYGON Z ((0 0 1, 4 0 2, 4 4 3, 0 0 1))'::GEOMETRY, 'xyz')]
st_geomfromgeoarrow scalar Converts a flat GeoArrow struct back into a GEOMETRY; fields are matched by name, so their order in the struct does not matter, and the zs / ms lists are read when present. NULL [st_geomfromgeoarrow({'geometry_type': 2::UTINYINT, 'xs': [0.0, 1.0, 2.0], 'ys': [0.0, 1.0, 2.0], 'ring_offsets': []::INTEGER[], 'geom_offsets': []::INTEGER[]})]
st_geomfromgeoarrow scalar Converts any GeoArrow native encoding into a GEOMETRY, with geometry_type naming the type as a constant string ('point', 'linestring', 'polygon', 'multipoint', 'multilinestring' or 'multipolygon', optionally with a z, m or zm suffix); the name is required because LineString and MultiPoint, and Polygon and MultiLineString, share one DuckDB type. NULL [st_geomfromgeoarrow('linestring', [{'x': 0.0, 'y': 0.0}, {'x': 1.0, 'y': 1.0}])]
st_geomfromgeoarrowlinestring scalar Converts a GeoArrow native LineString encoding (STRUCT(x DOUBLE, y DOUBLE)[], or its XYZ / XYM / XYZM equivalent) into a LineString GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowlinestring([{'x': 0.0, 'y': 0.0}, {'x': 4.0, 'y': 0.0}])]
st_geomfromgeoarrowmultilinestring scalar Converts a GeoArrow native MultiLineString encoding (STRUCT(x DOUBLE, y DOUBLE)[][], or its XYZ / XYM / XYZM equivalent) into a MultiLineString GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowmultilinestring([[{'x': 0.0, 'y': 0.0}, {'x': 4.0, 'y': 0.0}], [{'x': 4.0, 'y': 4.0}, {'x': 8.0, 'y': 8.0}]])]
st_geomfromgeoarrowmultipoint scalar Converts a GeoArrow native MultiPoint encoding (STRUCT(x DOUBLE, y DOUBLE)[], or its XYZ / XYM / XYZM equivalent) into a MultiPoint GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowmultipoint([{'x': 0.0, 'y': 0.0}, {'x': 4.0, 'y': 0.0}])]
st_geomfromgeoarrowmultipolygon scalar Converts a GeoArrow native MultiPolygon encoding (STRUCT(x DOUBLE, y DOUBLE)[][][], or its XYZ / XYM / XYZM equivalent) into a MultiPolygon GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowmultipolygon([[[{'x': 0.0, 'y': 0.0}, {'x': 4.0, 'y': 0.0}, {'x': 4.0, 'y': 4.0}, {'x': 0.0, 'y': 0.0}]]])]
st_geomfromgeoarrowpoint scalar Converts a GeoArrow native Point encoding (STRUCT(x DOUBLE, y DOUBLE), or its XYZ / XYM / XYZM equivalent) into a Point GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowpoint({'x': 30.0, 'y': 10.0})]
st_geomfromgeoarrowpolygon scalar Converts a GeoArrow native Polygon encoding (STRUCT(x DOUBLE, y DOUBLE)[][], or its XYZ / XYM / XYZM equivalent) into a Polygon GEOMETRY; the value's own type says which ordinates are present, so no dimensions argument is needed. NULL [st_geomfromgeoarrowpolygon([[{'x': 0.0, 'y': 0.0}, {'x': 4.0, 'y': 0.0}, {'x': 4.0, 'y': 4.0}, {'x': 0.0, 'y': 0.0}]])]

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

name description input_type scope aliases typed_value
temp_directory Set the directory to which temporary files are written. VARCHAR GLOBAL [] post.db.tmp