Skip to content
potluckdb

Database

Swift: also in Python · Node · Go · Rust · Dart · Java and Kotlin · .NET · C++ · Objective-C

The current writable database.

query, execute and transaction share one convenience connection, created when first needed. connect() creates additional independent connections. A remote supplied at open enables sync(). By default, it also starts automatic synchronization in both directions. Concepts explains the remote and synchronization model.

Discard full quarantine records and return the number cleared.

Compact safety records remain until authenticated retention permits their retirement.

Close all owned connections, then the local store. Repeated calls have the same effect.

close() fails with invalid_state while any owned connection has an active managed transaction. This never closes your Remote.

Create another independent SQLite connection to this database.

Each explicit connection takes its own ConnectionOptions. Closing it leaves the database and siblings usable. Ordinary SQLite locking permits at most one writer at a time.

Run exactly one state-changing statement on the convenience connection.

The connection reference explains intent rules.

Run one statement with read execution intent on the convenience connection.

The connection reference explains intent rules.

Adopt the authenticated remote revision and replay local work.

The call downloads the revision and stages it durably. It applies the revision while blocking database access and restarting attached connections. It then replays safe pending statements.

The result names transaction IDs in these groups:

  • Already published
  • Replayed
  • Quarantined
  • Still pending

Prepared state survives a crash and restart. Production considerations describes replay limits, including FAIL statements and reports after interrupted resolution.

Replace the synchronization policy and return the new status. SyncPolicy.manual() disables automatic work but not explicit sync() or resolveConflict().

Return a typed DatabaseStatus containing these values:

  • Current revision
  • Pending writes
  • Residency and budget
  • Connection count
  • Synchronization state
  • Next delay
  • Conflict revision
  • Lifecycle

nextSyncInMilliseconds gives the delay until automatic synchronization, in milliseconds. 0 means it is due now. The driver sets it at its last step. It does not count down between steps. It can therefore overstate the remaining delay by the time since that step. It never understates it.

An idle automatic database reports its idle pull interval. nil means nothing is scheduled, so waiting on it would wait forever. This occurs when any of these applies:

  • The policy is manual.
  • A cycle is running.
  • A conflict awaits resolution.
  • Automatic synchronization failed permanently.
  • The database is closed.

When something is scheduled, wait using this field. Do not sleep for a guessed interval instead. On an idle machine, the interval can pass before the work completes.

connectionCount includes connections you opened with connect() and the convenience connection created on the database’s first statement. A database with no statements through its convenience connection and no explicit connections reports zero.

Synchronize once with the remote.

If the device has local writes to publish, this call publishes them. Otherwise, it checks the remote head and pulls a newer revision if one exists. A failed attempt keeps its prepared writes for a later attempt, and that retry can leave newer writes pending.

It returns exactly one result: .upToDate, .pushed, .pulled or .conflict. A .conflict is returned as a value without throwing an error. Automatic synchronization stays paused in that state until resolveConflict runs. Without a remote, this call fails with remote_required.

Begin one managed transaction on the convenience connection. The default mode is immediate.

Use query to choose the engine. Default reads use SQLite. Select DuckDB with engine: .duckdb. Only these two engines are supported. An invalid selection fails instead of selecting the default.

The native SDK loads DuckDB when you first request an analytical read. OpenOptions.analyticalEngine selects the library for one database or snapshot. It takes priority over POTLUCKDB_DUCKDB_LIBRARY, package discovery where available, and the platform’s library search. An explicit selection, including an empty string, never uses a fallback.

See analytics engine installation for your platform. Without an implicit library, the read fails with analytical_engine_unavailable. If an explicit library cannot load, the read reports its loader error.

The analytics engine page lists each platform’s library URL and SHA-256 digest.

  1. Download the library for your platform.
  2. Verify its digest.
  3. Name the library in this language’s open option.
let options = OpenOptions(analyticalEngine: "/opt/potluckdb/lib/libduckdb.dylib")

DuckDB rejects the named binding forms :name and @name. Both engines accept $name and positional ? bindings. Booleans bind as INTEGER 0/1 on both. IS therefore asks the same question on either engine, unlike a DuckDB BOOLEAN binding.

Bare table names read the database’s main schema. Qualifiers such as temp. are not seen. For table names ending in .csv, .parquet or .json, use potluckdb_scan('name'). DuckDB otherwise treats those names as files.

NUMERIC and DECIMAL columns read as doubles. A value that a double cannot hold exactly fails the query instead of arriving rounded.

A storage failure during an analytical read reports analytical_engine_error, with the failure named in its message. The same query succeeds when storage answers.

Either engine runs one read per query. The analytical engine reads a snapshot of the same data through its own in-memory database. A statement sent to this engine therefore cannot change the stored data.

An engine can remain for the session’s lifetime. Changing its settings or catalog would change later queries on that session. Only SELECT and EXPLAIN are accepted. CREATE, SET, ATTACH, PREPARE and EXPLAIN ANALYZE are refused. EXPLAIN ANALYZE is refused because it executes the explained statement.

Use execute for writes to the stored data.