Devolutions.Ahtola.Core 0.1.0

Prefix Reserved
dotnet add package Devolutions.Ahtola.Core --version 0.1.0
                    
NuGet\Install-Package Devolutions.Ahtola.Core -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Devolutions.Ahtola.Core" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Devolutions.Ahtola.Core" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Devolutions.Ahtola.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Devolutions.Ahtola.Core --version 0.1.0
                    
#r "nuget: Devolutions.Ahtola.Core, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Devolutions.Ahtola.Core@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Devolutions.Ahtola.Core&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Devolutions.Ahtola.Core&version=0.1.0
                    
Install as a Cake Tool

Ahtola .NET

An experimental pure managed (C#) port of Turso’s SQLite-compatible database engine, with ADO.NET and EF Core providers.

⚠️ Experimental project. Ahtola is a research / prototype engine and is not production-ready. For production .NET workloads, use the official bindings to the original Turso Rust core at tursodatabase/turso.

Ahtola is a C# engine that reads and writes SQLite’s on-disk format directly — automatically vibe-ported from Turso’s Rust core, as a fun experiment. It is not a binding over native SQLite or over any Rust core — no native companion, P/Invoke SDK, or Rust toolchain is required to restore, build, pack, or run.

Install

dotnet add package Devolutions.Ahtola.Data.Sqlite
# optional EF Core provider (9.x on net8/net9, 10.x on net10):
dotnet add package Devolutions.Ahtola.EntityFrameworkCore.Sqlite

Targets: net8.0, net9.0, net10.0. No net48 / .NET Framework assets.

Package Role
Devolutions.Ahtola.Core Managed engine
Devolutions.Ahtola.Data.Sqlite ADO.NET provider + Microsoft.Data.Sqlite-compatible facade; embeds Ahtola.Data
Devolutions.Ahtola.EntityFrameworkCore.Sqlite EF Core provider (UseAhtola)
Layer Name
NuGet PackageId Devolutions.Ahtola.*
Assemblies Devolutions.Ahtola.*
Namespaces / types Ahtola.* (AhtolaConnection, UseAhtola, …)
Project folders src/Ahtola.*

Quick start

SQLite-compatible facade (drop-in using swap from Microsoft.Data.Sqlite):

using Ahtola.Data.Sqlite;

using var connection = new SqliteConnection("Data Source=app.db");
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE t(a INTEGER, b TEXT)");
connection.ExecuteNonQuery("INSERT INTO t VALUES (1, 'hello')");

using var command = connection.CreateCommand();
command.CommandText = "SELECT a, b FROM t";
using var reader = command.ExecuteReader();
while (reader.Read())
    Console.WriteLine($"{reader.GetInt32(0)} {reader.GetString(1)}");

Ahtola types (same package):

using Ahtola;

using var connection = new AhtolaConnection("Data Source=:memory:");
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE t(a, b)");
// AhtolaConnection, AhtolaCommand, AhtolaParameter, AhtolaFactory.Instance, …

EF Core:

options.UseAhtola("Data Source=app.db");

Common connection-string keywords: Data Source, Mode, Cache, Pooling, Foreign Keys, Default Timeout / Command Timeout, Foreign Read Only, DateTimeKind, BinaryGUID, Password (passphrase → AES-256-GCM), or Encryption Cipher + Encryption Key (hex AES-128/256-GCM). Default local provider is managed-only.

Standard SQLite files

Managed open of unencrypted SQLite databases created by System.Data.SQLite / Microsoft.Data.Sqlite / native sqlite3 is supported (Data Source=path only; no special flags). Ahtola is byte-compatible with the on-disk format for normal read/write workloads.

File encryption (not SEE / SQLCipher)

Encryption is layered so new recipes can be added without rewriting the pager:

Layer Role Extension point
Passphrase scheme Password to AES key IAhtolaPassphraseScheme + AhtolaPassphraseSchemes; CS Password Scheme=
Built-in AHTLA page crypto On-disk AES-GCM pages (AHTLA header) AhtolaEncryptionOptions / Encryption Cipher + Encryption Key
External page codec Entirely different page layout IPageCodec (mutually exclusive with built-in encryption)
Mechanism Connection string Notes
Passphrase (explicit scheme) Password=secret;Password Scheme=Ahtola.Password.v1 Preferred for apps (e.g. RDM). Scheme id is a stable KDF contract.
Passphrase (default scheme) Password=secret Same as Ahtola.Password.v1 when Password Scheme is omitted
Raw key Encryption Cipher=Aes256Gcm; Encryption Key=<64 hex chars> Same on-disk AHTLA format
Rekey SqliteConnection.ChangePassword / ClearPassword / SetPassword Rewrite backup + atomic file replace; exclusive access

Built-in scheme Ahtola.Password.v1: PBKDF2-HMAC-SHA256, fixed domain salt Ahtola.Password.v1, 210k iterations to AES-256-GCM. Changing KDF bytes requires a new scheme id (via AhtolaPassphraseSchemes.Register or a future built-in), never a silent change to v1.

Do not combine Password and Encryption Key. Legacy SEE/SQLCipher files are not opened by passphrase schemes — use a dedicated IPageCodec or export/recreate under Ahtola password / plain SQLite.

Wrong/missing password failures include the phrase file is encrypted or is not a database for SDS-shaped detection.

PowerShell module

Devolutions.Ahtola.Sqlite is a binary PowerShell module that exposes the Ahtola engine through *-AhtolaSqlite* cmdlets. Its implementation is ported from synedgy.PSSqlite and re-backed onto Ahtola.Data.Sqlite instead of Microsoft.Data.Sqlite / SQLitePCLRaw — so importing it pulls in no native SQLite assets. The public command noun is AhtolaSqlite to avoid collisions with other SQLite PowerShell modules.

Requires PowerShell 7.4+. Windows PowerShell 5.1 is not supported.

Getting the module

It isn't on the PowerShell Gallery yet, so build it from a clone:

./build.ps1 pack-powershell
# -> artifacts/powershell-modules/Devolutions.Ahtola.Sqlite

Then import it from anywhere pwsh 7 runs — no native SQLite binary, no .NET SDK needed at import time:

Import-Module ./artifacts/powershell-modules/Devolutions.Ahtola.Sqlite
Get-Command -Module Devolutions.Ahtola.Sqlite

Model types are available as module-qualified type accelerators, e.g. [Devolutions.Ahtola.Sqlite.SqliteDBConfig].

Cmdlets

Cmdlet Purpose
New-AhtolaSqliteConnection / Test-AhtolaSqliteConnection / Close-AhtolaSqliteConnection / Clear-AhtolaSqliteConnectionPool Open, test, close/dispose, and explicitly clear managed connection pools
Invoke-AhtolaSqliteQuery Run parameterized SQL; emits PSCustomObject rows by default and supports scalar, non-query, DataTable, DataSet, and detached-reader modes
Start-AhtolaSqliteTransaction / Save-AhtolaSqliteTransaction / Complete-AhtolaSqliteTransaction / Undo-AhtolaSqliteTransaction Start, save, commit/release, or roll back managed transactions and savepoints
Invoke-AhtolaSqliteBulkCopy Insert pipeline objects, dictionaries, or DataRow values in an all-or-nothing transaction
Backup-AhtolaSqliteDatabase Copy one managed SQLite database into a distinct destination connection
Get-AhtolaSqliteSchema / Get-AhtolaSqliteTable / Get-AhtolaSqliteIndex / Get-AhtolaSqliteDatabaseInfo Inspect provider schema, database objects, and database page/journal information
Test-AhtolaSqliteIntegrity / Optimize-AhtolaSqliteDatabase / Checkpoint-AhtolaSqliteDatabase / Invoke-AhtolaSqliteMaintenance Run focused integrity, optimization, WAL checkpoint, and constrained maintenance operations
Export-AhtolaSqliteTable / Import-AhtolaSqliteTable Move table data as portable JSON or CSV; this is distinct from a database backup
Set-AhtolaSqlitePassword / Clear-AhtolaSqlitePassword Encrypt, rekey, or decrypt file-backed managed Ahtola databases using a SecureString passphrase
Get-AhtolaSqliteRow / New-AhtolaSqliteRow / Set-AhtolaSqliteRow / Remove-AhtolaSqliteRow CRUD driven by a programmatically constructed SQLiteDBConfig + -Table (+ -Values / -Where); update/delete emit affected-row counts
Get-AhtolaSqliteDatabaseMetadata / Compare-AhtolaSqliteDatabaseVersion Read stored metadata; compare deployed vs expected configuration version

New-AhtolaSqliteConnection returns an open connection. Every cmdlet that receives -Connection may open a closed connection but never closes or disposes it. Configuration-driven CRUD creates and disposes its own temporary connection only when -Connection is omitted. -SqliteConnection, -SqliteDBConfig, -TableName, -RowData, and -ClauseData remain compatibility aliases; use -Connection, -Configuration, -Table, -Values, and -Where in new scripts.

Invoke-AhtolaSqliteQuery and the Get-AhtolaSqliteRow family support -As DataTable | DetachedDataReader | DataSet | OrderedDictionary | PSCustomObject; Invoke-AhtolaSqliteQuery additionally supports Scalar and NonQuery. DataReader remains a compatibility alias for DetachedDataReader: it is a materialized snapshot, not a live streaming reader.

Bulk imports fail and roll back their own transaction on the first conflicting row. When passed a caller-owned transaction, the cmdlet uses a savepoint and rolls back only that bulk operation.

Example

# Ad hoc query and default PowerShell-object output
$connection = New-AhtolaSqliteConnection -ConnectionString 'Data Source=:memory:'
Invoke-AhtolaSqliteQuery -Connection $connection `
    -CommandText 'SELECT id, name FROM t WHERE name = $name' `
    -Parameters @{ '$name' = 'b' }

$transaction = Start-AhtolaSqliteTransaction -Connection $connection
Invoke-AhtolaSqliteQuery -Connection $connection -Transaction $transaction `
    -CommandText 'UPDATE Items SET Name = $name WHERE Id = $id' `
    -Parameters @{ '$name' = 'updated'; '$id' = 1 } -As NonQuery
Complete-AhtolaSqliteTransaction -Transaction $transaction

# Portable table export/import infers JSON or CSV from the file extension.
Export-AhtolaSqliteTable -Connection $connection -Table Items -Path ./items.json
Import-AhtolaSqliteTable -Connection $connection -Table Items -Path ./items.csv
$connection | Close-AhtolaSqliteConnection -ClearPool

If you'd rather call the ADO.NET provider from a plain script module instead of using these cmdlets, see samples/PSSqlite.Managed.

What this is good for

  • Fully managed local SQLite-format databases with no native assets
  • Small-to-moderate workloads, in-process embedding, constrained deployment
  • A familiar ADO.NET / MDS-shaped API and an EF Core provider

Important limits

Treat Ahtola as SQLite-compatible, not a full SQLite replacement:

  • In-memory working set — tables and intermediate results stay in the process heap; nothing spills to disk. Prefer modest databases and explicit transactions for writes (managed writes are slower than native SQLite and the gap grows with table size).
  • PlannerANALYZE / sqlite_stat1 feed index scoring and limited join cost gates (selective outer for two-table INNER nested loops; equijoin hash build side). Full System-R DP join reordering and multi-index AND intersection are still deferred; OUTER JOIN order stays correctness-preserving. Prefer ORDER BY when order matters (GROUP BY is first-encounter order).
  • File-backed platforms — Windows, 64-bit Linux, and macOS. In-memory works everywhere; other platforms (e.g. 32-bit Linux) throw PlatformNotSupportedException on physical open. macOS uses POSIX fcntl(F_SETLK) (process-associated locks, not Linux OFD); multi-engine claims on macOS need host verification.
  • Multi-engine files (Stage 6) — physical opens use SQLite main-file SHARED locking (Windows / 64-bit Linux / macOS). Managed and stock SQLite can share the same live WAL database on Windows/Linux (-shm DMS + peer WAL visibility on new statements). Pooling may retain managed handles until Pooling=False or SqliteConnection.ClearAllPools(). PENDING/RESERVED DELETE-mode polish and a Turso binary differential remain optional depth. See docs/wal-interoperability-contract.md.
  • Foreign read-onlyMode=ReadOnly;Foreign Read Only=True;Pooling=False can read a DB still held by native SQLite/Turso (e.g. winget index.db) without taking main-file locks.
  • MVCC — process-local PRAGMA journal_mode=mvcc + BEGIN CONCURRENT with dual-cursor SELECT/DML routing, logical log, and a checkpoint SM skeleton (PRAGMA wal_checkpoint in MVCC mode). Not cross-process; residual schema- cookie polish and full per-page b-tree checkpoint SM remain open — see docs/mvcc-port-contract.md.
  • Not implemented — virtual tables / FTS / R-Tree, loadable extensions, raw sqlite3* handles (Handle is null), AEGIS encryption ciphers, sync engine / CDC, CREATE SEQUENCE, typed-value extensions.
  • Native / Sync companions — not shipped. Connection-string paths that need them fail closed. OS P/Invoke in the pager for locks/WAL is intentional engine code, not a Rust SDK binding.
  • Remote Hrana — optional pure-managed HTTP /v2/pipeline on AhtolaConnection (tests use a canned server). Not a cloud product surface.

Encryption format v0 uses a fixed 5-byte magic AHTLA, then version and cipher id (AES-GCM page AEAD).

Building from source

Requires the .NET SDK and PowerShell 7+:

./build.ps1 build
./build.ps1 test
./build.ps1 pack              # -> ./artifacts/managed-packages
./build.ps1 pack-powershell   # -> ./artifacts/powershell-modules
./build.ps1 validate-runtime  # packed consumer trim + NativeAOT publish

Contributor details — the full task list, validation gates, conformance suite, and repo layout — live in AGENTS.md and docs/.

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Devolutions.Ahtola.Core:

Package Downloads
Devolutions.Ahtola.Data.Sqlite

Managed ADO.NET provider for Ahtola: a Microsoft.Data.Sqlite-compatible facade over the pure managed Ahtola Core engine. No native companion required. Ahtola is a Devolutions project.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 78 8/14/2026