Native Postgres driver
dox_postgres_native is the default Postgres driver of the Dox ORM.
Rust talks to the database. Your models, queries and transactions stay the
same. You do not change any config.
- Rust (tokio-postgres) owns the connections and the pool.
- Dart sends many queries to Rust in one call. Rust sends many results back in one message.
- Each connection keeps its prepared statements. The same SQL is not parsed again.
- Values have the same Dart types as with the
postgrespackage. Errors are the sameServerExceptionclasses.
Alpha
This driver is new. If you see a problem, use the Dart driver and tell us.
Speed
One find-by-id query (SELECT ... WHERE id = @id), AOT build
(dart build cli), Postgres 14 on the same machine (Apple M-series),
4 connections:
| Dart driver | Native driver | |
|---|---|---|
| One query at a time | 95 µs | 60 µs |
| 64 queries in flight, one isolate | 45 µs per query | 12.5 µs per query |
| 4 isolates, 64 in flight each, 16 connections per pool | 39,500 queries/s | 64,000 queries/s |
The gain is biggest when many requests run at the same time, like in a web server.
Install
dox_orm depends on dox_postgres_native. You do not add it yourself.
Add it only to use PgNativePool without the ORM:
The build hook builds the Rust library with cargo, so you need
Rust installed. Ready-built libraries (like the ones
dox_http_native has) are not published for this driver yet.
Without Rust, the ORM still works: it uses the Dart driver and prints one
warning line (see below).
Use dart run, dart test or dart build cli. dart compile exe does not
run build hooks.
Native is the default
You do not change any config. The ORM picks the driver like this:
driverFactoryis set: the ORM uses your driver. It wins over everything below.- You ask for the Dart driver (see below), or the connection uses TLS: the ORM uses the Dart driver.
- The native library loads: the ORM uses the native driver.
- The native library does not load (no library for your system, no Rust to build it, or a load error): the ORM uses the Dart driver. It prints one warning line to stderr, like this:
Named connections (withConnection('x'), transaction(..., connection: 'x')) follow
the same rules.
Use the Dart driver
For all connections, set the env var:
For one connection, set native: false in extra:
ConnectionConfig(
driver: Driver.postgres,
// ... host, user, password, database as before
extra: <String, dynamic>{'native': false},
debug: false,
),
Postgres with TLS (useSSL: true or extra['sslMode']) always uses the
Dart driver, because the native driver has no TLS yet.
Options
The driver reads these keys from extra of the ConnectionConfig:
| Key | Default | What it does |
|---|---|---|
maxConnectionCount |
10 |
Most connections in the pool. |
timeZone |
UTC |
Time zone of the session, like the Dart driver. |
applicationName |
none | Name of the app in pg_stat_activity. |
threads |
1 |
Rust threads for all pools of the process. 0 is one thread with a single-thread runtime. Only the first pool sets it. |
Each isolate that runs setup() makes its own pool. To share one pool
between isolates, give driver.pool.handle (an int) to the other
isolates and use PostgresNativeDriver(PgNativePool.fromHandle(handle))
there. PostgresNativeDriver comes from package:dox_orm/dox_orm.dart.
Use it without the ORM
PgNativePool pool = PgNativePool.open(
host: 'localhost',
user: 'postgres',
password: 'postgres',
database: 'postgres',
);
PgNativeResult result = await pool.query(
'SELECT id, name FROM users WHERE id = @id',
parameters: <String, dynamic>{'id': 1},
);
print(result.rows); // [{id: 1, name: Ada}]
int tx = await pool.begin();
await pool.query('UPDATE users SET name = @n', parameters: <String, dynamic>{'n': 'Bob'}, transaction: tx);
await pool.commit(tx); // or pool.rollback(tx)
parametersis a map for@name, or a list for$1, $2.- A transaction runs on one connection. Its queries run in the order you send them.
Types
The same as the postgres package:
| Postgres | Dart |
|---|---|
int2, int4, int8 |
int |
float4, float8 |
double |
numeric |
String |
text, varchar, char |
String |
bool |
bool |
timestamp, timestamptz, date |
DateTime in UTC |
json, jsonb |
the decoded JSON value |
uuid |
String |
bytea |
Uint8List |
| arrays of most types above | List |
NULL |
null |
Other types decode with the type registry of the postgres package.
Errors
A server error throws the same exception as the Dart driver:
ServerException, or UniqueViolationException and
ForeignKeyViolationException, with the same code, detail,
constraintName and other fields. Other errors (eg. the server is down)
throw PgException.
Not yet
- SSL. A connection with
useSSL: trueuses the Dart driver. maxConnectionAge,queryTimeoutand the otherextrakeys of the Dart driver are not read.- A nested
transaction()joins the outer one, like the Dart driver (no savepoints).