@amritk/nish-x86_64-linux 0.20.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL.md +52 -10
- package/bin/nish +0 -0
- package/docs/AI.md +2777 -0
- package/package.json +2 -1
- package/runtime/browser.d.ts +6 -0
- package/runtime/browser.mjs +77 -0
- package/runtime/core/arrays.d.ts +36 -0
- package/runtime/core/arrays.mjs +153 -0
- package/runtime/core/checks.mjs +20 -0
- package/runtime/core/host.d.ts +80 -0
- package/runtime/core/host.mjs +325 -0
- package/runtime/core/numbers.d.ts +66 -0
- package/runtime/core/numbers.mjs +343 -0
- package/runtime/core/result.d.ts +45 -0
- package/runtime/core/result.mjs +140 -0
- package/runtime/core/strings.d.ts +14 -0
- package/runtime/core/strings.mjs +169 -0
- package/runtime/core.d.ts +9 -0
- package/runtime/core.mjs +55 -0
- package/runtime/host.d.ts +6 -0
- package/runtime/nish.d.ts +46 -2
- package/runtime/nish.h +75 -2
- package/runtime/nish.mjs +23 -3
- package/runtime/node.mjs +386 -0
- package/runtime/runtime-bytes.c +401 -0
- package/runtime/runtime-cross.c +1 -1
- package/runtime/runtime-host.c +1 -1
- package/runtime/runtime-net.c +12 -1
- package/runtime/runtime-os.c +1 -1
- package/runtime/runtime-parallel.c +1 -1
- package/runtime/runtime-simd.c +231 -7
- package/runtime/runtime-term.c +504 -0
- package/runtime/runtime-wasm.c +0 -11
- package/runtime/runtime.c +190 -6
- package/runtime/shim.mjs +6 -985
- package/runtime/sqlite/LICENSE.md +85 -0
- package/runtime/sqlite/README.md +45 -0
- package/runtime/sqlite/nish-sqlite.c +359 -0
- package/runtime/sqlite/sqlite3.c +271131 -0
- package/runtime/sqlite/sqlite3.h +14447 -0
- package/scripts/build.sh +311 -59
- package/std/LICENSE-fast-float +23 -0
- package/std/LICENSE-fdlibm +8 -0
- package/std/README.md +32 -12
- package/std/base64.ts +116 -0
- package/std/bytes.ts +256 -0
- package/std/cli.ts +344 -0
- package/std/collections.ts +6 -5
- package/std/crypto/LICENSE-crypt_blowfish +26 -0
- package/std/crypto/base64url.ts +125 -0
- package/std/crypto/bcrypt.ts +1557 -0
- package/std/crypto/hmac.ts +138 -2
- package/std/crypto/x509.ts +11 -122
- package/std/json-tokenizer.ts +2998 -57
- package/std/json-value.ts +22 -3
- package/std/json.ts +87 -8
- package/std/math.ts +608 -0
- package/std/net/http1-server.ts +282 -40
- package/std/net/http1.ts +40 -21
- package/std/net/http3-server.ts +50 -12
- package/std/net/postgres.ts +2294 -0
- package/std/net/prefork.ts +23 -3
- package/std/net/quic-listener.ts +20 -4
- package/std/random.ts +66 -4
- package/std/regex.ts +4274 -0
- package/std/sqlite.ts +391 -0
- package/std/term-io.ts +978 -0
- package/std/term-pixels.ts +874 -0
- package/std/term-probe.ts +459 -0
- package/std/term-rate.ts +993 -0
- package/std/term.ts +2453 -0
- package/std/text.ts +90 -7
- package/std/yaml-lines.ts +141 -0
- package/std/yaml.ts +4675 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
License Information
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
SQLite Is Public Domain
|
|
5
|
+
-----------------------
|
|
6
|
+
|
|
7
|
+
The SQLite source code, including all of the files in the directories
|
|
8
|
+
listed in the bullets below are
|
|
9
|
+
[Public Domain](https://sqlite.org/copyright.html).
|
|
10
|
+
The authors have submitted written affidavits releasing their work to
|
|
11
|
+
the public for any use. Every byte of the public-domain code can be
|
|
12
|
+
traced back to the original authors. The files of this repository
|
|
13
|
+
that are public domain include the following:
|
|
14
|
+
|
|
15
|
+
* All of the primary SQLite source code files found in the
|
|
16
|
+
[src/ directory](https://sqlite.org/src/tree/src?type=tree&expand)
|
|
17
|
+
* All of the test cases and testing code in the
|
|
18
|
+
[test/ directory](https://sqlite.org/src/tree/test?type=tree&expand)
|
|
19
|
+
* All of the SQLite extension source code and test cases in the
|
|
20
|
+
[ext/ directory](https://sqlite.org/src/tree/ext?type=tree&expand)
|
|
21
|
+
* All code that ends up in the "sqlite3.c" and "sqlite3.h" build products
|
|
22
|
+
that actually implement the SQLite RDBMS.
|
|
23
|
+
* All of the code used to compile the
|
|
24
|
+
[command-line interface](https://sqlite.org/cli.html)
|
|
25
|
+
* All of the code used to build various utility programs such as
|
|
26
|
+
"sqldiff", "sqlite3_rsync", and "sqlite3_analyzer".
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
The public domain source files usually contain a header comment
|
|
30
|
+
similar to the following to make it clear that the software is
|
|
31
|
+
public domain.
|
|
32
|
+
|
|
33
|
+
> The author disclaims copyright to this source code. In place of
|
|
34
|
+
> a legal notice, here is a blessing:
|
|
35
|
+
>
|
|
36
|
+
> * May you do good and not evil.
|
|
37
|
+
> * May you find forgiveness for yourself and forgive others.
|
|
38
|
+
> * May you share freely, never taking more than you give.
|
|
39
|
+
|
|
40
|
+
Almost every file you find in this source repository will be
|
|
41
|
+
public domain. But there are a small number of exceptions:
|
|
42
|
+
|
|
43
|
+
Non-Public-Domain Code Included With This Source Repository AS A Convenience
|
|
44
|
+
----------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
This repository contains a (relatively) small amount of non-public-domain
|
|
47
|
+
code used to help implement the configuration and build logic. In other
|
|
48
|
+
words, there are some non-public-domain files used to implement:
|
|
49
|
+
|
|
50
|
+
> ./configure && make
|
|
51
|
+
|
|
52
|
+
In all cases, the non-public-domain files included with this
|
|
53
|
+
repository have generous BSD-style licenses. So anyone is free to
|
|
54
|
+
use any of the code in this source repository for any purpose, though
|
|
55
|
+
attribution may be required to reuse or republish the configure and
|
|
56
|
+
build scripts. None of the non-public-domain code ever actually reaches
|
|
57
|
+
the build products, such as "sqlite3.c", however, so no attribution is
|
|
58
|
+
required to use SQLite itself. The non-public-domain code consists of
|
|
59
|
+
scripts used to help compile SQLite. The non-public-domain code is
|
|
60
|
+
technically not part of SQLite. The non-public-domain code is
|
|
61
|
+
included in this repository as a convenience to developers, so that those
|
|
62
|
+
who want to build SQLite do not need to go download a bunch of
|
|
63
|
+
third-party build scripts in order to compile SQLite.
|
|
64
|
+
|
|
65
|
+
Non-public-domain code included in this respository includes:
|
|
66
|
+
|
|
67
|
+
* The ["autosetup"](http://msteveb.github.io/autosetup/) configuration
|
|
68
|
+
system that is contained (mostly) in the autosetup/ directory, but also
|
|
69
|
+
includes the "./configure" script at the top-level of this archive.
|
|
70
|
+
Autosetup has a separate BSD-style license. See the
|
|
71
|
+
[autosetup/LICENSE](http://msteveb.github.io/autosetup/license/)
|
|
72
|
+
for details.
|
|
73
|
+
|
|
74
|
+
* There are BSD-style licenses on some of the configuration
|
|
75
|
+
software found in the legacy autoconf/ directory and its
|
|
76
|
+
subdirectories.
|
|
77
|
+
|
|
78
|
+
The following unix shell command can be run from the top-level
|
|
79
|
+
of this source repository in order to remove all non-public-domain
|
|
80
|
+
code:
|
|
81
|
+
|
|
82
|
+
> rm -rf configure autosetup autoconf
|
|
83
|
+
|
|
84
|
+
If you unpack this source repository and then run the command above, what
|
|
85
|
+
is left will be 100% public domain.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# runtime/sqlite/
|
|
2
|
+
|
|
3
|
+
The [SQLite](https://sqlite.org/) amalgamation, vendored so that a Nish program
|
|
4
|
+
that calls SQLite links it with no library installed on the system.
|
|
5
|
+
|
|
6
|
+
| | |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| Version | 3.54.1 (`SQLITE_SOURCE_ID` `2026-10-16 14:45:20 555e07ef…`) |
|
|
9
|
+
| From | <https://sqlite.org/2026/sqlite-amalgamation-3540100.zip> |
|
|
10
|
+
| SHA3-256 of the archive | `92281c86e2957f9b9305890f9ac04204caa7b677cc868dc326d942689df28e30` |
|
|
11
|
+
| SHA3-256 of `sqlite3.c` | `e2b869d3003b33c942b7dd7063604fbc53553e1b66609570df39b9b7b558ee81` |
|
|
12
|
+
| SHA3-256 of `sqlite3.h` | `15ef3f5dbc4a7a980f828fa0d1e473cee5a124e7bb77e9bc70fc0bfa3f9a2af8` |
|
|
13
|
+
| Taken | `sqlite3.c` and `sqlite3.h`, byte for byte; not `shell.c` or `sqlite3ext.h` |
|
|
14
|
+
| Vendored | 2026-10-24 |
|
|
15
|
+
| Licence | public domain ([sqlite.org/copyright.html](https://sqlite.org/copyright.html)); `LICENSE.md` is upstream's, from <https://sqlite.org/src/raw/LICENSE.md?ci=version-3.54.1> |
|
|
16
|
+
|
|
17
|
+
`sqlite3.c` and `sqlite3.h` are never edited. A change SQLite needs is a
|
|
18
|
+
compile-time option in `scripts/build.sh`, or code in a file of our own beside
|
|
19
|
+
them.
|
|
20
|
+
|
|
21
|
+
## How it is linked
|
|
22
|
+
|
|
23
|
+
`scripts/build.sh` compiles every `*.c` here for a link whose IR declares an
|
|
24
|
+
`sqlite3_*` or `nishsqlite_*` function, and for no other link. The options are
|
|
25
|
+
in `build.sh`, under "SQLite's compile-time options". `NISH_SQLITE_CFLAGS` adds
|
|
26
|
+
to them (`docs/guide/using-nish/cli.md`). `nish --link` and `nish run` compile
|
|
27
|
+
these units once per recipe into an entry of the runtime cache of their own
|
|
28
|
+
(`src/compile.ts`, `cachedRuntime`). `src/run-cache.ts` reads this directory
|
|
29
|
+
for the units and the files the cache key fingerprints (`sqliteUnits`,
|
|
30
|
+
`sqliteFingerprint`), so a file added here needs no list updated.
|
|
31
|
+
`tests/run.js` ("sqlite-link") checks the two hashes above against the files.
|
|
32
|
+
|
|
33
|
+
## Updating
|
|
34
|
+
|
|
35
|
+
1. Download the new `sqlite-amalgamation-<NNNNNNN>.zip` from
|
|
36
|
+
<https://sqlite.org/download.html>. Check its SHA3-256 against the one on
|
|
37
|
+
that page.
|
|
38
|
+
2. Copy `sqlite3.c` and `sqlite3.h` over the ones here, unchanged. Replace
|
|
39
|
+
`LICENSE.md` with the one tagged for that version, if it differs.
|
|
40
|
+
3. Update the table above, the two file hashes included (`openssl dgst
|
|
41
|
+
-sha3-256 sqlite3.c sqlite3.h`), the version in `THIRD_PARTY_NOTICES.md`, and the
|
|
42
|
+
numbers in `tests/link/sqlite_link*/expected.out`.
|
|
43
|
+
4. Run `node tests/run.js link`, `node tests/run.js sqlite-link`,
|
|
44
|
+
`WASI_SYSROOT=/usr node tests/run.js wasi` and the third-party-licence
|
|
45
|
+
section.
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/* The C half of `nish/sqlite` (std/sqlite.ts): the handle tables, and one
|
|
2
|
+
* adapter per SQLite call that a Nish declaration cannot make by itself.
|
|
3
|
+
*
|
|
4
|
+
* A Nish program cannot hold an `sqlite3 *` in a value it exports, take an
|
|
5
|
+
* out-pointer (`sqlite3 **`) or name `SQLITE_TRANSIENT`, so this file keeps
|
|
6
|
+
* every connection and every prepared statement in a table and hands the
|
|
7
|
+
* program an `int32_t` handle into it. A handle is the slot's index in the low
|
|
8
|
+
* 16 bits and the slot's generation in the 15 above them, so it is never 0
|
|
9
|
+
* or negative. Freeing a slot moves its generation on, and a handle whose
|
|
10
|
+
* generation is not the slot's answers SQLITE_MISUSE, so a statement used
|
|
11
|
+
* after `finalize`, or after its database's `close`, is refused rather than
|
|
12
|
+
* reaching a freed pointer. A slot whose generation reaches 32,767, the
|
|
13
|
+
* generation's width, is retired rather than restarted at 1, so no handle
|
|
14
|
+
* ever names a slot twice and a stale handle can never alias a live one. A
|
|
15
|
+
* table that has retired or filled all 65,535 of its slots answers
|
|
16
|
+
* SQLITE_NOMEM, which takes some two billion opens or prepares.
|
|
17
|
+
*
|
|
18
|
+
* The tables are thread-local under --threads (`NISH_TLS`, ../nish.h). A
|
|
19
|
+
* connection and its statements belong to the thread that opened them: a
|
|
20
|
+
* handle passed to another thread names nothing there and answers
|
|
21
|
+
* SQLITE_MISUSE. That is also why the tables need no lock. SQLite is compiled
|
|
22
|
+
* SQLITE_THREADSAFE=2 under --threads (scripts/build.sh), which allows one
|
|
23
|
+
* connection per thread. A thread's tables are not freed when it exits.
|
|
24
|
+
*
|
|
25
|
+
* Nothing here allocates except a table growing (`slot_take`) and SQLite
|
|
26
|
+
* itself. Each adapter is a table load and the SQLite call, compiled to LTO
|
|
27
|
+
* bitcode (scripts/build.sh, `sqlite_units`), so it inlines into the program.
|
|
28
|
+
*
|
|
29
|
+
* Results follow SQLite: an `int32_t` result code, extended, because every
|
|
30
|
+
* connection is opened with SQLITE_OPEN_EXRESCODE. Two adapters answer a
|
|
31
|
+
* handle or a length when they succeed and the negated code when they fail.
|
|
32
|
+
* Text and blobs are bound SQLITE_TRANSIENT, so SQLite copies them, because
|
|
33
|
+
* the program lends its bytes for the length of one call
|
|
34
|
+
* (docs/LANGUAGE.md, "Calling C"). */
|
|
35
|
+
|
|
36
|
+
#include <stdint.h>
|
|
37
|
+
#include <stdlib.h>
|
|
38
|
+
#include <string.h>
|
|
39
|
+
|
|
40
|
+
#include "../nish.h"
|
|
41
|
+
#include "sqlite3.h"
|
|
42
|
+
|
|
43
|
+
typedef struct nishsqlite_slot {
|
|
44
|
+
void *p; /* the sqlite3 * or sqlite3_stmt *, NULL while free */
|
|
45
|
+
int32_t gen; /* 1..32767, the high bits of the slot's handle */
|
|
46
|
+
int32_t owner; /* a statement's database handle; 0 for a database */
|
|
47
|
+
int32_t next; /* the next free slot, oldest first; 0 ends the list */
|
|
48
|
+
} nishsqlite_slot;
|
|
49
|
+
|
|
50
|
+
typedef struct nishsqlite_table {
|
|
51
|
+
nishsqlite_slot *at; /* at[0] is never used, so no handle is 0 */
|
|
52
|
+
int32_t len;
|
|
53
|
+
int32_t cap;
|
|
54
|
+
int32_t head; /* the oldest free slot, 0 when none */
|
|
55
|
+
int32_t tail;
|
|
56
|
+
} nishsqlite_table;
|
|
57
|
+
|
|
58
|
+
#define NISH_SQLITE_INDEX 0xffff
|
|
59
|
+
#define NISH_SQLITE_GEN_MAX 0x7fff
|
|
60
|
+
|
|
61
|
+
static NISH_TLS nishsqlite_table nishsqlite_dbs;
|
|
62
|
+
static NISH_TLS nishsqlite_table nishsqlite_stmts;
|
|
63
|
+
|
|
64
|
+
/* What the last failed `nishsqlite_open` said, kept because the connection it
|
|
65
|
+
* came from is closed before the open answers. */
|
|
66
|
+
static NISH_TLS char nishsqlite_open_message[256];
|
|
67
|
+
|
|
68
|
+
static inline nishsqlite_slot *slot_of(nishsqlite_table *t, int32_t h) {
|
|
69
|
+
int32_t i = h & NISH_SQLITE_INDEX;
|
|
70
|
+
if (h <= 0 || i >= t->len) return NULL;
|
|
71
|
+
nishsqlite_slot *s = &t->at[i];
|
|
72
|
+
if (s->p == NULL || s->gen != (h >> 16)) return NULL;
|
|
73
|
+
return s;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static inline sqlite3 *db_of(int32_t h) {
|
|
77
|
+
nishsqlite_slot *s = slot_of(&nishsqlite_dbs, h);
|
|
78
|
+
return s ? (sqlite3 *)s->p : NULL;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static inline sqlite3_stmt *stmt_of(int32_t h) {
|
|
82
|
+
nishsqlite_slot *s = slot_of(&nishsqlite_stmts, h);
|
|
83
|
+
return s ? (sqlite3_stmt *)s->p : NULL;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* A slot for `p`, and its handle; 0 when the table is full or cannot grow. */
|
|
87
|
+
static int32_t slot_take(nishsqlite_table *t, void *p, int32_t owner) {
|
|
88
|
+
int32_t i = t->head;
|
|
89
|
+
if (i != 0) {
|
|
90
|
+
t->head = t->at[i].next;
|
|
91
|
+
if (t->head == 0) t->tail = 0;
|
|
92
|
+
} else {
|
|
93
|
+
if (t->len == 0) t->len = 1;
|
|
94
|
+
if (t->len > NISH_SQLITE_INDEX) return 0;
|
|
95
|
+
if (t->len >= t->cap) {
|
|
96
|
+
int32_t cap = t->cap ? t->cap * 2 : 16;
|
|
97
|
+
nishsqlite_slot *at = realloc(t->at, (size_t)cap * sizeof *at);
|
|
98
|
+
if (at == NULL) return 0;
|
|
99
|
+
memset(at + t->cap, 0, (size_t)(cap - t->cap) * sizeof *at); /* at[0] stays empty */
|
|
100
|
+
t->at = at;
|
|
101
|
+
t->cap = cap;
|
|
102
|
+
}
|
|
103
|
+
i = t->len++;
|
|
104
|
+
t->at[i].gen = 1;
|
|
105
|
+
}
|
|
106
|
+
t->at[i].p = p;
|
|
107
|
+
t->at[i].owner = owner;
|
|
108
|
+
t->at[i].next = 0;
|
|
109
|
+
return (t->at[i].gen << 16) | i;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Frees the slot `h` names and moves its generation on, so `h` names nothing.
|
|
113
|
+
* A slot at the last generation is retired: it stays empty and off the free
|
|
114
|
+
* list, so its handles are never handed out again. */
|
|
115
|
+
static void slot_give(nishsqlite_table *t, int32_t h) {
|
|
116
|
+
int32_t i = h & NISH_SQLITE_INDEX;
|
|
117
|
+
nishsqlite_slot *s = &t->at[i];
|
|
118
|
+
s->p = NULL;
|
|
119
|
+
s->next = 0;
|
|
120
|
+
if (s->gen == NISH_SQLITE_GEN_MAX) return;
|
|
121
|
+
s->gen++;
|
|
122
|
+
if (t->tail != 0) t->at[t->tail].next = i;
|
|
123
|
+
else t->head = i;
|
|
124
|
+
t->tail = i;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* ---- Connections -------------------------------------------------------- */
|
|
128
|
+
|
|
129
|
+
#define NISH_SQLITE_OPEN_FLAGS \
|
|
130
|
+
(SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | \
|
|
131
|
+
SQLITE_OPEN_URI | SQLITE_OPEN_MEMORY | SQLITE_OPEN_NOFOLLOW)
|
|
132
|
+
|
|
133
|
+
/* A handle, or the negated extended code with its message kept for
|
|
134
|
+
* `nishsqlite_open_errmsg`. The flags are SQLite's, less those this build
|
|
135
|
+
* has no use for, and must hold READONLY, READWRITE or READWRITE|CREATE:
|
|
136
|
+
* anything else is SQLITE_MISUSE, where SQLite leaves it undefined. */
|
|
137
|
+
int32_t nishsqlite_open(const char *path, int32_t flags) {
|
|
138
|
+
int32_t mode = flags & 7;
|
|
139
|
+
if ((flags & ~NISH_SQLITE_OPEN_FLAGS) != 0 || (mode != 1 && mode != 2 && mode != 6)) {
|
|
140
|
+
strcpy(nishsqlite_open_message, sqlite3_errstr(SQLITE_MISUSE));
|
|
141
|
+
return -SQLITE_MISUSE;
|
|
142
|
+
}
|
|
143
|
+
sqlite3 *db = NULL;
|
|
144
|
+
int rc = sqlite3_open_v2(path, &db, flags | SQLITE_OPEN_EXRESCODE, NULL);
|
|
145
|
+
if (rc == SQLITE_OK) {
|
|
146
|
+
int32_t h = slot_take(&nishsqlite_dbs, db, 0);
|
|
147
|
+
if (h != 0) return h;
|
|
148
|
+
rc = SQLITE_NOMEM;
|
|
149
|
+
}
|
|
150
|
+
const char *message = db && rc != SQLITE_NOMEM ? sqlite3_errmsg(db) : sqlite3_errstr(rc);
|
|
151
|
+
strncpy(nishsqlite_open_message, message, sizeof nishsqlite_open_message - 1);
|
|
152
|
+
sqlite3_close_v2(db);
|
|
153
|
+
return -rc;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* The message of the last `nishsqlite_open` that failed on this thread. */
|
|
157
|
+
const char *nishsqlite_open_errmsg(void) { return nishsqlite_open_message; }
|
|
158
|
+
|
|
159
|
+
/* Finalizes every statement of the connection, frees their handles, then
|
|
160
|
+
* closes it. close_v2 rather than close, so a connection something else still
|
|
161
|
+
* holds (none can, today) is closed when that ends instead of staying open.
|
|
162
|
+
* The handle is freed only once the close succeeds, so a close that fails
|
|
163
|
+
* leaves the connection usable and its message readable. */
|
|
164
|
+
int32_t nishsqlite_close(int32_t h) {
|
|
165
|
+
sqlite3 *db = db_of(h);
|
|
166
|
+
if (db == NULL) return SQLITE_MISUSE;
|
|
167
|
+
nishsqlite_table *t = &nishsqlite_stmts;
|
|
168
|
+
for (int32_t i = 1; i < t->len; i++) {
|
|
169
|
+
if (t->at[i].p != NULL && t->at[i].owner == h) {
|
|
170
|
+
sqlite3_finalize((sqlite3_stmt *)t->at[i].p);
|
|
171
|
+
slot_give(t, (t->at[i].gen << 16) | i);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
int rc = sqlite3_close_v2(db);
|
|
175
|
+
if (rc == SQLITE_OK) slot_give(&nishsqlite_dbs, h);
|
|
176
|
+
return rc;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
int32_t nishsqlite_exec(int32_t h, const char *sql) {
|
|
180
|
+
sqlite3 *db = db_of(h);
|
|
181
|
+
return db ? sqlite3_exec(db, sql, NULL, NULL, NULL) : SQLITE_MISUSE;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* The connection's message for its last failure, or SQLITE_MISUSE's own for
|
|
185
|
+
* a handle that names no connection. */
|
|
186
|
+
const char *nishsqlite_errmsg(int32_t h) {
|
|
187
|
+
sqlite3 *db = db_of(h);
|
|
188
|
+
return db ? sqlite3_errmsg(db) : sqlite3_errstr(SQLITE_MISUSE);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
int64_t nishsqlite_last_insert_rowid(int32_t h) {
|
|
192
|
+
sqlite3 *db = db_of(h);
|
|
193
|
+
return db ? sqlite3_last_insert_rowid(db) : 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
int64_t nishsqlite_changes(int32_t h) {
|
|
197
|
+
sqlite3 *db = db_of(h);
|
|
198
|
+
return db ? sqlite3_changes64(db) : 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* ---- Statements --------------------------------------------------------- */
|
|
202
|
+
|
|
203
|
+
/* A statement handle for the first statement of `sql`, or the negated code.
|
|
204
|
+
* Text with no statement in it, only space or comments, is SQLITE_MISUSE:
|
|
205
|
+
* SQLite answers OK and no statement, which leaves nothing to hand back. */
|
|
206
|
+
int32_t nishsqlite_prepare(int32_t h, const char *sql) {
|
|
207
|
+
sqlite3 *db = db_of(h);
|
|
208
|
+
if (db == NULL) return -SQLITE_MISUSE;
|
|
209
|
+
sqlite3_stmt *st = NULL;
|
|
210
|
+
int rc = sqlite3_prepare_v3(db, sql, -1, SQLITE_PREPARE_PERSISTENT, &st, NULL);
|
|
211
|
+
if (rc != SQLITE_OK) return -rc;
|
|
212
|
+
if (st == NULL) return -SQLITE_MISUSE;
|
|
213
|
+
int32_t s = slot_take(&nishsqlite_stmts, st, h);
|
|
214
|
+
if (s != 0) return s;
|
|
215
|
+
sqlite3_finalize(st);
|
|
216
|
+
return -SQLITE_NOMEM;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* The message of the statement's connection, as `nishsqlite_errmsg`. */
|
|
220
|
+
const char *nishsqlite_stmt_errmsg(int32_t h) {
|
|
221
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
222
|
+
return st ? sqlite3_errmsg(sqlite3_db_handle(st)) : sqlite3_errstr(SQLITE_MISUSE);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
int32_t nishsqlite_finalize(int32_t h) {
|
|
226
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
227
|
+
if (st == NULL) return SQLITE_MISUSE;
|
|
228
|
+
sqlite3_finalize(st);
|
|
229
|
+
slot_give(&nishsqlite_stmts, h);
|
|
230
|
+
return SQLITE_OK;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
int32_t nishsqlite_step(int32_t h) {
|
|
234
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
235
|
+
return st ? sqlite3_step(st) : SQLITE_MISUSE;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* SQLite's reset answers the last step's failure again; the program has seen
|
|
239
|
+
* that from `step`, so this answers only whether the handle is good. */
|
|
240
|
+
int32_t nishsqlite_reset(int32_t h) {
|
|
241
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
242
|
+
if (st == NULL) return SQLITE_MISUSE;
|
|
243
|
+
sqlite3_reset(st);
|
|
244
|
+
return SQLITE_OK;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
int32_t nishsqlite_clear_bindings(int32_t h) {
|
|
248
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
249
|
+
return st ? sqlite3_clear_bindings(st) : SQLITE_MISUSE;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
int32_t nishsqlite_bind_i64(int32_t h, int32_t i, int64_t v) {
|
|
253
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
254
|
+
return st ? sqlite3_bind_int64(st, i, v) : SQLITE_MISUSE;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
int32_t nishsqlite_bind_f64(int32_t h, int32_t i, double v) {
|
|
258
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
259
|
+
return st ? sqlite3_bind_double(st, i, v) : SQLITE_MISUSE;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
int32_t nishsqlite_bind_null(int32_t h, int32_t i) {
|
|
263
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
264
|
+
return st ? sqlite3_bind_null(st, i) : SQLITE_MISUSE;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
int32_t nishsqlite_bind_text(int32_t h, int32_t i, const char *text) {
|
|
268
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
269
|
+
return st ? sqlite3_bind_text(st, i, text, -1, SQLITE_TRANSIENT) : SQLITE_MISUSE;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Binds `buf[off, off + len)`, `n` the buffer's length: as text when `blob` is
|
|
273
|
+
* 0, as a blob otherwise. A window outside the buffer is SQLITE_MISUSE. A
|
|
274
|
+
* window of no bytes binds the empty value, never NULL, which is what SQLite
|
|
275
|
+
* would bind for the pointer of an empty array. */
|
|
276
|
+
int32_t nishsqlite_bind_bytes(int32_t h, int32_t i, const uint8_t *buf, uint64_t n, int32_t off,
|
|
277
|
+
int32_t len, int32_t blob) {
|
|
278
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
279
|
+
if (st == NULL || off < 0 || len < 0 || (uint64_t)off + (uint64_t)len > n) return SQLITE_MISUSE;
|
|
280
|
+
const void *p = len == 0 ? (const void *)"" : (const void *)(buf + off);
|
|
281
|
+
return blob ? sqlite3_bind_blob(st, i, p, len, SQLITE_TRANSIENT)
|
|
282
|
+
: sqlite3_bind_text(st, i, (const char *)p, len, SQLITE_TRANSIENT);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* ---- Columns ------------------------------------------------------------ */
|
|
286
|
+
|
|
287
|
+
/* These answer what SQLite does for a column that is not there, 0 and
|
|
288
|
+
* SQLITE_NULL, for a handle that names no statement too: a read cannot fail,
|
|
289
|
+
* and the step before it already answered whether the statement is good. A
|
|
290
|
+
* column that is not there, or any column when no row is current (before the
|
|
291
|
+
* first step, or after the last), is answered here, before SQLite, which would
|
|
292
|
+
* otherwise record SQLITE_RANGE as the connection's last error. */
|
|
293
|
+
|
|
294
|
+
/* The statement `h` names, when its current row has a column `c`; NULL
|
|
295
|
+
* otherwise. sqlite3_data_count is 0 when no row is current. */
|
|
296
|
+
static inline sqlite3_stmt *column_of(int32_t h, int32_t c) {
|
|
297
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
298
|
+
return st && c >= 0 && c < sqlite3_data_count(st) ? st : NULL;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
int32_t nishsqlite_column_count(int32_t h) {
|
|
302
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
303
|
+
return st ? sqlite3_column_count(st) : 0;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
int32_t nishsqlite_column_type(int32_t h, int32_t c) {
|
|
307
|
+
sqlite3_stmt *st = column_of(h, c);
|
|
308
|
+
return st ? sqlite3_column_type(st, c) : SQLITE_NULL;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
int64_t nishsqlite_column_i64(int32_t h, int32_t c) {
|
|
312
|
+
sqlite3_stmt *st = column_of(h, c);
|
|
313
|
+
return st ? sqlite3_column_int64(st, c) : 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
double nishsqlite_column_f64(int32_t h, int32_t c) {
|
|
317
|
+
sqlite3_stmt *st = column_of(h, c);
|
|
318
|
+
return st ? sqlite3_column_double(st, c) : 0.0;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* The column's length in bytes as `nishsqlite_column_into` would copy it:
|
|
322
|
+
* a blob's bytes, or anything else as text. */
|
|
323
|
+
int32_t nishsqlite_column_bytes(int32_t h, int32_t c) {
|
|
324
|
+
sqlite3_stmt *st = column_of(h, c);
|
|
325
|
+
if (st == NULL) return 0;
|
|
326
|
+
if (sqlite3_column_type(st, c) != SQLITE_BLOB) sqlite3_column_text(st, c);
|
|
327
|
+
return sqlite3_column_bytes(st, c);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* The column as text, for a `string` result; NULL for SQL NULL. */
|
|
331
|
+
const char *nishsqlite_column_text(int32_t h, int32_t c) {
|
|
332
|
+
sqlite3_stmt *st = column_of(h, c);
|
|
333
|
+
return st ? (const char *)sqlite3_column_text(st, c) : NULL;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Copies column `c`, a blob's bytes or anything else as text, into `buf` at
|
|
337
|
+
* `at`, `n` the buffer's length, and answers the column's length. It copies
|
|
338
|
+
* only when all of it fits, so a length past `n - at` says how much room the
|
|
339
|
+
* read needs and nothing was written. SQLITE_MISUSE for a bad handle or an
|
|
340
|
+
* `at` outside `0..n`, SQLITE_RANGE for a column that is not there, and
|
|
341
|
+
* SQLITE_NOMEM when SQLite cannot convert a value to text, all negated. Only
|
|
342
|
+
* a NULL or a blob has no pointer and is still read: an empty blob has none.
|
|
343
|
+
* A column of the statement read when no row is current answers 0 and writes
|
|
344
|
+
* nothing, as a NULL does, without asking SQLite. */
|
|
345
|
+
int32_t nishsqlite_column_into(int32_t h, int32_t c, uint8_t *buf, uint64_t n, int32_t at) {
|
|
346
|
+
sqlite3_stmt *st = stmt_of(h);
|
|
347
|
+
if (st == NULL || at < 0 || (uint64_t)at > n) return -SQLITE_MISUSE;
|
|
348
|
+
/* With a row current sqlite3_data_count is the column count, so the row's
|
|
349
|
+
* path asks SQLite once where it would ask twice. */
|
|
350
|
+
int32_t cols = sqlite3_data_count(st);
|
|
351
|
+
if (cols == 0) return c < 0 || c >= sqlite3_column_count(st) ? -SQLITE_RANGE : 0;
|
|
352
|
+
if (c < 0 || c >= cols) return -SQLITE_RANGE;
|
|
353
|
+
int type = sqlite3_column_type(st, c);
|
|
354
|
+
const void *p = type == SQLITE_BLOB ? sqlite3_column_blob(st, c) : (const void *)sqlite3_column_text(st, c);
|
|
355
|
+
if (p == NULL && type != SQLITE_NULL && type != SQLITE_BLOB) return -SQLITE_NOMEM;
|
|
356
|
+
int32_t len = sqlite3_column_bytes(st, c);
|
|
357
|
+
if (p != NULL && (uint64_t)len <= n - (uint64_t)at) memcpy(buf + at, p, (size_t)len);
|
|
358
|
+
return len;
|
|
359
|
+
}
|