mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-19 00:49:13 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf14f190b2 | ||
|
|
6ca92b035d | ||
|
|
2912adf226 | ||
|
|
b3f83a4392 | ||
|
|
1223c4fc80 | ||
|
|
e9d6509577 | ||
|
|
81dd786af7 | ||
|
|
a2253558ef | ||
|
|
466d14a9e0 | ||
|
|
ada7b3a906 | ||
|
|
eba73a87d9 |
16
.github/actions/vmactions/template.yml
vendored
Normal file
16
.github/actions/vmactions/template.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: VM Actions matrix
|
||||
description: VM Actions matrix template
|
||||
|
||||
inputs:
|
||||
run:
|
||||
description: The CI command to run
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: ${VMACTIONS}
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: ${{inputs.run}}
|
||||
6
.github/workflows/build-test.sh
vendored
6
.github/workflows/build-test.sh
vendored
@@ -8,4 +8,8 @@ for p in $(go list ./...); do
|
||||
name="$(basename "$p").test"
|
||||
(cd ${dir}; go test -c ${BUILDFLAGS:-})
|
||||
[ -f "${dir}/${name}" ] && echo "(cd ${dir}; ./${name} ${TESTFLAGS:-})" >> test.sh
|
||||
done
|
||||
done
|
||||
|
||||
if [[ -v VMACTIONS ]]; then
|
||||
envsubst < .github/actions/vmactions/template.yml > .github/actions/vmactions/action.yml
|
||||
fi
|
||||
2
.github/workflows/repro.sh
vendored
2
.github/workflows/repro.sh
vendored
@@ -5,7 +5,7 @@ if [[ "$OSTYPE" == "linux"* ]]; then
|
||||
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-linux.tar.gz"
|
||||
BINARYEN="https://github.com/WebAssembly/binaryen/releases/download/version_120/binaryen-version_120-x86_64-linux.tar.gz"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-macos.tar.gz"
|
||||
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-arm64-macos.tar.gz"
|
||||
BINARYEN="https://github.com/WebAssembly/binaryen/releases/download/version_120/binaryen-version_120-arm64-macos.tar.gz"
|
||||
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
|
||||
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-windows.tar.gz"
|
||||
|
||||
96
.github/workflows/test.yml
vendored
96
.github/workflows/test.yml
vendored
@@ -5,12 +5,14 @@ on:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
- '**.wasm'
|
||||
- '**.wasm.bz2'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
- '**.wasm'
|
||||
- '**.wasm.bz2'
|
||||
workflow_dispatch:
|
||||
@@ -83,21 +85,6 @@ jobs:
|
||||
github.event_name == 'push' &&
|
||||
matrix.os == 'ubuntu-latest'
|
||||
|
||||
test-intel:
|
||||
runs-on: macos-13
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Git LFS pull
|
||||
uses: ./.github/actions/lfs
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
|
||||
test-bsd:
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -105,19 +92,17 @@ jobs:
|
||||
- name: freebsd
|
||||
version: '14.1'
|
||||
flags: '-test.v'
|
||||
- name: openbsd
|
||||
version: '7.5'
|
||||
flags: '-test.v -test.short'
|
||||
- name: netbsd
|
||||
version: '10.0'
|
||||
flags: '-test.v'
|
||||
- name: openbsd
|
||||
version: '7.5'
|
||||
flags: '-test.v -test.short'
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with: { go-version: stable }
|
||||
|
||||
- name: Git LFS pull
|
||||
uses: ./.github/actions/lfs
|
||||
@@ -137,6 +122,44 @@ jobs:
|
||||
run: . ./test.sh
|
||||
sync_files: runner-to-vm
|
||||
|
||||
test-vm:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: dragonfly
|
||||
action: 'vmactions/dragonflybsd-vm@v1'
|
||||
tflags: '-test.v'
|
||||
- name: illumos
|
||||
action: 'vmactions/omnios-vm@v1'
|
||||
tflags: '-test.v'
|
||||
- name: solaris
|
||||
action: 'vmactions/solaris-vm@v1'
|
||||
bflags: '-tags sqlite3_dotlk'
|
||||
tflags: '-test.v'
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Git LFS pull
|
||||
uses: ./.github/actions/lfs
|
||||
|
||||
- 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
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: . ./test.sh
|
||||
|
||||
test-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
@@ -165,8 +188,8 @@ jobs:
|
||||
- name: Test s390x (big-endian)
|
||||
run: GOARCH=s390x go test -v -short -tags sqlite3_dotlk ./...
|
||||
|
||||
test-vm:
|
||||
runs-on: ubuntu-latest
|
||||
test-macintel:
|
||||
runs-on: macos-13
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
@@ -177,30 +200,5 @@ jobs:
|
||||
- name: Git LFS pull
|
||||
uses: ./.github/actions/lfs
|
||||
|
||||
- name: Build illumos
|
||||
env:
|
||||
GOOS: illumos
|
||||
TESTFLAGS: '-test.v -test.short'
|
||||
run: .github/workflows/build-test.sh
|
||||
|
||||
- name: Test illumos
|
||||
uses: vmactions/omnios-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: . ./test.sh
|
||||
|
||||
- name: Build Solaris
|
||||
env:
|
||||
GOOS: solaris
|
||||
TESTFLAGS: '-test.v -test.short'
|
||||
BUILDFLAGS: '-tags sqlite3_dotlk'
|
||||
run: .github/workflows/build-test.sh
|
||||
|
||||
- name: Test Solaris
|
||||
uses: vmactions/solaris-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: . ./test.sh
|
||||
continue-on-error: true
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
15
README.md
15
README.md
@@ -77,7 +77,7 @@ It also benefits greatly from [SQLite's](https://sqlite.org/testing.html) and
|
||||
Every commit is [tested](https://github.com/ncruces/go-sqlite3/wiki/Test-matrix) on
|
||||
Linux (amd64/arm64/386/riscv64/ppc64le/s390x), macOS (amd64/arm64),
|
||||
Windows (amd64), FreeBSD (amd64), OpenBSD (amd64), NetBSD (amd64),
|
||||
illumos (amd64), and Solaris (amd64).
|
||||
DragonFly BSD (amd64), illumos (amd64), and Solaris (amd64).
|
||||
|
||||
The Go VFS is tested by running SQLite's
|
||||
[mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c).
|
||||
@@ -90,9 +90,20 @@ Perfomance of the [`database/sql`](https://pkg.go.dev/database/sql) driver is
|
||||
The Wasm and VFS layers are also tested by running SQLite's
|
||||
[speedtest1](https://github.com/sqlite/sqlite/blob/master/test/speedtest1.c).
|
||||
|
||||
### FAQ, issues, new features
|
||||
|
||||
For questions, please see [Discussions](https://github.com/ncruces/go-sqlite3/discussions/categories/q-a).
|
||||
|
||||
Also, post there if you used this driver for something interesting
|
||||
([_"Show and tell"_](https://github.com/ncruces/go-sqlite3/discussions/categories/show-and-tell)),
|
||||
have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/ideas)…
|
||||
|
||||
The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs we want fixed,
|
||||
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)
|
||||
- [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Embeddable Wasm build of SQLite
|
||||
|
||||
This folder includes an embeddable Wasm build of SQLite 3.47.0 for use with
|
||||
This folder includes an embeddable Wasm build of SQLite 3.47.1 for use with
|
||||
[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
|
||||
|
||||
The following optional features are compiled in:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Embeddable Wasm build of SQLite
|
||||
|
||||
This folder includes an embeddable Wasm build of SQLite 3.47.0, including the experimental
|
||||
This folder includes an embeddable Wasm build of SQLite, including the experimental
|
||||
[`BEGIN CONCURRENT`](https://sqlite.org/src/doc/begin-concurrent/doc/begin_concurrent.md) and
|
||||
[Wal2](https://sqlite.org/cgi/src/doc/wal2/doc/wal2.md) patches.
|
||||
|
||||
|
||||
Binary file not shown.
@@ -42,7 +42,7 @@ func Test_bcw2(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != "3.47.0" {
|
||||
if version != "3.48.0" {
|
||||
t.Error(version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ mkdir -p build/ext/
|
||||
cp "$ROOT"/sqlite3/*.[ch] build/
|
||||
cp "$ROOT"/sqlite3/*.patch build/
|
||||
|
||||
# https://sqlite.org/src/info/d2d954d43abe20a3
|
||||
curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=d2d954d4 | tar xz
|
||||
# https://sqlite.org/src/info/e03dd0bd313817da
|
||||
curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=e03dd0bd | tar xz
|
||||
|
||||
cd sqlite
|
||||
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
|
||||
|
||||
@@ -19,7 +19,7 @@ func Test_init(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != "3.47.0" {
|
||||
if version != "3.47.1" {
|
||||
t.Error(version)
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
21
go.mod
21
go.mod
@@ -5,17 +5,20 @@ go 1.21
|
||||
toolchain go1.23.0
|
||||
|
||||
require (
|
||||
github.com/dchest/siphash v1.2.3
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/ncruces/julianday v1.0.0
|
||||
github.com/ncruces/sort v0.1.2
|
||||
github.com/psanford/httpreadat v0.1.0
|
||||
github.com/tetratelabs/wazero v1.8.1
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/sys v0.26.0
|
||||
golang.org/x/text v0.19.0
|
||||
lukechampine.com/adiantum v1.1.1
|
||||
github.com/tetratelabs/wazero v1.8.2
|
||||
golang.org/x/crypto v0.29.0
|
||||
golang.org/x/sys v0.27.0
|
||||
)
|
||||
|
||||
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/sync v0.9.0 // test
|
||||
golang.org/x/text v0.20.0 // ext/unicode
|
||||
lukechampine.com/adiantum v1.1.1 // vfs/adiantum
|
||||
)
|
||||
|
||||
retract v0.4.0 // tagged from the wrong branch
|
||||
|
||||
20
go.sum
20
go.sum
@@ -8,15 +8,15 @@ github.com/ncruces/sort v0.1.2 h1:zKQ9CA4fpHPF6xsUhRTfi5EEryspuBpe/QA4VWQOV1U=
|
||||
github.com/ncruces/sort v0.1.2/go.mod h1:vEJUTBJtebIuCMmXD18GKo5GJGhsay+xZFOoBEIXFmE=
|
||||
github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIwZLUE=
|
||||
github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE=
|
||||
github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550=
|
||||
github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4=
|
||||
github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
lukechampine.com/adiantum v1.1.1 h1:4fp6gTxWCqpEbLy40ExiYDDED3oUNWx5cTqBCtPdZqA=
|
||||
lukechampine.com/adiantum v1.1.1/go.mod h1:LrAYVnTYLnUtE/yMp5bQr0HstAf060YUF8nM0B6+rUw=
|
||||
|
||||
@@ -9,5 +9,6 @@ golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.21
|
||||
toolchain go1.23.0
|
||||
|
||||
require (
|
||||
github.com/ncruces/go-sqlite3 v0.20.0
|
||||
github.com/ncruces/go-sqlite3 v0.20.2
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ require (
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/ncruces/julianday v1.0.0 // indirect
|
||||
github.com/tetratelabs/wazero v1.8.1 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
github.com/tetratelabs/wazero v1.8.2 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
)
|
||||
|
||||
@@ -2,15 +2,15 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/ncruces/go-sqlite3 v0.20.0 h1:/nBLvYxj7sk9S6y57nmMFvoQ/KJtGo0pNi8J80s8oJU=
|
||||
github.com/ncruces/go-sqlite3 v0.20.0/go.mod h1:yL4ZNWGsr1/8pcLfpPW1RT1WFdvyeHonrgIwwi4rvkg=
|
||||
github.com/ncruces/go-sqlite3 v0.20.2 h1:cMLIwrLZQuCWVCEOowSqlIlpzgbag3jnYVW4NM5u01M=
|
||||
github.com/ncruces/go-sqlite3 v0.20.2/go.mod h1:yL4ZNWGsr1/8pcLfpPW1RT1WFdvyeHonrgIwwi4rvkg=
|
||||
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
|
||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550=
|
||||
github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4=
|
||||
github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# handle, and interrupt, sqlite3_busy_timeout.
|
||||
--- sqlite3.c.orig
|
||||
+++ sqlite3.c
|
||||
@@ -182908,7 +182908,7 @@
|
||||
@@ -182928,7 +182928,7 @@
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
if( ms>0 ){
|
||||
|
||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
|
||||
cd -P -- "$(dirname -- "$0")"
|
||||
|
||||
curl -#OL "https://sqlite.org/2024/sqlite-amalgamation-3470000.zip"
|
||||
curl -#OL "https://sqlite.org/2024/sqlite-amalgamation-3470100.zip"
|
||||
unzip -d . sqlite-amalgamation-*.zip
|
||||
mv sqlite-amalgamation-*/sqlite3.c .
|
||||
mv sqlite-amalgamation-*/sqlite3.h .
|
||||
@@ -21,25 +21,25 @@ cat *.patch | patch --no-backup-if-mismatch
|
||||
|
||||
mkdir -p ext/
|
||||
cd ext/
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/anycollseq.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/base64.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/decimal.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/ieee754.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/regexp.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/series.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/spellfix.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/ext/misc/uint.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/anycollseq.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/base64.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/decimal.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/ieee754.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/regexp.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/series.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/spellfix.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/ext/misc/uint.c"
|
||||
cd ~-
|
||||
|
||||
cd ../vfs/tests/mptest/testdata/
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/mptest.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/config01.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/config02.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/crash01.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/crash02.subtest"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/mptest/multiwrite01.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/mptest.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/config01.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/config02.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/crash01.test"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/crash02.subtest"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/mptest/multiwrite01.test"
|
||||
cd ~-
|
||||
|
||||
cd ../vfs/tests/speedtest1/testdata/
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.0/test/speedtest1.c"
|
||||
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.47.1/test/speedtest1.c"
|
||||
cd ~-
|
||||
@@ -1,7 +1,7 @@
|
||||
# Remove VFS registration. Go handles it.
|
||||
--- sqlite3.c.orig
|
||||
+++ sqlite3.c
|
||||
@@ -26594,7 +26594,7 @@
|
||||
@@ -26603,7 +26603,7 @@
|
||||
sqlite3_free(p);
|
||||
return sqlite3_os_init();
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
/*
|
||||
** The list of all registered VFS implementations.
|
||||
*/
|
||||
@@ -26691,7 +26691,7 @@
|
||||
@@ -26700,7 +26700,7 @@
|
||||
sqlite3_mutex_leave(mutex);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ like SQLite.
|
||||
|
||||
You can also opt into a cross-platform locking implementation
|
||||
with the `sqlite3_dotlk` build tag.
|
||||
The only requirement is an atomic `os.Mkdir`.
|
||||
|
||||
Otherwise, file locking is not supported, and you must use
|
||||
[`nolock=1`](https://sqlite.org/uri.html#urinolock)
|
||||
|
||||
@@ -198,11 +198,13 @@ func (h *hbshFile) WriteAt(p []byte, off int64) (n int, err error) {
|
||||
func (h *hbshFile) DeviceCharacteristics() vfs.DeviceCharacteristic {
|
||||
var _ [0]struct{} = [blockSize - 4096]struct{}{} // Ensure blockSize is 4K.
|
||||
return h.File.DeviceCharacteristics() & (0 |
|
||||
// The only safe flags are these:
|
||||
// These flags are safe:
|
||||
vfs.IOCAP_ATOMIC4K |
|
||||
vfs.IOCAP_UNDELETABLE_WHEN_OPEN |
|
||||
vfs.IOCAP_IMMUTABLE |
|
||||
vfs.IOCAP_BATCH_ATOMIC)
|
||||
vfs.IOCAP_SEQUENTIAL |
|
||||
vfs.IOCAP_SUBPAGE_READ |
|
||||
vfs.IOCAP_BATCH_ATOMIC |
|
||||
vfs.IOCAP_UNDELETABLE_WHEN_OPEN)
|
||||
}
|
||||
|
||||
func (h *hbshFile) SectorSize() int {
|
||||
|
||||
@@ -101,6 +101,14 @@ func (c cksmFile) Pragma(name string, value string) (string, error) {
|
||||
return "", _NOTFOUND
|
||||
}
|
||||
|
||||
func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic {
|
||||
res := c.File.DeviceCharacteristics()
|
||||
if c.verifyCksm {
|
||||
res &^= IOCAP_SUBPAGE_READ
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg uint32) _ErrorCode {
|
||||
switch op {
|
||||
case _FCNTL_CKPT_START:
|
||||
|
||||
@@ -177,6 +177,7 @@ const (
|
||||
IOCAP_POWERSAFE_OVERWRITE DeviceCharacteristic = 0x00001000
|
||||
IOCAP_IMMUTABLE DeviceCharacteristic = 0x00002000
|
||||
IOCAP_BATCH_ATOMIC DeviceCharacteristic = 0x00004000
|
||||
IOCAP_SUBPAGE_READ DeviceCharacteristic = 0x00008000
|
||||
)
|
||||
|
||||
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
|
||||
|
||||
@@ -187,7 +187,7 @@ func (f *vfsFile) SectorSize() int {
|
||||
}
|
||||
|
||||
func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic {
|
||||
var res DeviceCharacteristic
|
||||
res := IOCAP_SUBPAGE_READ
|
||||
if osBatchAtomic(f.File) {
|
||||
res |= IOCAP_BATCH_ATOMIC
|
||||
}
|
||||
|
||||
@@ -15,9 +15,15 @@ func osGetSharedLock(file *os.File) _ErrorCode {
|
||||
func osGetReservedLock(file *os.File) _ErrorCode {
|
||||
rc := osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
|
||||
if rc == _BUSY {
|
||||
// The documentation states the lock is upgraded by releasing the previous lock,
|
||||
// then acquiring the new lock.
|
||||
// This is a race, so return BUSY_SNAPSHOT to ensure the transaction is aborted.
|
||||
// The documentation states that a lock is upgraded by
|
||||
// releasing the previous lock, then acquiring the new lock.
|
||||
// Going over the source code of various BSDs, though,
|
||||
// with LOCK_NB, the lock is not released,
|
||||
// and EAGAIN is returned holding the shared lock.
|
||||
// Still, if we're already in a transaction, we want to abort it,
|
||||
// so return BUSY_SNAPSHOT here. If there's no transaction active,
|
||||
// SQLite will change this back to SQLITE_BUSY,
|
||||
// and invoke the busy handler if appropriate.
|
||||
return _BUSY_SNAPSHOT
|
||||
}
|
||||
return rc
|
||||
@@ -33,9 +39,11 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode {
|
||||
func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode {
|
||||
rc := osLock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
|
||||
if rc == _BUSY {
|
||||
// The documentation states the lock is upgraded by releasing the previous lock,
|
||||
// then acquiring the new lock.
|
||||
// This is a race, so return IOERR_RDLOCK to ensure the transaction is aborted.
|
||||
// The documentation states that a lock is downgraded by
|
||||
// releasing the previous lock then acquiring the new lock.
|
||||
// Going over the source code of various BSDs, though,
|
||||
// with LOCK_SH|LOCK_NB this should never happen.
|
||||
// Return IOERR_RDLOCK, as BUSY would cause an assert to fail.
|
||||
return _IOERR_RDLOCK
|
||||
}
|
||||
return _OK
|
||||
@@ -50,7 +58,10 @@ func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode {
|
||||
}
|
||||
|
||||
func osCheckReservedLock(file *os.File) (bool, _ErrorCode) {
|
||||
// Test the RESERVED lock.
|
||||
// Test the RESERVED lock with fcntl(F_GETLK).
|
||||
// This only works on systems where fcntl and flock are compatible.
|
||||
// However, SQLite only calls this while holding a shared lock,
|
||||
// so the difference is immaterial.
|
||||
lock, rc := osTestLock(file, _RESERVED_BYTE, 1)
|
||||
return lock == unix.F_WRLCK, rc
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ func osGetSharedLock(file *os.File) _ErrorCode {
|
||||
name := file.Name()
|
||||
locker := vfsDotLocks[name]
|
||||
if locker == nil {
|
||||
err := os.Mkdir(name+".lock", 0777)
|
||||
f, err := os.OpenFile(name+".lock", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
|
||||
f.Close()
|
||||
if errors.Is(err, fs.ErrExist) {
|
||||
return _BUSY // Another process has the lock.
|
||||
}
|
||||
|
||||
@@ -50,14 +50,17 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode {
|
||||
|
||||
if rc != _OK {
|
||||
// Reacquire the SHARED lock.
|
||||
osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0)
|
||||
if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK {
|
||||
// notest // this should never happen
|
||||
return _IOERR_RDLOCK
|
||||
}
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
|
||||
if state >= LOCK_EXCLUSIVE {
|
||||
// Release the EXCLUSIVE lock.
|
||||
// Release the EXCLUSIVE lock while holding the PENDING lock.
|
||||
osUnlock(file, _SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
// Reacquire the SHARED lock.
|
||||
@@ -78,7 +81,7 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
|
||||
}
|
||||
|
||||
func osReleaseLock(file *os.File, state LockLevel) _ErrorCode {
|
||||
// Release all locks.
|
||||
// Release all locks, PENDING must be last.
|
||||
if state >= LOCK_RESERVED {
|
||||
osUnlock(file, _RESERVED_BYTE, 1)
|
||||
}
|
||||
|
||||
@@ -77,5 +77,5 @@ func (readerFile) SectorSize() int {
|
||||
}
|
||||
|
||||
func (readerFile) DeviceCharacteristics() vfs.DeviceCharacteristic {
|
||||
return vfs.IOCAP_IMMUTABLE
|
||||
return vfs.IOCAP_IMMUTABLE | vfs.IOCAP_SUBPAGE_READ
|
||||
}
|
||||
|
||||
100
vfs/shm_bsd.go
100
vfs/shm_bsd.go
@@ -14,52 +14,52 @@ import (
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
)
|
||||
|
||||
type vfsShmFile struct {
|
||||
type vfsShmParent struct {
|
||||
*os.File
|
||||
info os.FileInfo
|
||||
|
||||
refs int // +checklocks:vfsShmFilesMtx
|
||||
refs int // +checklocks:vfsShmListMtx
|
||||
|
||||
lock [_SHM_NLOCK]int16 // +checklocks:Mutex
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var (
|
||||
// +checklocks:vfsShmFilesMtx
|
||||
vfsShmFiles []*vfsShmFile
|
||||
vfsShmFilesMtx sync.Mutex
|
||||
// +checklocks:vfsShmListMtx
|
||||
vfsShmList []*vfsShmParent
|
||||
vfsShmListMtx sync.Mutex
|
||||
)
|
||||
|
||||
type vfsShm struct {
|
||||
*vfsShmFile
|
||||
*vfsShmParent
|
||||
path string
|
||||
lock [_SHM_NLOCK]bool
|
||||
regions []*util.MappedRegion
|
||||
}
|
||||
|
||||
func (s *vfsShm) Close() error {
|
||||
if s.vfsShmFile == nil {
|
||||
if s.vfsShmParent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vfsShmFilesMtx.Lock()
|
||||
defer vfsShmFilesMtx.Unlock()
|
||||
vfsShmListMtx.Lock()
|
||||
defer vfsShmListMtx.Unlock()
|
||||
|
||||
// Unlock everything.
|
||||
s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK)
|
||||
|
||||
// Decrease reference count.
|
||||
if s.vfsShmFile.refs > 0 {
|
||||
s.vfsShmFile.refs--
|
||||
s.vfsShmFile = nil
|
||||
if s.vfsShmParent.refs > 0 {
|
||||
s.vfsShmParent.refs--
|
||||
s.vfsShmParent = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
err := s.File.Close()
|
||||
for i, g := range vfsShmFiles {
|
||||
if g == s.vfsShmFile {
|
||||
vfsShmFiles[i] = nil
|
||||
s.vfsShmFile = nil
|
||||
for i, g := range vfsShmList {
|
||||
if g == s.vfsShmParent {
|
||||
vfsShmList[i] = nil
|
||||
s.vfsShmParent = nil
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func (s *vfsShm) Close() error {
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
if s.vfsShmFile != nil {
|
||||
if s.vfsShmParent != nil {
|
||||
return _OK
|
||||
}
|
||||
|
||||
@@ -85,13 +85,13 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
return _IOERR_FSTAT
|
||||
}
|
||||
|
||||
vfsShmFilesMtx.Lock()
|
||||
defer vfsShmFilesMtx.Unlock()
|
||||
vfsShmListMtx.Lock()
|
||||
defer vfsShmListMtx.Unlock()
|
||||
|
||||
// Find a shared file, increase the reference count.
|
||||
for _, g := range vfsShmFiles {
|
||||
for _, g := range vfsShmList {
|
||||
if g != nil && os.SameFile(fi, g.info) {
|
||||
s.vfsShmFile = g
|
||||
s.vfsShmParent = g
|
||||
g.refs++
|
||||
return _OK
|
||||
}
|
||||
@@ -107,18 +107,18 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
}
|
||||
|
||||
// Add the new shared file.
|
||||
s.vfsShmFile = &vfsShmFile{
|
||||
s.vfsShmParent = &vfsShmParent{
|
||||
File: f,
|
||||
info: fi,
|
||||
}
|
||||
f = nil // Don't close the file.
|
||||
for i, g := range vfsShmFiles {
|
||||
for i, g := range vfsShmList {
|
||||
if g == nil {
|
||||
vfsShmFiles[i] = s.vfsShmFile
|
||||
vfsShmList[i] = s.vfsShmParent
|
||||
return _OK
|
||||
}
|
||||
}
|
||||
vfsShmFiles = append(vfsShmFiles, s.vfsShmFile)
|
||||
vfsShmList = append(vfsShmList, s.vfsShmParent)
|
||||
return _OK
|
||||
}
|
||||
|
||||
@@ -157,57 +157,11 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
switch {
|
||||
case flags&_SHM_UNLOCK != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
if s.vfsShmFile.lock[i] == 0 {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i] <= 0 {
|
||||
s.vfsShmFile.lock[i] = 0
|
||||
} else {
|
||||
s.vfsShmFile.lock[i]--
|
||||
}
|
||||
s.lock[i] = false
|
||||
}
|
||||
}
|
||||
case flags&_SHM_SHARED != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i]+1 <= 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmFile.lock[i]++
|
||||
s.lock[i] = true
|
||||
}
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i] != 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmFile.lock[i] = -1
|
||||
s.lock[i] = true
|
||||
}
|
||||
default:
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
|
||||
return _OK
|
||||
return s.shmMemLock(offset, n, flags)
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmUnmap(delete bool) {
|
||||
if s.vfsShmFile == nil {
|
||||
if s.vfsShmParent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,10 @@ const (
|
||||
//
|
||||
// https://sqlite.org/walformat.html#the_wal_index_file_format
|
||||
|
||||
func (s *vfsShm) shmAcquire() {
|
||||
func (s *vfsShm) shmAcquire(ptr *_ErrorCode) {
|
||||
if ptr != nil && *ptr != _OK {
|
||||
return
|
||||
}
|
||||
if len(s.ptrs) == 0 || shmUnmodified(s.shadow[0][:], s.shared[0][:]) {
|
||||
return
|
||||
}
|
||||
@@ -69,7 +72,7 @@ func (s *vfsShm) shmRelease() {
|
||||
|
||||
func (s *vfsShm) shmBarrier() {
|
||||
s.Lock()
|
||||
s.shmAcquire()
|
||||
s.shmAcquire(nil)
|
||||
s.shmRelease()
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
@@ -13,22 +13,22 @@ import (
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
)
|
||||
|
||||
type vfsShmBuffer struct {
|
||||
type vfsShmParent struct {
|
||||
shared [][_WALINDEX_PGSZ]byte
|
||||
refs int // +checklocks:vfsShmBuffersMtx
|
||||
refs int // +checklocks:vfsShmListMtx
|
||||
|
||||
lock [_SHM_NLOCK]int16 // +checklocks:Mutex
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var (
|
||||
// +checklocks:vfsShmBuffersMtx
|
||||
vfsShmBuffers = map[string]*vfsShmBuffer{}
|
||||
vfsShmBuffersMtx sync.Mutex
|
||||
// +checklocks:vfsShmListMtx
|
||||
vfsShmList = map[string]*vfsShmParent{}
|
||||
vfsShmListMtx sync.Mutex
|
||||
)
|
||||
|
||||
type vfsShm struct {
|
||||
*vfsShmBuffer
|
||||
*vfsShmParent
|
||||
mod api.Module
|
||||
alloc api.Function
|
||||
free api.Function
|
||||
@@ -40,20 +40,20 @@ type vfsShm struct {
|
||||
}
|
||||
|
||||
func (s *vfsShm) Close() error {
|
||||
if s.vfsShmBuffer == nil {
|
||||
if s.vfsShmParent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vfsShmBuffersMtx.Lock()
|
||||
defer vfsShmBuffersMtx.Unlock()
|
||||
vfsShmListMtx.Lock()
|
||||
defer vfsShmListMtx.Unlock()
|
||||
|
||||
// Unlock everything.
|
||||
s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK)
|
||||
|
||||
// Decrease reference count.
|
||||
if s.vfsShmBuffer.refs > 0 {
|
||||
s.vfsShmBuffer.refs--
|
||||
s.vfsShmBuffer = nil
|
||||
if s.vfsShmParent.refs > 0 {
|
||||
s.vfsShmParent.refs--
|
||||
s.vfsShmParent = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -61,22 +61,22 @@ func (s *vfsShm) Close() error {
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
return _IOERR_UNLOCK
|
||||
}
|
||||
delete(vfsShmBuffers, s.path)
|
||||
s.vfsShmBuffer = nil
|
||||
delete(vfsShmList, s.path)
|
||||
s.vfsShmParent = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
if s.vfsShmBuffer != nil {
|
||||
if s.vfsShmParent != nil {
|
||||
return _OK
|
||||
}
|
||||
|
||||
vfsShmBuffersMtx.Lock()
|
||||
defer vfsShmBuffersMtx.Unlock()
|
||||
vfsShmListMtx.Lock()
|
||||
defer vfsShmListMtx.Unlock()
|
||||
|
||||
// Find a shared buffer, increase the reference count.
|
||||
if g, ok := vfsShmBuffers[s.path]; ok {
|
||||
s.vfsShmBuffer = g
|
||||
if g, ok := vfsShmList[s.path]; ok {
|
||||
s.vfsShmParent = g
|
||||
g.refs++
|
||||
return _OK
|
||||
}
|
||||
@@ -92,8 +92,8 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
}
|
||||
|
||||
// Add the new shared buffer.
|
||||
s.vfsShmBuffer = &vfsShmBuffer{}
|
||||
vfsShmBuffers[s.path] = s.vfsShmBuffer
|
||||
s.vfsShmParent = &vfsShmParent{}
|
||||
vfsShmList[s.path] = s.vfsShmParent
|
||||
return _OK
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
defer s.shmAcquire()
|
||||
defer s.shmAcquire(nil)
|
||||
|
||||
// Extend shared memory.
|
||||
if int(id) >= len(s.shared) {
|
||||
@@ -125,7 +125,6 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
// Allocate shadow memory.
|
||||
if int(id) >= len(s.shadow) {
|
||||
s.shadow = append(s.shadow, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shadow)+1)...)
|
||||
s.shadow[0][4] = 1 // force invalidation
|
||||
}
|
||||
|
||||
// Allocate local memory.
|
||||
@@ -141,70 +140,26 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
s.ptrs = append(s.ptrs, uint32(s.stack[0]))
|
||||
}
|
||||
|
||||
s.shadow[0][4] = 1
|
||||
return s.ptrs[id], _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
switch {
|
||||
case flags&_SHM_LOCK != 0:
|
||||
defer s.shmAcquire()
|
||||
defer s.shmAcquire(&rc)
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
s.shmRelease()
|
||||
}
|
||||
|
||||
switch {
|
||||
case flags&_SHM_UNLOCK != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
if s.vfsShmBuffer.lock[i] == 0 {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmBuffer.lock[i] <= 0 {
|
||||
s.vfsShmBuffer.lock[i] = 0
|
||||
} else {
|
||||
s.vfsShmBuffer.lock[i]--
|
||||
}
|
||||
s.lock[i] = false
|
||||
}
|
||||
}
|
||||
case flags&_SHM_SHARED != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmBuffer.lock[i]+1 <= 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmBuffer.lock[i]++
|
||||
s.lock[i] = true
|
||||
}
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmBuffer.lock[i] != 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmBuffer.lock[i] = -1
|
||||
s.lock[i] = true
|
||||
}
|
||||
default:
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
|
||||
return _OK
|
||||
return s.shmMemLock(offset, n, flags)
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmUnmap(delete bool) {
|
||||
if s.vfsShmBuffer == nil {
|
||||
if s.vfsShmParent == nil {
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
55
vfs/shm_memlk.go
Normal file
55
vfs/shm_memlk.go
Normal file
@@ -0,0 +1,55 @@
|
||||
//go:build ((freebsd || openbsd || netbsd || dragonfly || illumos) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le) && !sqlite3_nosys) || sqlite3_flock || sqlite3_dotlk
|
||||
|
||||
package vfs
|
||||
|
||||
import "github.com/ncruces/go-sqlite3/internal/util"
|
||||
|
||||
// +checklocks:s.Mutex
|
||||
func (s *vfsShm) shmMemLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
switch {
|
||||
case flags&_SHM_UNLOCK != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
if s.vfsShmParent.lock[i] == 0 {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmParent.lock[i] <= 0 {
|
||||
s.vfsShmParent.lock[i] = 0
|
||||
} else {
|
||||
s.vfsShmParent.lock[i]--
|
||||
}
|
||||
s.lock[i] = false
|
||||
}
|
||||
}
|
||||
case flags&_SHM_SHARED != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmParent.lock[i]+1 <= 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmParent.lock[i]++
|
||||
s.lock[i] = true
|
||||
}
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmParent.lock[i] != 0 {
|
||||
return _BUSY
|
||||
}
|
||||
}
|
||||
for i := offset; i < offset+n; i++ {
|
||||
s.vfsShmParent.lock[i] = -1
|
||||
s.lock[i] = true
|
||||
}
|
||||
default:
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
|
||||
return _OK
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
return osReadLock(s.File, _SHM_DMS, 1, time.Millisecond)
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ uint32, rc _ErrorCode) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
@@ -78,7 +78,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
return 0, rc
|
||||
}
|
||||
|
||||
defer s.shmAcquire()
|
||||
defer s.shmAcquire(&rc)
|
||||
|
||||
// Check if file is big enough.
|
||||
o, err := s.Seek(0, io.SeekEnd)
|
||||
@@ -107,7 +107,6 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
// Allocate shadow memory.
|
||||
if int(id) >= len(s.shadow) {
|
||||
s.shadow = append(s.shadow, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shadow)+1)...)
|
||||
s.shadow[0][4] = 1 // force invalidation
|
||||
}
|
||||
|
||||
// Allocate local memory.
|
||||
@@ -123,22 +122,23 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
s.ptrs = append(s.ptrs, uint32(s.stack[0]))
|
||||
}
|
||||
|
||||
s.shadow[0][4] = 1
|
||||
return s.ptrs[id], _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
switch {
|
||||
case flags&_SHM_LOCK != 0:
|
||||
defer s.shmAcquire()
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
s.shmRelease()
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) {
|
||||
var timeout time.Duration
|
||||
if s.blocking {
|
||||
timeout = time.Millisecond
|
||||
}
|
||||
|
||||
switch {
|
||||
case flags&_SHM_LOCK != 0:
|
||||
defer s.shmAcquire(&rc)
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
s.shmRelease()
|
||||
}
|
||||
|
||||
switch {
|
||||
case flags&_SHM_UNLOCK != 0:
|
||||
return osUnlock(s.File, _SHM_BASE+uint32(offset), uint32(n))
|
||||
|
||||
4
vfs/tests/mptest/testdata/mptest.wasm.bz2
vendored
4
vfs/tests/mptest/testdata/mptest.wasm.bz2
vendored
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4a2ed4f7fe323843e78c59a23e0bd078d807745a3e6276a9862ff08bb7bdac18
|
||||
size 480769
|
||||
oid sha256:802b6453e73f0e94773b93a0e5a7abfe427187e916a3258cd5093959def61bda
|
||||
size 480661
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:98abb49f1b6acf5398c08556571d44acdc7258484e510b3f8c7a19ee42b5821c
|
||||
size 493373
|
||||
oid sha256:7ba2fd84fb88e54f60280c41bc7389c946ef1abc5cb9c795bbb32bc0f5760c65
|
||||
size 493557
|
||||
|
||||
@@ -194,11 +194,13 @@ func (x *xtsFile) WriteAt(p []byte, off int64) (n int, err error) {
|
||||
func (x *xtsFile) DeviceCharacteristics() vfs.DeviceCharacteristic {
|
||||
var _ [0]struct{} = [sectorSize - 512]struct{}{} // Ensure sectorSize is 512.
|
||||
return x.File.DeviceCharacteristics() & (0 |
|
||||
// The only safe flags are these:
|
||||
// These flags are safe:
|
||||
vfs.IOCAP_ATOMIC512 |
|
||||
vfs.IOCAP_UNDELETABLE_WHEN_OPEN |
|
||||
vfs.IOCAP_IMMUTABLE |
|
||||
vfs.IOCAP_BATCH_ATOMIC)
|
||||
vfs.IOCAP_SEQUENTIAL |
|
||||
vfs.IOCAP_SUBPAGE_READ |
|
||||
vfs.IOCAP_BATCH_ATOMIC |
|
||||
vfs.IOCAP_UNDELETABLE_WHEN_OPEN)
|
||||
}
|
||||
|
||||
func (x *xtsFile) SectorSize() int {
|
||||
|
||||
Reference in New Issue
Block a user