Skip to content

Native PostGIS Support for Prisma#7685

Open
lh0x00 wants to merge 3 commits intoprisma:mainfrom
lh0x00:feature/support-postgis-features
Open

Native PostGIS Support for Prisma#7685
lh0x00 wants to merge 3 commits intoprisma:mainfrom
lh0x00:feature/support-postgis-features

Conversation

@lh0x00
Copy link
Contributor

@lh0x00 lh0x00 commented Mar 21, 2026

See full features at prisma/prisma#29365

Summary by CodeRabbit

  • Documentation
    • Enhanced CRUD docs with a new geometry-based filtering example and updated link to geometry-field guidance.
    • Published a comprehensive "Working with geometry fields" guide covering PostGIS setup, geometry types, read/write examples, spatial predicates (near/within/intersects), distance ordering, null-handling, and migration/optimization notes.
    • Added PostGIS extension docs with Prisma schema examples, spatial query usage, and updated frontmatter metadata quoting.

@vercel
Copy link

vercel bot commented Mar 21, 2026

@lh0x00 is attempting to deploy a commit to the Prisma Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 21, 2026

Walkthrough

Documentation additions and edits introducing Prisma's native Geometry(...) support for PostgreSQL/PostGIS: a new geometry-fields guide, CRUD spatial filtering example, and PostGIS notes in the PostgreSQL extensions page. Metadata quoting was standardized in two frontmatter files. (Docs-only changes.)

Changes

