Upgrade Notes¶
This page covers upgrade steps from each recent release. Each section lists the shipping changes and the call-site updates most projects will want to make. Nothing in 1.4.x or 1.5.x is a breaking API change; everything is additive or strictly a bug fix, so upgrades should be drop-in.
Releases:
- 1.5.1 -- docs refresh
- 1.5.0 -- query UX
- 1.4.0 -- SurrealDB v3 support
- 1.3.1 -- embedded migration fix
1.5.1 -- docs refresh¶
Patch release. No code changes; docs-site only.
- New pages: SurrealDB v3 patterns, Query UX helpers, and this upgrade guide.
- CLI reference extended to cover
surql orchestratesubcommands. - README examples rewritten to use the 1.5.0 helpers.
__version__aligned topyproject.toml.
No action required.
1.5.0 -- query UX¶
Additive. All previous call shapes keep working.
What's new¶
- Record-ID helpers:
type_record(table, id)/type_thing(table, id)returnSurrealFnwrappers for the two SurrealDB record-construction builtins. - Function factories:
time_now_fn,math_mean_fn,math_sum_fn,math_min_fn,math_max_fn,math_ceil_fn,math_floor_fn,math_round_fn,math_abs_fn,string_len,string_concat,string_lower,string_upper,count_if. Each returns aSurrealFnthat composes withQuery.set(...),Query.select([...]), andaggregate_records(select={...}). - Result helpers:
extract_many(alias forextract_result) andhas_result(alias forhas_results). aggregate_records: typedSELECT ... GROUP BY | GROUP ALLhelper returning list-of-dicts.- Builder API:
Query.set(**fields),Query.update(target, data=None), andQuery.select(...)now acceptsSurrealFn/Expressionprojection items alongside strings.
Recommended call-site updates¶
Before:
await client.execute(
"SELECT count(*) AS total, math::sum(amount) AS revenue "
"FROM order WHERE status = 'paid' GROUP ALL"
)
After:
from surql import aggregate_records, count_if, math_sum_fn
rows = await aggregate_records(
table='order',
select={
'total': count_if(),
'revenue': math_sum_fn('amount'),
},
where="status = 'paid'",
group_all=True,
)
Before:
After:
from surql import Query, time_now_fn
sql = (
Query()
.update('user:alice')
.set(status='active', last_seen=time_now_fn())
.to_surql()
)
await client.execute(sql)
See Query UX helpers for the full surface with before/after side-by-side examples.
1.4.0 -- SurrealDB v3 support¶
Additive at the Python API level. The SurrealQL emitted by the library changed to forms that both v2 and v3 accept. No user-visible code changes are required; the behaviour differences below are worth being aware of.
What's new¶
- Datetime cast on
_migration_history:record_migration()now writesapplied_at = <datetime> $applied_at. - Buffered
BEGIN/COMMIT:DatabaseClient.execute()batches transaction-scoped statements into a single RPC frame so v3 honours the commit. GROUP ALLoncount_records:count_records()now appendsGROUP ALLso v3 accepts the aggregate. The helper still accepts both the envelope shape and a bare scalar list from the SDK.type::recordovertype::thing: select record-ID targets route throughtype::record(...)on v3.type_recordis now preferred overtype_thingin new code.- Idempotent DDL:
DEFINE TABLE _migration_history IF NOT EXISTS(and theif_not_existsflag across the schema generator) sosurql migrate upis safe to re-run. - Graph depth unrolling:
traverse(...)unrolls{min..max}depth ranges into literal hop unions that v3 accepts. - SDK pin: minimum
surrealdbSDK bumped to v2.0.0a1, which speaks v3's RPC protocol. - CI: new
v3-integrationworkflow runs the integration suite againstsurrealdb/surrealdb:v3.0.5; nightly matrix runs againstsurrealdb/surrealdb:latest.
Recommended call-site updates¶
Nothing is required to keep 1.3.x code running. If you hand-write SurrealQL anywhere (raw client.execute() calls), audit for the v3-required forms:
- Replace
count(*)withcount()and addGROUP ALLto any full-table aggregate. See v3 patterns: count() aggregates. - Cast datetime literals explicitly:
<datetime> $valueor<datetime> '2026-...'. See v3 patterns: datetime cast. - Prefer
type::record('table', id)overtype::thing('table', id)for new expressions. See v3 patterns: record-ID construction. - Ensure
BEGIN TRANSACTION; ...; COMMIT TRANSACTION;is issued in a singleclient.execute(...)call, or use thetransaction()context manager which already does so.
1.3.1 -- embedded migration fix¶
Bug-fix release for embedded engines (mem://, memory://, file://, surrealkv://).
execute_migration()now detects embedded URL schemes and skips theBEGIN TRANSACTION/COMMIT TRANSACTIONwrapper; the upstream SDK'squery()returns an empty list for transaction-control statements in embedded mode, which previously surfaced asIndexError: list index out of range.- Migrations remain effectively atomic in embedded mode because the engine lives in the host process; a crash during migration takes the process with it rather than leaving a partial schema.
No action required. Existing remote (ws://, http://) connections retain the transactional wrapper.