Skip to content

Consider porting some Postgre-only query builder features #6334

@mercmobily

Description

@mercmobily

Some PostgreSQL-only features could be supported in other dialects. This comes from seeing how many "Postgres-only" features are there in the documentation.

Why this came up

  • Postgres has many features, and Knex has a lot of PG-only APIs.
  • Some of these features might be “portable enough” to map to other SQL engines.
  • The big question: do we want "mostly the same" behaviour across DBs, or keep these as PG-only?

This is a quick summary that might help making a decision. Consider that we don't even have to implement all of them.

Features that might be portable (with caveats)

  1. .updateFrom()
  • Could map to:
    • MySQL/MariaDB: UPDATE ... JOIN ...
    • MSSQL/Oracle: UPDATE ... FROM ...
  • Caveats:
    • If a join matches multiple rows, some DBs may update a row more than once.
    • Alias and column rules differ between engines.
    • You often need extra table prefixes to avoid ambiguity.
  1. .using() (DELETE ... USING)
  • Could map to:
    • MySQL: DELETE ... USING
    • MSSQL/Oracle: multi-table delete patterns
  • Caveats:
    • Target table syntax differs (some need DELETE t FROM ...).
    • Join rules can change which rows get deleted.
    • Outer joins can behave differently.
    • Some engines restrict deleting from a table that is also joined.
  1. .distinctOn()
  • Could emulate with:
    • ROW_NUMBER() OVER (PARTITION BY ...) + WHERE row_number = 1
    • Works in MySQL 8+, MSSQL, Oracle; not MySQL < 8
  • Caveats:
    • Needs a clear ORDER BY to pick the “first” row.
    • Postgres has strict rules about ORDER BY that other DBs might not enforce.
    • Performance can be very different vs native DISTINCT ON.

Doing this would be worth it if we get the same results without these features, using more standard SQL. But that often means more verbose SQL and less readable queries. So porting is only worth it if we accept "mostly equivalent" behaviour and document the caveats clearly.

Possible next steps (if we ever want to do this)

  • Pick one feature (maybe updateFrom) and try a careful multi-dialect mapping.
  • Add clear docs that explain differences and limits.
  • Add tests that show where behaviour differs.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions