-
Notifications
You must be signed in to change notification settings - Fork 0
Production Readiness
Status of A3SQL for live use by units, multiplayer servers, and large mods, and the concrete gaps to close before you rely on it in production.
Everything below is exercised by the CI smoke test, which loads the real
release extension binary and runs the mod's own production SQL through the
exact C ABI Arma uses ("a3sql" callExtension stmt):
python3 tools/sql_smoke_test.py --bin a3sql_x64.so tools/smoke_test.sql| Area | Status |
|---|---|
| All 4 extension binaries (x64/i686 × Linux/Windows) | Verified loading + executing via ctypes/C harnesses, incl. under wine for the DLLs |
| STRING + ARRAY callExtension forms | Both work; every SQF call site routes correctly |
| The mod's own schema (patch_rules, patch_presets, server_commands) | Create/CRUD/cursor/prepare/save/load round-trip green |
| SQL injection surface |
$1 param substitution + escaping; call compile removed (RCE-class) |
| TCP listener | Loopback-only, optional LOGIN auth, per-statement panic barrier |
| 524 Rust tests + miri + clippy -D warnings + hemtt check | All green in CI |
Ranked by risk. Each is a real, confirmed limitation — not theoretical.
The parser is sqlparser (mature), but execution is hand-rolled. Real bugs
were found and fixed in v0.2.0 (UNIQUE treated as PK, datetime('now') in
VALUES rejected, no numeric→TEXT affinity). More incompatibilities will
surface with real-world SQL.
Close it: every mod must run its own SQL through the smoke test before shipping. The tool exists for exactly this. Engine-side: build a SQLite compatibility corpus (run a known SQL suite against both engines, diff behaviour) and fix the top divergences.
OUTPUT_BUF_SIZE = 20480. SELECTs returning more than that fail with
ERR_INTERNAL — mods must paginate with LIMIT/OFFSET. Arma 3's own
callExtension ceiling is ~30 KB (v2.20), so there is headroom to raise
the cap, but not to unbounded.
Close it: raise to 30 KB; document the cap + pagination pattern in
Module-Guide.md. Consider an explicit fetch_rows/cursor mode for big dumps
(partial: cursor create/fetch/drop already exists).
SAVE is a synchronous full-file write. A crash mid-write (server kill, power loss) can corrupt the save file. No WAL, no checksum, no atomic rename.
Close it: write to *.tmp then rename (atomic on POSIX/NTFS);
append a checksum trailer and verify on LOAD; keep the last-good backup
(*.bak) on load failure. This is ~30 lines in dispatch/commands/io.rs.
All queries serialize on one Mutex<Database>. Fine for Arma's
single-threaded server and unit-scale data (thousands of rows). If a mod
hammers the TCP listener from many clients concurrently, expect contention.
Close it: only if profiling shows it. RwLock split (reads vs writes)
is the cheap upgrade; per-connection batching is the expensive one.
No credentials set (set_credentials never called) → any local process can
run SQL over the loopback listener. Acceptable on a dedicated box.
Close it: require credentials by default (config flag
listener_require_auth = true); document in TCP-Connector.md.
Binary save format has magic + version byte; older saves are rejected on mismatch. Fine pre-1.0, but document that saves are NOT forward/backward compatible across versions, and make the failure message actionable ("save from v0.1.2 — migrate via export_sql").
| Consumer | Blocking gaps | Can ship today? |
|---|---|---|
| Small unit (single server, <10k rows) | none | Yes |
| Multiplayer server (public, dedicated host) | #5 (set credentials), #3 (back up a3sql_data) | Yes with hygiene |
| Big mod (heavy SQL, big datasets) | #1 (smoke-test own SQL), #2 (pagination) | After SQL pass |
-
python3 tools/sql_smoke_test.py tools/smoke_test.sql→ all PASS - Run your mod's own SQL through the smoke test → all PASS
- Set listener credentials via CBA settings
- Point
a3sql_database_auto_save_pathsomewhere backed up; test a restore - Verify a >20 KB SELECT errors cleanly, then paginate or use cursors