feat(plugin-postgresql): render PostGIS geometry/geography as EWKT (#1458)#1467
feat(plugin-postgresql): render PostGIS geometry/geography as EWKT (#1458)#1467shubhank-saxena wants to merge 9 commits into
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db02badf8a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
I have read the CLA Document and I hereby sign the CLA. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63524583c5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Code review: PostGIS EWKT renderingTwo automated reviews ran against this branch: a repo-wide review and a Codex diff-scoped review. Findings are merged and deduplicated below. The feature is well-scoped and well-tested; the careful SQL-aware tokenizer (handles Must fix before merge
Follow-ups (fine to defer)
What is goodOID probing at connect, preserving the original |
|
Thanks for the thorough review. All four must-fix items are addressed in 1 + 2 — double execution and parameterized queries (
|
…rom PostGIS rewrite
…-running the query
4f1ee84 to
90f1a8f
Compare
|
Rebased onto the latest main to clear a CHANGELOG conflict (the sidebar-tree and password-source entries collided with the PostGIS line). Only the changelog needed resolving. One thing to note: the rebase rewrote the commit hashes, so the SHAs I referenced in the review replies above point at the old pre-rebase commits. The code is all still here, just under new hashes. Nothing was dropped. |
Summary
geometryandgeographycolumns now render as EWKT (SRID=4326;POINT(-73 40.7237)) in the data grid instead of raw EWKB hex. We probepg_typefor the dynamic PostGIS OIDs once at connect time, detect spatial columns in the result metadata, and convert the already-fetched EWKB-hex values to EWKT.SELECT ST_AsEWKT(t::geometry) FROM unnest($1::text[]) WITH ORDINALITY AS x(t, ord) ORDER BY ord. The hex values are passed as one boundtext[]parameter, order preserved viaWITH ORDINALITY; NULL stays NULL andPOINT EMPTYround-trips. If the conversion query fails it logs and keeps the raw hex (no error surfaced). Because nothing re-runs the user statement, side effects can't double-apply and the parameterized path converts identically.textafter conversion, so we overridecolumnTypeNamesback to the originalgeometry/geography. The data grid still shows the correct type, and a future edit-back PR has the signal it needs to wrapUPDATE ... SET geom = ST_GeomFromEWKT($1)with SRID injection. No PluginKit ABI change.Scope and structure
All changes live inside
Plugins/PostgreSQLDriverPlugin/. NoTableProPluginKitchange, nocurrentPluginKitVersionbump:PostGISSpatialRewrite.swiftholds the pure helpers (probe query, the two conversion queries, and the array-literal builder) asenum PostGISSpatialRewrite.PostgreSQLPluginDriver.connect()sets acore.onPostConnecthook that refreshescatalogPresenceandpostgisOids.LibPQDriverCore.connect()invokes the hook, and sincereconnect()routes throughconnect(), transient reconnects re-probe and the OID map is never left stale.LibPQPluginConnection.fetchResults(from:)parses the result, then if the cached OID map flags any spatial columns it converts those columns' fetched hex values via a boundtext[]parameter.PQclearfor the original result is indeferinexecuteQuerySyncso cancellation no longer leaks the result handle.executeQuerySyncandexecuteParameterizedQuerySyncgo through the same conversion, so parameterized queries (SELECT geom FROM places WHERE id = $1) render EWKT too.Out of scope (follow-up issues)
geometry[]/geography[]array support,raster,box2d,box3d.ST_GeomFromEWKTwith SRID injection.streamQuerysingle-row mode); only the bufferedfetchResultspath is wired.Reconnect
LibPQDriverCoregained anonPostConnecthook invoked at the end ofconnect().reconnect()routes throughconnect(), so a transient connection loss re-runs the PostGIS OID probe (and catalog-presence probe) and the cache is never left stale. This closes the gap an earlier revision documented as pre-existing.Tests
Pure Swift Testing suite at
TableProTests/Plugins/PostGISSpatialRewriteTests.swift. The helper source is mirrored intoTableProTests/PluginTestSources/PostGISSpatialRewrite.swiftas a symlink, matching the other plugin mirrors. Coverage:conversionQuery(forTypeName:):geometry/geographymap to the right query, unknown type names return nil, and the queries applyST_AsEWKTover a single boundtext[]parameter (never the user statement).arrayLiteral(from:): single / multiple / empty inputs, order preservation,nilbecomes an unquotedNULLelement, all-NULL arrays, and embedded"/\escaping.The earlier safe-to-wrap tokenizer (and its tests) is removed: with no re-execution there's nothing to gate, so the predicate stack that guarded the second
PQexecis gone.Verified end-to-end
Tested locally against PostgreSQL 18 + PostGIS (Kartoza image,
geometryandgeographytypes). Schema used:places(geometry(Point, 4326)):pointrenders as EWKT, NULL stays NULL,POINT EMPTYround-trips:shapes(geometry(Polygon, 4326)): polygons render as EWKT:checkpoints(geography(Point, 4326)): confirms thegeographytype is converted too, not justgeometry:The parameterized path (item 2 from the review) was re-verified live:
SELECT * FROM places WHERE id = $1now renders EWKT, where it previously returned raw hex.Still worth a maintainer's eye on a non-PostGIS database: opening any PostgreSQL connection without PostGIS installed should be a no-op (the probe returns empty, and the conversion path stays dormant). I didn't have a Postgres-without-PostGIS container handy to demonstrate, but the code path is the empty-map guard in
fetchResultsand the probe'scatchblock inprobePostgisOids().