GEOGRAPHY and spatial¶
Status: shipped.
The emulator implements BigQuery's GEOGRAPHY type by backing it with
DuckDB's spatial extension (GEOMETRY). The extension is required:
the emulator fails fast at startup if it can't be loaded — see
ADR 0019 for the rationale.
Quick example¶
from google.cloud import bigquery
client = bigquery.Client(...) # pointing at bqemulator
# 1. Create a table with a GEOGRAPHY column.
schema = [
bigquery.SchemaField("id", "INT64", mode="REQUIRED"),
bigquery.SchemaField("loc", "GEOGRAPHY"),
]
client.create_table(bigquery.Table("p.ds.places", schema=schema))
# 2. Insert WKT strings — the emulator converts them to WKB and stores
# them in DuckDB's GEOMETRY column.
client.insert_rows_json(
"p.ds.places",
[
{"id": 1, "loc": "POINT(-73.985 40.758)"}, # Times Square
{"id": 2, "loc": "POINT(-73.975 40.785)"}, # Central Park
{"id": 3, "loc": "POINT(-122.41 37.77)"}, # San Francisco
],
)
# 3. Spatial query: which points are within 5km of Times Square?
job = client.query(
"SELECT id FROM `p.ds.places` "
"WHERE ST_DWITHIN(loc, ST_GEOGFROMTEXT('POINT(-73.985 40.758)'), 5000) "
"ORDER BY id",
)
for row in job.result():
print(row.id)
Constructors¶
| BigQuery | DuckDB equivalent | Notes |
|---|---|---|
ST_GEOGFROMTEXT(wkt) |
ST_GeomFromText(wkt) |
WKT input |
ST_GEOGFROMGEOJSON(j) |
ST_GeomFromGeoJSON(j) |
GeoJSON input |
ST_GEOGFROMWKB(b) |
ST_GeomFromHEXWKB(hex(b)) |
Raw WKB bytes → hex inside DuckDB |
ST_GEOGPOINT(lon, lat) |
ST_Point(lon, lat) |
(longitude, latitude) order |
Predicates and measurements¶
ST_DWITHIN, ST_INTERSECTS, ST_CONTAINS, ST_WITHIN, ST_DISTANCE,
ST_AREA, ST_PERIMETER, ST_LENGTH, ST_X, ST_Y, ST_GEOMETRYTYPE,
ST_DIMENSION, ST_ISEMPTY, ST_NUMPOINTS / ST_NPOINTS,
ST_BOUNDINGBOX (aliased to ST_Envelope), ST_ISCOLLECTION all map
to their DuckDB counterparts (or, for the renamed/derived ones, to
equivalent expressions). See
reference/sql-function-mapping.md
for the complete table.
Set operations¶
ST_UNION, ST_INTERSECTION, ST_BUFFER, ST_CENTROID, ST_CONVEXHULL,
ST_DUMP round-trip through DuckDB unchanged.
Output¶
ST_ASTEXT(g) returns the canonical WKT representation; ST_ASGEOJSON(g)
returns GeoJSON. When a GEOGRAPHY column is projected directly in a
result set, the emulator converts the stored WKB to WKT on the way to
the REST wire format — clients see strings like "POINT (1 2)".
Limitations¶
- DuckDB's
GEOMETRYis planar (Cartesian); BigQuery'sGEOGRAPHYis spheroidal. Distance / area / perimeter values agree at small scales but diverge at continental scales. Use the emulator for unit tests and CI flow validation; rely on real BigQuery for production geo-analytics accuracy. ADR 0019 records the trade-off. ST_GeogFromWKBrequires the WKB input bytes to be valid; an invalid payload surfaces as a DuckDB error.