Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd529b4e1c | ||
|
|
5333f203e0 | ||
|
|
5db4440521 | ||
|
|
ca962ab55b | ||
|
|
fab434685b | ||
|
|
aeb79a1e8f | ||
|
|
764539773a | ||
|
|
2900c3e2a1 | ||
|
|
d581398704 | ||
|
|
f063720e7f | ||
|
|
cc974a6e22 | ||
|
|
2f00389562 | ||
|
|
25266ab966 | ||
|
|
dc662cff13 | ||
|
|
174151ad8f | ||
|
|
312b416f2a | ||
|
|
b7dd234638 | ||
|
|
c5396f115d | ||
|
|
89efb65dbb | ||
|
|
a2be335b4f | ||
|
|
ce78ca9e71 | ||
|
|
79143838cd | ||
|
|
3bd7753abc | ||
|
|
57d9e999b5 | ||
|
|
7c278c53d1 |
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo 'set -eux' > test.sh
|
||||
|
||||
for p in $(go list ./...); do
|
||||
dir=".${p#github.com/ncruces/go-sqlite3}"
|
||||
name="$(basename "$p").test"
|
||||
(cd ${dir}; go test -c ${BUILDFLAGS:-})
|
||||
[ -f "${dir}/${name}" ] && echo "(cd ${dir}; ./${name} ${TESTFLAGS:-})" >> test.sh
|
||||
done
|
||||
|
||||
if [[ -v VMACTIONS ]]; then
|
||||
envsubst < .github/actions/vmactions/template.yml > .github/actions/vmactions/action.yml
|
||||
fi
|
||||
@@ -1,260 +0,0 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'main' ]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
- '**.wasm'
|
||||
- '**.yml'
|
||||
pull_request:
|
||||
branches: [ 'main' ]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
- '**.wasm'
|
||||
- '**.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Format
|
||||
run: gofmt -s -w . && git diff --exit-code
|
||||
if: matrix.os != 'windows-latest'
|
||||
|
||||
- name: Tidy
|
||||
run: go mod tidy && git diff --exit-code
|
||||
|
||||
- name: Download
|
||||
run: go mod download
|
||||
|
||||
- name: Verify
|
||||
run: go mod verify
|
||||
|
||||
- name: Vet
|
||||
run: go vet ./...
|
||||
|
||||
- name: Build
|
||||
run: go build ./...
|
||||
|
||||
- name: Test
|
||||
run: go test ./... -bench . -benchtime=1x
|
||||
|
||||
- name: Test BSD locks
|
||||
run: go test -tags sqlite3_flock ./...
|
||||
if: matrix.os != 'windows-latest'
|
||||
|
||||
- name: Test dot locks
|
||||
run: go test -tags sqlite3_dotlk ./...
|
||||
if: matrix.os != 'windows-latest'
|
||||
|
||||
- name: Test modules
|
||||
shell: bash
|
||||
run: |
|
||||
go work init .
|
||||
go work use -r gormlite
|
||||
go test ./gormlite
|
||||
|
||||
- name: Test GORM
|
||||
shell: bash
|
||||
run: gormlite/test.sh
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- name: Collect coverage
|
||||
run: |
|
||||
go get -tool github.com/dave/courtney@v0.4.4
|
||||
go tool courtney
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
matrix.os == 'ubuntu-latest'
|
||||
|
||||
- uses: ncruces/go-coverage-report@v0
|
||||
with:
|
||||
coverage-file: coverage.out
|
||||
chart: true
|
||||
amend: true
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
matrix.os == 'ubuntu-latest'
|
||||
|
||||
test-cross:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: freebsd
|
||||
version: '15.0'
|
||||
- name: netbsd
|
||||
version: '10.1'
|
||||
- name: illumos
|
||||
action: omnios
|
||||
version: 'r151056'
|
||||
tflags: '-test.short'
|
||||
- name: openbsd
|
||||
version: '7.8'
|
||||
tflags: '-test.short'
|
||||
- name: freebsd
|
||||
arch: arm64
|
||||
version: '15.0'
|
||||
tflags: '-test.short'
|
||||
- name: netbsd
|
||||
arch: arm64
|
||||
version: '10.1'
|
||||
tflags: '-test.short'
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GOOS: ${{ matrix.os.name }}
|
||||
GOARCH: ${{ matrix.os.arch }}
|
||||
TESTFLAGS: ${{ matrix.os.tflags }}
|
||||
run: .github/workflows/build-test.sh
|
||||
|
||||
- name: Test
|
||||
uses: cross-platform-actions/action@v1.0.0
|
||||
with:
|
||||
operating_system: ${{ matrix.os.action || matrix.os.name }}
|
||||
architecture: ${{ matrix.os.arch }}
|
||||
version: ${{ matrix.os.version }}
|
||||
shell: bash
|
||||
run: . ./test.sh
|
||||
sync_files: runner-to-vm
|
||||
|
||||
test-vm:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: dragonfly
|
||||
action: 'vmactions/dragonflybsd-vm@v1'
|
||||
tflags: '-test.short'
|
||||
- name: illumos
|
||||
action: 'vmactions/openindiana-vm@v0'
|
||||
tflags: '-test.short'
|
||||
- name: solaris
|
||||
action: 'vmactions/solaris-vm@v1'
|
||||
bflags: '-tags sqlite3_dotlk'
|
||||
tflags: '-test.short'
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GOOS: ${{ matrix.os.name }}
|
||||
BUILDFLAGS: ${{ matrix.os.bflags }}
|
||||
TESTFLAGS: ${{ matrix.os.tflags }}
|
||||
VMACTIONS: ${{ matrix.os.action }}
|
||||
run: .github/workflows/build-test.sh
|
||||
|
||||
- name: Test
|
||||
uses: ./.github/actions/vmactions
|
||||
|
||||
test-wasip1:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Setup
|
||||
run: echo "$(go env GOROOT)/lib/wasm" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Test wasmtime
|
||||
env:
|
||||
GOOS: wasip1
|
||||
GOARCH: wasm
|
||||
GOWASIRUNTIME: wasmtime
|
||||
GOWASIRUNTIMEARGS: '--env CI=true --optimize opt-level=0'
|
||||
run: go test -short -tags sqlite3_dotlk -skip Example ./...
|
||||
|
||||
test-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: docker/setup-qemu-action@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Test 32-bit
|
||||
run: GOARCH=386 go test ./...
|
||||
|
||||
- name: Test loong64
|
||||
run: GOARCH=loong64 go test -short ./...
|
||||
|
||||
- name: Test riscv64
|
||||
run: GOARCH=riscv64 go test -short ./...
|
||||
|
||||
- name: Test ppc64le
|
||||
run: GOARCH=ppc64le go test -short ./...
|
||||
|
||||
- name: Test s390x
|
||||
run: GOARCH=s390x go test -short ./...
|
||||
|
||||
test-linux-arm:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
|
||||
- name: Test 32-bit
|
||||
run: GOARCH=arm GOARM=7 go test ./...
|
||||
|
||||
test-os-other:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-11-arm]
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
|
||||
test-linux-other:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04-riscv, ubuntu-24.04-s390x, ubuntu-24.04-ppc64le-p10]
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: test-qemu
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
@@ -0,0 +1,20 @@
|
||||
# Fork of ncruces/go-sqlite3. Allowlist UPSTREAM test fixtures + example crypto
|
||||
# keys (SHA-256/MD5 of the empty string used in the adiantum/XTS VFS tests, and
|
||||
# the SQLite C amalgamation). Hanzo additions (hanzovfs/, cmd/) are still scanned.
|
||||
[extend]
|
||||
useDefault = true
|
||||
|
||||
[allowlist]
|
||||
description = "Upstream SQLite + crypto-VFS test fixtures (not real secrets)"
|
||||
paths = [
|
||||
'''sqlite3/sqlite3\.c''',
|
||||
'''sqlite3/sqlite3ext\.h''',
|
||||
'''vfs/adiantum/.*''',
|
||||
'''vfs/xts/.*''',
|
||||
'''vfs/tests/.*''',
|
||||
'''tests/.*''',
|
||||
]
|
||||
regexes = [
|
||||
'''e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855''',
|
||||
'''d41d8cd98f00b204e9800998ecf8427e''',
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
# CI/CD for hanzoai/platform (the Hanzo PaaS) — NOT GitHub Actions.
|
||||
# The platform runs `make ci` as a build step and/or a scheduled (cron) task.
|
||||
# Works identically locally and anywhere: `make ci`.
|
||||
SHELL := /usr/bin/env bash
|
||||
export GOPRIVATE := github.com/hanzoai,github.com/luxfi
|
||||
export GOFLAGS := -mod=mod
|
||||
BIN := $(CURDIR)/.bin
|
||||
export PATH := $(BIN):$(PATH)
|
||||
GITLEAKS_VERSION ?= 8.21.2
|
||||
ARCH := $(shell uname -m | sed 's/x86_64/x64/; s/aarch64/arm64/')
|
||||
|
||||
.PHONY: ci build test scan vuln secrets sbom tools clean
|
||||
ci: build test scan ## full pipeline (build -> test -> scan)
|
||||
build:
|
||||
go build ./...
|
||||
test:
|
||||
go test ./...
|
||||
scan: vuln secrets sbom
|
||||
vuln:
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
govulncheck ./...
|
||||
secrets: $(BIN)/gitleaks
|
||||
gitleaks detect --source . --redact --no-banner --exit-code 1
|
||||
sbom: $(BIN)/syft
|
||||
syft . -o cyclonedx-json=sbom.cyclonedx.json -q
|
||||
tools: $(BIN)/gitleaks $(BIN)/syft
|
||||
clean:
|
||||
rm -rf $(BIN) sbom.cyclonedx.json
|
||||
|
||||
$(BIN)/gitleaks:
|
||||
@mkdir -p $(BIN)
|
||||
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v$(GITLEAKS_VERSION)/gitleaks_$(GITLEAKS_VERSION)_linux_$(ARCH).tar.gz" | tar -xz -C $(BIN) gitleaks
|
||||
$(BIN)/syft:
|
||||
@mkdir -p $(BIN)
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b $(BIN) >/dev/null
|
||||
@@ -0,0 +1,7 @@
|
||||
github.com/hanzoai/sqlite3 — canonical Hanzo SQLite.
|
||||
|
||||
Fork of github.com/ncruces/go-sqlite3 (MIT, Copyright (c) 2023 Nuno Cruces).
|
||||
The upstream MIT LICENSE is retained in full. Hanzo additions (the hanzovfs
|
||||
native encrypted VFS, module path, build pins) are likewise MIT-licensed.
|
||||
|
||||
Pure-Go, no cgo. WASM SQLite blob from github.com/ncruces/go-sqlite3-wasm (upstream).
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# CI/CD on hanzoai/platform — no GitHub Actions
|
||||
|
||||
This repo is built, run, and scanned by **hanzoai/platform** (the Hanzo PaaS),
|
||||
not GitHub Actions. `.github/workflows` is intentionally absent.
|
||||
|
||||
- **Build / run** — the platform builds via Dockerfile / Nixpacks / Railpack and
|
||||
runs the result; auto-deploy on push.
|
||||
- **Actions (CI)** — a platform **Scheduled Task** (and/or build step) runs
|
||||
`make ci` = `build → test → scan` (govulncheck + gitleaks + CycloneDX SBOM),
|
||||
on push and on a cron. SOC 2 CC7.x/CC8.x evidence (artifacts to hanzoai/audit).
|
||||
- The platform build env carries Git credentials for `github.com/hanzoai` +
|
||||
`github.com/luxfi`, so cross-org private modules resolve natively — no per-repo
|
||||
token dance (the thing that made GitHub Actions painful).
|
||||
|
||||
Run anywhere: `make ci`.
|
||||
@@ -55,8 +55,6 @@ db.QueryRow(`SELECT sqlite_version()`).Scan(&version)
|
||||
- [JSON support](https://sqlite.org/json1.html)
|
||||
([example](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-package-Json))
|
||||
- [math functions](https://sqlite.org/lang_mathfunc.html)
|
||||
- [full-text search](https://sqlite.org/fts5.html)
|
||||
- [geospatial search](https://sqlite.org/geopoly.html)
|
||||
- [Unicode support](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode)
|
||||
- [statistics functions](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats)
|
||||
- [encryption at rest](vfs/adiantum/README.md)
|
||||
@@ -89,7 +87,8 @@ Every commit is tested on:
|
||||
* illumos: amd64
|
||||
* Solaris: amd64
|
||||
|
||||
Certain operating system and CPU combinations have some limitations. See the [support matrix](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix) for a complete overview.
|
||||
Certain operating system and CPU combinations have some limitations.
|
||||
See the [support matrix](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix) for a complete overview.
|
||||
|
||||
The Go VFS is tested by running SQLite's
|
||||
[mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c).
|
||||
@@ -122,9 +121,23 @@ have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/idea
|
||||
The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs,
|
||||
and features we're working on, planning to work on, or asking for help with.
|
||||
|
||||
### Alternatives
|
||||
---
|
||||
|
||||
- [`modernc.org/sqlite`](https://pkg.go.dev/modernc.org/sqlite)
|
||||
- [`crawshaw.io/sqlite`](https://pkg.go.dev/crawshaw.io/sqlite)
|
||||
- [`github.com/mattn/go-sqlite3`](https://pkg.go.dev/github.com/mattn/go-sqlite3)
|
||||
- [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite)
|
||||
## Hanzo fork
|
||||
|
||||
`github.com/hanzoai/sqlite3` is the **canonical Hanzo SQLite** — a fork of
|
||||
`ncruces/go-sqlite3` (MIT) adding the **`hanzovfs`** native encrypted VFS for
|
||||
per-tenant SQLite ⇒ `hanzoai/vfs` ⇒ S3 (HIP-0302 / HIP-0107), no FUSE, no cgo.
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/hanzoai/sqlite3"
|
||||
_ "github.com/hanzoai/sqlite3/hanzovfs" // registers vfs=hanzo
|
||||
_ "github.com/hanzoai/sqlite3/embed"
|
||||
)
|
||||
db, _ := sqlite3.Open("file:/orgs/acme/app.db?vfs=hanzo")
|
||||
```
|
||||
|
||||
**Deprecates** `modernc.org/sqlite` (no custom-VFS hook) and direct use of
|
||||
`ncruces/go-sqlite3`. Benchmarked 3.6× faster writes / ~92× faster point-reads
|
||||
than the FUSE-mounted path; per-page AEAD encryption costs ~0.
|
||||
|
||||
@@ -120,8 +120,7 @@ func (b *Backup) Step(nPage int) (done bool, err error) {
|
||||
//
|
||||
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
|
||||
func (b *Backup) Remaining() int {
|
||||
n := int32(b.c.wrp.Xsqlite3_backup_remaining(int32(b.handle)))
|
||||
return int(n)
|
||||
return int(b.c.wrp.Xsqlite3_backup_remaining(int32(b.handle)))
|
||||
}
|
||||
|
||||
// PageCount returns the total number of pages in the source database
|
||||
@@ -129,6 +128,5 @@ func (b *Backup) Remaining() int {
|
||||
//
|
||||
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
|
||||
func (b *Backup) PageCount() int {
|
||||
n := int32(b.c.wrp.Xsqlite3_backup_pagecount(int32(b.handle)))
|
||||
return int(n)
|
||||
return int(b.c.wrp.Xsqlite3_backup_pagecount(int32(b.handle)))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package sqlite3
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// ZeroBlob represents a zero-filled, length n BLOB
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// hanzovfs-bench: native PQ SQLite VFS throughput (in-process, no FUSE).
|
||||
// go run github.com/hanzoai/sqlite3/cmd/hanzovfs-bench@latest
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/hanzoai/sqlite3"
|
||||
_ "github.com/hanzoai/sqlite3/embed"
|
||||
"github.com/hanzoai/sqlite3/hanzovfs"
|
||||
"github.com/luxfi/age"
|
||||
)
|
||||
|
||||
func bench(label, dsn string) {
|
||||
db, err := sqlite3.Open(dsn)
|
||||
if err != nil { fmt.Printf("%-24s OPEN ERR %v\n", label, err); return }
|
||||
defer db.Close()
|
||||
db.Exec(`PRAGMA journal_mode=MEMORY; PRAGMA synchronous=OFF;`)
|
||||
db.Exec(`CREATE TABLE t(id INTEGER PRIMARY KEY, email TEXT, body TEXT)`)
|
||||
const n = 20000
|
||||
t0 := time.Now()
|
||||
db.Exec("BEGIN")
|
||||
st, _, _ := db.Prepare("INSERT INTO t(email,body) VALUES(?,?)")
|
||||
for i := 0; i < n; i++ {
|
||||
st.BindText(1, fmt.Sprintf("u%d@hanzo.ai", i))
|
||||
st.BindText(2, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
|
||||
st.Step(); st.Reset()
|
||||
}
|
||||
st.Close(); db.Exec("COMMIT")
|
||||
ins := float64(n) / time.Since(t0).Seconds()
|
||||
t0 = time.Now()
|
||||
sel, _, _ := db.Prepare("SELECT body FROM t WHERE id=?")
|
||||
for i := 0; i < 5000; i++ { sel.BindInt(1, 1+(i*7)%n); sel.Step(); sel.Reset() }
|
||||
sel.Close()
|
||||
fmt.Printf("%-24s insert=%9.0f rows/s point_sel=%9.0f q/s\n", label, ins, 5000/time.Since(t0).Seconds())
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Printf("hanzovfs-bench %s/%s (%d CPU)\n", runtime.GOOS, runtime.GOARCH, runtime.NumCPU())
|
||||
id, rcpt, err := hanzovfs.GenerateIdentity()
|
||||
if err != nil { panic(err) }
|
||||
dir, _ := os.MkdirTemp("", "hvfs")
|
||||
hanzovfs.Register("pq", hanzovfs.Config{Dir: dir, Recipients: []age.Recipient{rcpt}, Identities: []age.Identity{id}})
|
||||
bench("native PQ VFS (ML-KEM)", "file:/orgs/acme/bench.db?vfs=pq")
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/vfs"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/vfs"
|
||||
)
|
||||
|
||||
// Config makes configuration changes to a database connection.
|
||||
@@ -146,7 +146,7 @@ func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, erro
|
||||
rc = res_t(c.wrp.Xsqlite3_file_control(
|
||||
int32(c.handle), int32(schemaPtr),
|
||||
int32(op), int32(ptr)))
|
||||
ret = uint32(c.wrp.Read32(ptr))
|
||||
ret = c.wrp.Read32(ptr)
|
||||
|
||||
case FCNTL_LOCKSTATE:
|
||||
rc = res_t(c.wrp.Xsqlite3_file_control(
|
||||
@@ -193,8 +193,7 @@ func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, erro
|
||||
//
|
||||
// https://sqlite.org/c3ref/limit.html
|
||||
func (c *Conn) Limit(id LimitCategory, value int) int {
|
||||
v := int32(c.wrp.Xsqlite3_limit(int32(c.handle), int32(id), int32(value)))
|
||||
return int(v)
|
||||
return int(c.wrp.Xsqlite3_limit(int32(c.handle), int32(id), int32(value)))
|
||||
}
|
||||
|
||||
// SetAuthorizer registers an authorizer callback with the database connection.
|
||||
@@ -236,7 +235,7 @@ func (e *env) Xgo_authorizer(pDB, action, zName3rd, zName4th, zSchema, zInner in
|
||||
// Trace registers a trace callback function against the database connection.
|
||||
//
|
||||
// https://sqlite.org/c3ref/trace_v2.html
|
||||
func (c *Conn) Trace(mask TraceEvent, cb func(evt TraceEvent, arg1 any, arg2 any) error) error {
|
||||
func (c *Conn) Trace(mask TraceEvent, cb func(evt TraceEvent, arg1, arg2 any) error) error {
|
||||
rc := res_t(c.wrp.Xsqlite3_trace_go(int32(c.handle), int32(mask)))
|
||||
if err := c.error(rc); err != nil {
|
||||
return err
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/sqlite3_wrap"
|
||||
"github.com/ncruces/go-sqlite3/vfs"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/sqlite3_wrap"
|
||||
"github.com/hanzoai/sqlite3/vfs"
|
||||
)
|
||||
|
||||
// Conn is a database connection handle.
|
||||
@@ -34,6 +34,7 @@ type Conn struct {
|
||||
update func(AuthorizerActionCode, string, string, int64)
|
||||
commit func() bool
|
||||
rollback func()
|
||||
preupdate func(PreUpdateData)
|
||||
|
||||
busy1st time.Time
|
||||
busylst time.Time
|
||||
@@ -119,8 +120,8 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) {
|
||||
c.wrp.Xsqlite3_progress_handler_go(int32(handle), 1000)
|
||||
if flags|OPEN_URI != 0 && strings.HasPrefix(filename, "file:") {
|
||||
var pragmas strings.Builder
|
||||
if _, after, ok := strings.Cut(filename, "?"); ok {
|
||||
query, _ := url.ParseQuery(after)
|
||||
if u, err := url.Parse(filename); err == nil {
|
||||
query := u.Query()
|
||||
for _, p := range query["_pragma"] {
|
||||
pragmas.WriteString(`PRAGMA `)
|
||||
pragmas.WriteString(p)
|
||||
@@ -259,7 +260,7 @@ func (c *Conn) Filename(schema string) *vfs.Filename {
|
||||
// ReadOnly determines if a database is read-only.
|
||||
//
|
||||
// https://sqlite.org/c3ref/db_readonly.html
|
||||
func (c *Conn) ReadOnly(schema string) (ro bool, ok bool) {
|
||||
func (c *Conn) ReadOnly(schema string) (ro, ok bool) {
|
||||
var ptr ptr_t
|
||||
if schema != "" {
|
||||
defer c.arena.Mark()()
|
||||
@@ -506,7 +507,7 @@ func (c *Conn) errorFor(handle ptr_t, rc res_t, sql ...string) error {
|
||||
}
|
||||
|
||||
if len(sql) != 0 {
|
||||
if i := int32(c.wrp.Xsqlite3_error_offset(int32(handle))); i != -1 {
|
||||
if i := c.wrp.Xsqlite3_error_offset(int32(handle)); i != -1 {
|
||||
query = sql[0][i:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package sqlite3
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/sqlite3_wrap"
|
||||
"github.com/hanzoai/sqlite3/internal/sqlite3_wrap"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Context is the context in which an SQL function executes.
|
||||
@@ -217,6 +217,6 @@ func (ctx Context) ResultSubtype(t uint) {
|
||||
//
|
||||
// https://sqlite.org/c3ref/vtab_nochange.html
|
||||
func (ctx Context) VTabNoChange() bool {
|
||||
b := int32(ctx.c.wrp.Xsqlite3_vtab_nochange(int32(ctx.handle)))
|
||||
b := ctx.c.wrp.Xsqlite3_vtab_nochange(int32(ctx.handle))
|
||||
return b != 0
|
||||
}
|
||||
|
||||
+59
-50
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Importing package driver registers a [database/sql] driver named "sqlite3".
|
||||
//
|
||||
// import _ "github.com/ncruces/go-sqlite3/driver"
|
||||
// import _ "github.com/hanzoai/sqlite3/driver"
|
||||
//
|
||||
// The data source name for "sqlite3" databases can be a filename or a "file:" [URI].
|
||||
//
|
||||
@@ -107,14 +107,14 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
)
|
||||
|
||||
// This variable can be replaced with -ldflags:
|
||||
//
|
||||
// go build -ldflags="-X github.com/ncruces/go-sqlite3/driver.driverName=sqlite"
|
||||
// go build -ldflags="-X github.com/hanzoai/sqlite3/driver.driverName=sqlite"
|
||||
var driverName = "sqlite3"
|
||||
|
||||
func init() {
|
||||
@@ -174,15 +174,17 @@ func newConnector(name string, init, term func(*sqlite3.Conn) error) (*connector
|
||||
|
||||
var txlock, timefmt string
|
||||
if strings.HasPrefix(name, "file:") {
|
||||
if _, after, ok := strings.Cut(name, "?"); ok {
|
||||
query, err := url.ParseQuery(after)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txlock = query.Get("_txlock")
|
||||
timefmt = query.Get("_timefmt")
|
||||
c.pragmas = query.Has("_pragma")
|
||||
u, err := url.Parse(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txlock = query.Get("_txlock")
|
||||
timefmt = query.Get("_timefmt")
|
||||
c.pragmas = query.Has("_pragma")
|
||||
}
|
||||
|
||||
switch txlock {
|
||||
@@ -782,17 +784,23 @@ func (r *rows) ColumnTypeScanType(index int) (typ reflect.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rows) Next(dest []driver.Value) error {
|
||||
func (r *rows) NextRow() error {
|
||||
c := r.Stmt.Conn()
|
||||
if old := c.SetInterrupt(r.ctx); old != r.ctx {
|
||||
defer c.SetInterrupt(old)
|
||||
}
|
||||
if r.Stmt.Step() {
|
||||
return nil
|
||||
}
|
||||
if err := r.Stmt.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
if !r.Stmt.Step() {
|
||||
if err := r.Stmt.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return io.EOF
|
||||
func (r *rows) Next(dest []driver.Value) error {
|
||||
if err := r.NextRow(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := unsafe.Slice((*any)(unsafe.SliceData(dest)), len(dest))
|
||||
@@ -800,37 +808,38 @@ func (r *rows) Next(dest []driver.Value) error {
|
||||
return err
|
||||
}
|
||||
for i := range dest {
|
||||
scan := r.scanType(i)
|
||||
if v, ok := dest[i].([]byte); ok {
|
||||
if len(v) == cap(v) { // a BLOB
|
||||
continue
|
||||
}
|
||||
if scan != _TEXT {
|
||||
switch r.tmWrite {
|
||||
case "", time.RFC3339, time.RFC3339Nano:
|
||||
t, ok := maybeTime(v)
|
||||
if ok {
|
||||
dest[i] = t
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
dest[i] = string(v)
|
||||
}
|
||||
switch scan {
|
||||
case _TIME:
|
||||
t, err := r.tmRead.Decode(dest[i])
|
||||
if err == nil {
|
||||
dest[i] = t
|
||||
}
|
||||
case _BOOL:
|
||||
switch dest[i] {
|
||||
case int64(0):
|
||||
dest[i] = false
|
||||
case int64(1):
|
||||
dest[i] = true
|
||||
}
|
||||
}
|
||||
dest[i] = r.convert(i, dest[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rows) convert(i int, val driver.Value) driver.Value {
|
||||
scan := r.scanType(i)
|
||||
if v, ok := val.([]byte); ok {
|
||||
if len(v) == cap(v) { // a BLOB
|
||||
return val
|
||||
}
|
||||
if scan != _TEXT {
|
||||
t, ok := r.maybeTime(v)
|
||||
if ok {
|
||||
return t
|
||||
}
|
||||
}
|
||||
val = string(v)
|
||||
}
|
||||
switch scan {
|
||||
case _TIME:
|
||||
t, err := r.tmRead.Decode(val)
|
||||
if err == nil {
|
||||
return t
|
||||
}
|
||||
case _BOOL:
|
||||
switch val {
|
||||
case int64(0):
|
||||
return false
|
||||
case int64(1):
|
||||
return true
|
||||
}
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
//go:build go1.27
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func (r *rows) ScanColumn(ctx driver.ScanContext, i int, dest any) error {
|
||||
typ := r.Stmt.ColumnType(i)
|
||||
|
||||
// Fast path.
|
||||
var src any
|
||||
switch typ {
|
||||
case sqlite3.NULL:
|
||||
// src = nil
|
||||
case sqlite3.FLOAT:
|
||||
f := r.stmt.ColumnFloat(i)
|
||||
if r.scanFloat(f, dest) {
|
||||
return nil
|
||||
}
|
||||
src = f
|
||||
case sqlite3.INTEGER:
|
||||
i := r.stmt.ColumnInt64(i)
|
||||
if r.scanInt(i, dest) {
|
||||
return nil
|
||||
}
|
||||
if r.scanFloat(float64(i), dest) {
|
||||
return nil
|
||||
}
|
||||
src = i
|
||||
default:
|
||||
var b []byte
|
||||
if typ == sqlite3.TEXT {
|
||||
b = r.stmt.ColumnRawText(i)
|
||||
} else {
|
||||
b = r.stmt.ColumnRawBlob(i)
|
||||
}
|
||||
switch d := dest.(type) {
|
||||
case *sql.RawBytes:
|
||||
*d = b
|
||||
return nil
|
||||
case *string:
|
||||
*d = string(b)
|
||||
return nil
|
||||
case *sql.NullString:
|
||||
d.String = string(b)
|
||||
d.Valid = true
|
||||
return nil
|
||||
case *[]byte:
|
||||
*d = append((*d)[:0], b...)
|
||||
return nil
|
||||
}
|
||||
src = b
|
||||
}
|
||||
|
||||
// Time handling.
|
||||
if typ != sqlite3.NULL && typ != sqlite3.BLOB {
|
||||
var ok bool
|
||||
switch d := dest.(type) {
|
||||
case *time.Time:
|
||||
*d, ok = r.scanTime(src)
|
||||
case *sql.NullTime:
|
||||
d.Time, ok = r.scanTime(src)
|
||||
d.Valid = ok
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback.
|
||||
return sql.ConvertAssign(ctx, dest, r.convert(i, src))
|
||||
}
|
||||
|
||||
func (r *rows) scanTime(src any) (_ time.Time, _ bool) {
|
||||
if s, ok := src.([]byte); ok {
|
||||
if t, ok := r.maybeTime(s); ok {
|
||||
return t, true
|
||||
}
|
||||
src = string(s)
|
||||
}
|
||||
t, err := r.tmRead.Decode(src)
|
||||
return t, err == nil
|
||||
}
|
||||
|
||||
func (r *rows) scanFloat(f float64, dest any) bool {
|
||||
switch d := dest.(type) {
|
||||
case *float64:
|
||||
*d = f
|
||||
case *float32:
|
||||
*d = float32(f)
|
||||
case *sql.NullFloat64:
|
||||
d.Float64 = f
|
||||
d.Valid = true
|
||||
case *sql.Null[float32]:
|
||||
d.V = float32(f)
|
||||
d.Valid = true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *rows) scanInt(i int64, dest any) bool {
|
||||
switch d := dest.(type) {
|
||||
case *int64:
|
||||
*d = i
|
||||
case *sql.NullInt64:
|
||||
d.Int64 = i
|
||||
d.Valid = true
|
||||
|
||||
case *uint64:
|
||||
*d = uint64(i)
|
||||
return 0 <= i
|
||||
case *sql.Null[uint64]:
|
||||
d.V = uint64(i)
|
||||
d.Valid = true
|
||||
return 0 <= i
|
||||
|
||||
case *int:
|
||||
*d = int(i)
|
||||
return math.MinInt <= i && i <= math.MaxInt
|
||||
case *sql.Null[int]:
|
||||
d.V = int(i)
|
||||
d.Valid = true
|
||||
return math.MinInt <= i && i <= math.MaxInt
|
||||
|
||||
case *uint:
|
||||
*d = uint(i)
|
||||
return 0 <= i && uint64(i) <= math.MaxUint
|
||||
case *sql.Null[uint]:
|
||||
d.V = uint(i)
|
||||
d.Valid = true
|
||||
return 0 <= i && uint64(i) <= math.MaxUint
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
+44
-4
@@ -9,13 +9,14 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_Open_error(t *testing.T) {
|
||||
@@ -534,6 +535,45 @@ func Test_ColumnType_ScanType(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_rows_ScanColumn(t *testing.T) {
|
||||
t.Parallel()
|
||||
dsn := memdb.TestDB(t)
|
||||
|
||||
db, err := Open(dsn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var tm time.Time
|
||||
err = db.QueryRow(`SELECT NULL`).Scan(&tm)
|
||||
if err == nil {
|
||||
t.Error("want error")
|
||||
}
|
||||
// Go 1.27
|
||||
err = db.QueryRow(`SELECT datetime()`).Scan(&tm)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "sql: Scan error") {
|
||||
t.Error(err)
|
||||
}
|
||||
if err == nil && tm.IsZero() {
|
||||
t.Error(tm)
|
||||
}
|
||||
|
||||
var nt sql.NullTime
|
||||
err = db.QueryRow(`SELECT NULL`).Scan(&nt)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// Go 1.27
|
||||
err = db.QueryRow(`SELECT datetime()`).Scan(&nt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "sql: Scan error") {
|
||||
t.Error(err)
|
||||
}
|
||||
if err == nil && nt.Time.IsZero() {
|
||||
t.Error(nt.Time)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_loop(b *testing.B) {
|
||||
ctx := testcfg.Context(b)
|
||||
db, err := Open(":memory:")
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
_ "github.com/ncruces/go-sqlite3/driver"
|
||||
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
_ "github.com/hanzoai/sqlite3/driver"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example_customTime() {
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
_ "github.com/ncruces/go-sqlite3/driver"
|
||||
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
_ "github.com/hanzoai/sqlite3/driver"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example_json() {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Savepoint establishes a new transaction savepoint.
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func ExampleSavepoint() {
|
||||
|
||||
+11
-3
@@ -6,10 +6,18 @@ import (
|
||||
)
|
||||
|
||||
// Convert a string in [time.RFC3339Nano] format into a [time.Time]
|
||||
// if it roundtrips back to the same string.
|
||||
// if that's the format we're using to persist them,
|
||||
// and if it roundtrips back to the same string.
|
||||
// This way times can be persisted to, and recovered from, the database,
|
||||
// but if a string is needed, [database/sql] will recover the same string.
|
||||
func maybeTime(text []byte) (_ time.Time, _ bool) {
|
||||
// but if a string is wanted, [database/sql] will recover the same string.
|
||||
func (r *rows) maybeTime(text []byte) (_ time.Time, _ bool) {
|
||||
switch r.tmWrite {
|
||||
case "", time.RFC3339, time.RFC3339Nano:
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// Weed out (some) values that can't possibly be
|
||||
// [time.RFC3339Nano] timestamps.
|
||||
if len(text) < len("2006-01-02T15:04:05Z") {
|
||||
|
||||
+4
-2
@@ -21,8 +21,9 @@ func Fuzz_stringOrTime_1(f *testing.F) {
|
||||
f.Add("2006-01-02T15:04:05.9999999999Z")
|
||||
f.Add("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
||||
|
||||
r := rows{stmt: &stmt{}}
|
||||
f.Fuzz(func(t *testing.T, str string) {
|
||||
v, ok := maybeTime([]byte(str))
|
||||
v, ok := r.maybeTime([]byte(str))
|
||||
if ok {
|
||||
// Make sure times round-trip to the same string:
|
||||
// https://pkg.go.dev/database/sql#Rows.Scan
|
||||
@@ -50,8 +51,9 @@ func Fuzz_stringOrTime_2(f *testing.F) {
|
||||
f.Add(int64(639095955742), int64(222_222_222)) // twosday, year 22222AD
|
||||
f.Add(int64(-763421161058), int64(222_222_222)) // twosday, year 22222BC
|
||||
|
||||
r := rows{stmt: &stmt{}}
|
||||
checkTime := func(t testing.TB, date time.Time) {
|
||||
v, ok := maybeTime(date.AppendFormat(nil, time.RFC3339Nano))
|
||||
v, ok := r.maybeTime(date.AppendFormat(nil, time.RFC3339Nano))
|
||||
if ok {
|
||||
// Make sure times round-trip to the same time:
|
||||
if !v.Equal(date) {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func Test_namedValues(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// Package embed is no longer needed.
|
||||
//
|
||||
// Deprecated: importing github.com/ncruces/go-sqlite3/embed is unnecessary.
|
||||
// Deprecated: importing github.com/hanzoai/sqlite3/embed is unnecessary.
|
||||
package embed
|
||||
|
||||
func init() {
|
||||
println("If you're reading this, you're unnecessarily importing github.com/ncruces/go-sqlite3/embed.")
|
||||
println("If you're reading this, you're unnecessarily importing github.com/hanzoai/sqlite3/embed.")
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/sqlite3_wrap"
|
||||
"github.com/hanzoai/sqlite3/internal/sqlite3_wrap"
|
||||
)
|
||||
|
||||
// Error wraps an SQLite Error Code.
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/sqlite3_wrap"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/sqlite3_wrap"
|
||||
)
|
||||
|
||||
func Test_assertErr(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
const memory = ":memory:"
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/base64"
|
||||
"sync"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
+11
-1
@@ -17,16 +17,24 @@ you can load into your database connections.
|
||||
reads [comma-separated values](https://sqlite.org/csv.html).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/fileio`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/fileio)
|
||||
reads, writes and lists files.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/fts5`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/fts5)
|
||||
provides [full-text search](https://sqlite.org/fts5.html).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/hash`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/hash)
|
||||
provides cryptographic hash functions.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/ipaddr`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/ipaddr)
|
||||
provides functions to manipulate IPs and CIDRs.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/lines`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/lines)
|
||||
reads data [line-by-line](https://github.com/asg017/sqlite-lines).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/pivot`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/pivot)
|
||||
creates [pivot tables](https://github.com/jakethaw/pivot_vtab).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/regexp`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/regexp)
|
||||
provides regular expression functions.
|
||||
provides [regular expression](https://github.com/nalgeon/sqlean/blob/main/docs/regexp.md) functions.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/rtree`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/rtree)
|
||||
provides [multi-dimensional](https://sqlite.org/rtree.html) and [geospatial](https://sqlite.org/geopoly.html) indexes.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/serdes`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/serdes)
|
||||
(de)serializes databases.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/spellfix1`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/spellfix1)
|
||||
searches a vocabulary for [close matches](https://sqlite.org/spellfix1.html).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/statement`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/statement)
|
||||
creates [parameterized views](https://github.com/0x09/sqlite-statement-vtab).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/stats`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats)
|
||||
@@ -35,6 +43,8 @@ you can load into your database connections.
|
||||
provides [Unicode aware](https://sqlite.org/src/dir/ext/icu) functions.
|
||||
- [`github.com/ncruces/go-sqlite3/ext/uuid`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/uuid)
|
||||
generates [UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/vec1`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/vec1)
|
||||
provides approximate nearest-neighbor [vector search](https://sqlite.org/vec1/doc/trunk/doc/vec1.md).
|
||||
- [`github.com/ncruces/go-sqlite3/ext/zorder`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/zorder)
|
||||
maps multidimensional data to one dimension.
|
||||
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
)
|
||||
|
||||
// Register registers the array single-argument, table-valued SQL function.
|
||||
|
||||
+13
-6
@@ -1,21 +1,27 @@
|
||||
package array_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/array"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/array"
|
||||
"github.com/hanzoai/sqlite3/ext/rtree"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example_driver() {
|
||||
db, err := driver.Open("file:/test.db?vfs=memdb", array.Register)
|
||||
db, err := driver.Open("file:/test.db?vfs=memdb", func(c *sqlite3.Conn) error {
|
||||
return errors.Join(
|
||||
array.Register(c),
|
||||
rtree.Register(c))
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -51,6 +57,7 @@ func Example_driver() {
|
||||
|
||||
func Example() {
|
||||
sqlite3.AutoExtension(array.Register)
|
||||
sqlite3.AutoExtension(rtree.Register)
|
||||
|
||||
db, err := sqlite3.Open(":memory:")
|
||||
if err != nil {
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers the SQL functions:
|
||||
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/array"
|
||||
"github.com/ncruces/go-sqlite3/ext/blobio"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/array"
|
||||
"github.com/hanzoai/sqlite3/ext/blobio"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
|
||||
+3
-3
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
"github.com/dchest/siphash"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/util/sql3util"
|
||||
)
|
||||
|
||||
// Register registers the bloom_filter virtual table:
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/bloom"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/bloom"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3/util/sql3util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/closure"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/closure"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
"github.com/hanzoai/sqlite3/util/sql3util"
|
||||
)
|
||||
|
||||
func uintArg(key, val string) (int, error) {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package csv
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
"github.com/hanzoai/sqlite3/util/sql3util"
|
||||
)
|
||||
|
||||
func Test_uintArg(t *testing.T) {
|
||||
|
||||
+5
-5
@@ -15,11 +15,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/ncruces/go-sqlite3/util/osutil"
|
||||
"github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3/util/osutil"
|
||||
"github.com/hanzoai/sqlite3/util/sql3util"
|
||||
)
|
||||
|
||||
// Register registers the CSV virtual table.
|
||||
|
||||
+3
-3
@@ -6,9 +6,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/csv"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/csv"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func getSchema(header bool, columns int, row []string) string {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package csv
|
||||
|
||||
import "github.com/ncruces/go-sqlite3/util/sql3util"
|
||||
import "github.com/hanzoai/sqlite3/util/sql3util"
|
||||
|
||||
func getColumnAffinities(schema string) ([]sql3util.Affinity, error) {
|
||||
tab, err := sql3util.ParseTable(schema)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Register registers SQL functions readfile, writefile, lsmode,
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/fileio"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/fileio"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_lsmode(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/fileio"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/fileio"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_fsdir(t *testing.T) {
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/util/fsutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/util/fsutil"
|
||||
)
|
||||
|
||||
func writefile(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_writefile(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Package fts5 provides the fts5 extension.
|
||||
//
|
||||
// https://sqlite.org/fts5.html
|
||||
package fts5
|
||||
|
||||
import (
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v3/fts5"
|
||||
)
|
||||
|
||||
// Register registers the fts5 extension.
|
||||
func Register(db *sqlite3.Conn) error {
|
||||
return sqlite3.ExtensionInit(db, fts5.New, fts5.DylinkInfo)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package fts5_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/fts5"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
db, err := driver.Open("file:/test.db?vfs=memdb", fts5.Register)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(`
|
||||
CREATE VIRTUAL TABLE docs USING fts5(title, body);
|
||||
INSERT INTO docs(title, body) VALUES
|
||||
('Go Programming', 'An intensive guide to Go routines.'),
|
||||
('SQLite Tutorial', 'Learn how to use virtual tables efficiently.');
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var title string
|
||||
err = db.QueryRow("SELECT title FROM docs WHERE docs MATCH 'Go AND routines'").Scan(&title)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(title)
|
||||
// Output: Go Programming
|
||||
}
|
||||
+2
-2
@@ -3,8 +3,8 @@ package hash
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
func blake2sFunc(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ import (
|
||||
"crypto"
|
||||
"errors"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers cryptographic hash functions for a database connection.
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
_ "golang.org/x/crypto/md4"
|
||||
_ "golang.org/x/crypto/ripemd160"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ package hash
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
func sha224Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ package hash
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
func sha3Func(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Register IP/CIDR functions for a database connection.
|
||||
|
||||
@@ -3,10 +3,10 @@ package ipaddr_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/ipaddr"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/ipaddr"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ import (
|
||||
"io"
|
||||
"io/fs"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/util/osutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/util/osutil"
|
||||
)
|
||||
|
||||
// Register registers the lines and lines_read table-valued functions.
|
||||
|
||||
@@ -10,11 +10,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/lines"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/lines"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
|
||||
@@ -3,7 +3,7 @@ package pivot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func Test_operator(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers the pivot virtual table.
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/pivot"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/pivot"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
// https://antonz.org/sqlite-pivot-table/
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Register registers Unicode aware functions for a database connection.
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Package rtree provides the rtree and geopoly virtual tables.
|
||||
//
|
||||
// https://sqlite.org/rtree.html
|
||||
// https://sqlite.org/geopoly.html
|
||||
package rtree
|
||||
|
||||
import (
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v3/rtree"
|
||||
)
|
||||
|
||||
// Register registers the rtree and geopoly virtual tables.
|
||||
func Register(db *sqlite3.Conn) error {
|
||||
return sqlite3.ExtensionInit(db, rtree.New, rtree.DylinkInfo)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package rtree_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/rtree"
|
||||
_ "github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Example_rtree() {
|
||||
db, err := driver.Open("file:/test.db?vfs=memdb", rtree.Register)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(`
|
||||
CREATE VIRTUAL TABLE locations USING rtree(id, minX, maxX, minY, maxY);
|
||||
INSERT INTO locations VALUES (1, -10.0, -5.0, 30.0, 35.0);
|
||||
INSERT INTO locations VALUES (2, 100.0, 105.0, 0.0, 5.0);
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var id int
|
||||
err = db.QueryRow(`SELECT id FROM locations WHERE
|
||||
minX >= -12.0 AND maxX <= -4.0 AND
|
||||
minY >= 28.0 AND maxY <= 36.0`).Scan(&id)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(id)
|
||||
// Output: 1
|
||||
}
|
||||
|
||||
func Example_geopoly() {
|
||||
db, err := driver.Open("file:/test.db?vfs=memdb", rtree.Register)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(`
|
||||
CREATE VIRTUAL TABLE areas USING geopoly(name);
|
||||
INSERT INTO areas(name, _shape) VALUES ('Triangle Area', '[[0,0],[2,0],[1,2],[0,0]]');
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var name string
|
||||
err = db.QueryRow("SELECT name FROM areas WHERE geopoly_contains_point(_shape, 1.0, 1.0)").Scan(&name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(name)
|
||||
// Output: Triangle Area
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
package serdes
|
||||
|
||||
import (
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/util/vfsutil"
|
||||
"github.com/ncruces/go-sqlite3/vfs"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/util/vfsutil"
|
||||
"github.com/hanzoai/sqlite3/vfs"
|
||||
)
|
||||
|
||||
const vfsName = "github.com/ncruces/go-sqlite3/ext/serdes.sliceVFS"
|
||||
const vfsName = "github.com/hanzoai/sqlite3/ext/serdes.sliceVFS"
|
||||
|
||||
func init() {
|
||||
vfs.Register(vfsName, sliceVFS{})
|
||||
@@ -37,8 +37,8 @@ func Serialize(db *sqlite3.Conn, schema string) ([]byte, error) {
|
||||
//
|
||||
// https://sqlite.org/c3ref/deserialize.html
|
||||
//
|
||||
// ["memdb"]: https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb
|
||||
// ["reader"]: https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/readervfs
|
||||
// ["memdb"]: https://pkg.go.dev/github.com/hanzoai/sqlite3/vfs/memdb
|
||||
// ["reader"]: https://pkg.go.dev/github.com/hanzoai/sqlite3/vfs/readervfs
|
||||
func Deserialize(db *sqlite3.Conn, schema string, data []byte) error {
|
||||
fileToOpen <- &data
|
||||
return db.Restore(schema, "file:serdes.db?immutable=1&vfs="+vfsName)
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/serdes"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/serdes"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs"
|
||||
)
|
||||
|
||||
//go:embed testdata/wal.db
|
||||
@@ -102,7 +102,7 @@ func httpGet() ([]byte, error) {
|
||||
}
|
||||
|
||||
func TestOpen_errors(t *testing.T) {
|
||||
_, err := sqlite3.OpenContext(testcfg.Context(t), "file:test.db?vfs=github.com/ncruces/go-sqlite3/ext/serdes.sliceVFS")
|
||||
_, err := sqlite3.OpenContext(testcfg.Context(t), "file:test.db?vfs=github.com/hanzoai/sqlite3/ext/serdes.sliceVFS")
|
||||
if err == nil {
|
||||
t.Error("want error")
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func TestOpen_errors(t *testing.T) {
|
||||
t.Errorf("got %v, want sqlite3.CANTOPEN", err)
|
||||
}
|
||||
|
||||
_, err = sqlite3.OpenContext(testcfg.Context(t), "file:serdes.db?vfs=github.com/ncruces/go-sqlite3/ext/serdes.sliceVFS")
|
||||
_, err = sqlite3.OpenContext(testcfg.Context(t), "file:serdes.db?vfs=github.com/hanzoai/sqlite3/ext/serdes.sliceVFS")
|
||||
if err == nil {
|
||||
t.Error("want error")
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
package spellfix1
|
||||
|
||||
import (
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v2/spellfix"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v3/spellfix"
|
||||
)
|
||||
|
||||
// Register registers the spellfix1 virtual table.
|
||||
|
||||
@@ -3,10 +3,10 @@ package spellfix1_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/spellfix1"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/spellfix1"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers the statement virtual table.
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/statement"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/statement"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package stats
|
||||
|
||||
import "github.com/ncruces/go-sqlite3"
|
||||
import "github.com/hanzoai/sqlite3"
|
||||
|
||||
const (
|
||||
every = iota
|
||||
|
||||
@@ -3,8 +3,8 @@ package stats_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestRegister_boolean(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package stats
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func cot(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package stats
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func newMode() sqlite3.AggregateFunction {
|
||||
|
||||
@@ -3,8 +3,8 @@ package stats_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestRegister_mode(t *testing.T) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"math"
|
||||
"slices"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
"github.com/ncruces/sort/quick"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestRegister_percentile(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ package stats
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Register registers statistics functions.
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/stats"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/stats"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/hanzoai/sqlite3/internal/util"
|
||||
)
|
||||
|
||||
// Welford's algorithm with Kahan summation:
|
||||
|
||||
@@ -39,8 +39,8 @@ import (
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// RegisterLike must be set to false to not register a Unicode aware LIKE operator.
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers the SQL functions:
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_generate(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
package vec1
|
||||
|
||||
import (
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v2/vec1"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/ncruces/go-sqlite3-wasm/v3/vec1"
|
||||
)
|
||||
|
||||
// Register registers the vec1 vector extension.
|
||||
|
||||
@@ -3,10 +3,10 @@ package vec1_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/vec1"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/vec1"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
||||
@@ -6,8 +6,8 @@ package zorder
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/internal/errutil"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// Register registers the zorder and unzorder SQL functions.
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/driver"
|
||||
"github.com/ncruces/go-sqlite3/ext/zorder"
|
||||
"github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
"github.com/hanzoai/sqlite3/driver"
|
||||
"github.com/hanzoai/sqlite3/ext/zorder"
|
||||
"github.com/hanzoai/sqlite3/internal/testcfg"
|
||||
"github.com/hanzoai/sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func Test_zorder(t *testing.T) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"iter"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/hanzoai/sqlite3/internal/errutil"
|
||||
)
|
||||
|
||||
// CollationNeeded registers a callback to be invoked
|
||||
@@ -85,7 +87,7 @@ func (c *Conn) CreateAggregateFunction(name string, nArg int, flag FunctionFlag,
|
||||
namePtr := c.arena.String(name)
|
||||
if fn != nil {
|
||||
funcPtr = c.wrp.AddHandle(AggregateConstructor(func() AggregateFunction {
|
||||
var a aggregateFunc
|
||||
a := aggregateFunc{fn: fn}
|
||||
coro := func(yieldCoro func(struct{}) bool) {
|
||||
seq := func(yieldSeq func([]Value) bool) {
|
||||
for yieldSeq(a.arg) {
|
||||
@@ -120,13 +122,7 @@ func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn
|
||||
defer c.arena.Mark()()
|
||||
namePtr := c.arena.String(name)
|
||||
if fn != nil {
|
||||
funcPtr = c.wrp.AddHandle(AggregateConstructor(func() AggregateFunction {
|
||||
agg := fn()
|
||||
if win, ok := agg.(WindowFunction); ok {
|
||||
return win
|
||||
}
|
||||
return agg
|
||||
}))
|
||||
funcPtr = c.wrp.AddHandle(fn)
|
||||
}
|
||||
rc := res_t(c.wrp.Xsqlite3_create_window_function_go(
|
||||
int32(c.handle), int32(namePtr), int32(nArg),
|
||||
@@ -231,7 +227,12 @@ func (e *env) Xgo_inverse(pCtx, pAgg, nArg, pArg int32) {
|
||||
db := e.DB.(*Conn)
|
||||
args := callbackArgs(db, nArg, ptr_t(pArg))
|
||||
defer returnArgs(args)
|
||||
fn := db.wrp.GetHandle(ptr_t(pAgg)).(WindowFunction)
|
||||
fn, ok := db.wrp.GetHandle(ptr_t(pAgg)).(WindowFunction)
|
||||
if !ok {
|
||||
Context{db, ptr_t(pCtx)}.ResultError(
|
||||
errutil.ErrorString("may not be used as a window function"))
|
||||
return // notest
|
||||
}
|
||||
fn.Inverse(Context{db, ptr_t(pCtx)}, *args...)
|
||||
}
|
||||
|
||||
@@ -281,11 +282,14 @@ func returnArgs(p *[]Value) {
|
||||
type aggregateFunc struct {
|
||||
next func() (struct{}, bool)
|
||||
stop func()
|
||||
fn AggregateSeqFunction
|
||||
ctx Context
|
||||
arg []Value
|
||||
step bool
|
||||
}
|
||||
|
||||
func (a *aggregateFunc) Step(ctx Context, arg ...Value) {
|
||||
a.step = true
|
||||
a.ctx = ctx
|
||||
a.arg = append(a.arg[:0], arg...)
|
||||
if _, more := a.next(); !more {
|
||||
@@ -296,9 +300,14 @@ func (a *aggregateFunc) Step(ctx Context, arg ...Value) {
|
||||
func (a *aggregateFunc) Value(ctx Context) {
|
||||
a.ctx = ctx
|
||||
a.stop()
|
||||
if !a.step {
|
||||
a.fn(&a.ctx, noValuesSeq)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *aggregateFunc) Close() error {
|
||||
a.stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func noValuesSeq(func([]Value) bool) {}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import (
|
||||
"iter"
|
||||
"log"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func ExampleConn_CreateAggregateFunction() {
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ import (
|
||||
"log"
|
||||
"regexp"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/ncruces/go-sqlite3/ext/unicode"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
"github.com/hanzoai/sqlite3/ext/unicode"
|
||||
)
|
||||
|
||||
func ExampleConn_CreateCollation() {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import (
|
||||
"log"
|
||||
"unicode"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
func ExampleConn_CreateWindowFunction() {
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
module github.com/ncruces/go-sqlite3
|
||||
module github.com/hanzoai/sqlite3
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/ncruces/go-sqlite3-wasm/v2 v2.2.35301
|
||||
github.com/luxfi/age v1.5.0
|
||||
github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302
|
||||
github.com/ncruces/julianday v1.0.0
|
||||
github.com/ncruces/sort v0.1.6
|
||||
github.com/ncruces/sort v1.0.0
|
||||
github.com/ncruces/wbt v1.0.0
|
||||
golang.org/x/sys v0.44.0
|
||||
golang.org/x/sys v0.46.0
|
||||
)
|
||||
|
||||
require filippo.io/hpke v0.4.0 // indirect
|
||||
|
||||
require (
|
||||
github.com/dchest/siphash v1.2.3 // ext/bloom
|
||||
github.com/google/uuid v1.6.0 // ext/uuid
|
||||
github.com/psanford/httpreadat v0.1.0 // example
|
||||
golang.org/x/crypto v0.51.0 // vfs/adiantum vfs/xts
|
||||
golang.org/x/sync v0.20.0 // test
|
||||
golang.org/x/text v0.37.0 // ext/unicode
|
||||
golang.org/x/crypto v0.53.0 // vfs/adiantum vfs/xts
|
||||
golang.org/x/sync v0.21.0 // test
|
||||
golang.org/x/text v0.38.0 // ext/unicode
|
||||
lukechampine.com/adiantum v1.1.1 // vfs/adiantum
|
||||
)
|
||||
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd h1:ZLsPO6WdZ5zatV4UfVpr7oAwLGRZ+sebTUruuM4Ra3M=
|
||||
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd/go.mod h1:SrHC2C7r5GkDk8R+NFVzYy/sdj0Ypg9htaPXQq5Cqeo=
|
||||
filippo.io/hpke v0.4.0 h1:p575VVQ6ted4pL+it6M00V/f2qTZITO0zgmdKCkd5+A=
|
||||
filippo.io/hpke v0.4.0/go.mod h1:EmAN849/P3qdeK+PCMkDpDm83vRHM5cDipBJ8xbQLVY=
|
||||
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
||||
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/ncruces/go-sqlite3-wasm/v2 v2.2.35301 h1:PPb3vECU21cZr2CrzYG7idXLBpWETDcdVEnXg3vqRpM=
|
||||
github.com/ncruces/go-sqlite3-wasm/v2 v2.2.35301/go.mod h1:q34C+veYmxQ7XRFgCKSeD6hq5vP/C517Hkl4iu+A5ao=
|
||||
github.com/luxfi/age v1.5.0 h1:G69HbSV4R3vKEH9B0CulnRaMdSdf4RalMgP8xKmxHeI=
|
||||
github.com/luxfi/age v1.5.0/go.mod h1:iAYAxgvrXxcy746+Ovh/eWWDuF9teJLNcCSSOX9RYW0=
|
||||
github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302 h1:Cew7/eNAMd1zhpXYBjofBua/63pFvbvB2h4PM/p6gKU=
|
||||
github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302/go.mod h1:xe0CfafDUxfh+fSVKjHHMiAxoG9KALt5nFtbGNb/jRs=
|
||||
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
|
||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/ncruces/sort v0.1.6 h1:TrsJfGRH1AoWoaeB4/+gCohot9+cA6u/INaH5agIhNk=
|
||||
github.com/ncruces/sort v0.1.6/go.mod h1:obJToO4rYr6VWP0Uw5FYymgYGt3Br4RXcs/JdKaXAPk=
|
||||
github.com/ncruces/sort v1.0.0 h1:tXeitUzE3B8I2z+rsqbKUBThBlJJ34glqCDP0XReJmk=
|
||||
github.com/ncruces/sort v1.0.0/go.mod h1:obJToO4rYr6VWP0Uw5FYymgYGt3Br4RXcs/JdKaXAPk=
|
||||
github.com/ncruces/wbt v1.0.0 h1:8iBE7UPjTLUpzu3/FCRjAmuQjWzgxo10RGBgt3ooLSc=
|
||||
github.com/ncruces/wbt v1.0.0/go.mod h1:DtF92amvMxH69EmBFUSFWRDAlo6hOEfoNQnClxj9C/c=
|
||||
github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIwZLUE=
|
||||
github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE=
|
||||
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
|
||||
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
lukechampine.com/adiantum v1.1.1 h1:4fp6gTxWCqpEbLy40ExiYDDED3oUNWx5cTqBCtPdZqA=
|
||||
lukechampine.com/adiantum v1.1.1/go.mod h1:LrAYVnTYLnUtE/yMp5bQr0HstAf060YUF8nM0B6+rUw=
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
"github.com/hanzoai/sqlite3"
|
||||
)
|
||||
|
||||
// Translate it will translate the error to native gorm errors.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user