Alongside CQL, Ferrosa speaks the PostgreSQL frontend/backend protocol (v3) with SCRAM-SHA-256 authentication — so psql, psycopg2, tokio-postgres, and other standard clients can connect to the same data. This page documents what works today, how it is tested, and where it is headed.
Ferrosa implements the PostgreSQL v3 wire protocol on port 5432 with SCRAM-SHA-256 authentication. Both the simple query protocol and the extended query protocol (Parse / Bind / Describe / Execute / Sync) are supported.
# Any standard PostgreSQL client connects: psql "host=127.0.0.1 port=5432 user=ferrosa_user dbname=ferrosa" # psycopg2 / tokio-postgres / Postgrex use the same wire + SCRAM auth.
The active transaction status (I idle, T in-transaction, E failed) is reported in ReadyForQuery exactly as PostgreSQL does, so drivers track transaction state correctly.
The query surface is verified row-for-row against PostgreSQL across a fixed corpus:
| Capability | Status | Notes |
|---|---|---|
Projection & * | ✓ | column lists and star |
| WHERE | ✓ | =, !=, </<=/>/>=, AND/OR/NOT, parentheses |
| Three-valued logic | ✓ | comparisons with NULL are UNKNOWN → excluded (Kleene AND/OR/NOT) |
| JOIN | ✓ | inner equi-join |
| GROUP BY + aggregates | ✓ | COUNT, SUM, MIN, MAX, AVG; empty SUM/MIN → NULL |
| HAVING / DISTINCT | ✓ | |
| ORDER BY / LIMIT / OFFSET | ✓ | ASC/DESC, multi-key; text orders by C collation (byte order) |
| Expression selects | ✓ | SELECT 1, version(), current_database() (simple + extended) |
| Scalar types | ✓ | int, text, bool, float8, numeric, uuid, bytea, inet, timestamp, date, time |
Single-row DML writes through the same storage engine the CQL path uses, sharing one canonical row encoder so a row written over Postgres reads back identically over CQL.
INSERT INTO kv (id, v, n) VALUES (1, 'one', 10); -- INSERT 0 1 UPDATE kv SET v = 'ONE' WHERE id = 1; -- UPDATE 1 DELETE FROM kv WHERE id = 1; -- DELETE 1
NULL deletes the cell (it reads back as SQL NULL, not "" / 0).UPDATE of a non-existent key is an upsert. The WHERE clause must specify the full primary key.BEGIN / COMMIT / ROLLBACK are honored at the protocol level: the connection moves through idle → in-transaction → (on error) failed, and a failed transaction rejects further statements with SQLSTATE 25P02 until ROLLBACK.
Every CI build runs a differential oracle: the same data and the same SQL are executed against a real PostgreSQL 16 and the Ferrosa front-end, and the result sets must agree. It is the cross-check that catches the front-end silently diverging from PostgreSQL.
COLLATE "C" ordering contract. The corpus covers SELECT, the full INSERT/UPDATE/DELETE lifecycle, and temporal/numeric/inet types.
See the postgres-oracle job in .github/workflows/ci.yml and ferrosa-postgres/tests/differential_oracle.rs.
These surface a clean driver error today rather than silently-wrong results, and are tracked on the roadmap:
| Feature | Status |
|---|---|
$N params in DML | in progress — extended-protocol bind for writes |
RETURNING / ON CONFLICT | planned |
IS [NOT] NULL | planned |
Subqueries, WITH, UNION, window functions | not supported |
Non-C collations | v1 is COLLATE "C" only |