AsyncNativeOdbcConnection class

Non-blocking wrapper around ODBC using a long-lived worker isolate.

Architecture: All FFI/ODBC operations run in a dedicated worker isolate. The main thread stays responsive; no blocking FFI calls run on the UI thread.

How it works

  1. initialize spawns a worker isolate and loads the ODBC driver.
  2. Each operation sends a request (via SendPort) to the worker.
  3. The worker runs the FFI call and sends back the result (via ReceivePort).
  4. The main thread never blocks on ODBC.

Performance

  • Worker spawn (one-time): ~50–100 ms.
  • Per-operation overhead: ~1–3 ms.
  • Parallel queries: N queries complete in the time of the longest (not the sum).

Request timeout

Use requestTimeout to avoid UI hangs when the worker does not respond (default 30s). Pass Duration.zero or null to disable.

Example

final async = AsyncNativeOdbcConnection(
  requestTimeout: Duration(seconds: 30),
);
await async.initialize();

final connId = await async.connect(dsn);
final data = await async.executeQueryParams(connId, 'SELECT 1', []);
await async.disconnect(connId);

async.dispose(); // Pending requests complete with error

See also:

Constructors

AsyncNativeOdbcConnection({Duration? requestTimeout, void isolateEntry(SendPort)?, bool autoRecoverOnWorkerCrash = false})

Properties

autoRecoverOnWorkerCrash bool
When true, on worker isolate error/done WorkerCrashRecovery.handleWorkerCrash is invoked after failing pending requests. All previous connection IDs are invalid after recovery; callers must reconnect.
final
hashCode int
The hash code for this object.
no setterinherited
isInitialized bool
Whether the worker isolate and ODBC environment are initialized.
no setter
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
workerIsolateForTesting Isolate?
Worker isolate, exposed for testing (e.g., to simulate crash).
no setter

Methods

beginTransaction(int connectionId, int isolationLevel) Future<int>
Starts a transaction in the worker for connectionId with isolationLevel. Returns the transaction ID on success.
bulkInsertArray(int connectionId, String table, List<String> columns, Uint8List dataBuffer, int rowCount) Future<int>
Performs bulk insert on connectionId: table, columns, dataBuffer, rowCount. Returns rows inserted, or negative on error.
bulkInsertParallel(int poolId, String table, List<String> columns, Uint8List dataBuffer, int parallelism) Future<int>
Performs parallel bulk insert on poolId. Returns rows inserted, or negative value on error.
cancelStatement(int stmtId) Future<bool>
Requests cancellation of prepared statement stmtId in the worker.
catalogColumns(int connectionId, String table) Future<Uint8List?>
Returns catalog columns for table on connectionId. Binary result or null on error.
catalogTables(int connectionId, {String catalog = '', String schema = ''}) Future<Uint8List?>
Returns catalog tables for connectionId (optional catalog and schema). Returns binary result or null on error.
catalogTypeInfo(int connectionId) Future<Uint8List?>
Returns type info for connectionId. Binary result or null on error.
clearAllStatements() Future<int>
clearStatementCache() Future<bool>
Clears the prepared statement cache in the worker.
closeStatement(int stmtId) Future<bool>
Closes the prepared statement stmtId in the worker.
commitTransaction(int txnId) Future<bool>
Commits the transaction identified by txnId in the worker.
connect(String connectionString, {int timeoutMs = 0}) Future<int>
Opens a connection in the worker using connectionString.
createSavepoint(int txnId, String name) Future<bool>
Creates a savepoint name within the transaction txnId in the worker.
detectDriver(String connectionString) Future<String?>
Detects the database driver from a connection string.
disconnect(int connectionId) Future<bool>
Closes the connection identified by connectionId in the worker.
dispose() → void
Shuts down the worker isolate and releases resources.
executePrepared(int stmtId, List<ParamValue>? params, int timeoutOverrideMs, int fetchSize, {int? maxBufferBytes}) Future<Uint8List?>
Executes a prepared statement stmtId in the worker with optional params. Returns the binary result, or null on error.
executePreparedNamed(int stmtId, Map<String, Object?> namedParams, int timeoutOverrideMs, int fetchSize, {int? maxBufferBytes}) Future<Uint8List?>
Executes a prepared statement stmtId using named parameters.
executeQueryMulti(int connectionId, String sql, {int? maxBufferBytes}) Future<Uint8List?>
Executes sql on connectionId for multi-result sets in the worker. When maxBufferBytes is set, caps the result buffer size. Returns the binary result, or null on error.
executeQueryNamed(int connectionId, String sql, Map<String, Object?> namedParams, {int? maxBufferBytes}) Future<Uint8List?>
Executes sql on connectionId using named parameters.
executeQueryParams(int connectionId, String sql, List<ParamValue> params, {int? maxBufferBytes}) Future<Uint8List?>
Executes sql on connectionId with params in the worker.
getCacheMetrics() Future<PreparedStatementMetrics?>
Returns prepared statement cache metrics from the worker.
getError() Future<String>
Returns the last error message from the worker (plain text).
getMetrics() Future<OdbcMetrics?>
Returns ODBC metrics from the worker (query count, errors, latency, etc.).
getStructuredError() Future<StructuredError?>
Returns the last structured error (message, SQLSTATE, native code), or null if there is no error.
initialize() Future<bool>
Initializes the worker isolate and ODBC environment.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
poolClose(int poolId) Future<bool>
Closes pool poolId in the worker.
poolCreate(String connectionString, int maxSize) Future<int>
Creates a connection pool in the worker. Returns pool ID on success.
poolGetConnection(int poolId) Future<int>
Obtains a connection from pool poolId. Returns connection ID on success.
poolGetState(int poolId) Future<({int idle, int size})?>
Returns the current state (size, idle) of pool poolId, or null on error.
poolHealthCheck(int poolId) Future<bool>
Runs a health check on pool poolId.
poolReleaseConnection(int connectionId) Future<bool>
Returns connectionId to its pool.
prepare(int connectionId, String sql, {int timeoutMs = 0}) Future<int>
Prepares sql on connectionId in the worker.
prepareNamed(int connectionId, String sql, {int timeoutMs = 0}) Future<int>
Prepares sql with named parameters on connectionId in the worker.
recoverWorker() Future<void>
Disposes the current worker and re-initializes a fresh one.
releaseSavepoint(int txnId, String name) Future<bool>
Releases savepoint name in transaction txnId. Transaction stays active.
rollbackToSavepoint(int txnId, String name) Future<bool>
Rolls back to savepoint name in transaction txnId. Transaction stays active.
rollbackTransaction(int txnId) Future<bool>
Rolls back the transaction identified by txnId in the worker.
streamQuery(int connectionId, String sql, {int chunkSize = 1000, int? maxBufferBytes}) Stream<ParsedRowBuffer>
Runs sql in the worker using native streaming.
streamQueryBatched(int connectionId, String sql, {int fetchSize = 1000, int chunkSize = 64 * 1024, int? maxBufferBytes}) Stream<ParsedRowBuffer>
Runs sql in the worker using native batched streaming.
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited