module sqlite/sqlite-result

import sqlite/capi

// Result codes returned from SQLite3 C API routines.
pub type sqlite-result
  Ok
  Row
  Done
  Error-Code(code: sqlite-error, pos: int)
  Ok-Load-Permanently

// Error result codes.
//
// The base variants correspond to the primary result codes.
// With the exception of `SQLITE_OK_LOAD_PERMANENTLY`, extended result codes
// are represented by an additional argument to the primary result code's constructor.
// All error codes carry the field for such arguments, even if there is no
// extended result code associated with it, so that wildcard pattern matches
// do not need to update if new extended result codes are added in the future.
pub type sqlite-error
  Error(ext: maybe<ext-error>)
  Internal(ext: maybe<ext-internal>)
  Perm(ext: maybe<ext-perm>)
  Abort(ext: maybe<ext-abort>)
  Busy(ext: maybe<ext-busy>)
  Locked(ext: maybe<ext-locked>)
  No-Mem(ext: maybe<ext-no-mem>)
  Read-Only(ext: maybe<ext-read-only>)
  Interrupt(ext: maybe<ext-interrupt>)
  IO-Err(ext: maybe<ext-io-err>)
  Corrupt(ext: maybe<ext-corrupt>)
  Not-Found(ext: maybe<ext-not-found>)
  Full(ext: maybe<ext-full>)
  Cant-Open(ext: maybe<ext-cant-open>)
  Protocol(ext: maybe<ext-protocol>)
  Schema(ext: maybe<ext-schema>)
  Too-Big(ext: maybe<ext-too-big>)
  Constraint(ext: maybe<ext-constraint>)
  Mismatch(ext: maybe<ext-mismatch>)
  Misuse(ext: maybe<ext-misuse>)
  No-LFS(ext: maybe<ext-no-lfs>)
  Auth(ext: maybe<ext-auth>)
  Range(ext: maybe<ext-range>)
  Not-A-DB(ext: maybe<ext-not-a-db>)
  Notice(ext: maybe<ext-notice>)
  Warning(ext: maybe<ext-warning>)
  // Empty(ext: maybe<ext-empty>) // unused
  // Format(ext: maybe<ext-format>) // unused

// Extended result codes for the `ERROR` primary result code.
pub type ext-error
  Error-Missing-Coll-Seq
  Error-Retry
  Error-Snapshot

// Extended result codes for the `INTERNAL` primary result code.
pub type ext-internal

// Extended result codes for the `PERM` primary result code.
pub type ext-perm

// Extended result codes for the `ABORT` primary result code.
pub type ext-abort
  Abort-Rollback

// Extended result codes for the `BUSY` primary result code.
pub type ext-busy
  Busy-Recovery
  Busy-Snapshot
  Busy-Timeout

// Extended result codes for the `LOCKED` primary result code.
pub type ext-locked
  Locked-Shared-Cache
  Locked-VTab

// Extended result codes for the `NOMEM` primary result code.
pub type ext-no-mem

// Extended result codes for the `READONLY` primary result code.
pub type ext-read-only
  Read-Only-Recovery
  Read-Only-Cant-Lock
  Read-Only-Rollback
  Read-Only-DB-Moved
  Read-Only-Cant-Init
  Read-Only-Directory

// Extended result codes for the `INTERRUPT` primary result code.
pub type ext-interrupt

// Extended result codes for the `IOERR` primary result code.
pub type ext-io-err
  IO-Err-Read
  IO-Err-Short-Read
  IO-Err-Write
  IO-Err-Fsync
  IO-Err-Dir-Fsync
  IO-Err-Truncate
  IO-Err-Fstat
  IO-Err-Unlock
  IO-Err-Read-Lock
  IO-Err-Delete
  IO-Err-No-Mem
  IO-Err-Access
  IO-Err-Check-Reserved-Lock
  IO-Err-Lock
  IO-Err-Close
  IO-Err-Shm-Open
  IO-Err-Shm-Size
  IO-Err-Shm-Map
  IO-Err-Seek
  IO-Err-Delete-No-Ent
  IO-Err-Mmap
  IO-Err-Get-Temp-Path
  IO-Err-Convpath
  IO-Err-Vnode
  IO-Err-Auth
  IO-Err-Begin-Atomic
  IO-Err-Commit-Atomic
  IO-Err-Rollback-Atomic
  IO-Err-Data
  IO-Err-Corrupt-FS
  // IO-Err-Blocked // unused
  // IO-Err-Dir-Close // unused
  // IO-Err-Shm-Lock // unused

// Extended result codes for the `CORRUPT` primary result code.
pub type ext-corrupt
  Corrupt-Vtab
  Corrupt-Sequence
  Corrupt-Index

// Extended result codes for the `NOTFOUND` primary result code.
pub type ext-not-found

// Extended result codes for the `FULL` primary result code.
pub type ext-full

// Extended result codes for the `CANTOPEN` primary result code.
pub type ext-cant-open
  Cant-Open-Isdir
  Cant-Open-Fullpath
  Cant-Open-Convpath
  Cant-Open-DirtyWAL
  Cant-Open-Symlink
  // Cant-Open-Notempdir // unused

// Extended result codes for the `PROTOCOL` primary result code.
pub type ext-protocol

// Extended result codes for the `SCHEMA` primary result code.
pub type ext-schema

// Extended result codes for the `TOOBIG` primary result code.
pub type ext-too-big

// Extended result codes for the `CONSTRAINT` primary result code.
pub type ext-constraint
  Constraint-Check
  Constraint-Commithook
  Constraint-Foreignkey
  Constraint-Function
  Constraint-Notnull
  Constraint-Primarykey
  Constraint-Trigger
  Constraint-Unique
  Constraint-VTab
  Constraint-Rowid
  Constraint-Pinned
  Constraint-Datatype

// Extended result codes for the `MISMATCH` primary result code.
pub type ext-mismatch

// Extended result codes for the `MISUSE` primary result code.
pub type ext-misuse

// Extended result codes for the `NOLFS` primary result code.
pub type ext-no-lfs

// Extended result codes for the `AUTH` primary result code.
pub type ext-auth
  Auth-User

// Extended result codes for the `RANGE` primary result code.
pub type ext-range

// Extended result codes for the `NOTADB` primary result code.
pub type ext-not-a-db

// Extended result codes for the `NOTICE` primary result code.
pub type ext-notice
  Notice-Recover-WAL
  Notice-Recover-Rollback

// Extended result codes for the `WARNING` primary result code.
pub type ext-warning
  Warning-Autoindex

// Convert an SQLite3 result to its integer value.
pub fun int32(r: sqlite-result): int32
  match r
    Ok -> 0.int32
    Row -> 100.int32
    Done -> 101.int32
    Error-Code(err, _) -> match err
      Error(Nothing) -> 1.int32
      Error(Just(Error-Missing-Coll-Seq)) -> 257.int32
      Error(Just(Error-Retry)) -> 513.int32
      Error(Just(Error-Snapshot)) -> 769.int32
      Internal(_) -> 2.int32
      Perm(_) -> 3.int32
      Abort(Nothing) -> 4.int32
      Abort(Just(Abort-Rollback)) -> 516.int32
      Busy(Nothing) -> 5.int32
      Busy(Just(Busy-Recovery)) -> 261.int32
      Busy(Just(Busy-Snapshot)) -> 517.int32
      Busy(Just(Busy-Timeout)) -> 773.int32
      Locked(Nothing) -> 6.int32
      Locked(Just(Locked-Shared-Cache)) -> 262.int32
      Locked(Just(Locked-VTab)) -> 518.int32
      No-Mem(_) -> 7.int32
      Read-Only(Nothing) -> 8.int32
      Read-Only(Just(Read-Only-Recovery)) -> 264.int32
      Read-Only(Just(Read-Only-Cant-Lock)) -> 520.int32
      Read-Only(Just(Read-Only-Rollback)) -> 776.int32
      Read-Only(Just(Read-Only-DB-Moved)) -> 1032.int32
      Read-Only(Just(Read-Only-Cant-Init)) -> 1288.int32
      Read-Only(Just(Read-Only-Directory)) -> 1544.int32
      Interrupt(_) -> 9.int32
      IO-Err(Nothing) -> 10.int32
      IO-Err(Just(IO-Err-Read)) -> 266.int32
      IO-Err(Just(IO-Err-Short-Read)) -> 522.int32
      IO-Err(Just(IO-Err-Write)) -> 778.int32
      IO-Err(Just(IO-Err-Fsync)) -> 1034.int32
      IO-Err(Just(IO-Err-Dir-Fsync)) -> 1290.int32
      IO-Err(Just(IO-Err-Truncate)) -> 1546.int32
      IO-Err(Just(IO-Err-Fstat)) -> 1802.int32
      IO-Err(Just(IO-Err-Unlock)) -> 2058.int32
      IO-Err(Just(IO-Err-Read-Lock)) -> 2314.int32
      IO-Err(Just(IO-Err-Delete)) -> 2570.int32
      IO-Err(Just(IO-Err-No-Mem)) -> 3082.int32
      IO-Err(Just(IO-Err-Access)) -> 3338.int32
      IO-Err(Just(IO-Err-Check-Reserved-Lock)) -> 3594.int32
      IO-Err(Just(IO-Err-Lock)) -> 3850.int32
      IO-Err(Just(IO-Err-Close)) -> 4106.int32
      IO-Err(Just(IO-Err-Shm-Open)) -> 4618.int32
      IO-Err(Just(IO-Err-Shm-Size)) -> 4874.int32
      IO-Err(Just(IO-Err-Shm-Map)) -> 5386.int32
      IO-Err(Just(IO-Err-Seek)) -> 5642.int32
      IO-Err(Just(IO-Err-Delete-No-Ent)) -> 5898.int32
      IO-Err(Just(IO-Err-Mmap)) -> 6154.int32
      IO-Err(Just(IO-Err-Get-Temp-Path)) -> 6410.int32
      IO-Err(Just(IO-Err-Convpath)) -> 6666.int32
      IO-Err(Just(IO-Err-Vnode)) -> 6922.int32
      IO-Err(Just(IO-Err-Auth)) -> 7178.int32
      IO-Err(Just(IO-Err-Begin-Atomic)) -> 7434.int32
      IO-Err(Just(IO-Err-Commit-Atomic)) -> 7690.int32
      IO-Err(Just(IO-Err-Rollback-Atomic)) -> 7946.int32
      IO-Err(Just(IO-Err-Data)) -> 8202.int32
      IO-Err(Just(IO-Err-Corrupt-FS)) -> 8458.int32
      Corrupt(Nothing) -> 11.int32
      Corrupt(Just(Corrupt-Vtab)) -> 267.int32
      Corrupt(Just(Corrupt-Sequence)) -> 523.int32
      Corrupt(Just(Corrupt-Index)) -> 779.int32
      Not-Found(_) -> 12.int32
      Full(_) -> 13.int32
      Cant-Open(Nothing) -> 14.int32
      Cant-Open(Just(Cant-Open-Isdir)) -> 526.int32
      Cant-Open(Just(Cant-Open-Fullpath)) -> 782.int32
      Cant-Open(Just(Cant-Open-Convpath)) -> 1038.int32
      Cant-Open(Just(Cant-Open-DirtyWAL)) -> 1294.int32
      Cant-Open(Just(Cant-Open-Symlink)) -> 1550.int32
      Protocol(_) -> 15.int32
      Schema(_) -> 17.int32
      Too-Big(_) -> 18.int32
      Constraint(Nothing) -> 19.int32
      Constraint(Just(Constraint-Check)) -> 275.int32
      Constraint(Just(Constraint-Commithook)) -> 531.int32
      Constraint(Just(Constraint-Foreignkey)) -> 787.int32
      Constraint(Just(Constraint-Function)) -> 1043.int32
      Constraint(Just(Constraint-Notnull)) -> 1299.int32
      Constraint(Just(Constraint-Primarykey)) -> 1555.int32
      Constraint(Just(Constraint-Trigger)) -> 1811.int32
      Constraint(Just(Constraint-Unique)) -> 2067.int32
      Constraint(Just(Constraint-VTab)) -> 2323.int32
      Constraint(Just(Constraint-Rowid)) -> 2579.int32
      Constraint(Just(Constraint-Pinned)) -> 2835.int32
      Constraint(Just(Constraint-Datatype)) -> 3091.int32
      Mismatch(_) -> 20.int32
      Misuse(_) -> 21.int32
      No-LFS(_) -> 21.int32
      Auth(Nothing) -> 23.int32
      Auth(Just(Auth-User)) -> 279.int32
      Range(_) -> 25.int32
      Not-A-DB(_) -> 26.int32
      Notice(Nothing) -> 27.int32
      Notice(Just(Notice-Recover-WAL)) -> 283.int32
      Notice(Just(Notice-Recover-Rollback)) -> 539.int32
      Warning(Nothing) -> 28.int32
      Warning(Just(Warning-Autoindex)) -> 284.int32
    Ok-Load-Permanently -> 256.int32

// Get the SQLite result corresponding to a result code from the C API.
// Throws an exception if `r` does not correspond to a valid result.
pub fun int32/sqlite-result(r: int32, pos: int = -1): exn sqlite-result
  match r.int
    0 -> Ok
    256 -> Ok-Load-Permanently
    1 -> Error-Code(Error(Nothing), pos)
    257 -> Error-Code(Error(Just(Error-Missing-Coll-Seq)), pos)
    513 -> Error-Code(Error(Just(Error-Retry)), pos)
    769 -> Error-Code(Error(Just(Error-Snapshot)), pos)
    2 -> Error-Code(Internal(Nothing), pos)
    3 -> Error-Code(Perm(Nothing), pos)
    4 -> Error-Code(Abort(Nothing), pos)
    516 -> Error-Code(Abort(Just(Abort-Rollback)), pos)
    5 -> Error-Code(Busy(Nothing), pos)
    261 -> Error-Code(Busy(Just(Busy-Recovery)), pos)
    517 -> Error-Code(Busy(Just(Busy-Snapshot)), pos)
    773 -> Error-Code(Busy(Just(Busy-Timeout)), pos)
    6 -> Error-Code(Locked(Nothing), pos)
    262 -> Error-Code(Locked(Just(Locked-Shared-Cache)), pos)
    518 -> Error-Code(Locked(Just(Locked-VTab)), pos)
    7 -> Error-Code(No-Mem(Nothing), pos)
    8 -> Error-Code(Read-Only(Nothing), pos)
    264 -> Error-Code(Read-Only(Just(Read-Only-Recovery)), pos)
    520 -> Error-Code(Read-Only(Just(Read-Only-Cant-Lock)), pos)
    776 -> Error-Code(Read-Only(Just(Read-Only-Rollback)), pos)
    1032 -> Error-Code(Read-Only(Just(Read-Only-DB-Moved)), pos)
    1288 -> Error-Code(Read-Only(Just(Read-Only-Cant-Init)), pos)
    1544 -> Error-Code(Read-Only(Just(Read-Only-Directory)), pos)
    9 -> Error-Code(Interrupt(Nothing), pos)
    10 -> Error-Code(IO-Err(Nothing), pos)
    266 -> Error-Code(IO-Err(Just(IO-Err-Read)), pos)
    522 -> Error-Code(IO-Err(Just(IO-Err-Short-Read)), pos)
    778 -> Error-Code(IO-Err(Just(IO-Err-Write)), pos)
    1034 -> Error-Code(IO-Err(Just(IO-Err-Fsync)), pos)
    1290 -> Error-Code(IO-Err(Just(IO-Err-Dir-Fsync)), pos)
    1546 -> Error-Code(IO-Err(Just(IO-Err-Truncate)), pos)
    1802 -> Error-Code(IO-Err(Just(IO-Err-Fstat)), pos)
    2058 -> Error-Code(IO-Err(Just(IO-Err-Unlock)), pos)
    2314 -> Error-Code(IO-Err(Just(IO-Err-Read-Lock)), pos)
    2570 -> Error-Code(IO-Err(Just(IO-Err-Delete)), pos)
    3082 -> Error-Code(IO-Err(Just(IO-Err-No-Mem)), pos)
    3338 -> Error-Code(IO-Err(Just(IO-Err-Access)), pos)
    3594 -> Error-Code(IO-Err(Just(IO-Err-Check-Reserved-Lock)), pos)
    3850 -> Error-Code(IO-Err(Just(IO-Err-Lock)), pos)
    4106 -> Error-Code(IO-Err(Just(IO-Err-Close)), pos)
    4618 -> Error-Code(IO-Err(Just(IO-Err-Shm-Open)), pos)
    4874 -> Error-Code(IO-Err(Just(IO-Err-Shm-Size)), pos)
    5386 -> Error-Code(IO-Err(Just(IO-Err-Shm-Map)), pos)
    5642 -> Error-Code(IO-Err(Just(IO-Err-Seek)), pos)
    5898 -> Error-Code(IO-Err(Just(IO-Err-Delete-No-Ent)), pos)
    6154 -> Error-Code(IO-Err(Just(IO-Err-Mmap)), pos)
    6410 -> Error-Code(IO-Err(Just(IO-Err-Get-Temp-Path)), pos)
    6666 -> Error-Code(IO-Err(Just(IO-Err-Convpath)), pos)
    6922 -> Error-Code(IO-Err(Just(IO-Err-Vnode)), pos)
    7178 -> Error-Code(IO-Err(Just(IO-Err-Auth)), pos)
    7434 -> Error-Code(IO-Err(Just(IO-Err-Begin-Atomic)), pos)
    7690 -> Error-Code(IO-Err(Just(IO-Err-Commit-Atomic)), pos)
    7946 -> Error-Code(IO-Err(Just(IO-Err-Rollback-Atomic)), pos)
    8202 -> Error-Code(IO-Err(Just(IO-Err-Data)), pos)
    8458 -> Error-Code(IO-Err(Just(IO-Err-Corrupt-FS)), pos)
    11 -> Error-Code(Corrupt(Nothing), pos)
    267 -> Error-Code(Corrupt(Just(Corrupt-Vtab)), pos)
    523 -> Error-Code(Corrupt(Just(Corrupt-Sequence)), pos)
    779 -> Error-Code(Corrupt(Just(Corrupt-Index)), pos)
    12 -> Error-Code(Not-Found(Nothing), pos)
    13 -> Error-Code(Full(Nothing), pos)
    14 -> Error-Code(Cant-Open(Nothing), pos)
    526 -> Error-Code(Cant-Open(Just(Cant-Open-Isdir)), pos)
    782 -> Error-Code(Cant-Open(Just(Cant-Open-Fullpath)), pos)
    1038 -> Error-Code(Cant-Open(Just(Cant-Open-Convpath)), pos)
    1294 -> Error-Code(Cant-Open(Just(Cant-Open-DirtyWAL)), pos)
    1550 -> Error-Code(Cant-Open(Just(Cant-Open-Symlink)), pos)
    15 -> Error-Code(Protocol(Nothing), pos)
    17 -> Error-Code(Schema(Nothing), pos)
    18 -> Error-Code(Too-Big(Nothing), pos)
    19 -> Error-Code(Constraint(Nothing), pos)
    275 -> Error-Code(Constraint(Just(Constraint-Check)), pos)
    531 -> Error-Code(Constraint(Just(Constraint-Commithook)), pos)
    787 -> Error-Code(Constraint(Just(Constraint-Foreignkey)), pos)
    1043 -> Error-Code(Constraint(Just(Constraint-Function)), pos)
    1299 -> Error-Code(Constraint(Just(Constraint-Notnull)), pos)
    1555 -> Error-Code(Constraint(Just(Constraint-Primarykey)), pos)
    1811 -> Error-Code(Constraint(Just(Constraint-Trigger)), pos)
    2067 -> Error-Code(Constraint(Just(Constraint-Unique)), pos)
    2323 -> Error-Code(Constraint(Just(Constraint-VTab)), pos)
    2579 -> Error-Code(Constraint(Just(Constraint-Rowid)), pos)
    2835 -> Error-Code(Constraint(Just(Constraint-Pinned)), pos)
    3091 -> Error-Code(Constraint(Just(Constraint-Datatype)), pos)
    20 -> Error-Code(Mismatch(Nothing), pos)
    21 -> Error-Code(Misuse(Nothing), pos)
    21 -> Error-Code(No-LFS(Nothing), pos)
    23 -> Error-Code(Auth(Nothing), pos)
    279 -> Error-Code(Auth(Just(Auth-User)), pos)
    25 -> Error-Code(Range(Nothing), pos)
    26 -> Error-Code(Not-A-DB(Nothing), pos)
    27 -> Error-Code(Notice(Nothing), pos)
    283 -> Error-Code(Notice(Just(Notice-Recover-WAL)), pos)
    539 -> Error-Code(Notice(Just(Notice-Recover-Rollback)), pos)
    28 -> Error-Code(Warning(Nothing), pos)
    284 -> Error-Code(Warning(Just(Warning-Autoindex)), pos)
    100 -> Row
    101 -> Done
    v -> throw("invalid SQLite3 result code " ++ v.show, ExnRange)