Cohort / File(s) Summary
New Geometry Field Documentation
apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx
New comprehensive guide for PostGIS + Prisma: prerequisites, Geometry(...) schema syntax (types, SRID, optional), GeoJSON coordinate expectations, read/write examples, spatial filters (near, within, intersects), distanceFrom ordering, TypeScript types, spatial index/migration tips, and common considerations.
CRUD docs update
apps/docs/content/docs/orm/prisma-client/queries/crud.mdx
Added a geometry-based read/filter example using where.position.near (with point and maxDistance), extended "See also" to link geometry-fields docs, and adjusted frontmatter quoting.
PostgreSQL extensions docs update
apps/docs/content/docs/orm/prisma-schema/postgresql-extensions.mdx
Standardized frontmatter quoting and added a PostGIS section: CREATE EXTENSION guidance, Prisma Geometry examples (SRID 4326, optional fields), supported shapes, spatial query examples (near, within, distanceFrom), and link to geometry-fields guide.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding native PostGIS support documentation for Prisma across multiple documentation pages.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx`:
- Around line 505-547: The query currently checks deliveryZone.boundary.within a
tiny polygon around customerLocation which is reversed; change the filter in
prisma.deliveryZone.findMany to check for polygons that contain or intersect the
customer point (e.g., use boundary.intersects with a Point built from
customerLocation, or run a raw SQL PostGIS call using ST_Contains/ST_Within with
the Point and the boundary in the correct order) so that you search for zones
that contain the customer's address (references: DeliveryZone.boundary,
prisma.deliveryZone.findMany, customerLocation, availableZones, canDeliver).
- Around line 837-843: The link to
"/v6/orm/prisma-client/queries/filtering-and-sorting" in
working-with-geometry-fields.mdx is inconsistent with the other versionless
cross-references; either migrate or copy the filtering-and-sorting content into
the current docs and update the link to
"/orm/prisma-client/queries/filtering-and-sorting", or if migration isn’t
possible add a brief clarifying note beside the current link (and adjust the
link text) stating it is v6-only and why; update the link string and surrounding
text in working-with-geometry-fields.mdx to ensure consistency with the other
links (e.g., the CRUD and PostgreSQL extensions references).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a1ae4728-4ff7-42e4-9c2d-09df0362adcd

📥 Commits

Reviewing files that changed from the base of the PR and between 1a02c1b and 077b643.

📒 Files selected for processing (3)
  • apps/docs/content/docs/orm/prisma-client/queries/crud.mdx
  • apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx
  • apps/docs/content/docs/orm/prisma-schema/postgresql-extensions.mdx

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx (1)

909-909: ⚠️ Potential issue | 🟡 Minor

Unify the cross-version “Filtering and sorting” reference.

Line 909 links to /v6/... while adjacent links target current-version docs, which creates a version-jump in this page’s navigation flow. Please either migrate/update that target to the current docs path or explicitly label the link as v6-only in the link text.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx`
at line 909, The link "[Filtering and
sorting](/v6/orm/prisma-client/queries/filtering-and-sorting)" creates an
unexpected version jump on this page; update that anchor so it points to the
current-version docs path (replace
/v6/orm/prisma-client/queries/filtering-and-sorting with the equivalent
current-version URL) or, if the v6 content is intentionally referenced, change
the link text to explicitly indicate "Filtering and sorting (v6)" so users know
it targets v6; locate the anchor in working-with-geometry-fields.mdx and apply
one of these two fixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx`:
- Line 909: The link "[Filtering and
sorting](/v6/orm/prisma-client/queries/filtering-and-sorting)" creates an
unexpected version jump on this page; update that anchor so it points to the
current-version docs path (replace
/v6/orm/prisma-client/queries/filtering-and-sorting with the equivalent
current-version URL) or, if the v6 content is intentionally referenced, change
the link text to explicitly indicate "Filtering and sorting (v6)" so users know
it targets v6; locate the anchor in working-with-geometry-fields.mdx and apply
one of these two fixes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5d78e5d8-7de9-4cb1-b74f-dc4a29132df8

📥 Commits

Reviewing files that changed from the base of the PR and between 077b643 and cda16fd.

📒 Files selected for processing (1)
  • apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx

@BrenoRev
Copy link

While testing the spatial queries locally, I ran into a query planner issue on PostgreSQL 16: the planner underestimates the row count returned by the spatial CTE (estimates rows=1, actual can be 2000+), causing it to choose Nested Loop over Hash Join — which resulted in ~3.9s response time vs ~87ms.

To fix this, I wrapped all spatial queries in a Higher-Order Function (executeNearbyQuery) that enforces SET LOCAL enable_nestloop = off within the transaction scope before executing the query:

/**
 * Executes a spatial query with SET LOCAL enable_nestloop = off.
 *
 * The PostgreSQL 16 planner underestimates the number of rows returned by the spatial CTE
 * (estimates rows=1, actual can be 2000+), choosing Nested Loop instead of Hash Join.
 * Nested Loop with 2000+ iterations causes severe degradation (3.9s vs 87ms).
 *
 * Accepts PrismaClient or TransactionClient:
 * - PrismaClient: creates a transaction internally (SET LOCAL is reverted at the end)
 * - TransactionClient: uses the existing transaction and manually reverts after the query
 *
 * PostgreSQL 17+: this function may be removed. PG17 introduced statistics propagation
 * for materialized CTEs, fixing the row estimate and allowing the planner to choose
 * Hash Join automatically without SET LOCAL.
 */
export async function executeNearbyQuery<T>(
  prisma: PrismaClient | PrismaInterfaces.TransactionClient,
  query: string,
): Promise<T[]> {
  if ('$transaction' in prisma) {
    return (prisma as PrismaClient).$transaction(async (tx) => {
      await tx.$queryRaw(PrismaInterfaces.sql`SET LOCAL enable_nestloop = off`);
      return tx.$queryRaw<T[]>(
        PrismaInterfaces.sql`${PrismaInterfaces.raw(query)}`,
      );
    });
  }

  await prisma.$queryRaw(PrismaInterfaces.sql`SET LOCAL enable_nestloop = off`);
  const results = await prisma.$queryRaw<T[]>(
    PrismaInterfaces.sql`${PrismaInterfaces.raw(query)}`,
  );
  await prisma.$queryRaw(PrismaInterfaces.sql`SET LOCAL enable_nestloop = on`);
  return results;
}

In the index of

@@index([geometry], map: "IDX_ADDRESS_GEOMETRY", type: Gist)
@@index([geometry_mercator], map: "IDX_ADDRESS_GEOMETRY_MERCATOR", type: Gist)

These indexes are what enable the spatial candidate scan in the CTE. The nestloop workaround is a separate concern — it corrects the join strategy after the index scan, when PG16 misjudges the CTE row count downstream.

Should the Docs reference these indexes to make that relationship explicit, or is that coupling that doesn't belong there?

@vercel
Copy link

vercel bot commented Mar 22, 2026

Deployment failed with the following error:

The provided GitHub repository does not contain the requested branch or commit reference. Please ensure the repository is not empty.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx`:
- Around line 799-804: The example uses an inconsistent shape for the spatial
filter: change the `intersects` value to the same shape used elsewhere by
wrapping the GeoJSON into a `geometry` object; locate the `boundary` object
which currently has `intersects: { type: 'Point', coordinates: userLocation }`
and replace it with `intersects: { geometry: { type: 'Point', coordinates:
userLocation } }` so the client input matches the other examples and the
expected PostgreSQL workaround shape.
- Around line 785-788: Update the shorthand examples to match the documented API
shape: change the orderBy block using position.distanceFrom to pass an object
with a point and direction (i.e., distanceFrom: { point: [...], direction: "asc"
| "desc" }) instead of distanceFrom: userLocation, and for the intersects usage
wrap the geometry payload (i.e., intersects: { geometry: { type, coordinates }
}) to mirror the canonical examples; modify the examples in the workaround
section that reference orderBy.position.distanceFrom and any intersects
occurrences so they use these explicit object shapes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b06ee74d-4b76-46d3-a07b-1a83eacadf2a

📥 Commits

Reviewing files that changed from the base of the PR and between cda16fd and 70a4ab4.

📒 Files selected for processing (1)
  • apps/docs/content/docs/orm/prisma-client/special-fields-and-types/working-with-geometry-fields.mdx

@lh0x00
Copy link
Contributor Author

lh0x00 commented Mar 22, 2026

Thanks @BrenoRev for mentioning it, it's extremely helpful. I've updated the docs and exported the function to support it; you can see it at prisma/prisma#29365 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants