sqlrite 0.1.15__tar.gz → 0.1.17__tar.gz
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.
- {sqlrite-0.1.15 → sqlrite-0.1.17}/.github/workflows/release.yml +69 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/Cargo.lock +161 -5
- {sqlrite-0.1.15 → sqlrite-0.1.17}/Cargo.toml +9 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/PKG-INFO +59 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/README.md +36 -4
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/package.json +1 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/embedding.md +47 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/phase-7-plan.md +10 -6
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/release-plan.md +12 -3
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/roadmap.md +2 -2
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/supported-sql.md +33 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/pyproject.toml +1 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/scripts/bump-version.sh +7 -5
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/README.md +58 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/python/Cargo.toml +1 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/python/README.md +58 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/db/table.rs +50 -1
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/executor.rs +292 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/mod.rs +228 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/mod.rs +55 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/parser/create.rs +5 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/.github/workflows/ci.yml +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/.github/workflows/release-pr.yml +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/.github/workflows/rust.yml +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/.gitignore +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/CODE_OF_CONDUCT.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/LICENSE +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/MAINTAINERS +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/Makefile +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/index.html +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/package-lock.json +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/src/App.svelte +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/src/app.css +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/src/main.ts +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/src/vite-env.d.ts +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/svelte.config.js +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/tsconfig.json +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/desktop/vite.config.ts +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/_index.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/architecture.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/design-decisions.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/desktop.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/file-format.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/getting-started.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/pager.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/release-secrets.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/smoke-test.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/sql-engine.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/storage-model.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/docs/usage.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/README.md +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/c/Makefile +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/c/hello.c +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/go/go.mod +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/go/hello.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/nodejs/hello.mjs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/python/hello.py +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/rust/quickstart.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/wasm/Makefile +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/examples/wasm/index.html +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite - Desktop.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite Data Structures.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite Simple SQL Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite Simple SQL INSERT Execution High Level Diagram (Insert Row).png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite Simple SQL INSERT Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/SQLRite_logo.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/images/architecture.png +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/rust-toolchain.toml +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/AST.delete.example +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/AST.insert.exemple +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/AST.select.example +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/AST.update.example +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/CREATE TABLE sqlrite_schema.sql +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/CREATE_TABLE with duplicate.sql +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/CREATE_TABLE.sql +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/samples/INSERT.sql +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/conn.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/go.mod +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/rows.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/sqlrite.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/sqlrite_test.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/go/stmt.go +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/python/src/lib.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/sdk/python/tests/test_sqlrite.py +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/connection.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/error.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/lib.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/main.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/meta_command/mod.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/repl/mod.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/db/database.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/db/mod.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/db/secondary_index.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/hnsw.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/cell.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/file.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/header.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/hnsw_cell.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/index_cell.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/interior_page.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/overflow.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/page.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/pager.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/table_page.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/varint.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/pager/wal.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/parser/insert.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/parser/mod.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/parser/select.rs +0 -0
- {sqlrite-0.1.15 → sqlrite-0.1.17}/src/sql/tokenizer.rs +0 -0
|
@@ -126,6 +126,7 @@ jobs:
|
|
|
126
126
|
TAGS=(
|
|
127
127
|
"sqlrite-v$V"
|
|
128
128
|
"sqlrite-ffi-v$V"
|
|
129
|
+
"sqlrite-ask-v$V"
|
|
129
130
|
"sqlrite-desktop-v$V"
|
|
130
131
|
"sqlrite-py-v$V"
|
|
131
132
|
"sqlrite-node-v$V"
|
|
@@ -199,6 +200,73 @@ jobs:
|
|
|
199
200
|
See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
|
|
200
201
|
generate_release_notes: true
|
|
201
202
|
|
|
203
|
+
# ---------------------------------------------------------------------------
|
|
204
|
+
# Step 3a': publish the `sqlrite-ask` crate (Phase 7g.1) — natural-
|
|
205
|
+
# language → SQL adapter built on top of the engine. Same shape as
|
|
206
|
+
# `publish-crate` above; separate job so a registry hiccup on one
|
|
207
|
+
# doesn't block the other and re-runs are surgical.
|
|
208
|
+
#
|
|
209
|
+
# Crate name on crates.io: `sqlrite-ask`. Library name (the `use`
|
|
210
|
+
# path): `sqlrite_ask`. No alias-renaming this time — the short
|
|
211
|
+
# name was available unlike `sqlrite` (see Phase 6d retrospective
|
|
212
|
+
# for why the engine had to rename).
|
|
213
|
+
publish-ask:
|
|
214
|
+
name: Publish sqlrite-ask crate to crates.io
|
|
215
|
+
needs: [detect, tag-all, publish-crate]
|
|
216
|
+
if: needs.detect.outputs.should_release == 'true'
|
|
217
|
+
runs-on: ubuntu-latest
|
|
218
|
+
environment: release
|
|
219
|
+
steps:
|
|
220
|
+
- uses: actions/checkout@v4
|
|
221
|
+
|
|
222
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
223
|
+
|
|
224
|
+
- uses: Swatinem/rust-cache@v2
|
|
225
|
+
with:
|
|
226
|
+
shared-key: publish-ask
|
|
227
|
+
|
|
228
|
+
- name: cargo publish
|
|
229
|
+
env:
|
|
230
|
+
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
|
|
231
|
+
# `--no-verify` mirrors `publish-crate` — Release-PR CI
|
|
232
|
+
# already validated this commit.
|
|
233
|
+
#
|
|
234
|
+
# `needs: [..., publish-crate]` is load-bearing: sqlrite-ask
|
|
235
|
+
# depends on sqlrite-engine, and crates.io rejects publishes
|
|
236
|
+
# whose path-deps haven't yet resolved to a published version
|
|
237
|
+
# at the same number. Sequencing makes the dep visible by the
|
|
238
|
+
# time we publish.
|
|
239
|
+
run: cargo publish -p sqlrite-ask --no-verify
|
|
240
|
+
|
|
241
|
+
- name: GitHub Release
|
|
242
|
+
uses: softprops/action-gh-release@v2
|
|
243
|
+
with:
|
|
244
|
+
tag_name: sqlrite-ask-v${{ needs.detect.outputs.version }}
|
|
245
|
+
name: sqlrite-ask v${{ needs.detect.outputs.version }}
|
|
246
|
+
body: |
|
|
247
|
+
Published to crates.io: https://crates.io/crates/sqlrite-ask/${{ needs.detect.outputs.version }}
|
|
248
|
+
|
|
249
|
+
Natural-language → SQL adapter for SQLRite. Anthropic-first; OpenAI / Ollama follow-ups.
|
|
250
|
+
|
|
251
|
+
```toml
|
|
252
|
+
[dependencies]
|
|
253
|
+
sqlrite-engine = "${{ needs.detect.outputs.version }}"
|
|
254
|
+
sqlrite-ask = "${{ needs.detect.outputs.version }}"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```rust
|
|
258
|
+
use sqlrite::Connection;
|
|
259
|
+
use sqlrite_ask::{AskConfig, ConnectionAskExt};
|
|
260
|
+
|
|
261
|
+
let conn = Connection::open("foo.sqlrite")?;
|
|
262
|
+
let cfg = AskConfig::from_env()?; // SQLRITE_LLM_API_KEY etc.
|
|
263
|
+
let resp = conn.ask("How many users are over 30?", &cfg)?;
|
|
264
|
+
println!("Generated SQL: {}", resp.sql);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
|
|
268
|
+
generate_release_notes: true
|
|
269
|
+
|
|
202
270
|
# ---------------------------------------------------------------------------
|
|
203
271
|
# Step 3b: build `libsqlrite_c` for each supported platform and
|
|
204
272
|
# upload the tarballs to the `sqlrite-ffi-v<V>` GitHub Release.
|
|
@@ -1223,7 +1291,7 @@ jobs:
|
|
|
1223
1291
|
# config if we add one later.
|
|
1224
1292
|
finalize:
|
|
1225
1293
|
name: Finalize umbrella release
|
|
1226
|
-
needs: [detect, publish-crate, publish-ffi, publish-desktop, publish-python, publish-nodejs, publish-wasm, publish-go]
|
|
1294
|
+
needs: [detect, publish-crate, publish-ask, publish-ffi, publish-desktop, publish-python, publish-nodejs, publish-wasm, publish-go]
|
|
1227
1295
|
if: needs.detect.outputs.should_release == 'true'
|
|
1228
1296
|
runs-on: ubuntu-latest
|
|
1229
1297
|
steps:
|
|
@@ -106,6 +106,12 @@ dependencies = [
|
|
|
106
106
|
"object",
|
|
107
107
|
]
|
|
108
108
|
|
|
109
|
+
[[package]]
|
|
110
|
+
name = "ascii"
|
|
111
|
+
version = "1.1.0"
|
|
112
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
113
|
+
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
|
114
|
+
|
|
109
115
|
[[package]]
|
|
110
116
|
name = "atk"
|
|
111
117
|
version = "0.18.2"
|
|
@@ -396,6 +402,12 @@ dependencies = [
|
|
|
396
402
|
"windows-link 0.2.1",
|
|
397
403
|
]
|
|
398
404
|
|
|
405
|
+
[[package]]
|
|
406
|
+
name = "chunked_transfer"
|
|
407
|
+
version = "1.5.0"
|
|
408
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
409
|
+
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
|
|
410
|
+
|
|
399
411
|
[[package]]
|
|
400
412
|
name = "clap"
|
|
401
413
|
version = "4.6.1"
|
|
@@ -1557,6 +1569,12 @@ version = "1.10.1"
|
|
|
1557
1569
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1558
1570
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
|
1559
1571
|
|
|
1572
|
+
[[package]]
|
|
1573
|
+
name = "httpdate"
|
|
1574
|
+
version = "1.0.3"
|
|
1575
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1576
|
+
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|
1577
|
+
|
|
1560
1578
|
[[package]]
|
|
1561
1579
|
name = "hyper"
|
|
1562
1580
|
version = "1.9.0"
|
|
@@ -3267,6 +3285,20 @@ dependencies = [
|
|
|
3267
3285
|
"windows-sys 0.60.2",
|
|
3268
3286
|
]
|
|
3269
3287
|
|
|
3288
|
+
[[package]]
|
|
3289
|
+
name = "ring"
|
|
3290
|
+
version = "0.17.14"
|
|
3291
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3292
|
+
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|
3293
|
+
dependencies = [
|
|
3294
|
+
"cc",
|
|
3295
|
+
"cfg-if",
|
|
3296
|
+
"getrandom 0.2.17",
|
|
3297
|
+
"libc",
|
|
3298
|
+
"untrusted",
|
|
3299
|
+
"windows-sys 0.52.0",
|
|
3300
|
+
]
|
|
3301
|
+
|
|
3270
3302
|
[[package]]
|
|
3271
3303
|
name = "rustc-hash"
|
|
3272
3304
|
version = "2.1.2"
|
|
@@ -3295,6 +3327,41 @@ dependencies = [
|
|
|
3295
3327
|
"windows-sys 0.61.2",
|
|
3296
3328
|
]
|
|
3297
3329
|
|
|
3330
|
+
[[package]]
|
|
3331
|
+
name = "rustls"
|
|
3332
|
+
version = "0.23.40"
|
|
3333
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3334
|
+
checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
|
3335
|
+
dependencies = [
|
|
3336
|
+
"log",
|
|
3337
|
+
"once_cell",
|
|
3338
|
+
"ring",
|
|
3339
|
+
"rustls-pki-types",
|
|
3340
|
+
"rustls-webpki",
|
|
3341
|
+
"subtle",
|
|
3342
|
+
"zeroize",
|
|
3343
|
+
]
|
|
3344
|
+
|
|
3345
|
+
[[package]]
|
|
3346
|
+
name = "rustls-pki-types"
|
|
3347
|
+
version = "1.14.1"
|
|
3348
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3349
|
+
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
|
|
3350
|
+
dependencies = [
|
|
3351
|
+
"zeroize",
|
|
3352
|
+
]
|
|
3353
|
+
|
|
3354
|
+
[[package]]
|
|
3355
|
+
name = "rustls-webpki"
|
|
3356
|
+
version = "0.103.13"
|
|
3357
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3358
|
+
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
|
3359
|
+
dependencies = [
|
|
3360
|
+
"ring",
|
|
3361
|
+
"rustls-pki-types",
|
|
3362
|
+
"untrusted",
|
|
3363
|
+
]
|
|
3364
|
+
|
|
3298
3365
|
[[package]]
|
|
3299
3366
|
name = "rustversion"
|
|
3300
3367
|
version = "1.0.22"
|
|
@@ -3511,6 +3578,7 @@ version = "1.0.149"
|
|
|
3511
3578
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3512
3579
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
|
3513
3580
|
dependencies = [
|
|
3581
|
+
"indexmap 2.14.0",
|
|
3514
3582
|
"itoa",
|
|
3515
3583
|
"memchr",
|
|
3516
3584
|
"serde",
|
|
@@ -3734,9 +3802,21 @@ dependencies = [
|
|
|
3734
3802
|
"recursive",
|
|
3735
3803
|
]
|
|
3736
3804
|
|
|
3805
|
+
[[package]]
|
|
3806
|
+
name = "sqlrite-ask"
|
|
3807
|
+
version = "0.1.17"
|
|
3808
|
+
dependencies = [
|
|
3809
|
+
"serde",
|
|
3810
|
+
"serde_json",
|
|
3811
|
+
"sqlrite-engine",
|
|
3812
|
+
"thiserror 2.0.18",
|
|
3813
|
+
"tiny_http",
|
|
3814
|
+
"ureq",
|
|
3815
|
+
]
|
|
3816
|
+
|
|
3737
3817
|
[[package]]
|
|
3738
3818
|
name = "sqlrite-desktop"
|
|
3739
|
-
version = "0.1.
|
|
3819
|
+
version = "0.1.17"
|
|
3740
3820
|
dependencies = [
|
|
3741
3821
|
"serde",
|
|
3742
3822
|
"serde_json",
|
|
@@ -3748,7 +3828,7 @@ dependencies = [
|
|
|
3748
3828
|
|
|
3749
3829
|
[[package]]
|
|
3750
3830
|
name = "sqlrite-engine"
|
|
3751
|
-
version = "0.1.
|
|
3831
|
+
version = "0.1.17"
|
|
3752
3832
|
dependencies = [
|
|
3753
3833
|
"clap",
|
|
3754
3834
|
"env_logger",
|
|
@@ -3757,13 +3837,14 @@ dependencies = [
|
|
|
3757
3837
|
"prettytable-rs",
|
|
3758
3838
|
"rustyline",
|
|
3759
3839
|
"rustyline-derive",
|
|
3840
|
+
"serde_json",
|
|
3760
3841
|
"sqlparser",
|
|
3761
3842
|
"thiserror 2.0.18",
|
|
3762
3843
|
]
|
|
3763
3844
|
|
|
3764
3845
|
[[package]]
|
|
3765
3846
|
name = "sqlrite-ffi"
|
|
3766
|
-
version = "0.1.
|
|
3847
|
+
version = "0.1.17"
|
|
3767
3848
|
dependencies = [
|
|
3768
3849
|
"cbindgen",
|
|
3769
3850
|
"sqlrite-engine",
|
|
@@ -3771,7 +3852,7 @@ dependencies = [
|
|
|
3771
3852
|
|
|
3772
3853
|
[[package]]
|
|
3773
3854
|
name = "sqlrite-nodejs"
|
|
3774
|
-
version = "0.1.
|
|
3855
|
+
version = "0.1.17"
|
|
3775
3856
|
dependencies = [
|
|
3776
3857
|
"napi",
|
|
3777
3858
|
"napi-build",
|
|
@@ -3781,7 +3862,7 @@ dependencies = [
|
|
|
3781
3862
|
|
|
3782
3863
|
[[package]]
|
|
3783
3864
|
name = "sqlrite-python"
|
|
3784
|
-
version = "0.1.
|
|
3865
|
+
version = "0.1.17"
|
|
3785
3866
|
dependencies = [
|
|
3786
3867
|
"pyo3",
|
|
3787
3868
|
"sqlrite-engine",
|
|
@@ -3861,6 +3942,12 @@ version = "0.11.1"
|
|
|
3861
3942
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3862
3943
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|
3863
3944
|
|
|
3945
|
+
[[package]]
|
|
3946
|
+
name = "subtle"
|
|
3947
|
+
version = "2.6.1"
|
|
3948
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3949
|
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
3950
|
+
|
|
3864
3951
|
[[package]]
|
|
3865
3952
|
name = "swift-rs"
|
|
3866
3953
|
version = "1.0.7"
|
|
@@ -4371,6 +4458,18 @@ dependencies = [
|
|
|
4371
4458
|
"time-core",
|
|
4372
4459
|
]
|
|
4373
4460
|
|
|
4461
|
+
[[package]]
|
|
4462
|
+
name = "tiny_http"
|
|
4463
|
+
version = "0.12.0"
|
|
4464
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4465
|
+
checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82"
|
|
4466
|
+
dependencies = [
|
|
4467
|
+
"ascii",
|
|
4468
|
+
"chunked_transfer",
|
|
4469
|
+
"httpdate",
|
|
4470
|
+
"log",
|
|
4471
|
+
]
|
|
4472
|
+
|
|
4374
4473
|
[[package]]
|
|
4375
4474
|
name = "tinystr"
|
|
4376
4475
|
version = "0.8.3"
|
|
@@ -4694,6 +4793,30 @@ version = "0.2.4"
|
|
|
4694
4793
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4695
4794
|
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
4696
4795
|
|
|
4796
|
+
[[package]]
|
|
4797
|
+
name = "untrusted"
|
|
4798
|
+
version = "0.9.0"
|
|
4799
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4800
|
+
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
|
4801
|
+
|
|
4802
|
+
[[package]]
|
|
4803
|
+
name = "ureq"
|
|
4804
|
+
version = "2.12.1"
|
|
4805
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4806
|
+
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
|
|
4807
|
+
dependencies = [
|
|
4808
|
+
"base64 0.22.1",
|
|
4809
|
+
"flate2",
|
|
4810
|
+
"log",
|
|
4811
|
+
"once_cell",
|
|
4812
|
+
"rustls",
|
|
4813
|
+
"rustls-pki-types",
|
|
4814
|
+
"serde",
|
|
4815
|
+
"serde_json",
|
|
4816
|
+
"url",
|
|
4817
|
+
"webpki-roots 0.26.11",
|
|
4818
|
+
]
|
|
4819
|
+
|
|
4697
4820
|
[[package]]
|
|
4698
4821
|
name = "url"
|
|
4699
4822
|
version = "2.5.8"
|
|
@@ -4998,6 +5121,24 @@ dependencies = [
|
|
|
4998
5121
|
"system-deps",
|
|
4999
5122
|
]
|
|
5000
5123
|
|
|
5124
|
+
[[package]]
|
|
5125
|
+
name = "webpki-roots"
|
|
5126
|
+
version = "0.26.11"
|
|
5127
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
5128
|
+
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
|
|
5129
|
+
dependencies = [
|
|
5130
|
+
"webpki-roots 1.0.7",
|
|
5131
|
+
]
|
|
5132
|
+
|
|
5133
|
+
[[package]]
|
|
5134
|
+
name = "webpki-roots"
|
|
5135
|
+
version = "1.0.7"
|
|
5136
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
5137
|
+
checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
|
|
5138
|
+
dependencies = [
|
|
5139
|
+
"rustls-pki-types",
|
|
5140
|
+
]
|
|
5141
|
+
|
|
5001
5142
|
[[package]]
|
|
5002
5143
|
name = "webview2-com"
|
|
5003
5144
|
version = "0.38.2"
|
|
@@ -5228,6 +5369,15 @@ dependencies = [
|
|
|
5228
5369
|
"windows-targets 0.42.2",
|
|
5229
5370
|
]
|
|
5230
5371
|
|
|
5372
|
+
[[package]]
|
|
5373
|
+
name = "windows-sys"
|
|
5374
|
+
version = "0.52.0"
|
|
5375
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
5376
|
+
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
|
5377
|
+
dependencies = [
|
|
5378
|
+
"windows-targets 0.52.6",
|
|
5379
|
+
]
|
|
5380
|
+
|
|
5231
5381
|
[[package]]
|
|
5232
5382
|
name = "windows-sys"
|
|
5233
5383
|
version = "0.59.0"
|
|
@@ -5722,6 +5872,12 @@ dependencies = [
|
|
|
5722
5872
|
"synstructure",
|
|
5723
5873
|
]
|
|
5724
5874
|
|
|
5875
|
+
[[package]]
|
|
5876
|
+
name = "zeroize"
|
|
5877
|
+
version = "1.8.2"
|
|
5878
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
5879
|
+
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
|
5880
|
+
|
|
5725
5881
|
[[package]]
|
|
5726
5882
|
name = "zerotrie"
|
|
5727
5883
|
version = "0.2.4"
|
|
@@ -27,7 +27,7 @@ resolver = "3"
|
|
|
27
27
|
# `package =` key so the import name stays `sqlrite` internally:
|
|
28
28
|
# sqlrite = { package = "sqlrite-engine", path = "…" }
|
|
29
29
|
name = "sqlrite-engine"
|
|
30
|
-
version = "0.1.
|
|
30
|
+
version = "0.1.17"
|
|
31
31
|
authors = ["Joao Henrique Machado Silva <joaoh82@gmail.com>"]
|
|
32
32
|
edition = "2024"
|
|
33
33
|
rust-version = "1.85"
|
|
@@ -82,6 +82,14 @@ log = "0.4"
|
|
|
82
82
|
sqlparser = "0.61"
|
|
83
83
|
thiserror = "2.0"
|
|
84
84
|
prettytable-rs = "0.10"
|
|
85
|
+
# Phase 7e: JSON column type. `serde_json` powers both the validation
|
|
86
|
+
# step at INSERT time (parse-and-discard to confirm the text is valid
|
|
87
|
+
# JSON) and the path extraction inside the json_extract / json_type
|
|
88
|
+
# / json_array_length / json_object_keys SQL functions. `preserve_order`
|
|
89
|
+
# keeps object keys in insertion order so json_object_keys output is
|
|
90
|
+
# stable; without it, BTreeMap-backed Maps would alphabetically sort,
|
|
91
|
+
# which surprises callers re-serializing the same JSON.
|
|
92
|
+
serde_json = { version = "1", features = ["preserve_order"] }
|
|
85
93
|
|
|
86
94
|
# CLI-only deps (feature-gated). `optional = true` + the `cli`
|
|
87
95
|
# feature above means these only land in the dep graph when
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlrite
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.17
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -87,6 +87,64 @@ conn = sqlrite.connect_read_only("foo.sqlrite")
|
|
|
87
87
|
# connections on the same file coexist (shared OS lock).
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
### Vector columns + KNN (Phase 7a–7d)
|
|
91
|
+
|
|
92
|
+
The engine ships with a fixed-dimension `VECTOR(N)` storage class and three distance functions (`vec_distance_l2`, `vec_distance_cosine`, `vec_distance_dot`). Plain `cursor.execute(...)` is all you need from Python — values come back as Python lists of floats.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
cur.execute("CREATE TABLE docs (id INTEGER PRIMARY KEY, embedding VECTOR(384))")
|
|
96
|
+
cur.execute("INSERT INTO docs (id, embedding) VALUES (1, [0.1, 0.2, ..., 0.0])") # 384 floats
|
|
97
|
+
cur.execute("""
|
|
98
|
+
SELECT id FROM docs
|
|
99
|
+
ORDER BY vec_distance_l2(embedding, [0.1, 0.2, ..., 0.0])
|
|
100
|
+
LIMIT 10
|
|
101
|
+
""")
|
|
102
|
+
for row in cur:
|
|
103
|
+
print(row)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For larger collections, build an HNSW index — the executor will use it automatically when the `WHERE`/`ORDER BY` shape matches:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
cur.execute("CREATE INDEX idx_docs_emb ON docs USING hnsw (embedding)")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### JSON columns (Phase 7e)
|
|
113
|
+
|
|
114
|
+
`JSON` (and `JSONB` as an alias) columns store text, validated at INSERT/UPDATE time. Read with `json_extract` / `json_type` / `json_array_length` / `json_object_keys`. Path subset: `$`, `.key`, `[N]`, chained.
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
cur.execute("CREATE TABLE events (id INTEGER PRIMARY KEY, payload JSON)")
|
|
118
|
+
cur.execute(
|
|
119
|
+
"INSERT INTO events (payload) VALUES "
|
|
120
|
+
"('{\"user\": {\"name\": \"alice\"}, \"score\": 42}')"
|
|
121
|
+
)
|
|
122
|
+
cur.execute(
|
|
123
|
+
"SELECT json_extract(payload, '$.user.name'), json_type(payload, '$.score') FROM events"
|
|
124
|
+
)
|
|
125
|
+
print(cur.fetchall()) # [('alice', 'integer')]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
> `json_object_keys` returns a JSON-array text rather than a table-valued result (set-returning functions aren't supported yet).
|
|
129
|
+
|
|
130
|
+
### Natural-language → SQL (Phase 7g — *coming soon*)
|
|
131
|
+
|
|
132
|
+
The Phase 7g.2-7g.8 wave adds a Python-native `conn.ask()` that wraps the new `sqlrite-ask` Rust crate via PyO3. Today it's available only from Rust ([`sqlrite-ask` on crates.io](https://crates.io/crates/sqlrite-ask)); the Python wrapper lands in 7g.4 and will look like:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# 7g.4 preview — not yet released
|
|
136
|
+
import sqlrite
|
|
137
|
+
|
|
138
|
+
conn = sqlrite.connect("foo.sqlrite")
|
|
139
|
+
cfg = sqlrite.AskConfig.from_env() # SQLRITE_LLM_API_KEY etc.
|
|
140
|
+
resp = conn.ask("How many users are over 30?", cfg)
|
|
141
|
+
print(resp.sql) # "SELECT COUNT(*) FROM users WHERE age > 30"
|
|
142
|
+
print(resp.explanation) # "Counts users over the age threshold."
|
|
143
|
+
|
|
144
|
+
# Convenience:
|
|
145
|
+
rows = conn.ask_run("How many users are over 30?", cfg).fetchall()
|
|
146
|
+
```
|
|
147
|
+
|
|
90
148
|
## API surface
|
|
91
149
|
|
|
92
150
|
| Function / Method | Purpose |
|
|
@@ -158,6 +158,32 @@ Expressions in `WHERE` and `UPDATE`'s `SET` RHS:
|
|
|
158
158
|
| `.read FILENAME` | later |
|
|
159
159
|
| `.ast QUERY` | later |
|
|
160
160
|
|
|
161
|
+
#### Natural-language → SQL (`sqlrite-ask`)
|
|
162
|
+
|
|
163
|
+
*Phase 7g.1.* The companion crate [`sqlrite-ask`](sqlrite-ask/) turns a natural-language question into a SQL query against your database, using the [Anthropic API](https://docs.anthropic.com/) for the actual generation.
|
|
164
|
+
|
|
165
|
+
```toml
|
|
166
|
+
[dependencies]
|
|
167
|
+
sqlrite-engine = "0.1"
|
|
168
|
+
sqlrite-ask = "0.1"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```rust
|
|
172
|
+
use sqlrite::Connection;
|
|
173
|
+
use sqlrite_ask::{AskConfig, ConnectionAskExt};
|
|
174
|
+
|
|
175
|
+
let conn = Connection::open("foo.sqlrite")?;
|
|
176
|
+
let cfg = AskConfig::from_env()?; // SQLRITE_LLM_API_KEY etc.
|
|
177
|
+
let resp = conn.ask("How many users are over 30?", &cfg)?;
|
|
178
|
+
println!("Generated SQL: {}", resp.sql);
|
|
179
|
+
println!("Why: {}", resp.explanation);
|
|
180
|
+
// Caller decides whether to run resp.sql — the library deliberately doesn't.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Defaults:** `claude-sonnet-4-6`, `max_tokens: 1024`, schema dump cached for 5 minutes via Anthropic prompt caching (configurable to 1h or off via `AskConfig::cache_ttl`). Bring your own API key — set `SQLRITE_LLM_API_KEY` or pass it on `AskConfig`.
|
|
184
|
+
|
|
185
|
+
Per-product `ask()` wrappers (`.ask` REPL command, desktop "Ask" button, `conn.ask()` in the Python / Node / Go SDKs, and the MCP `ask` tool) ship in **7g.2-7g.8** as follow-up sub-phases. WASM gets a JS-callback shape so the API key never enters the browser. See [`docs/phase-7-plan.md`](docs/phase-7-plan.md) §7g for the full surface plan.
|
|
186
|
+
|
|
161
187
|
### Roadmap
|
|
162
188
|
|
|
163
189
|
The project is staged in phases, each independently shippable. A finished phase is committed to `main` before the next one starts.
|
|
@@ -236,10 +262,16 @@ Lockstep versioning — one dispatch bumps every product to the same `vX.Y.Z`. T
|
|
|
236
262
|
- [ ] macOS Apple Developer ID cert → `codesign` + `notarytool` in `tauri-action`
|
|
237
263
|
- [ ] Windows code-signing cert → `signtool` in `tauri-action`
|
|
238
264
|
|
|
239
|
-
**Phase 7 — AI-era extensions** *(
|
|
240
|
-
- [
|
|
241
|
-
- [
|
|
242
|
-
- [
|
|
265
|
+
**Phase 7 — AI-era extensions** *(in progress — full plan in [`docs/phase-7-plan.md`](docs/phase-7-plan.md))*
|
|
266
|
+
- [x] **7a — `VECTOR(N)` column type** *(v0.1.10)*: dense f32 vectors with bracket-array literal syntax (`[0.1, 0.2, ...]`); file format bumped to v4
|
|
267
|
+
- [x] **7b — Distance functions** *(v0.1.11)*: `vec_distance_l2/cosine/dot` + `ORDER BY <expr> LIMIT k` so KNN queries work end-to-end
|
|
268
|
+
- [x] **7c — Bounded-heap top-k optimization** *(v0.1.12)*
|
|
269
|
+
- [x] **7d — HNSW ANN index** *(v0.1.13–15)*: `CREATE INDEX … USING hnsw (col)`; recall@10 ≥ 0.95 at default `M=16, ef_construction=200, ef_search=50`; persisted as a `KIND_HNSW` cell tree
|
|
270
|
+
- [x] **7e — JSON column type + path queries** *(v0.1.16)*: `JSON` / `JSONB` columns stored as canonical text; `json_extract` / `json_type` / `json_array_length` / `json_object_keys`; `$.key`, `[N]`, chained JSONPath subset
|
|
271
|
+
- [x] **7g.1 — `sqlrite-ask` crate** *(this wave)*: foundational natural-language → SQL via the [Anthropic API](https://docs.anthropic.com/) (Sonnet 4.6 by default), prompt-cached schema dump, sync `ureq` HTTP. Public surface: `sqlrite_ask::ask(conn, q, &cfg)` or `conn.ask(q, &cfg)` via `ConnectionAskExt`.
|
|
272
|
+
- [ ] **7g.2-7g.8** — per-product `ask()` adapters: REPL `.ask`, desktop "Ask" button, Python/Node/Go/WASM SDKs, MCP `ask` tool
|
|
273
|
+
- [ ] **7h** — MCP server adapter (`sqlrite-mcp` binary)
|
|
274
|
+
- [ ] *(deferred to Phase 8)* Full-text search with BM25 + hybrid retrieval
|
|
243
275
|
|
|
244
276
|
**Possible extras** *(no committed phase)*
|
|
245
277
|
- Joins (`INNER`, `LEFT OUTER`, `CROSS` — SQLite does not support `RIGHT`/`FULL OUTER`)
|
|
@@ -71,6 +71,53 @@ See [Phase 4f notes in roadmap.md](roadmap.md) for the snapshot semantics and th
|
|
|
71
71
|
- **Parameter binding.** `stmt.query(&[&"alice"])` is the intended shape but the current implementation takes no arguments — use string interpolation for now. Parameter binding lands with the cursor refactor.
|
|
72
72
|
- **Cursor abstraction.** The Pager still eagerly loads every row at open time; `Rows` today wraps an in-memory `Vec`. Phase 5a's follow-up refactor streams rows through the B-Tree on demand — same public API, much lower memory for big SELECTs.
|
|
73
73
|
|
|
74
|
+
### Natural-language → SQL via `sqlrite-ask` (Phase 7g.1)
|
|
75
|
+
|
|
76
|
+
The companion crate [`sqlrite-ask`](../sqlrite-ask/) layers a natural-language → SQL helper on top of the engine. Engine stays pure-SQL with no HTTP / TLS / async deps; anyone who doesn't need `ask()` can ignore the crate entirely.
|
|
77
|
+
|
|
78
|
+
```toml
|
|
79
|
+
[dependencies]
|
|
80
|
+
sqlrite-engine = "0.1"
|
|
81
|
+
sqlrite-ask = "0.1"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```rust
|
|
85
|
+
use sqlrite::Connection;
|
|
86
|
+
use sqlrite_ask::{AskConfig, AskResponse, ConnectionAskExt};
|
|
87
|
+
|
|
88
|
+
let conn = Connection::open("foo.sqlrite")?;
|
|
89
|
+
let cfg = AskConfig::from_env()?; // reads SQLRITE_LLM_API_KEY etc.
|
|
90
|
+
let resp: AskResponse = conn.ask("How many users are over 30?", &cfg)?;
|
|
91
|
+
|
|
92
|
+
println!("Generated SQL: {}", resp.sql);
|
|
93
|
+
println!("Rationale: {}", resp.explanation);
|
|
94
|
+
println!("Tokens: in={}, out={}, cache_hit={}",
|
|
95
|
+
resp.usage.input_tokens,
|
|
96
|
+
resp.usage.output_tokens,
|
|
97
|
+
resp.usage.cache_read_input_tokens);
|
|
98
|
+
|
|
99
|
+
// Caller decides whether to execute the generated SQL — the library
|
|
100
|
+
// does NOT auto-execute. SDK convenience wrappers (Python's
|
|
101
|
+
// `conn.ask_run()`, Node's `db.askRun()`, etc.) add a one-shot
|
|
102
|
+
// generate-and-execute helper, but the default Rust API is
|
|
103
|
+
// "generate, return, let me decide".
|
|
104
|
+
let mut conn = conn; // need &mut for execute
|
|
105
|
+
let _ = conn.execute(&resp.sql)?;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**What `sqlrite-ask` provides:**
|
|
109
|
+
|
|
110
|
+
- `ask(conn, question, config) -> AskResponse` — free function entry point.
|
|
111
|
+
- `Connection::ask(question, config)` via the `ConnectionAskExt` trait — same flow, method syntax.
|
|
112
|
+
- `AskConfig::from_env()` — reads `SQLRITE_LLM_PROVIDER` / `_API_KEY` / `_MODEL` / `_MAX_TOKENS` / `_CACHE_TTL` with sensible defaults.
|
|
113
|
+
- `AnthropicProvider` — sync `ureq` POST to `https://api.anthropic.com/v1/messages`. The crate is provider-pluggable (a `Provider` trait + `Request` / `Response` types), with OpenAI and Ollama follow-ups planned for later 7g sub-phases.
|
|
114
|
+
- Schema-aware prompt construction — walks `Database.tables` deterministically (alphabetical) and emits a `<schema>...</schema>` block with `cache_control: ephemeral`, so the schema dump is served from Anthropic's prompt cache after the first call.
|
|
115
|
+
- Output parser tolerant to fenced JSON (`` ```json … ``` ``) or JSON-with-leading-prose, in addition to strict JSON.
|
|
116
|
+
|
|
117
|
+
**Defaults:** `claude-sonnet-4-6`, `max_tokens: 1024`, 5-minute prompt-cache TTL. Configurable via `AskConfig`.
|
|
118
|
+
|
|
119
|
+
**Per-product wrappers ship in 7g.2-7g.8** — REPL `.ask`, desktop "Ask" button, Python/Node/Go SDKs `conn.ask()`, WASM SDK with a JS-callback shape (so the API key stays out of the browser tab), and the MCP `ask` tool.
|
|
120
|
+
|
|
74
121
|
## The C FFI (Phase 5b)
|
|
75
122
|
|
|
76
123
|
The `sqlrite-ffi/` crate wraps the Rust API in a C ABI that every non-Rust SDK binds against. Build the shared library:
|
|
@@ -170,14 +170,14 @@ SELECT id, title FROM docs ORDER BY embedding <-> [0.1, ...] LIMIT 10;
|
|
|
170
170
|
|
|
171
171
|
---
|
|
172
172
|
|
|
173
|
-
### 7e — JSON column type + path queries
|
|
173
|
+
### ✅ 7e — JSON column type + path queries
|
|
174
174
|
|
|
175
|
-
**What.** New `JSON` data type.
|
|
175
|
+
**What.** New `JSON` data type. Stored as canonical UTF-8 text and validated at INSERT/UPDATE time via `serde_json::from_str`. The four path-extraction functions parse on demand:
|
|
176
176
|
|
|
177
177
|
- `json_extract(col, '$.path')` — returns the value at the path, NULL if absent
|
|
178
|
-
- `json_array_length(col, '$.path')` — array length, NULL for non-array
|
|
179
|
-
- `json_object_keys(col, '$.path')` —
|
|
180
|
-
- `json_type(col, '$.path')` — `'null'
|
|
178
|
+
- `json_array_length(col, '$.path')` — array length, NULL for non-array, errors for non-array-with-path-resolved
|
|
179
|
+
- `json_object_keys(col, '$.path')` — JSON-array text of keys (see scope-correction note in Q3 below; SQLite's set-returning shape requires features we don't have)
|
|
180
|
+
- `json_type(col, '$.path')` — `'null'` / `'true'` / `'false'` / `'integer'` / `'real'` / `'text'` / `'array'` / `'object'` (matches SQLite JSON1 conventions)
|
|
181
181
|
|
|
182
182
|
**Why this matters for AI-era specifically.** LLM tool-call outputs are JSON. RAG citation arrays are JSON. Agent scratchpads are JSON. Storing them as TEXT and re-parsing on every query is wasteful.
|
|
183
183
|
|
|
@@ -249,7 +249,7 @@ let rows = conn.execute(&resp.sql)?;
|
|
|
249
249
|
|
|
250
250
|
**Layered design.** The work splits into one library layer + several thin adapters:
|
|
251
251
|
|
|
252
|
-
-
|
|
252
|
+
- **✅ 7g.1 — `sqlrite-ask` crate (foundational, ~750 LOC code + tests).** New separate crate (not feature-gated on the engine) so the engine stays pure-SQL with no HTTP / async deps. Owns: provider adapters (Anthropic in 7g.1; OpenAI / Ollama follow-ups), prompt construction, schema introspection helper that walks `Database.tables` directly (typed walk — cheaper + more robust than reflecting through `sqlrite_master`), the `AskResponse` type, configuration loading from env (`SQLRITE_LLM_PROVIDER` / `_API_KEY` / `_MODEL` / `_MAX_TOKENS` / `_CACHE_TTL`) or a passed config struct. Depends on `sqlrite-engine` for the schema introspection. Public API: `ask()` free function, `ConnectionAskExt::ask` trait extension on `sqlrite::Connection`, `AskConfig::from_env()`, `AskResponse { sql, explanation, usage }`. Default model `claude-sonnet-4-6` per the cost-quality NL→SQL sweet spot. Sync `ureq` HTTP (rejected reqwest::blocking — pulls tokio in even on the blocking path); JSON request/response shapes hand-rolled in serde_json (~120 LOC) — there is no official Anthropic Rust SDK, and rolling our own matches Q5's "build it yourself" theme. Schema dump goes inside a `<schema>...</schema>` block with `cache_control: ephemeral` so repeat asks against the same DB hit Anthropic's prompt cache (5-min TTL default; 1-hour TTL via `CacheTtl::OneHour`). Output parsing is tolerant — strict JSON, fenced JSON, or JSON-with-leading-prose all parse — because real LLM output drifts even with strict prompts. 30 tests pass (26 unit + 4 integration via `tiny_http` localhost mock).
|
|
253
253
|
- **7g.2 — REPL `.ask` (~80 LOC).** Thin. Calls `sqlrite-ask`, prints the generated SQL, prompts `Y/n`, runs if confirmed. Most of the file is the rustyline integration.
|
|
254
254
|
- **7g.3 — Desktop UI (~150 LOC).** New "Ask" button + prompt input + inline SQL preview in the editor. Calls into `sqlrite-ask` from a Tauri command; the command lives in `desktop/src-tauri/`. Schema introspection runs server-side; HTTP call also server-side (so the API key stays in the app process, not the webview).
|
|
255
255
|
- **7g.4 — Python SDK (~80 LOC).** PyO3 wrapper around `sqlrite-ask`. `Connection.ask(question)` returns a Python object with `.sql` and `.explanation`. `Connection.ask_run(question)` is the convenience that calls `execute` after.
|
|
@@ -378,6 +378,10 @@ Q1–Q10 were resolved by the project owner on 2026-04-26. Each question keeps i
|
|
|
378
378
|
### Q3. JSON storage format
|
|
379
379
|
|
|
380
380
|
> **Decided: bincoded `serde_json::Value`** for the MVP. JSON indexing remains a future phase.
|
|
381
|
+
>
|
|
382
|
+
> **Scope correction (2026-04-28, during 7e implementation):** Q3's "bincoded `Value`" answer was settled before remembering that bincode was removed from the engine in Phase 3c (cell-based encoding replaced it). Rather than re-add bincode for one column type, **7e ships JSON-as-canonical-text** — same as SQLite's JSON1 extension. INSERT/UPDATE call `serde_json::from_str` to validate; the four `json_*` functions re-parse on demand. Trade-off: ~2× storage vs. binary, plus per-call parse overhead — both acceptable for MVP and consistent with SQLite's choice. JSONB-style binary indexing remains a future-phase optimization, but doesn't block 7e.
|
|
383
|
+
>
|
|
384
|
+
> One additional 7e divergence from the original plan: `json_object_keys` is supposed to be a *table-valued function* (one row per key, like SQLite's). We don't yet support set-returning functions in the executor, so 7e returns the keys as a JSON-array text instead. Caller can iterate via `json_array_length` + `json_extract` indexing. Documented in `docs/supported-sql.md` so users see the divergence up front.
|
|
381
385
|
|
|
382
386
|
- **bincoded `serde_json::Value`:** one-line implementation, fast read/write, opaque on disk.
|
|
383
387
|
- **Parsed AST as cell-encoded structure:** more code, but lets us index into JSON without a full deserialize.
|