// Convert an SQLite result to its corresponding primary result.
// E.g., `Constraint(Just(Constraint-Unique))` is converted to `Constraint(Nothing)`.
pub fun primary(r: sqlite-result): sqlite-result
  match r
    Error-Code(Error(Just(_)), pos) -> Error-Code(Error(Nothing), pos)
    Error-Code(Abort(Just(_)), pos) -> Error-Code(Abort(Nothing), pos)
    Error-Code(Busy(Just(_)), pos) -> Error-Code(Busy(Nothing), pos)
    Error-Code(Locked(Just(_)), pos) -> Error-Code(Locked(Nothing), pos)
    Error-Code(Read-Only(Just(_)), pos) -> Error-Code(Read-Only(Nothing), pos)
    Error-Code(IO-Err(Just(_)), pos) -> Error-Code(IO-Err(Nothing), pos)
    Error-Code(Corrupt(Just(_)), pos) -> Error-Code(Corrupt(Nothing), pos)
    Error-Code(Cant-Open(Just(_)), pos) -> Error-Code(Cant-Open(Nothing), pos)
    Error-Code(Constraint(Just(_)), pos) -> Error-Code(Constraint(Nothing), pos)
    Error-Code(Auth(Just(_)), pos) -> Error-Code(Auth(Nothing), pos)
    Error-Code(Notice(Just(_)), pos) -> Error-Code(Notice(Nothing), pos)
    Error-Code(Warning(Just(_)), pos) -> Error-Code(Warning(Nothing), pos)
    Ok-Load-Permanently -> Ok
    r -> r

// Get the message corresponding to a result code.
pub fun show(r: sqlite-result): string
  capi/errstr(r.int32)
