mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-12 21:58:58 -04:00
chore: reva bump -2.48.0 (#3230)
This commit is contained in:
1 parent
e12966a4fd
commit
bb4cd1ebf5
42 files changed
+9526
-5016
No files matched your search
@@ -64,7 +64,7 @@ require (
|
||||
github.com/open-policy-agent/opa v1.19.0
|
||||
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
|
||||
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d
|
||||
github.com/opencloud-eu/reva/v2 v2.47.0
|
||||
github.com/opencloud-eu/reva/v2 v2.48.0
|
||||
github.com/opensearch-project/opensearch-go/v4 v4.6.0
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -135,7 +135,7 @@ require (
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/alexedwards/argon2id v1.0.0 // indirect
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 // indirect
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2-default-no-op // indirect
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -274,10 +274,10 @@ require (
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.23 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.42 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.49 // indirect
|
||||
github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b // indirect
|
||||
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 // indirect
|
||||
github.com/miekg/dns v1.1.68 // indirect
|
||||
@@ -342,8 +342,8 @@ require (
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/sethvargo/go-diceware v0.5.0 // indirect
|
||||
github.com/sethvargo/go-password v0.3.1 // indirect
|
||||
github.com/sethvargo/go-diceware v0.6.0 // indirect
|
||||
github.com/sethvargo/go-password v0.4.0 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.5 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
@@ -389,7 +389,7 @@ require (
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
golang.org/x/tools v0.47.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.3 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
||||
@@ -115,8 +115,8 @@ github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2-default-no-op h1:p2zFsAzvhIpFya8AIOHIbWf7NGvO34QpLGclyf7nXj8=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2 h1:oEEedg1Xgi8drRjqB0f9tfjhLoInE0IYZfZ6zAhQUbY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
@@ -799,23 +799,23 @@ github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
|
||||
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
|
||||
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-sqlite3 v1.14.49 h1:B8jBHC3xhxZgxztrgruTuLucebnULQnx4W7cF7SAE9w=
|
||||
github.com/mattn/go-sqlite3 v1.14.49/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -942,8 +942,8 @@ github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+l
|
||||
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI=
|
||||
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d h1:JcqGDiyrcaQwVyV861TUyQgO7uEmsjkhfm7aQd84dOw=
|
||||
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
|
||||
github.com/opencloud-eu/reva/v2 v2.47.0 h1:bYul45qS8GmmN9PKplSZ78ZTZ6A+9xp/FfogqFVud18=
|
||||
github.com/opencloud-eu/reva/v2 v2.47.0/go.mod h1:zdpEKIMDT14w+MGUOWAi+rh+PAZBPUlb7AtIGFWx7Ds=
|
||||
github.com/opencloud-eu/reva/v2 v2.48.0 h1:G/4Jbv0DWWOfA5u5DtV0CB75pi9Wwtj7JkJQOEBvErs=
|
||||
github.com/opencloud-eu/reva/v2 v2.48.0/go.mod h1:ZCo/xQM6if+upZa7rJCmdifZ/Y5XHLCrscHytC39yI4=
|
||||
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI=
|
||||
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
@@ -1100,10 +1100,10 @@ github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aep
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sethvargo/go-diceware v0.5.0 h1:exrQ7GpaBo00GqRVM1N8ChXSsi3oS7tjQiIehsD+yR0=
|
||||
github.com/sethvargo/go-diceware v0.5.0/go.mod h1:Lg1SyPS7yQO6BBgTN5r4f2MUDkqGfLWsOjHPY0kA8iw=
|
||||
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
|
||||
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
|
||||
github.com/sethvargo/go-diceware v0.6.0 h1:B3nhMhbBP7KwtTQ7hHRIOmv5FqeD8bJs77RFrV24iWk=
|
||||
github.com/sethvargo/go-diceware v0.6.0/go.mod h1:lHmdB0xuWaJ06KCraW6bztRT+71Dp+lsXQvborhhsBc=
|
||||
github.com/sethvargo/go-password v0.4.0 h1:eSidVKQw5C7CmTDAtH3RipBTSjdU1ZRxQaynD2GWLVU=
|
||||
github.com/sethvargo/go-password v0.4.0/go.mod h1:PO3nYHwUpcHPR0F9woy7a4abZPvzRuqJr0GaeIYTm3k=
|
||||
github.com/shamaton/msgpack/v2 v2.4.1 h1:JtJ141QoQ3NqgPDsjq2v9VXlaON8SiQOwEaoNLEK/MQ=
|
||||
github.com/shamaton/msgpack/v2 v2.4.1/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
@@ -1703,8 +1703,8 @@ google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgn
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0 h1:mJiOtnGp0k/BcSgdu03G2NwnscCfCH+h2QKUBZr18KI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
// LatestTag is the latest released version plus the dev meta version.
|
||||
// Will be overwritten by the release pipeline
|
||||
// Needs a manual change for every tagged release
|
||||
LatestTag = "7.3.0+dev"
|
||||
LatestTag = "7.4.0+dev"
|
||||
|
||||
// Date indicates the build date.
|
||||
// This has been removed, it looks like you can only replace static strings with recent go versions
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
// Package assert enables defining [test properties] about your program or [workload]. It is part of the [Antithesis Go SDK], which enables Go applications to integrate with the [Antithesis platform].
|
||||
//
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build !enable_antithesis_sdk
|
||||
//go:build no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build !enable_antithesis_sdk
|
||||
//go:build no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package assert
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk
|
||||
//go:build !no_antithesis_sdk
|
||||
|
||||
package internal
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk && linux && amd64 && cgo
|
||||
//go:build !no_antithesis_sdk && linux && amd64 && cgo
|
||||
|
||||
package internal
|
||||
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
//go:build enable_antithesis_sdk && (!linux || !amd64 || !cgo)
|
||||
//go:build !no_antithesis_sdk && (!linux || !amd64 || !cgo)
|
||||
|
||||
package internal
|
||||
|
||||
|
||||
+19
-7
@@ -5,13 +5,13 @@ package colorable
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
syscall "golang.org/x/sys/windows"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
syscall "golang.org/x/sys/windows"
|
||||
"unsafe"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
@@ -93,6 +93,7 @@ type writer struct {
|
||||
handle syscall.Handle
|
||||
althandle syscall.Handle
|
||||
oldattr word
|
||||
curattr word
|
||||
oldpos coord
|
||||
rest bytes.Buffer
|
||||
mutex sync.Mutex
|
||||
@@ -112,7 +113,7 @@ func NewColorable(file *os.File) io.Writer {
|
||||
var csbi consoleScreenBufferInfo
|
||||
handle := syscall.Handle(file.Fd())
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
return &writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
|
||||
return &writer{out: file, handle: handle, oldattr: csbi.attributes, curattr: csbi.attributes, oldpos: coord{0, 0}}
|
||||
}
|
||||
return file
|
||||
}
|
||||
@@ -438,7 +439,11 @@ func (w *writer) Write(data []byte) (n int, err error) {
|
||||
w.mutex.Lock()
|
||||
defer w.mutex.Unlock()
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
|
||||
if w.rest.Len() == 0 && bytes.IndexByte(data, 0x1b) == -1 {
|
||||
w.out.Write(data)
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
handle := w.handle
|
||||
|
||||
@@ -517,7 +522,7 @@ loop:
|
||||
w.rest.Reset()
|
||||
break
|
||||
}
|
||||
buf.Write([]byte(string(c)))
|
||||
buf.WriteByte(c)
|
||||
}
|
||||
if m == 0 {
|
||||
break loop
|
||||
@@ -678,11 +683,11 @@ loop:
|
||||
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
case 'm':
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
attr := csbi.attributes
|
||||
attr := w.curattr
|
||||
cs := buf.String()
|
||||
if cs == "" {
|
||||
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
|
||||
w.curattr = w.oldattr
|
||||
continue
|
||||
}
|
||||
token := strings.Split(cs, ";")
|
||||
@@ -814,9 +819,12 @@ loop:
|
||||
attr |= backgroundBlue
|
||||
}
|
||||
}
|
||||
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
|
||||
}
|
||||
}
|
||||
if attr != w.curattr {
|
||||
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
|
||||
w.curattr = attr
|
||||
}
|
||||
case 'h':
|
||||
var ci consoleCursorInfo
|
||||
cs := buf.String()
|
||||
@@ -834,6 +842,8 @@ loop:
|
||||
w.althandle = syscall.Handle(h)
|
||||
if w.althandle != 0 {
|
||||
handle = w.althandle
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
w.curattr = csbi.attributes
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -853,6 +863,8 @@ loop:
|
||||
syscall.CloseHandle(w.althandle)
|
||||
w.althandle = 0
|
||||
handle = w.handle
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
w.curattr = csbi.attributes
|
||||
}
|
||||
}
|
||||
case 's':
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
//go:build (appengine || js || nacl || tinygo || wasm) && !windows
|
||||
// +build appengine js nacl tinygo wasm
|
||||
//go:build (appengine || js || nacl || tinygo || wasm || wasip1 || wasip2) && !windows
|
||||
// +build appengine js nacl tinygo wasm wasip1 wasip2
|
||||
// +build !windows
|
||||
|
||||
package isatty
|
||||
|
||||
+13
-2
@@ -31,6 +31,10 @@ func init() {
|
||||
if procGetFileInformationByHandleEx.Find() != nil {
|
||||
procGetFileInformationByHandleEx = nil
|
||||
}
|
||||
// Check if NtQueryObject is available.
|
||||
if procNtQueryObject.Find() != nil {
|
||||
procNtQueryObject = nil
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
@@ -43,6 +47,7 @@ func IsTerminal(fd uintptr) bool {
|
||||
// Check pipe name is used for cygwin/msys2 pty.
|
||||
// Cygwin/MSYS2 PTY has a name like:
|
||||
// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
|
||||
// On Windows 7 a trailing suffix (e.g. "-nat") may be appended.
|
||||
func isCygwinPipeName(name string) bool {
|
||||
token := strings.Split(name, "-")
|
||||
if len(token) < 5 {
|
||||
@@ -72,13 +77,19 @@ func isCygwinPipeName(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, t := range token[5:] {
|
||||
if t == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
|
||||
// getFileNameByHandle use the undocumented ntdll NtQueryObject to get file full name from file handler
|
||||
// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion
|
||||
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
|
||||
// Windows vista to 10
|
||||
// Windows Vista to 10
|
||||
// see https://stackoverflow.com/a/18792477 for details
|
||||
func getFileNameByHandle(fd uintptr) (string, error) {
|
||||
if procNtQueryObject == nil {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The following versions of go-runewidth are currently supported with
|
||||
security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| -------- | ------------------ |
|
||||
| 0.0.23 | :white_check_mark: |
|
||||
| < 0.0.23 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you discover a security vulnerability in go-runewidth, please report it
|
||||
privately via GitHub's "Report a vulnerability" feature on the Security tab
|
||||
of the repository (https://github.com/mattn/go-runewidth/security), or by
|
||||
emailing the maintainer at mattn.jp@gmail.com.
|
||||
|
||||
Please include a description of the issue, reproduction steps, and the
|
||||
affected version. You can expect an initial response within one week. If
|
||||
the vulnerability is accepted, a fix will be prepared and a new release
|
||||
will be published; you will be credited in the release notes unless you
|
||||
request otherwise. If the report is declined, you will receive an
|
||||
explanation of the reasoning.
|
||||
+118
-35
@@ -2,6 +2,7 @@ package runewidth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -25,13 +26,19 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
zerowidth table // combining + nonprint merged for faster zero-width lookup
|
||||
widewidth table // ambiguous + doublewidth merged for EA path
|
||||
zerowidth table // combining + nonprint merged for faster zero-width lookup
|
||||
widewidth table // ambiguous + doublewidth merged for EA path
|
||||
eastAsianWidth widthTable
|
||||
eastAsianWidth0 [0x300]byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
zerowidth = mergeIntervals(combining, nonprint)
|
||||
widewidth = mergeIntervals(ambiguous, doublewidth)
|
||||
eastAsianWidth = makeWidthTable(zerowidth, widewidth)
|
||||
for r := range eastAsianWidth0 {
|
||||
eastAsianWidth0[r] = byte(runeWidthEastAsian(rune(r)))
|
||||
}
|
||||
handleEnv()
|
||||
}
|
||||
|
||||
@@ -90,6 +97,14 @@ type interval struct {
|
||||
|
||||
type table []interval
|
||||
|
||||
type widthInterval struct {
|
||||
first rune
|
||||
last rune
|
||||
width byte
|
||||
}
|
||||
|
||||
type widthTable []widthInterval
|
||||
|
||||
func inTable(r rune, t table) bool {
|
||||
if r < t[0].first {
|
||||
return false
|
||||
@@ -116,6 +131,71 @@ func inTable(r rune, t table) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func makeWidthTable(zero, two table) widthTable {
|
||||
wt := make(widthTable, 0, len(zero)+len(two))
|
||||
zi := 0
|
||||
for _, iv := range two {
|
||||
start := iv.first
|
||||
for zi < len(zero) && zero[zi].last < start {
|
||||
zi++
|
||||
}
|
||||
for i := zi; i < len(zero) && zero[i].first <= iv.last; i++ {
|
||||
if start < zero[i].first {
|
||||
wt = append(wt, widthInterval{start, zero[i].first - 1, 2})
|
||||
}
|
||||
if start <= zero[i].last {
|
||||
start = zero[i].last + 1
|
||||
}
|
||||
if start > iv.last {
|
||||
break
|
||||
}
|
||||
}
|
||||
if start <= iv.last {
|
||||
wt = append(wt, widthInterval{start, iv.last, 2})
|
||||
}
|
||||
}
|
||||
for _, iv := range zero {
|
||||
wt = append(wt, widthInterval{iv.first, iv.last, 0})
|
||||
}
|
||||
sort.Slice(wt, func(i, j int) bool {
|
||||
return wt[i].first < wt[j].first
|
||||
})
|
||||
return wt
|
||||
}
|
||||
|
||||
func inWidthTable(r rune, t widthTable) (int, bool) {
|
||||
if r < t[0].first {
|
||||
return 0, false
|
||||
}
|
||||
if r > t[len(t)-1].last {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
bot := 0
|
||||
top := len(t) - 1
|
||||
for top >= bot {
|
||||
mid := (bot + top) >> 1
|
||||
|
||||
switch {
|
||||
case t[mid].last < r:
|
||||
bot = mid + 1
|
||||
case t[mid].first > r:
|
||||
top = mid - 1
|
||||
default:
|
||||
return int(t[mid].width), true
|
||||
}
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func runeWidthEastAsian(r rune) int {
|
||||
if w, ok := inWidthTable(r, eastAsianWidth); ok {
|
||||
return w
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
var private = table{
|
||||
{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
|
||||
}
|
||||
@@ -153,13 +233,16 @@ func (c *Condition) RuneWidth(r rune) int {
|
||||
}
|
||||
// optimized version, verified by TestRuneWidthChecksums()
|
||||
if !c.EastAsianWidth {
|
||||
switch {
|
||||
case r < 0x20:
|
||||
if r < 0x20 {
|
||||
return 0
|
||||
case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
|
||||
}
|
||||
if (r >= 0x7F && r <= 0x9F) || r == 0xAD { // nonprint
|
||||
return 0
|
||||
case r < 0x300:
|
||||
}
|
||||
if r < 0x300 {
|
||||
return 1
|
||||
}
|
||||
switch {
|
||||
case inTable(r, zerowidth):
|
||||
return 0
|
||||
case inTable(r, doublewidth):
|
||||
@@ -167,20 +250,18 @@ func (c *Condition) RuneWidth(r rune) int {
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case inTable(r, zerowidth):
|
||||
return 0
|
||||
case inTable(r, narrow):
|
||||
return 1
|
||||
case inTable(r, widewidth):
|
||||
return 2
|
||||
case !c.StrictEmojiNeutral && inTable(r, emoji):
|
||||
return 2
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if r < 0x300 {
|
||||
return int(eastAsianWidth0[r])
|
||||
}
|
||||
if w, ok := inWidthTable(r, eastAsianWidth); ok {
|
||||
return w
|
||||
}
|
||||
if !c.StrictEmojiNeutral && inTable(r, emoji) {
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation.
|
||||
@@ -206,6 +287,13 @@ func (c *Condition) CreateLUT() {
|
||||
|
||||
// StringWidth return width as you can see
|
||||
func (c *Condition) StringWidth(s string) (width int) {
|
||||
if len(s) == 1 {
|
||||
b := s[0]
|
||||
if b < 0x20 || b == 0x7F {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
if len(s) > 0 && len(s) <= utf8.UTFMax {
|
||||
r, size := utf8.DecodeRuneInString(s)
|
||||
if size == len(s) {
|
||||
@@ -213,15 +301,19 @@ func (c *Condition) StringWidth(s string) (width int) {
|
||||
}
|
||||
}
|
||||
// ASCII fast path: no grapheme clustering needed for pure ASCII
|
||||
if isAllASCII(s) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
b := s[i]
|
||||
if b >= 0x20 && b != 0x7F {
|
||||
width++
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
b := s[i]
|
||||
if b >= 0x80 {
|
||||
goto graphemes
|
||||
}
|
||||
if b >= 0x20 && b != 0x7F {
|
||||
width++
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
|
||||
graphemes:
|
||||
width = 0
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
@@ -236,15 +328,6 @@ func (c *Condition) StringWidth(s string) (width int) {
|
||||
return
|
||||
}
|
||||
|
||||
func isAllASCII(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= 0x80 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Truncate return string truncated with w cells
|
||||
func (c *Condition) Truncate(s string, w int, tail string) string {
|
||||
if c.StringWidth(s) <= w {
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
|
||||
language: en-US
|
||||
reviews:
|
||||
# Skip the vendored SQLite amalgamation. These files are copied verbatim from
|
||||
# upstream SQLite (see the License section in README.md) and are not code that
|
||||
# this project authors or reviews.
|
||||
path_filters:
|
||||
- "!sqlite3-binding.c"
|
||||
- "!sqlite3-binding.h"
|
||||
- "!sqlite3ext.h"
|
||||
auto_review:
|
||||
enabled: true
|
||||
drafts: false
|
||||
chat:
|
||||
auto_reply: true
|
||||
+13
-2
@@ -7,9 +7,18 @@ go-sqlite3
|
||||
[](https://codecov.io/gh/mattn/go-sqlite3)
|
||||
[](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
|
||||
|
||||
Latest stable version is v1.14 or later, not v2.
|
||||
## Sponsors
|
||||
|
||||
~~**NOTE:** The increase to v2 was an accident. There were no major changes or features.~~
|
||||
This project is proudly sponsored by:
|
||||
|
||||
<a href="https://coderabbit.link/mattn">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://victorious-bubble-f69a016683.media.strapiapp.com/White_Typemark_79b9189d19.svg">
|
||||
<img src="https://victorious-bubble-f69a016683.media.strapiapp.com/Orange_Typemark_43bf516c9d.svg" alt="CodeRabbit" width="320">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
Latest stable version is v1.14 or later, not v2.
|
||||
|
||||
# Description
|
||||
|
||||
@@ -125,6 +134,7 @@ Boolean values can be one of:
|
||||
| Transaction Lock | `_txlock` | <ul><li>immediate</li><li>deferred</li><li>exclusive</li></ul> | Specify locking behavior for transactions. |
|
||||
| Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. |
|
||||
| Cache Size | `_cache_size` | `int` | Maximum cache size; default is 2000K (2M). See [PRAGMA cache_size](https://sqlite.org/pragma.html#pragma_cache_size) |
|
||||
| Statement Cache Size | `_stmt_cache_size` | `int` | Maximum number of prepared statements cached per connection; default is 0 (disabled). Note that `sql.DB` is a connection pool, so each connection maintains its own independent cache. |
|
||||
|
||||
|
||||
## DSN Examples
|
||||
@@ -181,6 +191,7 @@ go build -tags "icu json1 fts5 secure_delete"
|
||||
| Tracing / Debug | sqlite_trace | Activate trace functions |
|
||||
| User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. |
|
||||
| Virtual Tables | sqlite_vtable | SQLite Virtual Tables see [SQLite Official VTABLE Documentation](https://www.sqlite.org/vtab.html) for more information, and a [full example here](https://github.com/mattn/go-sqlite3/tree/master/_example/vtable) |
|
||||
| The DBSTAT Virtual Table | sqlite_dbstat | The DBSTAT virtual table is a read-only virtual table that returns information about the amount of disk space used to store the content of an SQLite database. See [SQLite Official Documentation](https://www.sqlite.org/dbstat.html) for more information. |
|
||||
|
||||
# Compilation
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest release on the `v1.14.x` line receives security fixes.
|
||||
|
||||
| Version | Supported |
|
||||
| -------- | ------------------ |
|
||||
| 1.14.x | :white_check_mark: |
|
||||
| < 1.14 | :x: |
|
||||
|
||||
## Scope
|
||||
|
||||
`go-sqlite3` is a CGo binding that bundles the SQLite amalgamation
|
||||
(`sqlite3-binding.c` / `sqlite3-binding.h`). Please report issues to the
|
||||
appropriate project:
|
||||
|
||||
- Bugs in the Go binding layer, CGo glue, build tags, or this repository's
|
||||
own code: report here.
|
||||
- Vulnerabilities in SQLite itself: please report them upstream to the
|
||||
SQLite developers at <https://www.sqlite.org/>. Once a fix is released
|
||||
upstream, this repository will update the bundled amalgamation.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please **do not** open a public GitHub issue for security problems.
|
||||
|
||||
Use GitHub's private vulnerability reporting:
|
||||
<https://github.com/mattn/go-sqlite3/security/advisories/new>
|
||||
|
||||
This project is maintained on a best-effort basis by volunteers, so please
|
||||
allow reasonable time for investigation and a fix before any public
|
||||
d
|
||||
+103
-39
@@ -18,7 +18,7 @@ package sqlite3
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
|
||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s, int n);
|
||||
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
|
||||
*/
|
||||
import "C"
|
||||
@@ -29,12 +29,13 @@ import (
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//export callbackTrampoline
|
||||
func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
|
||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
||||
func callbackTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
|
||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
|
||||
fi := lookupHandle(C.sqlite3_user_data(ctx)).(*functionInfo)
|
||||
fi.Call(ctx, args)
|
||||
}
|
||||
@@ -59,9 +60,9 @@ func compareTrampoline(handlePtr unsafe.Pointer, la C.int, a *C.char, lb C.int,
|
||||
}
|
||||
|
||||
//export commitHookTrampoline
|
||||
func commitHookTrampoline(handle unsafe.Pointer) int {
|
||||
func commitHookTrampoline(handle unsafe.Pointer) C.int {
|
||||
callback := lookupHandle(handle).(func() int)
|
||||
return callback()
|
||||
return C.int(callback())
|
||||
}
|
||||
|
||||
//export rollbackHookTrampoline
|
||||
@@ -71,23 +72,23 @@ func rollbackHookTrampoline(handle unsafe.Pointer) {
|
||||
}
|
||||
|
||||
//export updateHookTrampoline
|
||||
func updateHookTrampoline(handle unsafe.Pointer, op int, db *C.char, table *C.char, rowid int64) {
|
||||
func updateHookTrampoline(handle unsafe.Pointer, op C.int, db *C.char, table *C.char, rowid int64) {
|
||||
callback := lookupHandle(handle).(func(int, string, string, int64))
|
||||
callback(op, C.GoString(db), C.GoString(table), rowid)
|
||||
callback(int(op), C.GoString(db), C.GoString(table), rowid)
|
||||
}
|
||||
|
||||
//export authorizerTrampoline
|
||||
func authorizerTrampoline(handle unsafe.Pointer, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
|
||||
func authorizerTrampoline(handle unsafe.Pointer, op C.int, arg1 *C.char, arg2 *C.char, arg3 *C.char) C.int {
|
||||
callback := lookupHandle(handle).(func(int, string, string, string) int)
|
||||
return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
|
||||
return C.int(callback(int(op), C.GoString(arg1), C.GoString(arg2), C.GoString(arg3)))
|
||||
}
|
||||
|
||||
//export preUpdateHookTrampoline
|
||||
func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
|
||||
func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op C.int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
|
||||
hval := lookupHandleVal(handle)
|
||||
data := SQLitePreUpdateData{
|
||||
Conn: hval.db,
|
||||
Op: op,
|
||||
Op: int(op),
|
||||
DatabaseName: C.GoString(db),
|
||||
TableName: C.GoString(table),
|
||||
OldRowID: oldrowid,
|
||||
@@ -104,39 +105,84 @@ type handleVal struct {
|
||||
}
|
||||
|
||||
var handleLock sync.Mutex
|
||||
var handleVals = make(map[unsafe.Pointer]handleVal)
|
||||
var handleVals atomic.Value // stores map[unsafe.Pointer]handleVal
|
||||
|
||||
func newHandle(db *SQLiteConn, v any) unsafe.Pointer {
|
||||
handleLock.Lock()
|
||||
defer handleLock.Unlock()
|
||||
val := handleVal{db: db, val: v}
|
||||
var p unsafe.Pointer = C.malloc(C.size_t(1))
|
||||
if p == nil {
|
||||
panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
|
||||
}
|
||||
handleVals[p] = val
|
||||
|
||||
handleLock.Lock()
|
||||
defer handleLock.Unlock()
|
||||
|
||||
next := cloneHandleVals(len(loadHandleVals()) + 1)
|
||||
next[p] = val
|
||||
handleVals.Store(next)
|
||||
return p
|
||||
}
|
||||
|
||||
func lookupHandleVal(handle unsafe.Pointer) handleVal {
|
||||
handleLock.Lock()
|
||||
defer handleLock.Unlock()
|
||||
return handleVals[handle]
|
||||
return loadHandleVals()[handle]
|
||||
}
|
||||
|
||||
func lookupHandle(handle unsafe.Pointer) any {
|
||||
return lookupHandleVal(handle).val
|
||||
}
|
||||
|
||||
// deleteHandle releases a single handle created by newHandle. It is a no-op
|
||||
// if the handle is unknown (e.g. already released).
|
||||
func deleteHandle(handle unsafe.Pointer) {
|
||||
handleLock.Lock()
|
||||
defer handleLock.Unlock()
|
||||
|
||||
current := loadHandleVals()
|
||||
if _, ok := current[handle]; !ok {
|
||||
return
|
||||
}
|
||||
next := make(map[unsafe.Pointer]handleVal, len(current)-1)
|
||||
for h, v := range current {
|
||||
if h == handle {
|
||||
continue
|
||||
}
|
||||
next[h] = v
|
||||
}
|
||||
handleVals.Store(next)
|
||||
C.free(handle)
|
||||
}
|
||||
|
||||
func deleteHandles(db *SQLiteConn) {
|
||||
handleLock.Lock()
|
||||
defer handleLock.Unlock()
|
||||
for handle, val := range handleVals {
|
||||
if val.db == db {
|
||||
delete(handleVals, handle)
|
||||
C.free(handle)
|
||||
}
|
||||
|
||||
current := loadHandleVals()
|
||||
if len(current) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
next := make(map[unsafe.Pointer]handleVal, len(current))
|
||||
for handle, val := range current {
|
||||
if val.db == db {
|
||||
C.free(handle)
|
||||
continue
|
||||
}
|
||||
next[handle] = val
|
||||
}
|
||||
handleVals.Store(next)
|
||||
}
|
||||
|
||||
func loadHandleVals() map[unsafe.Pointer]handleVal {
|
||||
m, _ := handleVals.Load().(map[unsafe.Pointer]handleVal)
|
||||
return m
|
||||
}
|
||||
|
||||
func cloneHandleVals(size int) map[unsafe.Pointer]handleVal {
|
||||
next := make(map[unsafe.Pointer]handleVal, size)
|
||||
for handle, val := range loadHandleVals() {
|
||||
next[handle] = val
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
// This is only here so that tests can refer to it.
|
||||
@@ -204,12 +250,13 @@ func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
|
||||
func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
|
||||
switch C.sqlite3_value_type(v) {
|
||||
case C.SQLITE_BLOB:
|
||||
l := C.sqlite3_value_bytes(v)
|
||||
p := (*C.char)(C.sqlite3_value_blob(v))
|
||||
l := C.sqlite3_value_bytes(v)
|
||||
return reflect.ValueOf(C.GoStringN(p, l)), nil
|
||||
case C.SQLITE_TEXT:
|
||||
c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
|
||||
return reflect.ValueOf(C.GoString(c)), nil
|
||||
l := C.sqlite3_value_bytes(v)
|
||||
return reflect.ValueOf(C.GoStringN(c, l)), nil
|
||||
default:
|
||||
return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
|
||||
}
|
||||
@@ -234,6 +281,16 @@ func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// callbackArgConvert returns conv as-is when the parameter type is the
|
||||
// canonical type conv produces, and wraps it with a cast for named types
|
||||
// (e.g. time.Duration), which reflect.Call would otherwise panic on.
|
||||
func callbackArgConvert(conv callbackArgConverter, typ, canonical reflect.Type) callbackArgConverter {
|
||||
if typ == canonical {
|
||||
return conv
|
||||
}
|
||||
return callbackArgCast{conv, typ}.Run
|
||||
}
|
||||
|
||||
func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
|
||||
switch typ.Kind() {
|
||||
case reflect.Interface:
|
||||
@@ -245,18 +302,18 @@ func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
|
||||
if typ.Elem().Kind() != reflect.Uint8 {
|
||||
return nil, errors.New("the only supported slice type is []byte")
|
||||
}
|
||||
return callbackArgBytes, nil
|
||||
return callbackArgConvert(callbackArgBytes, typ, reflect.TypeOf([]byte(nil))), nil
|
||||
case reflect.String:
|
||||
return callbackArgString, nil
|
||||
return callbackArgConvert(callbackArgString, typ, reflect.TypeOf("")), nil
|
||||
case reflect.Bool:
|
||||
return callbackArgBool, nil
|
||||
return callbackArgConvert(callbackArgBool, typ, reflect.TypeOf(false)), nil
|
||||
case reflect.Int64:
|
||||
return callbackArgInt64, nil
|
||||
return callbackArgConvert(callbackArgInt64, typ, reflect.TypeOf(int64(0))), nil
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
||||
c := callbackArgCast{callbackArgInt64, typ}
|
||||
return c.Run, nil
|
||||
case reflect.Float64:
|
||||
return callbackArgFloat64, nil
|
||||
return callbackArgConvert(callbackArgFloat64, typ, reflect.TypeOf(float64(0))), nil
|
||||
case reflect.Float32:
|
||||
c := callbackArgCast{callbackArgFloat64, typ}
|
||||
return c.Run, nil
|
||||
@@ -300,8 +357,7 @@ func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
||||
v = v.Convert(reflect.TypeOf(int64(0)))
|
||||
case reflect.Bool:
|
||||
b := v.Interface().(bool)
|
||||
if b {
|
||||
if v.Bool() {
|
||||
v = reflect.ValueOf(int64(1))
|
||||
} else {
|
||||
v = reflect.ValueOf(int64(0))
|
||||
@@ -310,7 +366,7 @@ func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||
return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
|
||||
}
|
||||
|
||||
C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
|
||||
C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Int()))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -323,7 +379,7 @@ func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||
return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
|
||||
}
|
||||
|
||||
C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
|
||||
C.sqlite3_result_double(ctx, C.double(v.Float()))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -331,11 +387,14 @@ func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||
if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
|
||||
return fmt.Errorf("cannot convert %s to BLOB", v.Type())
|
||||
}
|
||||
i := v.Interface()
|
||||
if i == nil || len(i.([]byte)) == 0 {
|
||||
bs := v.Bytes()
|
||||
if len(bs) == 0 {
|
||||
C.sqlite3_result_null(ctx)
|
||||
} else {
|
||||
bs := i.([]byte)
|
||||
if i64 && len(bs) > math.MaxInt32 {
|
||||
C.sqlite3_result_error_toobig(ctx)
|
||||
return nil
|
||||
}
|
||||
C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
|
||||
}
|
||||
return nil
|
||||
@@ -345,8 +404,13 @@ func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||
if v.Type().Kind() != reflect.String {
|
||||
return fmt.Errorf("cannot convert %s to TEXT", v.Type())
|
||||
}
|
||||
cstr := C.CString(v.Interface().(string))
|
||||
C._sqlite3_result_text(ctx, cstr)
|
||||
s := v.String()
|
||||
if i64 && len(s) > math.MaxInt32 {
|
||||
C.sqlite3_result_error_toobig(ctx)
|
||||
return nil
|
||||
}
|
||||
cstr := C.CString(s)
|
||||
C._sqlite3_result_text(ctx, cstr, C.int(len(s)))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+8257
-4585
File diff suppressed because it is too large.
Load diff
+485
-104
@@ -147,12 +147,12 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.51.3"
|
||||
#define SQLITE_VERSION_NUMBER 3051003
|
||||
#define SQLITE_SOURCE_ID "2026-03-13 10:38:09 737ae4a34738ffa0c3ff7f9bb18df914dd1cad163f28fd6b6e114a344fe6d618"
|
||||
#define SQLITE_SCM_BRANCH "branch-3.51"
|
||||
#define SQLITE_SCM_TAGS "release version-3.51.3"
|
||||
#define SQLITE_SCM_DATETIME "2026-03-13T10:38:09.694Z"
|
||||
#define SQLITE_VERSION "3.53.4"
|
||||
#define SQLITE_VERSION_NUMBER 3053004
|
||||
#define SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc"
|
||||
#define SQLITE_SCM_BRANCH "branch-3.53"
|
||||
#define SQLITE_SCM_TAGS "release version-3.53.4"
|
||||
#define SQLITE_SCM_DATETIME "2026-07-24T19:02:57.525Z"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -579,7 +579,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
||||
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
||||
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@@ -1291,6 +1291,12 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
|
||||
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
|
||||
|
||||
/* reserved file-control numbers:
|
||||
** 101
|
||||
** 102
|
||||
** 103
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@@ -1491,7 +1497,7 @@ typedef const char *sqlite3_filename;
|
||||
** greater and the function pointer is not NULL) and will fall back
|
||||
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
|
||||
**
|
||||
** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
|
||||
** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces
|
||||
** are not used by the SQLite core. These optional interfaces are provided
|
||||
** by some VFSes to facilitate testing of the VFS code. By overriding
|
||||
** system calls with functions under its control, a test program can
|
||||
@@ -1712,7 +1718,8 @@ SQLITE_API int sqlite3_os_end(void);
|
||||
** are called "anytime configuration options".
|
||||
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
|
||||
** [sqlite3_shutdown()] with a first argument that is not an anytime
|
||||
** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE.
|
||||
** configuration option, then the sqlite3_config() call will
|
||||
** return SQLITE_MISUSE.
|
||||
** Note, however, that ^sqlite3_config() can be called as part of the
|
||||
** implementation of an application-defined [sqlite3_os_init()].
|
||||
**
|
||||
@@ -2278,9 +2285,10 @@ struct sqlite3_mem_methods {
|
||||
** is less than 8. The "sz" argument should be a multiple of 8 less than
|
||||
** 65536. If "sz" does not meet this constraint, it is reduced in size until
|
||||
** it does.
|
||||
** <li><p>The third argument ("cnt") is the number of slots. Lookaside is disabled
|
||||
** if "cnt"is less than 1. The "cnt" value will be reduced, if necessary, so
|
||||
** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt"
|
||||
** <li><p>The third argument ("cnt") is the number of slots.
|
||||
** Lookaside is disabled if "cnt"is less than 1.
|
||||
* The "cnt" value will be reduced, if necessary, so
|
||||
** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt"
|
||||
** parameter is usually chosen so that the product of "sz" and "cnt" is less
|
||||
** than 1,000,000.
|
||||
** </ol>
|
||||
@@ -2568,12 +2576,15 @@ struct sqlite3_mem_methods {
|
||||
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
|
||||
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
|
||||
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
|
||||
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
|
||||
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
|
||||
** statistics. For statistics to be collected, the flag must be set on
|
||||
** the database handle both when the SQL statement is prepared and when it
|
||||
** is stepped. The flag is set (collection of statistics is enabled)
|
||||
** by default. <p>This option takes two arguments: an integer and a pointer to
|
||||
** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears
|
||||
** a flag that enables collection of run-time performance statistics
|
||||
** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle]
|
||||
** columns of the [bytecode virtual table].
|
||||
** For statistics to be collected, the flag must be set on
|
||||
** the database handle both when the SQL statement is
|
||||
** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped].
|
||||
** The flag is set (collection of statistics is enabled) by default.
|
||||
** <p>This option takes two arguments: an integer and a pointer to
|
||||
** an integer. The first argument is 1, 0, or -1 to enable, disable, or
|
||||
** leave unchanged the statement scanstatus option. If the second argument
|
||||
** is not NULL, then the value of the statement scanstatus setting after
|
||||
@@ -2646,16 +2657,34 @@ struct sqlite3_mem_methods {
|
||||
** comments are allowed in SQL text after processing the first argument.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_FP_DIGITS]]
|
||||
** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt>
|
||||
** <dd>The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines
|
||||
** the number of significant digits that SQLite will attempt to preserve when
|
||||
** converting floating point numbers (IEEE 754 "doubles") into text. The
|
||||
** default value 17, as of SQLite version 3.52.0. The value was 15 in all
|
||||
** prior versions.<p>
|
||||
** This option takes two arguments which are an integer and a pointer
|
||||
** to an integer. The first argument is a small integer, between 3 and 23, or
|
||||
** zero. The FP_DIGITS setting is changed to that small integer, or left
|
||||
** unaltered if the first argument is zero or out of range. The second argument
|
||||
** is a pointer to an integer. If the pointer is not NULL, then the value of
|
||||
** the FP_DIGITS setting, after possibly being modified by the first
|
||||
** arguments, is written into the integer to which the second argument points.
|
||||
** </dd>
|
||||
**
|
||||
** </dl>
|
||||
**
|
||||
** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
|
||||
**
|
||||
** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the
|
||||
** overall call to [sqlite3_db_config()] has a total of four parameters.
|
||||
** The first argument (the third parameter to sqlite3_db_config()) is an integer.
|
||||
** The second argument is a pointer to an integer. If the first argument is 1,
|
||||
** then the option becomes enabled. If the first integer argument is 0, then the
|
||||
** option is disabled. If the first argument is -1, then the option setting
|
||||
** The first argument (the third parameter to sqlite3_db_config()) is
|
||||
** an integer.
|
||||
** The second argument is a pointer to an integer. If the first argument is 1,
|
||||
** then the option becomes enabled. If the first integer argument is 0,
|
||||
** then the option is disabled.
|
||||
** If the first argument is -1, then the option setting
|
||||
** is unchanged. The second argument, the pointer to an integer, may be NULL.
|
||||
** If the second argument is not NULL, then a value of 0 or 1 is written into
|
||||
** the integer to which the second argument points, depending on whether the
|
||||
@@ -2663,9 +2692,10 @@ struct sqlite3_mem_methods {
|
||||
** the first argument.
|
||||
**
|
||||
** <p>While most SQLITE_DBCONFIG options use the argument format
|
||||
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
|
||||
** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
|
||||
** documentation of those exceptional options for details.
|
||||
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME],
|
||||
** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options
|
||||
** are different. See the documentation of those exceptional options for
|
||||
** details.
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
||||
@@ -2690,7 +2720,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
|
||||
#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@@ -4172,6 +4203,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename);
|
||||
** <li> sqlite3_errmsg()
|
||||
** <li> sqlite3_errmsg16()
|
||||
** <li> sqlite3_error_offset()
|
||||
** <li> sqlite3_db_handle()
|
||||
** </ul>
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
@@ -4218,7 +4250,7 @@ SQLITE_API const char *sqlite3_errstr(int);
|
||||
SQLITE_API int sqlite3_error_offset(sqlite3 *db);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Set Error Codes And Message
|
||||
** CAPI3REF: Set Error Code And Message
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** Set the error code of the database handle passed as the first argument
|
||||
@@ -4335,7 +4367,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** or in an ORDER BY or GROUP BY clause.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
||||
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
|
||||
** <dd>The maximum depth of the parse tree on any expression and
|
||||
** the maximum nesting depth for subqueries and VIEWs</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
|
||||
** <dd>The maximum depth of the LALR(1) parser stack used to analyze
|
||||
** input SQL statements.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
|
||||
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
|
||||
@@ -4362,7 +4399,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
||||
** <dd>The maximum depth of recursion for triggers.</dd>)^
|
||||
** <dd>The maximum depth of recursion for triggers, and the maximum
|
||||
** nesting depth for separate triggers.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
|
||||
** <dd>The maximum number of auxiliary worker threads that a single
|
||||
@@ -4381,6 +4419,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
|
||||
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
||||
#define SQLITE_LIMIT_WORKER_THREADS 11
|
||||
#define SQLITE_LIMIT_PARSER_DEPTH 12
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepare Flags
|
||||
@@ -4425,12 +4464,29 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** fails, the sqlite3_prepare_v3() call returns the same error indications
|
||||
** with or without this flag; it just omits the call to [sqlite3_log()] that
|
||||
** logs the error.
|
||||
**
|
||||
** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
|
||||
** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce
|
||||
** security constraints that would otherwise only be enforced when parsing
|
||||
** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag
|
||||
** causes the SQL compiler to treat the SQL statement being prepared as if
|
||||
** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and
|
||||
** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called
|
||||
** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only
|
||||
** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice
|
||||
** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that
|
||||
** is derived from parts of the database schema. In particular, virtual
|
||||
** table implementations that run SQL statements that are derived from
|
||||
** arguments to their CREATE VIRTUAL TABLE statement should always use
|
||||
** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to
|
||||
** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_PREPARE_PERSISTENT 0x01
|
||||
#define SQLITE_PREPARE_NORMALIZE 0x02
|
||||
#define SQLITE_PREPARE_NO_VTAB 0x04
|
||||
#define SQLITE_PREPARE_DONT_LOG 0x10
|
||||
#define SQLITE_PREPARE_FROM_DDL 0x20
|
||||
|
||||
/*
|
||||
** CAPI3REF: Compiling An SQL Statement
|
||||
@@ -4444,8 +4500,9 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
**
|
||||
** The preferred routine to use is [sqlite3_prepare_v2()]. The
|
||||
** [sqlite3_prepare()] interface is legacy and should be avoided.
|
||||
** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
|
||||
** for special purposes.
|
||||
** [sqlite3_prepare_v3()] has an extra
|
||||
** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is sometimes
|
||||
** needed for special purpose or to pass along security restrictions.
|
||||
**
|
||||
** The use of the UTF-8 interfaces is preferred, as SQLite currently
|
||||
** does all parsing using UTF-8. The UTF-16 interfaces are provided
|
||||
@@ -4850,8 +4907,8 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** it should be a pointer to well-formed UTF16 text.
|
||||
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
|
||||
** it should be a pointer to a well-formed unicode string that is
|
||||
** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
|
||||
** otherwise.
|
||||
** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT,
|
||||
** or UTF16 otherwise.
|
||||
**
|
||||
** [[byte-order determination rules]] ^The byte-order of
|
||||
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
|
||||
@@ -4897,10 +4954,15 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** object and pointer to it must remain valid until then. ^SQLite will then
|
||||
** manage the lifetime of its private copy.
|
||||
**
|
||||
** ^The sixth argument to sqlite3_bind_text64() must be one of
|
||||
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
|
||||
** to specify the encoding of the text in the third parameter. If
|
||||
** the sixth argument to sqlite3_bind_text64() is not one of the
|
||||
** ^The sixth argument (the E argument)
|
||||
** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of
|
||||
** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
|
||||
** or [SQLITE_UTF16LE] to specify the encoding of the text in the
|
||||
** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the
|
||||
** string argument is both UTF-8 encoded and is zero-terminated. In other
|
||||
** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at
|
||||
** least N+1 bytes and that the Z[N] byte is zero. If
|
||||
** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the
|
||||
** allowed values shown above, or if the text encoding is different
|
||||
** from the encoding specified by the sixth parameter, then the behavior
|
||||
** is undefined.
|
||||
@@ -5767,6 +5829,52 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
**
|
||||
** These constants define integer codes that represent the various
|
||||
** text encodings supported by SQLite.
|
||||
**
|
||||
** <dl>
|
||||
** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd>
|
||||
**
|
||||
** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16
|
||||
** with each code point being expressed "little endian" - the least significant
|
||||
** byte first. This is the usual encoding, for example on Windows.</dd>
|
||||
**
|
||||
** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16
|
||||
** with each code point being expressed "big endian" - the most significant
|
||||
** byte first. This encoding is less common, but is still sometimes seen,
|
||||
** specially on older systems.
|
||||
**
|
||||
** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16
|
||||
** with each code point being expressed either little endian or as big
|
||||
** endian, according to the native endianness of the host computer.
|
||||
**
|
||||
** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used
|
||||
** to declare the preferred text for [application-defined SQL functions]
|
||||
** created using [sqlite3_create_function()] and similar. If the preferred
|
||||
** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
|
||||
** parameter) is SQLITE_ANY, that indicates that the function does not have
|
||||
** a preference regarding the text encoding of its parameters and can take
|
||||
** any text encoding that the SQLite core find convenient to supply. This
|
||||
** option is deprecated. Please do not use it in new applications.
|
||||
**
|
||||
** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding
|
||||
** value may be used as the 3rd parameter (the eTextRep parameter) to
|
||||
** [sqlite3_create_collation()] and similar. This encoding value means
|
||||
** that the application-defined collating sequence created expects its
|
||||
** input strings to be in UTF16 in native byte order, and that the start
|
||||
** of the strings must be aligned to a 2-byte boundary.
|
||||
**
|
||||
** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be
|
||||
** used to specify the text encoding to strings input to
|
||||
** [sqlite3_result_text64()] and [sqlite3_bind_text64()].
|
||||
** The SQLITE_UTF8_ZT encoding means that the input string (call it "z")
|
||||
** is UTF-8 encoded and that it is zero-terminated. If the length parameter
|
||||
** (call it "n") is non-negative, this encoding option means that the caller
|
||||
** guarantees that z array contains at least n+1 bytes and that the z[n]
|
||||
** byte has a value of zero.
|
||||
** This option gives the same output as SQLITE_UTF8, but can be more efficient
|
||||
** by avoiding the need to make a copy of the input string, in some cases.
|
||||
** However, if z is allocated to hold fewer than n+1 bytes or if the
|
||||
** z[n] byte is not zero, undefined behavior may result.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
|
||||
#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
|
||||
@@ -5774,6 +5882,7 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
#define SQLITE_UTF16 4 /* Use native byte order */
|
||||
#define SQLITE_ANY 5 /* Deprecated */
|
||||
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
|
||||
#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Function Flags
|
||||
@@ -6008,26 +6117,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** the SQL function that supplied the [sqlite3_value*] parameters.
|
||||
**
|
||||
** As long as the input parameter is correct, these routines can only
|
||||
** fail if an out-of-memory error occurs during a format conversion.
|
||||
** Only the following subset of interfaces are subject to out-of-memory
|
||||
** errors:
|
||||
**
|
||||
** <ul>
|
||||
** <li> sqlite3_value_blob()
|
||||
** <li> sqlite3_value_text()
|
||||
** <li> sqlite3_value_text16()
|
||||
** <li> sqlite3_value_text16le()
|
||||
** <li> sqlite3_value_text16be()
|
||||
** <li> sqlite3_value_bytes()
|
||||
** <li> sqlite3_value_bytes16()
|
||||
** </ul>
|
||||
**
|
||||
** fail if an out-of-memory error occurs while trying to do a
|
||||
** UTF8→UTF16 or UTF16→UTF8 conversion.
|
||||
** If an out-of-memory error occurs, then the return value from these
|
||||
** routines is the same as if the column had contained an SQL NULL value.
|
||||
** Valid SQL NULL returns can be distinguished from out-of-memory errors
|
||||
** by invoking the [sqlite3_errcode()] immediately after the suspect
|
||||
** If the input sqlite3_value was not obtained from [sqlite3_value_dup()],
|
||||
** then valid SQL NULL returns can also be distinguished from
|
||||
** out-of-memory errors after extracting the value
|
||||
** by invoking the [sqlite3_errcode()] immediately after the suspicious
|
||||
** return value is obtained and before any
|
||||
** other SQLite interface is called on the same [database connection].
|
||||
** If the input sqlite3_value was obtained from sqlite3_value_dup() then
|
||||
** it is disconnected from the database connection and so sqlite3_errcode()
|
||||
** will not work.
|
||||
** In that case, the only way to distinguish an out-of-memory
|
||||
** condition from a true SQL NULL is to invoke sqlite3_value_type() on the
|
||||
** input to see if it is NULL prior to trying to extract the value.
|
||||
*/
|
||||
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
|
||||
SQLITE_API double sqlite3_value_double(sqlite3_value*);
|
||||
@@ -6054,7 +6159,8 @@ SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
|
||||
** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X)
|
||||
** returns something other than SQLITE_TEXT, then the return value from
|
||||
** sqlite3_value_encoding(X) is meaningless. ^Calls to
|
||||
** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)],
|
||||
** [sqlite3_value_text(X)], [sqlite3_value_text16(X)],
|
||||
** [sqlite3_value_text16be(X)],
|
||||
** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or
|
||||
** [sqlite3_value_bytes16(X)] might change the encoding of the value X and
|
||||
** thus change the return from subsequent calls to sqlite3_value_encoding(X).
|
||||
@@ -6185,17 +6291,17 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
** query execution, under some circumstances the associated auxiliary data
|
||||
** might be preserved. An example of where this might be useful is in a
|
||||
** regular-expression matching function. The compiled version of the regular
|
||||
** expression can be stored as auxiliary data associated with the pattern string.
|
||||
** Then as long as the pattern string remains the same,
|
||||
** expression can be stored as auxiliary data associated with the pattern
|
||||
** string. Then as long as the pattern string remains the same,
|
||||
** the compiled regular expression can be reused on multiple
|
||||
** invocations of the same function.
|
||||
**
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data
|
||||
** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
|
||||
** value to the application-defined function. ^N is zero for the left-most
|
||||
** function argument. ^If there is no auxiliary data
|
||||
** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
|
||||
** returns a NULL pointer.
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary
|
||||
** data associated by the sqlite3_set_auxdata(C,N,P,X) function with the
|
||||
** Nth argument value to the application-defined function. ^N is zero
|
||||
** for the left-most function argument. ^If there is no auxiliary data
|
||||
** associated with the function argument, the sqlite3_get_auxdata(C,N)
|
||||
** interface returns a NULL pointer.
|
||||
**
|
||||
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
|
||||
** N-th argument of the application-defined function. ^Subsequent
|
||||
@@ -6279,10 +6385,14 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
|
||||
**
|
||||
** There is no limit (other than available memory) on the number of different
|
||||
** client data pointers (with different names) that can be attached to a
|
||||
** single database connection. However, the implementation is optimized
|
||||
** for the case of having only one or two different client data names.
|
||||
** Applications and wrapper libraries are discouraged from using more than
|
||||
** one client data name each.
|
||||
** single database connection. However, the current implementation stores
|
||||
** the content on a linked list. Insert and retrieval performance will
|
||||
** be proportional to the number of entries. The design use case, and
|
||||
** the use case for which the implementation is optimized, is
|
||||
** that an application will store only small number of client data names,
|
||||
** typically just one or two. This interface is not intended to be a
|
||||
** generalized key/value store for thousands or millions of keys. It
|
||||
** will work for that, but performance might be disappointing.
|
||||
**
|
||||
** There is no way to enumerate the client data pointers
|
||||
** associated with a database connection. The N parameter can be thought
|
||||
@@ -6390,10 +6500,14 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** set the return value of the application-defined function to be
|
||||
** a text string which is represented as UTF-8, UTF-16 native byte order,
|
||||
** UTF-16 little endian, or UTF-16 big endian, respectively.
|
||||
** ^The sqlite3_result_text64() interface sets the return value of an
|
||||
** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
|
||||
** application-defined function to be a text string in an encoding
|
||||
** specified by the fifth (and last) parameter, which must be one
|
||||
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
|
||||
** specified the E parameter, which must be one
|
||||
** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
|
||||
** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
|
||||
** the result text is both UTF-8 and zero-terminated. In other words,
|
||||
** SQLITE_UTF8_ZT means that the Z array holds at least N+1 bytes and that
|
||||
** the Z[N] is zero.
|
||||
** ^SQLite takes the text result from the application from
|
||||
** the 2nd parameter of the sqlite3_result_text* interfaces.
|
||||
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
|
||||
@@ -6480,7 +6594,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
|
||||
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
|
||||
SQLITE_API void sqlite3_result_null(sqlite3_context*);
|
||||
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
|
||||
SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
|
||||
void(*)(void*), unsigned char encoding);
|
||||
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
@@ -7419,7 +7533,7 @@ SQLITE_API int sqlite3_table_column_metadata(
|
||||
** ^The sqlite3_load_extension() interface attempts to load an
|
||||
** [SQLite extension] library contained in the file zFile. If
|
||||
** the file cannot be loaded directly, attempts are made to load
|
||||
** with various operating-system specific extensions added.
|
||||
** with various operating-system specific filename extensions added.
|
||||
** So for example, if "samplelib" cannot be loaded, then names like
|
||||
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
|
||||
** be tried also.
|
||||
@@ -7427,10 +7541,10 @@ SQLITE_API int sqlite3_table_column_metadata(
|
||||
** ^The entry point is zProc.
|
||||
** ^(zProc may be 0, in which case SQLite will try to come up with an
|
||||
** entry point name on its own. It first tries "sqlite3_extension_init".
|
||||
** If that does not work, it constructs a name "sqlite3_X_init" where
|
||||
** X consists of the lower-case equivalent of all ASCII alphabetic
|
||||
** characters in the filename from the last "/" to the first following
|
||||
** "." and omitting any initial "lib".)^
|
||||
** If that does not work, it tries names of the form "sqlite3_X_init"
|
||||
** where X consists of the lower-case equivalent of all ASCII alphabetic
|
||||
** characters or all ASCII alphanumeric characters in the filename from
|
||||
** the last "/" to the first following "." and omitting any initial "lib".)^
|
||||
** ^The sqlite3_load_extension() interface returns
|
||||
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
|
||||
** ^If an error occurs and pzErrMsg is not 0, then the
|
||||
@@ -7504,7 +7618,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
||||
** <blockquote><pre>
|
||||
** int xEntryPoint(
|
||||
** sqlite3 *db,
|
||||
** const char **pzErrMsg,
|
||||
** char **pzErrMsg,
|
||||
** const struct sqlite3_api_routines *pThunk
|
||||
** );
|
||||
** </pre></blockquote>)^
|
||||
@@ -8254,13 +8368,6 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
|
||||
** and Windows.
|
||||
**
|
||||
** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
|
||||
** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
|
||||
** implementation is included with the library. In this case the
|
||||
** application must supply a custom mutex implementation using the
|
||||
** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
|
||||
** before calling sqlite3_initialize() or any other public sqlite3_
|
||||
** function that calls sqlite3_initialize().
|
||||
**
|
||||
** ^The sqlite3_mutex_alloc() routine allocates a new
|
||||
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
|
||||
@@ -8615,6 +8722,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_ATOF 34
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
@@ -8723,17 +8831,22 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*);
|
||||
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
|
||||
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
|
||||
** errors were encountered during construction of the string. ^The
|
||||
** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
|
||||
** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the
|
||||
** string in [sqlite3_str] object X is zero bytes long.
|
||||
**
|
||||
** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object
|
||||
** X and the string content it contains. Calling sqlite3_str_free(X) is
|
||||
** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)).
|
||||
*/
|
||||
SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
|
||||
SQLITE_API void sqlite3_str_free(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add Content To A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
**
|
||||
** These interfaces add content to an sqlite3_str object previously obtained
|
||||
** from [sqlite3_str_new()].
|
||||
** These interfaces add or remove content to an sqlite3_str object
|
||||
** previously obtained from [sqlite3_str_new()].
|
||||
**
|
||||
** ^The [sqlite3_str_appendf(X,F,...)] and
|
||||
** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
|
||||
@@ -8756,6 +8869,10 @@ SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
|
||||
** ^The [sqlite3_str_reset(X)] method resets the string under construction
|
||||
** inside [sqlite3_str] object X back to zero bytes in length.
|
||||
**
|
||||
** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string
|
||||
** under construction to be N bytes or less. This routine is a no-op if
|
||||
** N is negative or if the string is already N bytes or smaller in size.
|
||||
**
|
||||
** These methods do not return a result code. ^If an error occurs, that fact
|
||||
** is recorded in the [sqlite3_str] object and can be recovered by a
|
||||
** subsequent call to [sqlite3_str_errcode(X)].
|
||||
@@ -8766,6 +8883,7 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
|
||||
SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
|
||||
SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
|
||||
SQLITE_API void sqlite3_str_reset(sqlite3_str*);
|
||||
SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Of A Dynamic String
|
||||
@@ -10296,7 +10414,8 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
** <tr>
|
||||
** <td valign="top">sqlite3_vtab_distinct() return value
|
||||
** <td valign="top">Rows are returned in aOrderBy order
|
||||
** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
|
||||
** <td valign="top">Rows with the same value in all aOrderBy columns are
|
||||
** adjacent
|
||||
** <td valign="top">Duplicates over all colUsed columns may be omitted
|
||||
** <tr><td>0<td>yes<td>yes<td>no
|
||||
** <tr><td>1<td>no<td>yes<td>no
|
||||
@@ -10305,8 +10424,8 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
** </table>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are the same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
** values are the same value for sorting purposes, two NULL values are
|
||||
** considered to be the same. In other words, the comparison operator is "IS"
|
||||
** (or "IS NOT DISTINCT FROM") and not "==".
|
||||
**
|
||||
** If a virtual table implementation is unable to meet the requirements
|
||||
@@ -10599,9 +10718,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
|
||||
** a variable pointed to by the "pOut" parameter.
|
||||
**
|
||||
** The "flags" parameter must be passed a mask of flags. At present only
|
||||
** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
|
||||
** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX
|
||||
** is specified, then status information is available for all elements
|
||||
** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
|
||||
** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If
|
||||
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
|
||||
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
|
||||
** the EXPLAIN QUERY PLAN output) are available. Invoking API
|
||||
@@ -10615,7 +10734,8 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
|
||||
** elements used to implement the statement - a non-zero value is returned and
|
||||
** the variable that pOut points to is unchanged.
|
||||
**
|
||||
** See also: [sqlite3_stmt_scanstatus_reset()]
|
||||
** See also: [sqlite3_stmt_scanstatus_reset()] and the
|
||||
** [nexec and ncycle] columns of the [bytecode virtual table].
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_scanstatus(
|
||||
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
|
||||
@@ -11157,19 +11277,42 @@ SQLITE_API int sqlite3_deserialize(
|
||||
/*
|
||||
** CAPI3REF: Bind array values to the CARRAY table-valued function
|
||||
**
|
||||
** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
|
||||
** one of the first argument of the [carray() table-valued function]. The
|
||||
** S parameter is a pointer to the [prepared statement] that uses the carray()
|
||||
** functions. I is the parameter index to be bound. P is a pointer to the
|
||||
** array to be bound, and N is the number of eements in the array. The
|
||||
** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
|
||||
** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
|
||||
** indicate the datatype of the array being bound. The X argument is not a
|
||||
** NULL pointer, then SQLite will invoke the function X on the P parameter
|
||||
** after it has finished using P, even if the call to
|
||||
** sqlite3_carray_bind() fails. The special-case finalizer
|
||||
** SQLITE_TRANSIENT has no effect here.
|
||||
** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
|
||||
** parameter that is the first argument of the [carray() table-valued function].
|
||||
** The S parameter is a pointer to the [prepared statement] that uses the
|
||||
** carray() functions. I is the parameter index to be bound. I must be the
|
||||
** index of the parameter that is the first argument to the carray()
|
||||
** table-valued function. P is a pointer to the array to be bound, and N
|
||||
** is the number of elements in the array. The F argument is one of
|
||||
** constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
|
||||
** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
|
||||
** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
|
||||
**
|
||||
** If the X argument is not a NULL pointer or one of the special
|
||||
** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
|
||||
** the function X with argument D when it is finished using the data in P.
|
||||
** The call to X(D) is a destructor for the array P. The destructor X(D)
|
||||
** is invoked even if the call to sqlite3_carray_bind_v2() fails. If the X
|
||||
** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
|
||||
** that the data static and the destructor is never invoked. If the X
|
||||
** parameter is the special-case value [SQLITE_TRANSIENT], then
|
||||
** sqlite3_carray_bind_v2() makes its own private copy of the data prior
|
||||
** to returning and never invokes the destructor X.
|
||||
**
|
||||
** The sqlite3_carray_bind() function works the same as sqlite3_carray_bind_v2()
|
||||
** with a D parameter set to P. In other words,
|
||||
** sqlite3_carray_bind(S,I,P,N,F,X) is same as
|
||||
** sqlite3_carray_bind_v2(S,I,P,N,F,X,P).
|
||||
*/
|
||||
SQLITE_API int sqlite3_carray_bind_v2(
|
||||
sqlite3_stmt *pStmt, /* Statement to be bound */
|
||||
int i, /* Parameter index */
|
||||
void *aData, /* Pointer to array data */
|
||||
int nData, /* Number of data elements */
|
||||
int mFlags, /* CARRAY flags */
|
||||
void (*xDel)(void*), /* Destructor for aData */
|
||||
void *pDel /* Optional argument to xDel() */
|
||||
);
|
||||
SQLITE_API int sqlite3_carray_bind(
|
||||
sqlite3_stmt *pStmt, /* Statement to be bound */
|
||||
int i, /* Parameter index */
|
||||
@@ -12713,11 +12856,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
|
||||
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
||||
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
||||
** or SET DEFAULT.
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
|
||||
** Sometimes, a changeset contains two or more update statements such that
|
||||
** although after applying all updates the database will contain no
|
||||
** constraint violations, no single update can be applied before the others.
|
||||
** The simplest example of this is a pair of UPDATEs that have "swapped"
|
||||
** two column values with a UNIQUE constraint.
|
||||
** <p>
|
||||
** Usually, sqlite3changeset_apply() and similar functions work hard to try
|
||||
** to find a way to apply such a changeset. However, if this flag is set,
|
||||
** then all such updates are considered CONSTRAINT conflicts.
|
||||
*/
|
||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
||||
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
@@ -13200,6 +13355,232 @@ SQLITE_API int sqlite3session_config(int op, void *pArg);
|
||||
*/
|
||||
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure a changegroup object
|
||||
**
|
||||
** Configure the changegroup object passed as the first argument.
|
||||
** At present the only valid value for the second parameter is
|
||||
** [SQLITE_CHANGEGROUP_CONFIG_PATCHSET].
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_config(sqlite3_changegroup*, int, void *pArg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Options for sqlite3changegroup_config().
|
||||
**
|
||||
** The following values may be passed as the 2nd parameter to
|
||||
** sqlite3changegroup_config().
|
||||
**
|
||||
** <dt>SQLITE_CHANGEGROUP_CONFIG_PATCHSET <dd>
|
||||
** A changegroup object generates either a changeset or patchset. Usually,
|
||||
** this is determined by whether the first call to sqlite3changegroup_add()
|
||||
** is passed a changeset or a patchset. Or, if the first changes are added
|
||||
** to the changegroup object using the sqlite3changegroup_change_xxx()
|
||||
** APIs, then this option may be used to configure whether the changegroup
|
||||
** object generates a changeset or patchset.
|
||||
**
|
||||
** When this option is invoked, parameter pArg must point to a value of
|
||||
** type int. If the changegroup currently contains zero changes, and the
|
||||
** value of the int variable is zero or greater than zero, then the
|
||||
** changegroup is configured to generate a changeset or patchset,
|
||||
** respectively. It is a no-op, not an error, if the changegroup is not
|
||||
** configured because it has already started accumulating changes.
|
||||
**
|
||||
** Before returning, the int variable is set to 0 if the changegroup is
|
||||
** configured to generate a changeset, or 1 if it is configured to generate
|
||||
** a patchset.
|
||||
*/
|
||||
#define SQLITE_CHANGEGROUP_CONFIG_PATCHSET 1
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Begin adding a change to a changegroup
|
||||
**
|
||||
** This API is used, in concert with other sqlite3changegroup_change_xxx()
|
||||
** APIs, to add changes to a changegroup object one at a time. To add a
|
||||
** single change, the caller must:
|
||||
**
|
||||
** 1. Invoke sqlite3changegroup_change_begin() to indicate the type of
|
||||
** change (INSERT, UPDATE or DELETE), the affected table and whether
|
||||
** or not the change should be marked as indirect.
|
||||
**
|
||||
** 2. Invoke sqlite3changegroup_change_int64() or one of the other four
|
||||
** value functions - _null(), _double(), _text() or _blob() - one or
|
||||
** more times to specify old.* and new.* values for the change being
|
||||
** constructed.
|
||||
**
|
||||
** 3. Invoke sqlite3changegroup_change_finish() to either finish adding
|
||||
** the change to the group, or to discard the change altogether.
|
||||
**
|
||||
** The first argument to this function must be a pointer to the existing
|
||||
** changegroup object that the change will be added to. The second argument
|
||||
** must be SQLITE_INSERT, SQLITE_UPDATE or SQLITE_DELETE. The third is the
|
||||
** name of the table that the change affects, and the fourth is a boolean
|
||||
** flag specifying whether the change should be marked as "indirect" (if
|
||||
** bIndirect is non-zero) or not indirect (if bIndirect is zero).
|
||||
**
|
||||
** Following a successful call to this function, this function may not be
|
||||
** called again on the same changegroup object until after
|
||||
** sqlite3changegroup_change_finish() has been called. Doing so is an
|
||||
** SQLITE_MISUSE error.
|
||||
**
|
||||
** The changegroup object passed as the first argument must be already
|
||||
** configured with schema data for the specified table. It may be configured
|
||||
** either by calling sqlite3changegroup_schema() with a database that contains
|
||||
** the table, or sqlite3changegroup_add() with a changeset that contains the
|
||||
** table. If the changegroup object has not been configured with a schema for
|
||||
** the specified table when this function is called, SQLITE_ERROR is returned.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. Otherwise, if an error occurs, an
|
||||
** SQLite error code is returned. In this case, if argument pzErr is non-NULL,
|
||||
** then (*pzErr) may be set to point to a buffer containing a utf-8 formated,
|
||||
** nul-terminated, English language error message. It is the responsibility
|
||||
** of the caller to eventually free this buffer using sqlite3_free().
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_begin(
|
||||
sqlite3_changegroup*,
|
||||
int eOp,
|
||||
const char *zTab,
|
||||
int bIndirect,
|
||||
char **pzErr
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a 64-bit integer to a changegroup
|
||||
**
|
||||
** This function may only be called between a successful call to
|
||||
** sqlite3changegroup_change_begin() and its matching
|
||||
** sqlite3changegroup_change_finish() call. If it is called at any
|
||||
** other time, it is an SQLITE_MISUSE error. Calling this function
|
||||
** specifies a 64-bit integer value to be used in the change currently being
|
||||
** added to the changegroup object passed as the first argument.
|
||||
**
|
||||
** The second parameter, bNew, specifies whether the value is to be part of
|
||||
** the new.* (if bNew is non-zero) or old.* (if bNew is zero) record of
|
||||
** the change under construction. If this does not match the type of change
|
||||
** specified by the preceding call to sqlite3changegroup_change_begin() (i.e.
|
||||
** an old.* value for an SQLITE_INSERT change, or a new.* value for an
|
||||
** SQLITE_DELETE), then SQLITE_ERROR is returned.
|
||||
**
|
||||
** The third parameter specifies the column of the old.* or new.* record that
|
||||
** the value will be a part of. If the specified table has an explicit primary
|
||||
** key, then this is the index of the table column, numbered from 0 in the order
|
||||
** specified within the CREATE TABLE statement. Or, if the table uses an
|
||||
** implicit rowid key, then the column 0 is the rowid and the explicit columns
|
||||
** are numbered starting from 1. If the iCol parameter is less than 0 or greater
|
||||
** than the index of the last column in the table, SQLITE_RANGE is returned.
|
||||
**
|
||||
** The fourth parameter is the integer value to use as part of the old.* or
|
||||
** new.* record.
|
||||
**
|
||||
** If this call is successful, SQLITE_OK is returned. Otherwise, if an
|
||||
** error occurs, an SQLite error code is returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_int64(
|
||||
sqlite3_changegroup*,
|
||||
int bNew,
|
||||
int iCol,
|
||||
sqlite3_int64 iVal
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a NULL to a changegroup
|
||||
**
|
||||
** This function is similar to sqlite3changegroup_change_int64(). Except that
|
||||
** it configures the change currently under construction with a NULL value
|
||||
** instead of a 64-bit integer.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_null(sqlite3_changegroup*, int, int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add an double to a changegroup
|
||||
**
|
||||
** This function is similar to sqlite3changegroup_change_int64(). Except that
|
||||
** it configures the change currently being constructed with a real value
|
||||
** instead of a 64-bit integer.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_double(sqlite3_changegroup*, int, int, double);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a text value to a changegroup
|
||||
**
|
||||
** This function is similar to sqlite3changegroup_change_int64(). It configures
|
||||
** the currently accumulated change with a text value instead of a 64-bit
|
||||
** integer. Parameter pVal points to a buffer containing the text encoded using
|
||||
** utf-8. Parameter nVal may either be the size of the text value in bytes, or
|
||||
** else a negative value, in which case the buffer pVal points to is assumed to
|
||||
** be nul-terminated.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_text(
|
||||
sqlite3_changegroup*, int, int, const char *pVal, int nVal
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a blob to a changegroup
|
||||
**
|
||||
** This function is similar to sqlite3changegroup_change_int64(). It configures
|
||||
** the currently accumulated change with a blob value instead of a 64-bit
|
||||
** integer. Parameter pVal points to a buffer containing the blob. Parameter
|
||||
** nVal is the size of the blob in bytes.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_blob(
|
||||
sqlite3_changegroup*, int, int, const void *pVal, int nVal
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finish adding one-at-at-time changes to a changegroup
|
||||
**
|
||||
** This function may only be called following a successful call to
|
||||
** sqlite3changegroup_change_begin(). Otherwise, it is an SQLITE_MISUSE error.
|
||||
**
|
||||
** If parameter bDiscard is non-zero, then the current change is simply
|
||||
** discarded. In this case this function is always successful and SQLITE_OK
|
||||
** returned.
|
||||
**
|
||||
** If parameter bDiscard is zero, then an attempt is made to add the current
|
||||
** change to the changegroup. Assuming the changegroup is configured to
|
||||
** produce a changeset (not a patchset), this requires that:
|
||||
**
|
||||
** * If the change is an INSERT or DELETE, then a value must be specified
|
||||
** for all columns of the new.* or old.* record, respectively.
|
||||
**
|
||||
** * If the change is an UPDATE record, then values must be provided for
|
||||
** the PRIMARY KEY columns of the old.* record, but must not be provided
|
||||
** for PRIMARY KEY columns of the new.* record.
|
||||
**
|
||||
** * If the change is an UPDATE record, then for each non-PRIMARY KEY
|
||||
** column in the old.* record for which a value has been provided, a
|
||||
** value must also be provided for the same column in the new.* record.
|
||||
** Similarly, for each non-PK column in the old.* record for which
|
||||
** a value is not provided, a value must not be provided for the same
|
||||
** column in the new.* record.
|
||||
**
|
||||
** * All values specified for PRIMARY KEY columns must be non-NULL.
|
||||
**
|
||||
** Otherwise, it is an error.
|
||||
**
|
||||
** If the changegroup already contains a change for the same row (identified
|
||||
** by PRIMARY KEY columns), then the current change is combined with the
|
||||
** existing change in the same way as for sqlite3changegroup_add().
|
||||
**
|
||||
** For a patchset, all of the above rules apply except that it doesn't matter
|
||||
** whether or not values are provided for the non-PK old.* record columns
|
||||
** for an UPDATE or DELETE change. This means that code used to produce
|
||||
** a changeset using the sqlite3changegroup_change_xxx() APIs may also
|
||||
** be used to produce patchsets.
|
||||
**
|
||||
** If the call is successful, SQLITE_OK is returned. Otherwise, if an error
|
||||
** occurs, an SQLite error code is returned. If an error is returned and
|
||||
** parameter pzErr is not NULL, then (*pzErr) may be set to point to a buffer
|
||||
** containing a nul-terminated, utf-8 encoded, English language error message.
|
||||
** It is the responsibility of the caller to eventually free any such error
|
||||
** message buffer using sqlite3_free().
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_change_finish(
|
||||
sqlite3_changegroup*,
|
||||
int bDiscard,
|
||||
char **pzErr
|
||||
);
|
||||
|
||||
/*
|
||||
** Make sure we can call this stuff from C++.
|
||||
*/
|
||||
|
||||
+235
-130
@@ -69,13 +69,13 @@ _sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zV
|
||||
}
|
||||
|
||||
static int
|
||||
_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
|
||||
return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||
_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, sqlite3_uint64 np) {
|
||||
return sqlite3_bind_text64(stmt, n, p, np, SQLITE_TRANSIENT, SQLITE_UTF8);
|
||||
}
|
||||
|
||||
static int
|
||||
_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
|
||||
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||
_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, sqlite3_uint64 np) {
|
||||
return sqlite3_bind_blob64(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -220,8 +220,8 @@ _sqlite3_prepare_v2_internal(sqlite3 *db, const char *zSql, int nBytes, sqlite3_
|
||||
}
|
||||
#endif
|
||||
|
||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s) {
|
||||
sqlite3_result_text(ctx, s, -1, &free);
|
||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s, int n) {
|
||||
sqlite3_result_text(ctx, s, n, &free);
|
||||
}
|
||||
|
||||
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l) {
|
||||
@@ -445,15 +445,20 @@ type SQLiteDriver struct {
|
||||
|
||||
// SQLiteConn implements driver.Conn.
|
||||
type SQLiteConn struct {
|
||||
mu sync.Mutex
|
||||
db *C.sqlite3
|
||||
loc *time.Location
|
||||
txlock string
|
||||
funcs []*functionInfo
|
||||
aggregators []*aggInfo
|
||||
stmtCache map[string][]*SQLiteStmt
|
||||
stmtCacheSize int
|
||||
stmtCacheCount int
|
||||
mu sync.Mutex
|
||||
db *C.sqlite3
|
||||
loc *time.Location
|
||||
txlock string
|
||||
funcs []*functionInfo
|
||||
aggregators []*aggInfo
|
||||
// Prepared-statement cache. The slice is allocated at Open with a
|
||||
// fixed capacity equal to the configured cache size; cap bounds the
|
||||
// cache, len is the live count, and entries are ordered LRU-first
|
||||
// (index 0 is the oldest, the tail is most recently put). Access
|
||||
// requires mu; stmtCacheEnabled is immutable after Open and is the
|
||||
// only field safe to read without the lock.
|
||||
stmtCache []*SQLiteStmt
|
||||
stmtCacheEnabled bool
|
||||
}
|
||||
|
||||
// SQLiteTx implements driver.Tx.
|
||||
@@ -471,6 +476,12 @@ type SQLiteStmt struct {
|
||||
cls bool // True if the statement was created by SQLiteConn.Query
|
||||
namedParams map[string][3]int
|
||||
cacheKey string
|
||||
metadata *sqliteStmtMetadata
|
||||
}
|
||||
|
||||
type sqliteStmtMetadata struct {
|
||||
cols []string
|
||||
decltype []string
|
||||
}
|
||||
|
||||
// SQLiteResult implements sql.Result.
|
||||
@@ -1017,25 +1028,37 @@ func (c *SQLiteConn) query(ctx context.Context, query string, args []driver.Name
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.(*SQLiteStmt).cls = true
|
||||
ss := s.(*SQLiteStmt)
|
||||
ss.cls = true
|
||||
// sqlite3_prepare_v2 returns SQLITE_OK with a NULL statement handle
|
||||
// when the input is empty or contains only whitespace/comments.
|
||||
if ss.s == nil {
|
||||
tail := ss.t
|
||||
ss.Close()
|
||||
if tail == "" {
|
||||
return &SQLiteRows{cls: true, ctx: ctx}, nil
|
||||
}
|
||||
query = tail
|
||||
continue
|
||||
}
|
||||
na := s.NumInput()
|
||||
if len(args)-start < na {
|
||||
s.Close()
|
||||
ss.Close()
|
||||
return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args)-start)
|
||||
}
|
||||
stmtArgs := stmtArgs(args, start, na)
|
||||
rows, err := s.(*SQLiteStmt).query(ctx, stmtArgs)
|
||||
rows, err := ss.query(ctx, stmtArgs)
|
||||
if err != nil && err != driver.ErrSkip {
|
||||
s.Close()
|
||||
ss.Close()
|
||||
return rows, err
|
||||
}
|
||||
start += na
|
||||
tail := s.(*SQLiteStmt).t
|
||||
tail := ss.t
|
||||
if tail == "" {
|
||||
return rows, nil
|
||||
}
|
||||
rows.Close()
|
||||
s.Close()
|
||||
ss.Close()
|
||||
query = tail
|
||||
}
|
||||
}
|
||||
@@ -1572,6 +1595,20 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
return nil, errors.New("sqlite succeeded without returning a database")
|
||||
}
|
||||
|
||||
// Create connection to SQLite
|
||||
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
|
||||
if stmtCacheSize > 0 {
|
||||
conn.stmtCache = make([]*SQLiteStmt, 0, stmtCacheSize)
|
||||
conn.stmtCacheEnabled = true
|
||||
}
|
||||
|
||||
// fail closes the connection so no error path leaks the database
|
||||
// handle or any callback handles registered on it.
|
||||
fail := func(err error) (driver.Conn, error) {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exec := func(s string) error {
|
||||
cs := C.CString(s)
|
||||
rv := C.sqlite3_exec(db, cs, nil, nil, nil)
|
||||
@@ -1584,8 +1621,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
|
||||
// Busy timeout
|
||||
if err := exec(fmt.Sprintf("PRAGMA busy_timeout = %d;", busyTimeout)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// USER AUTHENTICATION
|
||||
@@ -1610,65 +1646,59 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// NO => Continue
|
||||
//
|
||||
|
||||
// Create connection to SQLite
|
||||
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock, stmtCacheSize: stmtCacheSize}
|
||||
if stmtCacheSize > 0 {
|
||||
conn.stmtCache = make(map[string][]*SQLiteStmt)
|
||||
}
|
||||
|
||||
// Password Cipher has to be registered before authentication
|
||||
if len(authCrypt) > 0 {
|
||||
switch strings.ToUpper(authCrypt) {
|
||||
case "SHA1":
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSHA1: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSHA1: %s", err))
|
||||
}
|
||||
case "SSHA1":
|
||||
if len(authSalt) == 0 {
|
||||
return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt")
|
||||
return fail(fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt"))
|
||||
}
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSSHA1: %s", err))
|
||||
}
|
||||
case "SHA256":
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSHA256: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSHA256: %s", err))
|
||||
}
|
||||
case "SSHA256":
|
||||
if len(authSalt) == 0 {
|
||||
return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt")
|
||||
return fail(fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt"))
|
||||
}
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSSHA256: %s", err))
|
||||
}
|
||||
case "SHA384":
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSHA384: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSHA384: %s", err))
|
||||
}
|
||||
case "SSHA384":
|
||||
if len(authSalt) == 0 {
|
||||
return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt")
|
||||
return fail(fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt"))
|
||||
}
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSSHA384: %s", err))
|
||||
}
|
||||
case "SHA512":
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSHA512: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSHA512: %s", err))
|
||||
}
|
||||
case "SSHA512":
|
||||
if len(authSalt) == 0 {
|
||||
return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt")
|
||||
return fail(fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt"))
|
||||
}
|
||||
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil {
|
||||
return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err)
|
||||
return fail(fmt.Errorf("CryptEncoderSSHA512: %s", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preform Authentication
|
||||
if err := conn.Authenticate(authUser, authPass); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// Register: authenticate
|
||||
@@ -1686,7 +1716,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// If the SQLITE_USER table is not present in the database file, then
|
||||
// this interface is a harmless no-op returnning SQLITE_OK.
|
||||
if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
//
|
||||
// Register: auth_user_add
|
||||
@@ -1699,7 +1729,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
|
||||
// non-admin user results in an error.
|
||||
if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
//
|
||||
// Register: auth_user_change
|
||||
@@ -1709,7 +1739,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// credentials or admin privilege setting. No user may change their own
|
||||
// admin privilege setting.
|
||||
if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
//
|
||||
// Register: auth_user_delete
|
||||
@@ -1719,13 +1749,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// the database cannot be converted into a no-authentication-required
|
||||
// database.
|
||||
if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// Register: auth_enabled
|
||||
// auth_enabled can be used to check if user authentication is enabled
|
||||
if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// Auto Vacuum
|
||||
@@ -1736,8 +1766,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// and activating user authentication creates the internal table `sqlite_user`.
|
||||
if autoVacuum > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA auto_vacuum = %d;", autoVacuum)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1747,17 +1776,17 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// has provided an username and password within the DSN.
|
||||
// We are not allowed to continue.
|
||||
if len(authUser) == 0 {
|
||||
return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'")
|
||||
return fail(fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'"))
|
||||
}
|
||||
if len(authPass) == 0 {
|
||||
return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'")
|
||||
return fail(fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'"))
|
||||
}
|
||||
|
||||
// Check if User Authentication is Enabled
|
||||
authExists := conn.AuthEnabled()
|
||||
if !authExists {
|
||||
if err := conn.AuthUserAdd(authUser, authPass, true); err != nil {
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1765,40 +1794,35 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// Case Sensitive LIKE
|
||||
if caseSensitiveLike > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA case_sensitive_like = %d;", caseSensitiveLike)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Defer Foreign Keys
|
||||
if deferForeignKeys > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Foreign Keys
|
||||
if foreignKeys > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA foreign_keys = %d;", foreignKeys)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore CHECK Constraints
|
||||
if ignoreCheckConstraints > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA ignore_check_constraints = %d;", ignoreCheckConstraints)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Journal Mode
|
||||
if journalMode != "" {
|
||||
if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1806,23 +1830,20 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// Because the default is NORMAL and this is not changed in this package
|
||||
// by using the compile time SQLITE_DEFAULT_LOCKING_MODE this PRAGMA can always be executed
|
||||
if err := exec(fmt.Sprintf("PRAGMA locking_mode = %s;", lockingMode)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// Query Only
|
||||
if queryOnly > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA query_only = %d;", queryOnly)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive Triggers
|
||||
if recursiveTriggers > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1833,8 +1854,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
// you can compile with secure_delete 'ON' and disable it for a specific database connection.
|
||||
if secureDelete != "DEFAULT" {
|
||||
if err := exec(fmt.Sprintf("PRAGMA secure_delete = %s;", secureDelete)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1842,37 +1862,32 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||
//
|
||||
// Because default is NORMAL this statement is always executed
|
||||
if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
|
||||
// Writable Schema
|
||||
if writableSchema > -1 {
|
||||
if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Cache Size
|
||||
if cacheSize != nil {
|
||||
if err := exec(fmt.Sprintf("PRAGMA cache_size = %d;", *cacheSize)); err != nil {
|
||||
C.sqlite3_close_v2(db)
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(d.Extensions) > 0 {
|
||||
if err := conn.loadExtensions(d.Extensions); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
if d.ConnectHook != nil {
|
||||
if err := d.ConnectHook(conn); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
return fail(err)
|
||||
}
|
||||
}
|
||||
runtime.SetFinalizer(conn, (*SQLiteConn).Close)
|
||||
@@ -1907,7 +1922,7 @@ func (c *SQLiteConn) dbConnOpen() bool {
|
||||
}
|
||||
|
||||
func (c *SQLiteConn) takeCachedStmt(query string) *SQLiteStmt {
|
||||
if c == nil || query == "" || c.stmtCacheSize <= 0 {
|
||||
if c == nil || query == "" || !c.stmtCacheEnabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1917,21 +1932,25 @@ func (c *SQLiteConn) takeCachedStmt(query string) *SQLiteStmt {
|
||||
if c.db == nil {
|
||||
return nil
|
||||
}
|
||||
stmts := c.stmtCache[query]
|
||||
if len(stmts) == 0 {
|
||||
return nil
|
||||
// Scan from the MRU end (tail) so that a stmt put just before is
|
||||
// found immediately.
|
||||
for i := len(c.stmtCache) - 1; i >= 0; i-- {
|
||||
s := c.stmtCache[i]
|
||||
if s.cacheKey != query {
|
||||
continue
|
||||
}
|
||||
n := len(c.stmtCache)
|
||||
copy(c.stmtCache[i:n-1], c.stmtCache[i+1:n])
|
||||
c.stmtCache[n-1] = nil
|
||||
c.stmtCache = c.stmtCache[:n-1]
|
||||
// The stmt was marked closed by Close before being cached, and
|
||||
// cls may have been set if Query opened it; reset both so the
|
||||
// caller gets a stmt equivalent to a fresh Prepare.
|
||||
s.closed = false
|
||||
s.cls = false
|
||||
return s
|
||||
}
|
||||
s := stmts[len(stmts)-1]
|
||||
if len(stmts) == 1 {
|
||||
delete(c.stmtCache, query)
|
||||
} else {
|
||||
c.stmtCache[query] = stmts[:len(stmts)-1]
|
||||
}
|
||||
c.stmtCacheCount--
|
||||
s.closed = false
|
||||
s.cls = false
|
||||
s.t = ""
|
||||
return s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *SQLiteConn) putCachedStmt(s *SQLiteStmt) bool {
|
||||
@@ -1942,32 +1961,50 @@ func (c *SQLiteConn) putCachedStmt(s *SQLiteStmt) bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
if c.db == nil || c.stmtCacheCount >= c.stmtCacheSize {
|
||||
return c.putCachedStmtLocked(s)
|
||||
}
|
||||
|
||||
func (c *SQLiteConn) putCachedStmtLocked(s *SQLiteStmt) bool {
|
||||
if c.db == nil {
|
||||
return false
|
||||
}
|
||||
rv := C._sqlite3_reset_clear(s.s)
|
||||
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
||||
return false
|
||||
}
|
||||
c.stmtCache[s.cacheKey] = append(c.stmtCache[s.cacheKey], s)
|
||||
c.stmtCacheCount++
|
||||
// If full, finalize the LRU entry at index 0 and shift left; the
|
||||
// freed tail slot is immediately reused by the append below.
|
||||
if len(c.stmtCache) == cap(c.stmtCache) {
|
||||
finalizeCachedStmt(c.stmtCache[0])
|
||||
copy(c.stmtCache, c.stmtCache[1:])
|
||||
c.stmtCache = c.stmtCache[:len(c.stmtCache)-1]
|
||||
}
|
||||
c.stmtCache = append(c.stmtCache, s)
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *SQLiteConn) closeCachedStmtsLocked() {
|
||||
for key, stmts := range c.stmtCache {
|
||||
for _, s := range stmts {
|
||||
if s == nil || s.s == nil {
|
||||
continue
|
||||
}
|
||||
runtime.SetFinalizer(s, nil)
|
||||
C.sqlite3_finalize(s.s)
|
||||
s.s = nil
|
||||
s.c = nil
|
||||
}
|
||||
delete(c.stmtCache, key)
|
||||
for i, s := range c.stmtCache {
|
||||
c.stmtCache[i] = nil
|
||||
finalizeCachedStmt(s)
|
||||
}
|
||||
c.stmtCacheCount = 0
|
||||
c.stmtCache = c.stmtCache[:0]
|
||||
}
|
||||
|
||||
// finalizeCachedStmt tears down a stmt that was sitting in the connection's
|
||||
// stmt cache. The caller must hold c.mu. It is safe to pass a nil stmt or a
|
||||
// stmt whose handle has already been released.
|
||||
func finalizeCachedStmt(s *SQLiteStmt) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
runtime.SetFinalizer(s, nil)
|
||||
if s.s != nil {
|
||||
C.sqlite3_finalize(s.s)
|
||||
s.s = nil
|
||||
}
|
||||
s.c = nil
|
||||
s.closed = true
|
||||
}
|
||||
|
||||
// Prepare the query string. Return a new statement.
|
||||
@@ -2002,7 +2039,7 @@ func (c *SQLiteConn) prepareWithCache(ctx context.Context, query string) (driver
|
||||
return nil, err
|
||||
}
|
||||
ss := stmt.(*SQLiteStmt)
|
||||
if ss.t == "" {
|
||||
if ss.t == "" && c.stmtCacheEnabled {
|
||||
ss.cacheKey = query
|
||||
}
|
||||
return ss, nil
|
||||
@@ -2033,7 +2070,9 @@ func (c *SQLiteConn) GetFilename(schemaName string) string {
|
||||
if schemaName == "" {
|
||||
schemaName = "main"
|
||||
}
|
||||
return C.GoString(C.sqlite3_db_filename(c.db, C.CString(schemaName)))
|
||||
cSchema := C.CString(schemaName)
|
||||
defer C.free(unsafe.Pointer(cSchema))
|
||||
return C.GoString(C.sqlite3_db_filename(c.db, cSchema))
|
||||
}
|
||||
|
||||
// GetLimit returns the current value of a run-time limit.
|
||||
@@ -2120,12 +2159,20 @@ func (s *SQLiteStmt) Close() error {
|
||||
s.c = nil
|
||||
return nil
|
||||
}
|
||||
if !conn.dbConnOpen() {
|
||||
if s.cacheKey != "" {
|
||||
conn.mu.Lock()
|
||||
if conn.db == nil {
|
||||
conn.mu.Unlock()
|
||||
return errors.New("sqlite statement with already closed database connection")
|
||||
}
|
||||
if conn.putCachedStmtLocked(s) {
|
||||
conn.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
conn.mu.Unlock()
|
||||
} else if !conn.dbConnOpen() {
|
||||
return errors.New("sqlite statement with already closed database connection")
|
||||
}
|
||||
if s.cacheKey != "" && conn.putCachedStmt(s) {
|
||||
return nil
|
||||
}
|
||||
s.s = nil
|
||||
s.c = nil
|
||||
rv := C.sqlite3_finalize(stmt)
|
||||
@@ -2144,9 +2191,9 @@ var placeHolder = []byte{0}
|
||||
|
||||
func bindText(s *C.sqlite3_stmt, n C.int, v string) C.int {
|
||||
if len(v) == 0 {
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.int(0))
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.sqlite3_uint64(0))
|
||||
}
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(unsafe.StringData(v))), C.int(len(v)))
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(unsafe.StringData(v))), C.sqlite3_uint64(len(v)))
|
||||
}
|
||||
|
||||
func bindValue(s *C.sqlite3_stmt, n C.int, value driver.Value) C.int {
|
||||
@@ -2172,14 +2219,14 @@ func bindValue(s *C.sqlite3_stmt, n C.int, value driver.Value) C.int {
|
||||
if ln == 0 {
|
||||
v = placeHolder
|
||||
}
|
||||
return C._sqlite3_bind_blob(s, n, unsafe.Pointer(&v[0]), C.int(ln))
|
||||
return C._sqlite3_bind_blob(s, n, unsafe.Pointer(&v[0]), C.sqlite3_uint64(ln))
|
||||
case time.Time:
|
||||
var buf [64]byte
|
||||
b := v.AppendFormat(buf[:0], SQLiteTimestampFormats[0])
|
||||
if len(b) == 0 {
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.int(0))
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.sqlite3_uint64(0))
|
||||
}
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
|
||||
return C._sqlite3_bind_text(s, n, (*C.char)(unsafe.Pointer(&b[0])), C.sqlite3_uint64(len(b)))
|
||||
default:
|
||||
return C.SQLITE_MISUSE
|
||||
}
|
||||
@@ -2238,6 +2285,17 @@ func stmtArgs(args []driver.NamedValue, start, na int) []driver.NamedValue {
|
||||
return stmtArgs
|
||||
}
|
||||
|
||||
// bindError converts a non-OK return code from bindValue into an error.
|
||||
// The synthetic SQLITE_MISUSE returned for unsupported Go types is never
|
||||
// recorded in the database handle, so lastError may report no error; fall
|
||||
// back to an explicit message instead of silently ignoring the failure.
|
||||
func (s *SQLiteStmt) bindError(v driver.Value) error {
|
||||
if err := s.c.lastError(); err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("sqlite3: unsupported bind type %T", v)
|
||||
}
|
||||
|
||||
func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
|
||||
rv := C._sqlite3_reset_clear(s.s)
|
||||
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
||||
@@ -2257,7 +2315,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
|
||||
n := C.int(arg.Ordinal)
|
||||
rv = bindValue(s.s, n, arg.Value)
|
||||
if rv != C.SQLITE_OK {
|
||||
return s.c.lastError()
|
||||
return s.bindError(arg.Value)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -2267,7 +2325,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
|
||||
if arg.Name == "" {
|
||||
rv = bindValue(s.s, C.int(arg.Ordinal), arg.Value)
|
||||
if rv != C.SQLITE_OK {
|
||||
return s.c.lastError()
|
||||
return s.bindError(arg.Value)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -2278,7 +2336,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
|
||||
}
|
||||
rv = bindValue(s.s, C.int(idx), arg.Value)
|
||||
if rv != C.SQLITE_OK {
|
||||
return s.c.lastError()
|
||||
return s.bindError(arg.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2439,14 +2497,51 @@ func (rc *SQLiteRows) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQLiteStmt) cacheMetadata() bool {
|
||||
return !s.cls || s.cacheKey != ""
|
||||
}
|
||||
|
||||
func (s *SQLiteStmt) columnNamesLocked(n int) []string {
|
||||
if s.metadata == nil {
|
||||
s.metadata = &sqliteStmtMetadata{}
|
||||
}
|
||||
if len(s.metadata.cols) != n {
|
||||
s.metadata.cols = make([]string, n)
|
||||
for i := range s.metadata.cols {
|
||||
s.metadata.cols[i] = C.GoString(C.sqlite3_column_name(s.s, C.int(i)))
|
||||
}
|
||||
}
|
||||
return s.metadata.cols
|
||||
}
|
||||
|
||||
func (s *SQLiteStmt) declTypesLocked(n int) []string {
|
||||
if s.metadata == nil {
|
||||
s.metadata = &sqliteStmtMetadata{}
|
||||
}
|
||||
if len(s.metadata.decltype) != n {
|
||||
s.metadata.decltype = make([]string, n)
|
||||
for i := range s.metadata.decltype {
|
||||
s.metadata.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(s.s, C.int(i))))
|
||||
}
|
||||
}
|
||||
return s.metadata.decltype
|
||||
}
|
||||
|
||||
// Columns return column names.
|
||||
func (rc *SQLiteRows) Columns() []string {
|
||||
if rc.s == nil {
|
||||
return rc.cols
|
||||
}
|
||||
rc.s.mu.Lock()
|
||||
defer rc.s.mu.Unlock()
|
||||
if rc.s.s != nil && int(rc.nc) != len(rc.cols) {
|
||||
rc.cols = make([]string, rc.nc)
|
||||
for i := range rc.cols {
|
||||
rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))
|
||||
if rc.s.cacheMetadata() {
|
||||
rc.cols = rc.s.columnNamesLocked(int(rc.nc))
|
||||
} else {
|
||||
rc.cols = make([]string, rc.nc)
|
||||
for i := range rc.cols {
|
||||
rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc.cols
|
||||
@@ -2454,9 +2549,13 @@ func (rc *SQLiteRows) Columns() []string {
|
||||
|
||||
func (rc *SQLiteRows) declTypes() []string {
|
||||
if rc.s.s != nil && rc.decltype == nil {
|
||||
rc.decltype = make([]string, rc.nc)
|
||||
for i := range rc.decltype {
|
||||
rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
|
||||
if rc.s.cacheMetadata() {
|
||||
rc.decltype = rc.s.declTypesLocked(int(rc.nc))
|
||||
} else {
|
||||
rc.decltype = make([]string, rc.nc)
|
||||
for i := range rc.decltype {
|
||||
rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc.decltype
|
||||
@@ -2464,6 +2563,9 @@ func (rc *SQLiteRows) declTypes() []string {
|
||||
|
||||
// DeclTypes return column types.
|
||||
func (rc *SQLiteRows) DeclTypes() []string {
|
||||
if rc.s == nil {
|
||||
return rc.decltype
|
||||
}
|
||||
rc.s.mu.Lock()
|
||||
defer rc.s.mu.Unlock()
|
||||
return rc.declTypes()
|
||||
@@ -2471,6 +2573,9 @@ func (rc *SQLiteRows) DeclTypes() []string {
|
||||
|
||||
// Next move cursor to next. Attempts to honor context timeout from QueryContext call.
|
||||
func (rc *SQLiteRows) Next(dest []driver.Value) error {
|
||||
if rc.s == nil {
|
||||
return io.EOF
|
||||
}
|
||||
rc.s.mu.Lock()
|
||||
defer rc.s.mu.Unlock()
|
||||
|
||||
|
||||
+9
-4
@@ -28,7 +28,6 @@ import "C"
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -91,9 +90,15 @@ func (c *SQLiteContext) ResultNull() {
|
||||
// ResultText sets the result of an SQL function.
|
||||
// See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html
|
||||
func (c *SQLiteContext) ResultText(s string) {
|
||||
h := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||
cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)
|
||||
C.my_result_text((*C.sqlite3_context)(c), cs, l)
|
||||
if i64 && len(s) > math.MaxInt32 {
|
||||
C.sqlite3_result_error_toobig((*C.sqlite3_context)(c))
|
||||
return
|
||||
}
|
||||
if len(s) == 0 {
|
||||
C.my_result_text((*C.sqlite3_context)(c), (*C.char)(unsafe.Pointer(&placeHolder[0])), 0)
|
||||
return
|
||||
}
|
||||
C.my_result_text((*C.sqlite3_context)(c), (*C.char)(unsafe.Pointer(unsafe.StringData(s))), C.int(len(s)))
|
||||
}
|
||||
|
||||
// ResultZeroblob sets the result of an SQL function.
|
||||
|
||||
+3
-3
@@ -74,11 +74,11 @@ func (c *SQLiteConn) loadExtension(lib string, entry *string) error {
|
||||
}
|
||||
|
||||
var errMsg *C.char
|
||||
defer C.sqlite3_free(unsafe.Pointer(errMsg))
|
||||
|
||||
rv := C.sqlite3_load_extension(c.db, clib, centry, &errMsg)
|
||||
if rv != C.SQLITE_OK {
|
||||
return errors.New(C.GoString(errMsg))
|
||||
err := errors.New(C.GoString(errMsg))
|
||||
C.sqlite3_free(unsafe.Pointer(errMsg))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2025 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||
// Copyright (C) 2025 Jakob Borg <jakob@kastelo.net>.
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build sqlite_dbstat
|
||||
// +build sqlite_dbstat
|
||||
|
||||
package sqlite3
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
*/
|
||||
import "C"
|
||||
+6
-2
@@ -59,13 +59,17 @@ func (d *SQLitePreUpdateData) row(dest []any, new bool) error {
|
||||
for i := 0; i < d.Count() && i < len(dest); i++ {
|
||||
var val *C.sqlite3_value
|
||||
var src any
|
||||
var rc C.int
|
||||
|
||||
// Initially I tried making this just a function pointer argument, but
|
||||
// it's absurdly complicated to pass C function pointers.
|
||||
if new {
|
||||
C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
|
||||
rc = C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
|
||||
} else {
|
||||
C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
|
||||
rc = C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
|
||||
}
|
||||
if rc != C.SQLITE_OK {
|
||||
return Error{Code: ErrNo(rc)}
|
||||
}
|
||||
|
||||
switch C.sqlite3_value_type(val) {
|
||||
|
||||
+3
@@ -60,6 +60,9 @@ func (c *SQLiteConn) Deserialize(b []byte, schema string) error {
|
||||
defer C.free(unsafe.Pointer(zSchema))
|
||||
|
||||
tmpBuf := (*C.uchar)(C.sqlite3_malloc64(C.sqlite3_uint64(len(b))))
|
||||
if tmpBuf == nil && len(b) > 0 {
|
||||
return fmt.Errorf("deserialize failed: out of memory")
|
||||
}
|
||||
copy(unsafe.Slice((*byte)(unsafe.Pointer(tmpBuf)), len(b)), b)
|
||||
|
||||
rc := C.sqlite3_deserialize(c.db, zSchema, tmpBuf, C.sqlite3_int64(len(b)),
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ package sqlite3
|
||||
extern void unlock_notify_callback(void *arg, int argc);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -82,7 +83,7 @@ func unlock_notify_wait(db *C.sqlite3) C.int {
|
||||
h := unt.add(c)
|
||||
defer unt.remove(h)
|
||||
|
||||
pargv := C.malloc(C.sizeof_uint)
|
||||
pargv := C.malloc(C.size_t(unsafe.Sizeof(uint(0))))
|
||||
defer C.free(pargv)
|
||||
|
||||
argv := (*[1]uint)(pargv)
|
||||
|
||||
+58
-31
@@ -113,6 +113,9 @@ uintptr_t goVOpen(void *pVTab, char **pzErr);
|
||||
|
||||
static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
|
||||
void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
|
||||
if (!vTabCursor) {
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
|
||||
if (!pCursor) {
|
||||
return SQLITE_NOMEM;
|
||||
@@ -270,7 +273,6 @@ import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -329,11 +331,7 @@ type InfoOrderBy struct {
|
||||
}
|
||||
|
||||
func constraints(info *C.sqlite3_index_info) []InfoConstraint {
|
||||
slice := *(*[]C.struct_sqlite3_index_constraint)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(info.aConstraint)),
|
||||
Len: int(info.nConstraint),
|
||||
Cap: int(info.nConstraint),
|
||||
}))
|
||||
slice := unsafe.Slice(info.aConstraint, int(info.nConstraint))
|
||||
|
||||
cst := make([]InfoConstraint, 0, len(slice))
|
||||
for _, c := range slice {
|
||||
@@ -351,11 +349,7 @@ func constraints(info *C.sqlite3_index_info) []InfoConstraint {
|
||||
}
|
||||
|
||||
func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
|
||||
slice := *(*[]C.struct_sqlite3_index_orderby)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(info.aOrderBy)),
|
||||
Len: int(info.nOrderBy),
|
||||
Cap: int(info.nOrderBy),
|
||||
}))
|
||||
slice := unsafe.Slice(info.aOrderBy, int(info.nOrderBy))
|
||||
|
||||
ob := make([]InfoOrderBy, 0, len(slice))
|
||||
for _, c := range slice {
|
||||
@@ -400,10 +394,7 @@ func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **
|
||||
return 0
|
||||
}
|
||||
args := make([]string, argc)
|
||||
var A []*C.char
|
||||
slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
|
||||
a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
|
||||
for i, s := range a.([]*C.char) {
|
||||
for i, s := range unsafe.Slice(argv, int(argc)) {
|
||||
args[i] = C.GoString(s)
|
||||
}
|
||||
var vTab VTab
|
||||
@@ -432,6 +423,9 @@ func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
|
||||
} else {
|
||||
err = vt.vTab.Disconnect()
|
||||
}
|
||||
// The vtab is gone as far as SQLite is concerned regardless of the
|
||||
// callback result, so release the handle either way.
|
||||
deleteHandle(pVTab)
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
@@ -460,20 +454,23 @@ func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
if res == nil {
|
||||
return mPrintf("%s", "BestIndex returned a nil IndexResult")
|
||||
}
|
||||
if len(res.Used) != len(csts) {
|
||||
return mPrintf("Result.Used != expected value", "")
|
||||
}
|
||||
|
||||
// Get a pointer to constraint_usage struct so we can update in place.
|
||||
|
||||
slice := *(*[]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(info.aConstraintUsage)),
|
||||
Len: int(info.nConstraint),
|
||||
Cap: int(info.nConstraint),
|
||||
}))
|
||||
slice := unsafe.Slice(info.aConstraintUsage, int(info.nConstraint))
|
||||
index := 1
|
||||
for i := range slice {
|
||||
if res.Used[i] {
|
||||
// SQLite returns "xBestIndex malfunction" when an argvIndex is
|
||||
// assigned to a constraint it marked as not usable, so ignore
|
||||
// Used for those; they may become usable on a later xBestIndex
|
||||
// invocation for a different plan.
|
||||
if res.Used[i] && csts[i].Usable {
|
||||
slice[i].argvIndex = C.int(index)
|
||||
slice[i].omit = C.uchar(1)
|
||||
index++
|
||||
@@ -488,19 +485,30 @@ func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
|
||||
}
|
||||
info.needToFreeIdxStr = C.int(1)
|
||||
|
||||
idxStr := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(info.idxStr)),
|
||||
Len: len(res.IdxStr) + 1,
|
||||
Cap: len(res.IdxStr) + 1,
|
||||
}))
|
||||
idxStr := unsafe.Slice((*byte)(unsafe.Pointer(info.idxStr)), len(res.IdxStr)+1)
|
||||
copy(idxStr, res.IdxStr)
|
||||
idxStr[len(idxStr)-1] = 0 // null-terminated string
|
||||
|
||||
if res.AlreadyOrdered {
|
||||
info.orderByConsumed = C.int(1)
|
||||
}
|
||||
info.estimatedCost = C.double(res.EstimatedCost)
|
||||
info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
|
||||
// SQLite pre-initializes estimatedCost and estimatedRows with sensible
|
||||
// defaults; overwriting them with the Go zero value would make every
|
||||
// candidate plan look free and break query planning, so only pass
|
||||
// values the implementation actually set.
|
||||
if res.EstimatedCost > 0 {
|
||||
info.estimatedCost = C.double(res.EstimatedCost)
|
||||
}
|
||||
if res.EstimatedRows > 0 {
|
||||
var rows int64
|
||||
if res.EstimatedRows >= float64(math.MaxInt64) {
|
||||
rows = math.MaxInt64
|
||||
} else if rows = int64(res.EstimatedRows); rows < 1 {
|
||||
// A positive fractional estimate must not truncate to 0.
|
||||
rows = 1
|
||||
}
|
||||
info.estimatedRows = C.sqlite3_int64(rows)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -509,6 +517,9 @@ func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
|
||||
func goVClose(pCursor unsafe.Pointer) *C.char {
|
||||
vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
|
||||
err := vtc.vTabCursor.Close()
|
||||
// The cursor is gone as far as SQLite is concerned regardless of the
|
||||
// callback result, so release the handle either way.
|
||||
deleteHandle(pCursor)
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
@@ -519,6 +530,7 @@ func goVClose(pCursor unsafe.Pointer) *C.char {
|
||||
func goMDestroy(pClientData unsafe.Pointer) {
|
||||
m := lookupHandle(pClientData).(*sqliteModule)
|
||||
m.module.DestroyModule()
|
||||
deleteHandle(pClientData)
|
||||
}
|
||||
|
||||
//export goVFilter
|
||||
@@ -531,7 +543,14 @@ func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
vals = append(vals, conv.Interface())
|
||||
|
||||
// work around for SQLITE_NULL
|
||||
x := conv.Interface()
|
||||
if z, ok := x.([]byte); ok && z == nil {
|
||||
x = nil
|
||||
}
|
||||
|
||||
vals = append(vals, x)
|
||||
}
|
||||
err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
|
||||
if err != nil {
|
||||
@@ -625,7 +644,15 @@ func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid
|
||||
}
|
||||
|
||||
case argc > 1:
|
||||
err = v.Update(vals[1], vals[2:])
|
||||
// Per the xUpdate contract argv[0] identifies the row being
|
||||
// updated while argv[1] is its new rowid. VTabUpdater has no
|
||||
// way to convey a rowid change, so reject it instead of
|
||||
// silently updating values under the old rowid.
|
||||
if vals[0] != vals[1] {
|
||||
err = fmt.Errorf("virtual %s table %sdoes not support changing the rowid", vt.module.name, tname)
|
||||
} else {
|
||||
err = v.Update(vals[0], vals[2:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,5 +752,5 @@ func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return fmt.Errorf("sqlite3: CreateModule requires a non-nil module")
|
||||
}
|
||||
+10
-1
@@ -376,7 +376,11 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.51.0 and later */
|
||||
int (*set_errmsg)(sqlite3*,int,const char*);
|
||||
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
|
||||
|
||||
/* Version 3.52.0 and later */
|
||||
void (*str_truncate)(sqlite3_str*,int);
|
||||
void (*str_free)(sqlite3_str*);
|
||||
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
|
||||
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -715,6 +719,11 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.51.0 and later */
|
||||
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
|
||||
#define sqlite3_db_status64 sqlite3_api->db_status64
|
||||
/* Version 3.52.0 and later */
|
||||
#define sqlite3_str_truncate sqlite3_api->str_truncate
|
||||
#define sqlite3_str_free sqlite3_api->str_free
|
||||
#define sqlite3_carray_bind sqlite3_api->carray_bind
|
||||
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+3
-3
@@ -27,15 +27,15 @@ func NewNatsKeyValue(c Config, log *zerolog.Logger) (jetstream.KeyValue, error)
|
||||
}
|
||||
opts := []nats.Option{
|
||||
nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
|
||||
log.Error().Err(err).Msg("Disconnected from NATS. Trying to reconnect...")
|
||||
log.Error().Err(err).Str("database", c.Database).Msg("Disconnected from NATS. Trying to reconnect...")
|
||||
}),
|
||||
nats.ReconnectHandler(func(nc *nats.Conn) {
|
||||
log.Error().Msgf("Successfully reconnected to NATS at: %s", nc.ConnectedUrl())
|
||||
log.Error().Str("database", c.Database).Msgf("Successfully reconnected to NATS at: %s", nc.ConnectedUrl())
|
||||
}),
|
||||
nats.ClosedHandler(func(nc *nats.Conn) {
|
||||
// Alright, it's time to give up. Send ourselves a SIGTERM to trigger a graceful
|
||||
// shutdown of the service.
|
||||
log.Error().Msg("NATS connection closed permanently. Shutting down...")
|
||||
log.Error().Str("database", c.Database).Msg("NATS connection closed permanently. Shutting down...")
|
||||
|
||||
pid := os.Getpid()
|
||||
process, err := os.FindProcess(pid)
|
||||
|
||||
Generated
Vendored
+15
-3
@@ -500,9 +500,21 @@ func (b HybridBackend) Lock(n MetadataNode) (UnlockFunc, error) {
|
||||
mlock, err := lockedfile.OpenFile(metaLockPath, os.O_RDWR|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// create the parent directory
|
||||
err = os.MkdirAll(filepath.Dir(metaLockPath), 0700)
|
||||
if err != nil {
|
||||
// The lock file's parent directories don't exist yet (or anymore).
|
||||
// We may only create the space's metadata directories, never the
|
||||
// space's base directory itself: locking a node (i.e. the space
|
||||
// root) whose space has been removed (or has not been created yet)
|
||||
// must not resurrect the spaca.
|
||||
base := b.metadataPathFunc(n)
|
||||
if base == "" {
|
||||
return nil, err
|
||||
}
|
||||
// base is the space's metadata directory (e.g. <spaceRoot>/.oc-nodes),
|
||||
// so its parent is the space's base directory.
|
||||
if _, statErr := os.Stat(filepath.Dir(base)); statErr != nil {
|
||||
return nil, statErr
|
||||
}
|
||||
if err = os.MkdirAll(filepath.Dir(metaLockPath), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mlock, err = lockedfile.OpenFile(metaLockPath, os.O_RDWR|os.O_CREATE, 0600)
|
||||
|
||||
Generated
Vendored
+3
-1
@@ -282,8 +282,10 @@ func (p AsyncPropagator) propagate(ctx context.Context, spaceID, nodeID string,
|
||||
|
||||
attrs := node.Attributes{}
|
||||
|
||||
// lock parent before reading treesize or tree time
|
||||
// we deliberately allow reading disabled spaces so that the metadata is always consistent (see https://github.com/opencloud-eu/reva/issues/747)
|
||||
_, subspan = tracer.Start(ctx, "node.LockAndReadNode")
|
||||
n, unlock, err := node.LockAndReadNode(ctx, p.lookup, spaceID, nodeID, "", false, nil, false)
|
||||
n, unlock, err := node.LockAndReadNode(ctx, p.lookup, spaceID, nodeID, "", true, nil, false)
|
||||
subspan.End()
|
||||
if err != nil {
|
||||
if n != nil && !n.Exists {
|
||||
|
||||
Generated
Vendored
+2
-1
@@ -92,7 +92,8 @@ func (p SyncPropagator) propagateItem(ctx context.Context, n *node.Node, sTime t
|
||||
attrs := node.Attributes{}
|
||||
|
||||
// lock parent before reading treesize or tree time
|
||||
n, unlock, err := node.LockAndReadNode(ctx, p.lookup, n.SpaceID, n.ParentID, "", false, n.SpaceRoot, false)
|
||||
// we deliberately allow reading disabled spaces so that the metadata is always consistent (see https://github.com/opencloud-eu/reva/issues/747)
|
||||
n, unlock, err := node.LockAndReadNode(ctx, p.lookup, n.SpaceID, n.ParentID, "", true, n.SpaceRoot, false)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
+6
@@ -252,6 +252,12 @@ func IsSpaceRoot(ri *storageprovider.ResourceInfo) bool {
|
||||
return f.GetOpaqueId() == s.GetOpaqueId() && f.GetSpaceId() == s.GetSpaceId()
|
||||
}
|
||||
|
||||
// IsProcessing checks if the given resource info is still being processed
|
||||
// (e.g. postprocessing after an upload has not finished yet).
|
||||
func IsProcessing(ri *storageprovider.ResourceInfo) bool {
|
||||
return ReadPlainFromOpaque(ri.GetOpaque(), "status") == "processing"
|
||||
}
|
||||
|
||||
func checkStatusCode(reason, message string, code rpc.Code) error {
|
||||
if code == rpc.Code_CODE_OK {
|
||||
return nil
|
||||
|
||||
+9
-3
@@ -4,10 +4,12 @@ import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// ErrNumWordsNegative is returned when a negative number of words is requested.
|
||||
var ErrNumWordsNegative = fmt.Errorf("number of words cannot be negative")
|
||||
|
||||
// sides is the number of sides on a die.
|
||||
var sides = big.NewInt(6)
|
||||
|
||||
@@ -68,6 +70,10 @@ func NewGenerator(i *GeneratorInput) (*Generator, error) {
|
||||
// non-overlapping words, use a single invocation of the function and split the
|
||||
// resulting string list.
|
||||
func (g *Generator) Generate(numWords int) ([]string, error) {
|
||||
if numWords < 0 {
|
||||
return nil, ErrNumWordsNegative
|
||||
}
|
||||
|
||||
if typ, ok := g.wordList.(WordListNumWordser); ok {
|
||||
if l := typ.NumWords(); numWords > l {
|
||||
return nil, fmt.Errorf("number of requested words (%d) cannot exceed the size of the wordlist (%d)",
|
||||
@@ -182,13 +188,13 @@ func (g *Generator) RollDie() (int, error) {
|
||||
func (g *Generator) RollWord(d int) (int, error) {
|
||||
var final int
|
||||
|
||||
for i := d; i > 0; i-- {
|
||||
for range d {
|
||||
res, err := g.RollDie()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
final += res * int(math.Pow(10, float64(i-1)))
|
||||
final = final*10 + res
|
||||
}
|
||||
|
||||
return final, nil
|
||||
|
||||
+13
-6
@@ -5,14 +5,13 @@
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// log.Printf(res)
|
||||
// log.Print(res)
|
||||
//
|
||||
// Most functions are safe for concurrent use.
|
||||
package password
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
@@ -47,19 +46,23 @@ const (
|
||||
var (
|
||||
// ErrExceedsTotalLength is the error returned with the number of digits and
|
||||
// symbols is greater than the total length.
|
||||
ErrExceedsTotalLength = errors.New("number of digits and symbols must be less than total length")
|
||||
ErrExceedsTotalLength = fmt.Errorf("number of digits and symbols must be less than total length")
|
||||
|
||||
// ErrLettersExceedsAvailable is the error returned with the number of letters
|
||||
// exceeds the number of available letters and repeats are not allowed.
|
||||
ErrLettersExceedsAvailable = errors.New("number of letters exceeds available letters and repeats are not allowed")
|
||||
ErrLettersExceedsAvailable = fmt.Errorf("number of letters exceeds available letters and repeats are not allowed")
|
||||
|
||||
// ErrDigitsExceedsAvailable is the error returned with the number of digits
|
||||
// exceeds the number of available digits and repeats are not allowed.
|
||||
ErrDigitsExceedsAvailable = errors.New("number of digits exceeds available digits and repeats are not allowed")
|
||||
ErrDigitsExceedsAvailable = fmt.Errorf("number of digits exceeds available digits and repeats are not allowed")
|
||||
|
||||
// ErrSymbolsExceedsAvailable is the error returned with the number of symbols
|
||||
// exceeds the number of available symbols and repeats are not allowed.
|
||||
ErrSymbolsExceedsAvailable = errors.New("number of symbols exceeds available symbols and repeats are not allowed")
|
||||
ErrSymbolsExceedsAvailable = fmt.Errorf("number of symbols exceeds available symbols and repeats are not allowed")
|
||||
|
||||
// ErrNegativeInput is the error returned when the number of digits or symbols
|
||||
// is negative.
|
||||
ErrNegativeInput = fmt.Errorf("number of digits and symbols must not be negative")
|
||||
)
|
||||
|
||||
// Generator is the stateful generator which can be used to customize the list
|
||||
@@ -129,6 +132,10 @@ func NewGenerator(i *GeneratorInput) (*Generator, error) {
|
||||
// The algorithm is fast, but it's not designed to be performant; it favors
|
||||
// entropy over speed. This function is safe for concurrent use.
|
||||
func (g *Generator) Generate(length, numDigits, numSymbols int, noUpper, allowRepeat bool) (string, error) {
|
||||
if numDigits < 0 || numSymbols < 0 {
|
||||
return "", ErrNegativeInput
|
||||
}
|
||||
|
||||
letters := g.lowerLetters
|
||||
if !noUpper {
|
||||
letters += g.upperLetters
|
||||
|
||||
Vendored
+12
-12
@@ -93,7 +93,7 @@ github.com/alexedwards/argon2id
|
||||
# github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
|
||||
## explicit
|
||||
github.com/amoghe/go-crypt
|
||||
# github.com/antithesishq/antithesis-sdk-go v0.7.2-default-no-op
|
||||
# github.com/antithesishq/antithesis-sdk-go v0.7.2
|
||||
## explicit; go 1.24.0
|
||||
github.com/antithesishq/antithesis-sdk-go/assert
|
||||
github.com/antithesishq/antithesis-sdk-go/internal
|
||||
@@ -1013,16 +1013,16 @@ github.com/magiconair/properties
|
||||
# github.com/mattermost/xml-roundtrip-validator v0.1.0
|
||||
## explicit; go 1.14
|
||||
github.com/mattermost/xml-roundtrip-validator
|
||||
# github.com/mattn/go-colorable v0.1.14
|
||||
# github.com/mattn/go-colorable v0.1.15
|
||||
## explicit; go 1.18
|
||||
github.com/mattn/go-colorable
|
||||
# github.com/mattn/go-isatty v0.0.20
|
||||
## explicit; go 1.15
|
||||
# github.com/mattn/go-isatty v0.0.22
|
||||
## explicit; go 1.21
|
||||
github.com/mattn/go-isatty
|
||||
# github.com/mattn/go-runewidth v0.0.23
|
||||
# github.com/mattn/go-runewidth v0.0.24
|
||||
## explicit; go 1.20
|
||||
github.com/mattn/go-runewidth
|
||||
# github.com/mattn/go-sqlite3 v1.14.42
|
||||
# github.com/mattn/go-sqlite3 v1.14.49
|
||||
## explicit; go 1.21
|
||||
github.com/mattn/go-sqlite3
|
||||
# github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b
|
||||
@@ -1364,7 +1364,7 @@ github.com/opencloud-eu/icap-client
|
||||
# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d
|
||||
## explicit; go 1.18
|
||||
github.com/opencloud-eu/libre-graph-api-go
|
||||
# github.com/opencloud-eu/reva/v2 v2.47.0
|
||||
# github.com/opencloud-eu/reva/v2 v2.48.0
|
||||
## explicit; go 1.25.8
|
||||
github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace
|
||||
github.com/opencloud-eu/reva/v2/cmd/revad/runtime
|
||||
@@ -1979,11 +1979,11 @@ github.com/sercand/kuberesolver/v5
|
||||
# github.com/sergi/go-diff v1.4.0
|
||||
## explicit; go 1.13
|
||||
github.com/sergi/go-diff/diffmatchpatch
|
||||
# github.com/sethvargo/go-diceware v0.5.0
|
||||
## explicit; go 1.22
|
||||
# github.com/sethvargo/go-diceware v0.6.0
|
||||
## explicit; go 1.25
|
||||
github.com/sethvargo/go-diceware/diceware
|
||||
# github.com/sethvargo/go-password v0.3.1
|
||||
## explicit; go 1.21
|
||||
# github.com/sethvargo/go-password v0.4.0
|
||||
## explicit; go 1.25
|
||||
github.com/sethvargo/go-password/password
|
||||
# github.com/shamaton/msgpack/v2 v2.4.1
|
||||
## explicit; go 1.20
|
||||
@@ -2572,7 +2572,7 @@ google.golang.org/genproto/protobuf/field_mask
|
||||
google.golang.org/genproto/googleapis/api
|
||||
google.golang.org/genproto/googleapis/api/annotations
|
||||
google.golang.org/genproto/googleapis/api/httpbody
|
||||
# google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa
|
||||
# google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0
|
||||
## explicit; go 1.25.0
|
||||
google.golang.org/genproto/googleapis/rpc/errdetails
|
||||
google.golang.org/genproto/googleapis/rpc/status
|
||||
|
||||
Reference in new issue
Block a user