Differences from PostgREST¶
FirebirdREST borrows PostgREST's URL grammar, Prefer headers, error shape and security model,
so PostgREST client libraries and habits mostly carry over. Firebird is not PostgreSQL, though.
firebirdrest-js wraps supabase-js's query builder
(@supabase/postgrest-js) for FirebirdREST; its test suite is the compatibility check for the
list below.
Same¶
selectwith aliases, casts, embedding,!hint,!inner, spread (...) and aggregates.- Filters
eq,neq,gt,gte,lt,lte,like,ilike,in,is,isdistinct,not., andor/andtrees. order(includingorder=embed(column)on to-one embeds),limit,offset,Range,Prefer: count=exact,count=plannedandcount=estimated.POST/PATCH/PUT/DELETE(PATCH/DELETEwithorderandlimit),Prefer: return=…,resolution=…,missing=default,tx=rollback,on_conflict,columns./rpc/<name>withGET(read-only) andPOST,Prefer: params=multiple-objectsandparams=single-object.- JWT role switching, an anonymous role, a pre-request hook, and claims available to SQL.
jwt-secretas an HMAC secret (also base64 encoded), a PEM key, a JWK or a JWKS, or@file; a JWT validation cache.server-timing-enabledand theServer-Timingheader (jwt,parse,transaction,response).application/vnd.pgrst.object+json, CSV, OpenAPI at/,{code, message, details, hint}errors.Prefer: handling=strict,max-affectedandtimezone; query plans withAccept: application/vnd.pgrst.plan(behinddb-plan-enabled).
Different¶
| Topic | PostgREST | FirebirdREST |
|---|---|---|
| Namespaces | exposed schemas, Accept-Profile |
the same on Firebird 6 (db-schemas, Accept-Profile, Content-Profile); Firebird 3–5 have no schemas: one namespace. Packaged routines are /rpc/package.name |
| Relationships across schemas | foreign keys into other exposed schemas | the same on Firebird 6: foreign keys between exposed schemas embed both ways |
| Identifier case | as stored | unquoted (upper case) names shown in lower case |
| Claims in SQL | current_setting('request.jwt.claims')::json |
RDB$GET_CONTEXT('USER_TRANSACTION', 'request.jwt.claim.<name>'), one variable per claim (Firebird has no JSON functions) |
| Computed fields / relationships | functions taking a table row | routines whose parameters are TYPE OF COLUMN <table>.<col> |
| To-one computed relationship | function returning one row | executable procedure |
| Extra operators | fts, cs, cd, ov, JSON ->/->>, ranges, arrays |
Firebird's containing, starting, similar; no JSON, array or range types in Firebird |
| Aggregates | off by default | on by default (db-aggregates-enabled) |
| Embedding | one SQL statement with lateral joins | one batched query per embed level |
| Roles | SET ROLE per transaction |
a connection pool per role (Firebird sets the role at connect time) |
| Metrics | pgrst_* metrics on the admin server |
firebirdrest_* metrics with their own names, at /metrics on the admin port (list) |
| Tracing | OpenTelemetry through a separate setup | otel-traces-endpoint: a span per request, transaction and SQL statement, joining the caller's traceparent |
| JWT keys from a URL | not built in | jwt-jwks-url fetches a provider's JWKS and follows key rotation |
| JWT cache size | jwt-cache-max-entries |
the same; entries also expire after 5 minutes and when the JWKS changes |
| Schema reload | NOTIFY pgrst |
POST_EVENT 'fbrest_reload' |
| Realtime | not built in (Supabase Realtime is a separate service) | GET /events/<name> streams POST_EVENTs as Server-Sent Events (events) |
Unfiltered PATCH/DELETE |
allowed (unless pg-safeupdate) | refused unless db-safe-updates = false |
| Request context cost | always set | only when the database reads it (db-request-context) |
params=single-object |
the body goes to a single json parameter |
the body goes to a single text parameter, as JSON text |
params=multiple-objects on set-returning routines |
no limit | at most 1024 objects per request, their arguments within 48 KB |
count=planned |
the planner's estimate of the query | the table's row count from index statistics; exact for filtered requests, views and procedures |
| Query plans | EXPLAIN output (text or JSON), also for writes |
Firebird's explained plan per statement, as text or as a JSON tree, also for writes (rolled back) |
Prefer: timezone |
changes how timestamptz is displayed |
WITH TIME ZONE values carry a zone in Firebird, so they are converted to the requested zone; ignored on Firebird 3 |
| Custom media types | handler functions per media type | any concrete Accept type returns a single value as is (details); a raw request body goes to a routine's only parameter |
| application/geo+json | built in | request it from a function that returns GeoJSON text |
Open an issue if you miss something.