sqlrite 0.1.16__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.16 → sqlrite-0.1.17}/.github/workflows/release.yml +69 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/Cargo.lock +159 -5
- {sqlrite-0.1.16 → sqlrite-0.1.17}/Cargo.toml +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/PKG-INFO +59 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/README.md +36 -4
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/package.json +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/embedding.md +47 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/phase-7-plan.md +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/release-plan.md +12 -3
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/roadmap.md +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/pyproject.toml +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/scripts/bump-version.sh +7 -5
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/README.md +58 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/python/Cargo.toml +1 -1
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/python/README.md +58 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/.github/workflows/ci.yml +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/.github/workflows/release-pr.yml +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/.github/workflows/rust.yml +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/.gitignore +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/CODE_OF_CONDUCT.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/LICENSE +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/MAINTAINERS +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/Makefile +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/index.html +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/package-lock.json +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/src/App.svelte +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/src/app.css +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/src/main.ts +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/src/vite-env.d.ts +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/svelte.config.js +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/tsconfig.json +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/desktop/vite.config.ts +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/_index.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/architecture.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/design-decisions.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/desktop.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/file-format.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/getting-started.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/pager.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/release-secrets.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/smoke-test.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/sql-engine.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/storage-model.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/supported-sql.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/docs/usage.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/README.md +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/c/Makefile +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/c/hello.c +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/go/go.mod +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/go/hello.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/nodejs/hello.mjs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/python/hello.py +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/rust/quickstart.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/wasm/Makefile +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/examples/wasm/index.html +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite - Desktop.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Data Structures.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Simple SQL Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Simple SQL INSERT Execution High Level Diagram (Insert Row).png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Simple SQL INSERT Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite_logo.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/images/architecture.png +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/rust-toolchain.toml +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/AST.delete.example +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/AST.insert.exemple +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/AST.select.example +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/AST.update.example +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/CREATE TABLE sqlrite_schema.sql +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/CREATE_TABLE with duplicate.sql +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/CREATE_TABLE.sql +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/samples/INSERT.sql +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/conn.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/go.mod +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/rows.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/sqlrite.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/sqlrite_test.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/go/stmt.go +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/python/src/lib.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/sdk/python/tests/test_sqlrite.py +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/connection.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/error.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/lib.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/main.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/meta_command/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/repl/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/db/database.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/db/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/db/secondary_index.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/db/table.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/executor.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/hnsw.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/cell.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/file.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/header.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/hnsw_cell.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/index_cell.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/interior_page.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/overflow.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/page.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/pager.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/table_page.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/varint.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/pager/wal.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/parser/create.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/parser/insert.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/parser/mod.rs +0 -0
- {sqlrite-0.1.16 → sqlrite-0.1.17}/src/sql/parser/select.rs +0 -0
- {sqlrite-0.1.16 → 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"
|
|
@@ -3735,9 +3802,21 @@ dependencies = [
|
|
|
3735
3802
|
"recursive",
|
|
3736
3803
|
]
|
|
3737
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
|
+
|
|
3738
3817
|
[[package]]
|
|
3739
3818
|
name = "sqlrite-desktop"
|
|
3740
|
-
version = "0.1.
|
|
3819
|
+
version = "0.1.17"
|
|
3741
3820
|
dependencies = [
|
|
3742
3821
|
"serde",
|
|
3743
3822
|
"serde_json",
|
|
@@ -3749,7 +3828,7 @@ dependencies = [
|
|
|
3749
3828
|
|
|
3750
3829
|
[[package]]
|
|
3751
3830
|
name = "sqlrite-engine"
|
|
3752
|
-
version = "0.1.
|
|
3831
|
+
version = "0.1.17"
|
|
3753
3832
|
dependencies = [
|
|
3754
3833
|
"clap",
|
|
3755
3834
|
"env_logger",
|
|
@@ -3765,7 +3844,7 @@ dependencies = [
|
|
|
3765
3844
|
|
|
3766
3845
|
[[package]]
|
|
3767
3846
|
name = "sqlrite-ffi"
|
|
3768
|
-
version = "0.1.
|
|
3847
|
+
version = "0.1.17"
|
|
3769
3848
|
dependencies = [
|
|
3770
3849
|
"cbindgen",
|
|
3771
3850
|
"sqlrite-engine",
|
|
@@ -3773,7 +3852,7 @@ dependencies = [
|
|
|
3773
3852
|
|
|
3774
3853
|
[[package]]
|
|
3775
3854
|
name = "sqlrite-nodejs"
|
|
3776
|
-
version = "0.1.
|
|
3855
|
+
version = "0.1.17"
|
|
3777
3856
|
dependencies = [
|
|
3778
3857
|
"napi",
|
|
3779
3858
|
"napi-build",
|
|
@@ -3783,7 +3862,7 @@ dependencies = [
|
|
|
3783
3862
|
|
|
3784
3863
|
[[package]]
|
|
3785
3864
|
name = "sqlrite-python"
|
|
3786
|
-
version = "0.1.
|
|
3865
|
+
version = "0.1.17"
|
|
3787
3866
|
dependencies = [
|
|
3788
3867
|
"pyo3",
|
|
3789
3868
|
"sqlrite-engine",
|
|
@@ -3863,6 +3942,12 @@ version = "0.11.1"
|
|
|
3863
3942
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3864
3943
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|
3865
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
|
+
|
|
3866
3951
|
[[package]]
|
|
3867
3952
|
name = "swift-rs"
|
|
3868
3953
|
version = "1.0.7"
|
|
@@ -4373,6 +4458,18 @@ dependencies = [
|
|
|
4373
4458
|
"time-core",
|
|
4374
4459
|
]
|
|
4375
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
|
+
|
|
4376
4473
|
[[package]]
|
|
4377
4474
|
name = "tinystr"
|
|
4378
4475
|
version = "0.8.3"
|
|
@@ -4696,6 +4793,30 @@ version = "0.2.4"
|
|
|
4696
4793
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4697
4794
|
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
4698
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
|
+
|
|
4699
4820
|
[[package]]
|
|
4700
4821
|
name = "url"
|
|
4701
4822
|
version = "2.5.8"
|
|
@@ -5000,6 +5121,24 @@ dependencies = [
|
|
|
5000
5121
|
"system-deps",
|
|
5001
5122
|
]
|
|
5002
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
|
+
|
|
5003
5142
|
[[package]]
|
|
5004
5143
|
name = "webview2-com"
|
|
5005
5144
|
version = "0.38.2"
|
|
@@ -5230,6 +5369,15 @@ dependencies = [
|
|
|
5230
5369
|
"windows-targets 0.42.2",
|
|
5231
5370
|
]
|
|
5232
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
|
+
|
|
5233
5381
|
[[package]]
|
|
5234
5382
|
name = "windows-sys"
|
|
5235
5383
|
version = "0.59.0"
|
|
@@ -5724,6 +5872,12 @@ dependencies = [
|
|
|
5724
5872
|
"synstructure",
|
|
5725
5873
|
]
|
|
5726
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
|
+
|
|
5727
5881
|
[[package]]
|
|
5728
5882
|
name = "zerotrie"
|
|
5729
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"
|
|
@@ -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:
|
|
@@ -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.
|
|
@@ -72,19 +72,27 @@ GitHub Releases by product ("show me every Python release").
|
|
|
72
72
|
|-----------------|------------------------|--------------------------------------------------|
|
|
73
73
|
| Rust engine | `sqlrite-vX.Y.Z` | crates.io + GitHub Release |
|
|
74
74
|
| C FFI shim | `sqlrite-ffi-vX.Y.Z` | GitHub Release (per-platform tarballs) |
|
|
75
|
+
| `sqlrite-ask` | `sqlrite-ask-vX.Y.Z` | crates.io + GitHub Release |
|
|
75
76
|
| Python SDK | `sqlrite-py-vX.Y.Z` | PyPI + GitHub Release |
|
|
76
77
|
| Node.js SDK | `sqlrite-node-vX.Y.Z` | npm (`@joaoh82/sqlrite`) + GitHub Release |
|
|
77
78
|
| Go SDK | `sdk/go/vX.Y.Z` | Git tag (no registry) + GitHub Release assets |
|
|
78
79
|
| WASM | `sqlrite-wasm-vX.Y.Z` | npm (`@joaoh82/sqlrite-wasm`) + GitHub Release |
|
|
79
80
|
| Desktop app | `sqlrite-desktop-vX.Y.Z` | GitHub Release (unsigned installers) |
|
|
80
|
-
| **Meta** | `vX.Y.Z` | GitHub Release (links to the other
|
|
81
|
+
| **Meta** | `vX.Y.Z` | GitHub Release (links to the other eight; acts as the "this was release 0.2.0" anchor) |
|
|
81
82
|
|
|
82
|
-
All
|
|
83
|
+
All nine tags point at the same commit — the merge commit of the
|
|
83
84
|
release PR. The meta tag is the umbrella release users can link to
|
|
84
|
-
in announcements; the
|
|
85
|
+
in announcements; the eight per-product tags are for tooling
|
|
85
86
|
(crates.io, Go module proxy, npm dist-tags, etc.) that expects a
|
|
86
87
|
specific format.
|
|
87
88
|
|
|
89
|
+
> **`sqlrite-ask` joined the lockstep wave in v0.1.17 (Phase 7g.1).** Gets
|
|
90
|
+
> its own tag and crates.io publish but ships in lockstep with everything
|
|
91
|
+
> else — same version every wave. `publish-ask` runs after `publish-crate`
|
|
92
|
+
> in `release.yml` because crates.io rejects publishes whose path-deps
|
|
93
|
+
> haven't yet resolved at the same version. `sqlrite-mcp` (Phase 7h) will
|
|
94
|
+
> add a ninth product line on the same pattern.
|
|
95
|
+
|
|
88
96
|
## Version bumping: exact file list
|
|
89
97
|
|
|
90
98
|
The release workflow edits these files in a single commit (the
|
|
@@ -95,6 +103,7 @@ matching new value:
|
|
|
95
103
|
|------------------------------------------|---------------------------------------------|
|
|
96
104
|
| `Cargo.toml` (root) | `[package].version` |
|
|
97
105
|
| `sqlrite-ffi/Cargo.toml` | `[package].version` |
|
|
106
|
+
| `sqlrite-ask/Cargo.toml` | `[package].version` |
|
|
98
107
|
| `sdk/python/Cargo.toml` | `[package].version` |
|
|
99
108
|
| `sdk/python/pyproject.toml` | `[project].version` |
|
|
100
109
|
| `sdk/nodejs/Cargo.toml` | `[package].version` |
|
|
@@ -476,7 +476,7 @@ Approved sub-phases (Q1–Q10 resolved):
|
|
|
476
476
|
- **✅ 7d — HNSW ANN index** — three PRs: 7d.1 (algorithm w/ recall@10 ≥ 0.95), 7d.2 (SQL integration + query optimizer), 7d.3 (persistence + DELETE/UPDATE rebuild). `CREATE INDEX … USING hnsw (col)`; fixed defaults `M=16, ef_construction=200, ef_search=50` (Q2). New `KIND_HNSW` cell tag.
|
|
477
477
|
- **✅ 7e — JSON column type + path queries** — `JSON` data type stored as canonical text (validated via `serde_json::from_str` at INSERT/UPDATE time; SQLite-JSON1-style — Q3 scope correction since bincode was removed in Phase 3c). Functions: `json_extract` / `json_type` / `json_array_length` / `json_object_keys`. Path subset supports `$`, `.key`, `[N]`, chained. `json_object_keys` returns a JSON-array text rather than a table-valued result (no set-returning functions in the executor yet).
|
|
478
478
|
- **7f — ~~Full-text search with BM25~~** — **deferred to Phase 8** (Q1).
|
|
479
|
-
- **7g — `ask()` API across the product surface** — natural-language → SQL via Anthropic API (Q4), Anthropic-first then OpenAI + Ollama follow-ups. Foundational 7g.1 introduces a new `sqlrite-ask` crate (Q10 — separate crate, not a feature flag). Thin per-product adapters in 7g.2-7g.8 cover REPL, desktop, Python, Node.js, Go, WASM (JS-callback shape per Q9), and the MCP `ask` tool.
|
|
479
|
+
- **7g — `ask()` API across the product surface** — natural-language → SQL via Anthropic API (Q4), Anthropic-first then OpenAI + Ollama follow-ups. Foundational **✅ 7g.1** introduces a new `sqlrite-ask` crate (Q10 — separate crate, not a feature flag) — `ask()` free function + `ConnectionAskExt` trait + `AskConfig::from_env()`, sync `ureq` POST to `/v1/messages`, schema-aware prompt with prompt-caching on the schema dump (Sonnet 4.6 default; configurable). Thin per-product adapters in 7g.2-7g.8 cover REPL, desktop, Python, Node.js, Go, WASM (JS-callback shape per Q9), and the MCP `ask` tool — and fold in the SDK README catch-up for VECTOR / JSON / HNSW capabilities along the way.
|
|
480
480
|
- **7h — MCP server adapter** — new `sqlrite-mcp` binary, hand-rolled JSON-RPC + tool framework (Q5).
|
|
481
481
|
|
|
482
482
|
Total scope budget: ~3-4 kLOC of new Rust across the wave. Each sub-phase ships as its own PR + release wave through the Phase 6 pipeline. The Phase 7 wave will likely close out **v0.2.0** (first minor bump after the 0.1.x Phase 6 cycle). Two new product lines added to lockstep versioning: `sqlrite-ask` and `sqlrite-mcp`.
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sqlrite"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.17"
|
|
8
8
|
description = "Python bindings for SQLRite — a small, embeddable SQLite clone written in Rust."
|
|
9
9
|
authors = [{ name = "Joao Henrique Machado Silva", email = "joaoh82@gmail.com" }]
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
# Usage:
|
|
6
6
|
# scripts/bump-version.sh 0.2.0
|
|
7
7
|
#
|
|
8
|
-
# Rewrites the version field in every manifest that carries one
|
|
9
|
-
# Cargo.toml / pyproject.toml files, plus three JSON manifests
|
|
10
|
-
# files total). Then you run `cargo build` yourself to
|
|
11
|
-
# Cargo.lock. Idempotent: running twice with the same version
|
|
12
|
-
# no-op; running twice with different versions lands on the
|
|
8
|
+
# Rewrites the version field in every manifest that carries one
|
|
9
|
+
# (eight Cargo.toml / pyproject.toml files, plus three JSON manifests
|
|
10
|
+
# — eleven files total). Then you run `cargo build` yourself to
|
|
11
|
+
# refresh Cargo.lock. Idempotent: running twice with the same version
|
|
12
|
+
# is a no-op; running twice with different versions lands on the
|
|
13
|
+
# second.
|
|
13
14
|
#
|
|
14
15
|
# Used by:
|
|
15
16
|
# - `release-pr.yml` GitHub Actions workflow as the version-bump
|
|
@@ -67,6 +68,7 @@ cd "$REPO_ROOT"
|
|
|
67
68
|
TOML_FILES=(
|
|
68
69
|
"Cargo.toml"
|
|
69
70
|
"sqlrite-ffi/Cargo.toml"
|
|
71
|
+
"sqlrite-ask/Cargo.toml"
|
|
70
72
|
"sdk/python/Cargo.toml"
|
|
71
73
|
"sdk/python/pyproject.toml"
|
|
72
74
|
"sdk/nodejs/Cargo.toml"
|
|
@@ -82,6 +82,64 @@ defer ro.Close()
|
|
|
82
82
|
// Reads work; any Exec throws with "read-only" in the message.
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### Vector columns + KNN (Phase 7a–7d)
|
|
86
|
+
|
|
87
|
+
`VECTOR(N)` storage class plus `vec_distance_l2` / `vec_distance_cosine` / `vec_distance_dot` distance functions. Vector literals are JSON-style bracket arrays `[0.1, 0.2, ...]`. Today the Go side bridges them as text — `database/sql` doesn't yet have a typed accessor for vectors:
|
|
88
|
+
|
|
89
|
+
```go
|
|
90
|
+
db.Exec(`CREATE TABLE docs (id INTEGER PRIMARY KEY, embedding VECTOR(384))`)
|
|
91
|
+
db.Exec(`INSERT INTO docs (id, embedding) VALUES (1, [0.1, 0.2, ..., 0.0])`)
|
|
92
|
+
|
|
93
|
+
rows, _ := db.Query(`
|
|
94
|
+
SELECT id FROM docs
|
|
95
|
+
ORDER BY vec_distance_l2(embedding, [0.1, 0.2, ..., 0.0])
|
|
96
|
+
LIMIT 10
|
|
97
|
+
`)
|
|
98
|
+
defer rows.Close()
|
|
99
|
+
for rows.Next() {
|
|
100
|
+
var id int64
|
|
101
|
+
rows.Scan(&id)
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For larger collections, build an HNSW index — the executor uses it automatically:
|
|
106
|
+
|
|
107
|
+
```go
|
|
108
|
+
db.Exec(`CREATE INDEX idx_docs_emb ON docs USING hnsw (embedding)`)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### JSON columns (Phase 7e)
|
|
112
|
+
|
|
113
|
+
`JSON` (and `JSONB` as an alias) columns are validated at INSERT/UPDATE time. Read with `json_extract` / `json_type` / `json_array_length` / `json_object_keys`. Path subset: `$`, `.key`, `[N]`, chained.
|
|
114
|
+
|
|
115
|
+
```go
|
|
116
|
+
db.Exec(`CREATE TABLE events (id INTEGER PRIMARY KEY, payload JSON)`)
|
|
117
|
+
db.Exec(`INSERT INTO events (payload) VALUES ('{"user": {"name": "alice"}, "score": 42}')`)
|
|
118
|
+
|
|
119
|
+
var name string
|
|
120
|
+
db.QueryRow(`SELECT json_extract(payload, '$.user.name') FROM events`).Scan(&name)
|
|
121
|
+
fmt.Println(name) // alice
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
> `json_object_keys` returns a JSON-array text rather than a table-valued result (set-returning functions aren't supported yet).
|
|
125
|
+
|
|
126
|
+
### Natural-language → SQL (Phase 7g — *coming soon*)
|
|
127
|
+
|
|
128
|
+
The Phase 7g.2-7g.8 wave adds `sqlrite.Ask(db, ...)` / `sqlrite.AskRun(db, ...)` that wrap the new [`sqlrite-ask`](https://crates.io/crates/sqlrite-ask) Rust crate through cgo. Today it's available only from Rust; the Go wrapper lands in 7g.6 and will look like:
|
|
129
|
+
|
|
130
|
+
```go
|
|
131
|
+
// 7g.6 preview — not yet released
|
|
132
|
+
import "github.com/joaoh82/rust_sqlite/sdk/go"
|
|
133
|
+
|
|
134
|
+
cfg := sqlrite.AskConfigFromEnv() // SQLRITE_LLM_API_KEY etc.
|
|
135
|
+
resp, err := sqlrite.Ask(db, "How many users are over 30?", cfg)
|
|
136
|
+
fmt.Println(resp.SQL) // "SELECT COUNT(*) FROM users WHERE age > 30"
|
|
137
|
+
fmt.Println(resp.Explanation) // "Counts users over the age threshold."
|
|
138
|
+
|
|
139
|
+
// Convenience:
|
|
140
|
+
rows, _ := sqlrite.AskRun(db, "How many users are over 30?", cfg)
|
|
141
|
+
```
|
|
142
|
+
|
|
85
143
|
## API surface
|
|
86
144
|
|
|
87
145
|
| Symbol | Purpose |
|
|
@@ -62,6 +62,64 @@ conn = sqlrite.connect_read_only("foo.sqlrite")
|
|
|
62
62
|
# connections on the same file coexist (shared OS lock).
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### Vector columns + KNN (Phase 7a–7d)
|
|
66
|
+
|
|
67
|
+
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.
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
cur.execute("CREATE TABLE docs (id INTEGER PRIMARY KEY, embedding VECTOR(384))")
|
|
71
|
+
cur.execute("INSERT INTO docs (id, embedding) VALUES (1, [0.1, 0.2, ..., 0.0])") # 384 floats
|
|
72
|
+
cur.execute("""
|
|
73
|
+
SELECT id FROM docs
|
|
74
|
+
ORDER BY vec_distance_l2(embedding, [0.1, 0.2, ..., 0.0])
|
|
75
|
+
LIMIT 10
|
|
76
|
+
""")
|
|
77
|
+
for row in cur:
|
|
78
|
+
print(row)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For larger collections, build an HNSW index — the executor will use it automatically when the `WHERE`/`ORDER BY` shape matches:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
cur.execute("CREATE INDEX idx_docs_emb ON docs USING hnsw (embedding)")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### JSON columns (Phase 7e)
|
|
88
|
+
|
|
89
|
+
`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.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
cur.execute("CREATE TABLE events (id INTEGER PRIMARY KEY, payload JSON)")
|
|
93
|
+
cur.execute(
|
|
94
|
+
"INSERT INTO events (payload) VALUES "
|
|
95
|
+
"('{\"user\": {\"name\": \"alice\"}, \"score\": 42}')"
|
|
96
|
+
)
|
|
97
|
+
cur.execute(
|
|
98
|
+
"SELECT json_extract(payload, '$.user.name'), json_type(payload, '$.score') FROM events"
|
|
99
|
+
)
|
|
100
|
+
print(cur.fetchall()) # [('alice', 'integer')]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> `json_object_keys` returns a JSON-array text rather than a table-valued result (set-returning functions aren't supported yet).
|
|
104
|
+
|
|
105
|
+
### Natural-language → SQL (Phase 7g — *coming soon*)
|
|
106
|
+
|
|
107
|
+
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:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# 7g.4 preview — not yet released
|
|
111
|
+
import sqlrite
|
|
112
|
+
|
|
113
|
+
conn = sqlrite.connect("foo.sqlrite")
|
|
114
|
+
cfg = sqlrite.AskConfig.from_env() # SQLRITE_LLM_API_KEY etc.
|
|
115
|
+
resp = conn.ask("How many users are over 30?", cfg)
|
|
116
|
+
print(resp.sql) # "SELECT COUNT(*) FROM users WHERE age > 30"
|
|
117
|
+
print(resp.explanation) # "Counts users over the age threshold."
|
|
118
|
+
|
|
119
|
+
# Convenience:
|
|
120
|
+
rows = conn.ask_run("How many users are over 30?", cfg).fetchall()
|
|
121
|
+
```
|
|
122
|
+
|
|
65
123
|
## API surface
|
|
66
124
|
|
|
67
125
|
| Function / Method | Purpose |
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Simple SQL Execution High Level Diagram.png
RENAMED
|
File without changes
|
|
File without changes
|
{sqlrite-0.1.16 → sqlrite-0.1.17}/images/SQLRite Simple SQL INSERT Execution High Level Diagram.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|