Compare commits

...

46 Commits

Author SHA1 Message Date
Nuno Cruces
7c820ede3c Driver time formatting. 2023-12-07 13:49:33 +00:00
Nuno Cruces
089a0c0670 Pivot virtual table. 2023-12-06 17:49:48 +00:00
Nuno Cruces
8b45cac16b Improved error handling. 2023-12-05 18:17:33 +00:00
Nuno Cruces
06d2ff6752 Optimize VFS find. 2023-12-05 14:11:20 +00:00
Nuno Cruces
987f0f13a2 Test CPUs. 2023-12-04 14:01:25 +00:00
Nuno Cruces
cd40213898 Reuse statement, API. 2023-12-04 13:46:48 +00:00
Nuno Cruces
8a0baedc10 Tests, fixes. 2023-12-02 12:17:18 +00:00
Nuno Cruces
c667a1f469 Declared type. 2023-12-02 12:17:18 +00:00
Nuno Cruces
9c562f5d8b Cache functions. 2023-12-02 12:17:18 +00:00
Nuno Cruces
d862f47d95 Deoptimize. 2023-12-02 12:17:18 +00:00
Nuno Cruces
a9e32fd3f0 Fix compiler crash. 2023-12-02 12:17:18 +00:00
Nuno Cruces
b262f5cd01 Statement virtual table. 2023-12-02 12:17:18 +00:00
Nuno Cruces
4160b9a4bb Simplify tails. 2023-11-30 18:18:27 +00:00
Nuno Cruces
dbaf2d99cd Unprotected values. 2023-11-30 00:29:41 +00:00
Nuno Cruces
3f05115cd7 Virtual table API. 2023-11-29 10:46:11 +00:00
Nuno Cruces
9bf14becaf Reentrant arenas. 2023-11-29 10:46:02 +00:00
Nuno Cruces
997e197f54 VFS tweaks. 2023-11-28 16:38:02 +00:00
Nuno Cruces
b81fe284b6 memdb WAL. 2023-11-28 11:40:04 +00:00
dependabot[bot]
269306c5c8 Bump golang.org/x/sys from 0.14.0 to 0.15.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.14.0 to 0.15.0.
- [Commits](https://github.com/golang/sys/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-28 02:00:06 +00:00
Nuno Cruces
8a18243830 Reproducible builds. 2023-11-28 01:55:26 +00:00
Nuno Cruces
fcd6cc91d8 Skip BOM. 2023-11-27 23:35:43 +00:00
Nuno Cruces
c1838fc0bc Fix encoding issues. 2023-11-27 15:37:53 +00:00
Nuno Cruces
dc0d8236bf Updated dependencies. 2023-11-25 00:39:20 +00:00
Nuno Cruces
ba18facb0d SQLite 3.44.2. 2023-11-25 00:10:38 +00:00
Nuno Cruces
5653efa70e Limits. 2023-11-25 00:10:32 +00:00
Nuno Cruces
1acb95917a Simplify aggregate context. 2023-11-24 15:33:17 +00:00
Nuno Cruces
e31a42fb22 Lines virtual table. 2023-11-23 15:59:24 +00:00
Nuno Cruces
aec69acca9 Update README.md 2023-11-23 13:03:38 +00:00
Nuno Cruces
f2d6bdb8b7 Tests. 2023-11-23 12:53:28 +00:00
Nuno Cruces
9bb01d1f8b CSV virtual table. 2023-11-23 03:36:54 +00:00
Nuno Cruces
83c15f2ddc Virtual table API. 2023-11-22 15:06:39 +00:00
Nuno Cruces
97d4248176 Array extension. 2023-11-21 13:40:55 +00:00
Nuno Cruces
22d1ae0068 Tweaks. 2023-11-21 09:45:47 +00:00
Nuno Cruces
ae1d696cf3 Virtual tables fixes. 2023-11-20 18:12:56 +00:00
Nuno Cruces
5992403052 Virtual tables. 2023-11-20 00:27:12 +00:00
Nuno Cruces
f212b6712d Error handling. 2023-11-18 10:15:18 +00:00
Nuno Cruces
a49cc084f3 Towards virtual tables. 2023-11-17 22:39:00 +00:00
Nuno Cruces
2c2f825bc5 Towards virtual tables. 2023-11-17 19:06:10 +00:00
Nuno Cruces
787086b8c1 Towards virtual tables. 2023-11-17 02:23:10 +00:00
Nuno Cruces
314098addb Towards virtual tables. 2023-11-15 10:57:19 +00:00
Nuno Cruces
4bf8a79c1d Towards virtual tables. 2023-11-14 13:56:27 +00:00
Nuno Cruces
90628ab8aa Text as byte slices. 2023-11-10 13:42:20 +00:00
Nuno Cruces
aa02c14430 Towards virtual tables. 2023-11-10 13:23:14 +00:00
Nuno Cruces
1dc06bff49 Simplify URLs. 2023-11-09 16:35:45 +00:00
Nuno Cruces
4e9173661b Foreign keys activation. 2023-11-09 16:20:44 +00:00
Nuno Cruces
591480cd39 Fix JSON. 2023-11-09 16:16:48 +00:00
108 changed files with 4642 additions and 1034 deletions

40
.github/workflows/cpu.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: CPUs
on:
workflow_dispatch:
jobs:
test-386:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: 'true'
- name: Set up
uses: actions/setup-go@v4
with:
go-version: stable
- name: Test
run: GOARCH=386 go test -v ./...
test-arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: 'true'
- name: Set up
uses: actions/setup-go@v4
with:
go-version: stable
- name: Install QEMU
uses: docker/setup-qemu-action@v3
- name: Test
run: GOARCH=arm64 go test -v ./...

View File

@@ -19,4 +19,4 @@ echo darwin-flock ; GOOS=darwin GOARCH=amd64 go build -tags sqlite3_flock .
echo darwin-nosys ; GOOS=darwin GOARCH=amd64 go build -tags sqlite3_nosys .
echo linux-nosys ; GOOS=linux GOARCH=amd64 go build -tags sqlite3_nosys .
echo windows-nosys ; GOOS=windows GOARCH=amd64 go build -tags sqlite3_nosys .
echo freebsd-nosys ; GOOS=freebsd GOARCH=amd64 go build -tags sqlite3_nosys .
echo freebsd-nosys ; GOOS=freebsd GOARCH=amd64 go build -tags sqlite3_nosys .

View File

@@ -4,13 +4,11 @@ on:
workflow_dispatch:
jobs:
test:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: 'true'
- name: Set up
uses: actions/setup-go@v4

23
.github/workflows/repro.sh vendored Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ "$OSTYPE" == "linux"* ]]; then
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz"
BINARYEN="https://github.com/WebAssembly/binaryen/releases/download/version_116/binaryen-version_116-x86_64-linux.tar.gz"
elif [[ "$OSTYPE" == "darwin"* ]]; then
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-macos.tar.gz"
BINARYEN="https://github.com/WebAssembly/binaryen/releases/download/version_116/binaryen-version_116-x86_64-macos.tar.gz"
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
WASI_SDK="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0.m-mingw.tar.gz"
BINARYEN="https://github.com/WebAssembly/binaryen/releases/download/version_116/binaryen-version_116-x86_64-windows.tar.gz"
fi
# Download tools
mkdir -p tools
[ -d "tools/wasi-sdk"* ] || curl -#L "$WASI_SDK" | tar xzC tools &
[ -d "tools/binaryen-version"* ] || curl -#L "$BINARYEN" | tar xzC tools &
wait
sqlite3/download.sh # Download SQLite
embed/build.sh # Build WASM
git diff --exit-code # Check diffs

24
.github/workflows/repro.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Reproducible build
on:
workflow_dispatch:
jobs:
build:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
lfs: 'true'
- name: Set up
uses: actions/setup-go@v4
with:
go-version: stable
- name: Build
run: .github/workflows/repro.sh

View File

@@ -8,38 +8,62 @@ Go module `github.com/ncruces/go-sqlite3` wraps a [WASM](https://webassembly.org
and uses [wazero](https://wazero.io/) to provide `cgo`-free SQLite bindings.
- [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3)
wraps the [C SQLite API](https://www.sqlite.org/cintro.html)
wraps the [C SQLite API](https://sqlite.org/cintro.html)
([example usage](https://pkg.go.dev/github.com/ncruces/go-sqlite3#example-package)).
- [`github.com/ncruces/go-sqlite3/driver`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver)
provides a [`database/sql`](https://pkg.go.dev/database/sql) driver
([example usage](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-package)).
- [`github.com/ncruces/go-sqlite3/embed`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/embed)
embeds a build of SQLite into your application.
- [`github.com/ncruces/go-sqlite3/ext/blob`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/blob)
simplifies incremental BLOB I/O.
- [`github.com/ncruces/go-sqlite3/ext/stats`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats)
registers [statistics functions](https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html).
- [`github.com/ncruces/go-sqlite3/ext/unicode`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode)
registers Unicode aware functions.
- [`github.com/ncruces/go-sqlite3/vfs`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs)
wraps the [C SQLite VFS API](https://www.sqlite.org/vfs.html) and provides a pure Go implementation.
wraps the [C SQLite VFS API](https://sqlite.org/vfs.html) and provides a pure Go implementation.
- [`github.com/ncruces/go-sqlite3/gormlite`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/gormlite)
provides a [GORM](https://gorm.io) driver.
### Loadable extensions
- [`github.com/ncruces/go-sqlite3/ext/array`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/blob)
provides the [`array`](https://sqlite.org/carray.html) table-valued function.
- [`github.com/ncruces/go-sqlite3/ext/blob`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/blob)
simplifies [incremental BLOB I/O](https://sqlite.org/c3ref/blob_open.html).
- [`github.com/ncruces/go-sqlite3/ext/csv`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/csv)
reads [comma-separated values](https://sqlite.org/csv.html).
- [`github.com/ncruces/go-sqlite3/ext/lines`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/lines)
reads files [line-by-line](https://github.com/asg017/sqlite-lines).
- [`github.com/ncruces/go-sqlite3/ext/pivot`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/pivot)
creates [pivot tables](https://github.com/jakethaw/pivot_vtab).
- [`github.com/ncruces/go-sqlite3/ext/statement`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/statement)
creates [table-valued functions with SQL](https://github.com/0x09/sqlite-statement-vtab).
- [`github.com/ncruces/go-sqlite3/ext/stats`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats)
provides [statistics functions](https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html).
- [`github.com/ncruces/go-sqlite3/ext/unicode`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode)
provides [Unicode aware](https://sqlite.org/src/dir/ext/icu) functions.
- [`github.com/ncruces/go-sqlite3/vfs/memdb`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb)
implements an in-memory VFS.
- [`github.com/ncruces/go-sqlite3/vfs/readervfs`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/readervfs)
implements a VFS for immutable databases.
- [`github.com/ncruces/go-sqlite3/gormlite`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/gormlite)
provides a [GORM](https://gorm.io) driver.
### Advanced features
- [x] [incremental BLOB I/O](https://sqlite.org/c3ref/blob_open.html)
- [x] [nested transactions](https://sqlite.org/lang_savepoint.html)
- [x] [custom functions](https://sqlite.org/c3ref/create_function.html)
- [x] [virtual tables](https://sqlite.org/vtab.html)
- [x] [custom VFSes](https://sqlite.org/vfs.html)
- [x] [online backup](https://sqlite.org/backup.html)
- [x] [JSON support](https://sqlite.org/json1.html)
- [x] [Unicode support](https://sqlite.org/src/dir/ext/icu)
### Caveats
This module replaces the SQLite [OS Interface](https://www.sqlite.org/vfs.html)
This module replaces the SQLite [OS Interface](https://sqlite.org/vfs.html)
(aka VFS) with a [pure Go](vfs/) implementation.
This has benefits, but also comes with some drawbacks.
#### Write-Ahead Logging
Because WASM does not support shared memory,
[WAL](https://www.sqlite.org/wal.html) support is [limited](https://www.sqlite.org/wal.html#noshm).
[WAL](https://sqlite.org/wal.html) support is [limited](https://sqlite.org/wal.html#noshm).
To work around this limitation, SQLite is [patched](sqlite3/locking_mode.patch)
to always use `EXCLUSIVE` locking mode for WAL databases.
@@ -52,7 +76,7 @@ with WAL mode databases you should disable connection pooling by calling
#### File Locking
POSIX advisory locks, which SQLite uses on Unix, are
[broken by design](https://www.sqlite.org/src/artifact/2e8b12?ln=1073-1161).
[broken by design](https://sqlite.org/src/artifact/2e8b12?ln=1073-1161).
On Linux, macOS and illumos, this module uses
[OFD locks](https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html)
@@ -67,7 +91,7 @@ On Windows, this module uses `LockFile`, `LockFileEx`, and `UnlockFile`,
like SQLite.
On all other platforms, file locking is not supported, and you must use
[`nolock=1`](https://www.sqlite.org/uri.html#urinolock)
[`nolock=1`](https://sqlite.org/uri.html#urinolock)
to open database files.
To use the [`database/sql`](https://pkg.go.dev/database/sql) driver
with `nolock=1` you must disable connection pooling by calling
@@ -81,22 +105,6 @@ on Linux, macOS, Windows and FreeBSD.
Performance is tested by running
[speedtest1](https://github.com/sqlite/sqlite/blob/master/test/speedtest1.c).
### Roadmap
- [ ] advanced SQLite features
- [x] custom functions
- [x] nested transactions
- [x] incremental BLOB I/O
- [x] online backup
- [x] JSON support
- [ ] virtual tables
- [ ] session extension
- [ ] custom VFSes
- [x] custom VFS API
- [x] in-memory VFS
- [x] read-only VFS, wrapping an [`io.ReaderAt`](https://pkg.go.dev/io#ReaderAt)
- [ ] cloud-based VFS, based on [Cloud Backed SQLite](https://sqlite.org/cloudsqlite/doc/trunk/www/index.wiki)
### Alternatives
- [`modernc.org/sqlite`](https://pkg.go.dev/modernc.org/sqlite)

View File

@@ -2,7 +2,7 @@ package sqlite3
// Backup is an handle to an ongoing online backup operation.
//
// https://www.sqlite.org/c3ref/backup.html
// https://sqlite.org/c3ref/backup.html
type Backup struct {
c *Conn
handle uint32
@@ -15,7 +15,7 @@ type Backup struct {
// and blocks until the entire backup is complete.
// Use [Conn.BackupInit] for incremental backup.
//
// https://www.sqlite.org/backup.html
// https://sqlite.org/backup.html
func (src *Conn) Backup(srcDB, dstURI string) error {
b, err := src.BackupInit(srcDB, dstURI)
if err != nil {
@@ -31,7 +31,7 @@ func (src *Conn) Backup(srcDB, dstURI string) error {
// Restore opens the SQLite database file srcURI,
// and blocks until the entire restore is complete.
//
// https://www.sqlite.org/backup.html
// https://sqlite.org/backup.html
func (dst *Conn) Restore(dstDB, srcURI string) error {
src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI)
if err != nil {
@@ -52,7 +52,7 @@ func (dst *Conn) Restore(dstDB, srcURI string) error {
// then initializes a backup that copies the contents of srcDB on the src connection
// to the "main" database in dstURI.
//
// https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) {
dst, err := src.openDB(dstURI, OPEN_READWRITE|OPEN_CREATE|OPEN_URI)
if err != nil {
@@ -62,7 +62,7 @@ func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) {
}
func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string) (*Backup, error) {
defer c.arena.reset()
defer c.arena.mark()()
dstPtr := c.arena.string(dstName)
srcPtr := c.arena.string(srcName)
@@ -71,12 +71,12 @@ func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string
other = src
}
r := c.call(c.api.backupInit,
r := c.call("sqlite3_backup_init",
uint64(dst), uint64(dstPtr),
uint64(src), uint64(srcPtr))
if r == 0 {
defer c.closeDB(other)
r = c.call(c.api.errcode, uint64(dst))
r = c.call("sqlite3_errcode", uint64(dst))
return nil, c.sqlite.error(r, dst)
}
@@ -91,13 +91,13 @@ func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string
//
// It is safe to close a nil, zero or closed Backup.
//
// https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
func (b *Backup) Close() error {
if b == nil || b.handle == 0 {
return nil
}
r := b.c.call(b.c.api.backupFinish, uint64(b.handle))
r := b.c.call("sqlite3_backup_finish", uint64(b.handle))
b.c.closeDB(b.otherc)
b.handle = 0
return b.c.error(r)
@@ -106,9 +106,9 @@ func (b *Backup) Close() error {
// Step copies up to nPage pages between the source and destination databases.
// If nPage is negative, all remaining source pages are copied.
//
// https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
func (b *Backup) Step(nPage int) (done bool, err error) {
r := b.c.call(b.c.api.backupStep, uint64(b.handle), uint64(nPage))
r := b.c.call("sqlite3_backup_step", uint64(b.handle), uint64(nPage))
if r == _DONE {
return true, nil
}
@@ -118,17 +118,17 @@ func (b *Backup) Step(nPage int) (done bool, err error) {
// Remaining returns the number of pages still to be backed up
// at the conclusion of the most recent [Backup.Step].
//
// https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
func (b *Backup) Remaining() int {
r := b.c.call(b.c.api.backupRemaining, uint64(b.handle))
r := b.c.call("sqlite3_backup_remaining", uint64(b.handle))
return int(r)
}
// PageCount returns the total number of pages in the source database
// at the conclusion of the most recent [Backup.Step].
//
// https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
func (b *Backup) PageCount() int {
r := b.c.call(b.c.api.backupPageCount, uint64(b.handle))
r := b.c.call("sqlite3_backup_pagecount", uint64(b.handle))
return int(r)
}

50
blob.go
View File

@@ -15,7 +15,7 @@ type ZeroBlob int64
//
// It implements [io.ReadWriteSeeker] for incremental BLOB I/O.
//
// https://www.sqlite.org/c3ref/blob.html
// https://sqlite.org/c3ref/blob.html
type Blob struct {
c *Conn
bytes int64
@@ -27,10 +27,10 @@ var _ io.ReadWriteSeeker = &Blob{}
// OpenBlob opens a BLOB for incremental I/O.
//
// https://www.sqlite.org/c3ref/blob_open.html
// https://sqlite.org/c3ref/blob_open.html
func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob, error) {
c.checkInterrupt()
defer c.arena.reset()
defer c.arena.mark()()
blobPtr := c.arena.new(ptrlen)
dbPtr := c.arena.string(db)
tablePtr := c.arena.string(table)
@@ -41,7 +41,7 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
flags = 1
}
r := c.call(c.api.blobOpen, uint64(c.handle),
r := c.call("sqlite3_blob_open", uint64(c.handle),
uint64(dbPtr), uint64(tablePtr), uint64(columnPtr),
uint64(row), flags, uint64(blobPtr))
@@ -51,7 +51,7 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
blob := Blob{c: c}
blob.handle = util.ReadUint32(c.mod, blobPtr)
blob.bytes = int64(c.call(c.api.blobBytes, uint64(blob.handle)))
blob.bytes = int64(c.call("sqlite3_blob_bytes", uint64(blob.handle)))
return &blob, nil
}
@@ -59,13 +59,13 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
//
// It is safe to close a nil, zero or closed Blob.
//
// https://www.sqlite.org/c3ref/blob_close.html
// https://sqlite.org/c3ref/blob_close.html
func (b *Blob) Close() error {
if b == nil || b.handle == 0 {
return nil
}
r := b.c.call(b.c.api.blobClose, uint64(b.handle))
r := b.c.call("sqlite3_blob_close", uint64(b.handle))
b.handle = 0
return b.c.error(r)
@@ -73,14 +73,14 @@ func (b *Blob) Close() error {
// Size returns the size of the BLOB in bytes.
//
// https://www.sqlite.org/c3ref/blob_bytes.html
// https://sqlite.org/c3ref/blob_bytes.html
func (b *Blob) Size() int64 {
return b.bytes
}
// Read implements the [io.Reader] interface.
//
// https://www.sqlite.org/c3ref/blob_read.html
// https://sqlite.org/c3ref/blob_read.html
func (b *Blob) Read(p []byte) (n int, err error) {
if b.offset >= b.bytes {
return 0, io.EOF
@@ -92,10 +92,10 @@ func (b *Blob) Read(p []byte) (n int, err error) {
want = avail
}
defer b.c.arena.reset()
defer b.c.arena.mark()()
ptr := b.c.arena.new(uint64(want))
r := b.c.call(b.c.api.blobRead, uint64(b.handle),
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
uint64(ptr), uint64(want), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -112,7 +112,7 @@ func (b *Blob) Read(p []byte) (n int, err error) {
// WriteTo implements the [io.WriterTo] interface.
//
// https://www.sqlite.org/c3ref/blob_read.html
// https://sqlite.org/c3ref/blob_read.html
func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
if b.offset >= b.bytes {
return 0, nil
@@ -124,11 +124,11 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
want = avail
}
ptr := b.c.new(uint64(want))
defer b.c.free(ptr)
defer b.c.arena.mark()()
ptr := b.c.arena.new(uint64(want))
for want > 0 {
r := b.c.call(b.c.api.blobRead, uint64(b.handle),
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
uint64(ptr), uint64(want), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -156,12 +156,12 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
// Write implements the [io.Writer] interface.
//
// https://www.sqlite.org/c3ref/blob_write.html
// https://sqlite.org/c3ref/blob_write.html
func (b *Blob) Write(p []byte) (n int, err error) {
defer b.c.arena.reset()
defer b.c.arena.mark()()
ptr := b.c.arena.bytes(p)
r := b.c.call(b.c.api.blobWrite, uint64(b.handle),
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
uint64(ptr), uint64(len(p)), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -173,7 +173,7 @@ func (b *Blob) Write(p []byte) (n int, err error) {
// ReadFrom implements the [io.ReaderFrom] interface.
//
// https://www.sqlite.org/c3ref/blob_write.html
// https://sqlite.org/c3ref/blob_write.html
func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
want := int64(1024 * 1024)
avail := b.bytes - b.offset
@@ -187,14 +187,14 @@ func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
want = 1
}
ptr := b.c.new(uint64(want))
defer b.c.free(ptr)
defer b.c.arena.mark()()
ptr := b.c.arena.new(uint64(want))
for {
mem := util.View(b.c.mod, ptr, uint64(want))
m, err := r.Read(mem[:want])
if m > 0 {
r := b.c.call(b.c.api.blobWrite, uint64(b.handle),
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
uint64(ptr), uint64(m), uint64(b.offset))
err := b.c.error(r)
if err != nil {
@@ -241,10 +241,10 @@ func (b *Blob) Seek(offset int64, whence int) (int64, error) {
// Reopen moves a BLOB handle to a new row of the same database table.
//
// https://www.sqlite.org/c3ref/blob_reopen.html
// https://sqlite.org/c3ref/blob_reopen.html
func (b *Blob) Reopen(row int64) error {
err := b.c.error(b.c.call(b.c.api.blobReopen, uint64(b.handle), uint64(row)))
b.bytes = int64(b.c.call(b.c.api.blobBytes, uint64(b.handle)))
err := b.c.error(b.c.call("sqlite3_blob_reopen", uint64(b.handle), uint64(row)))
b.bytes = int64(b.c.call("sqlite3_blob_bytes", uint64(b.handle)))
b.offset = 0
return err
}

74
conn.go
View File

@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net/url"
"runtime"
"strings"
"github.com/ncruces/go-sqlite3/internal/util"
@@ -15,7 +14,7 @@ import (
// Conn is a database connection handle.
// A Conn is not safe for concurrent use by multiple goroutines.
//
// https://www.sqlite.org/c3ref/sqlite3.html
// https://sqlite.org/c3ref/sqlite3.html
type Conn struct {
*sqlite
@@ -38,7 +37,7 @@ func Open(filename string) (*Conn, error) {
//
// sqlite3.Open("file:demo.db?_pragma=busy_timeout(10000)")
//
// https://www.sqlite.org/c3ref/open.html
// https://sqlite.org/c3ref/open.html
func OpenFlags(filename string, flags OpenFlag) (*Conn, error) {
if flags&(OPEN_READONLY|OPEN_READWRITE|OPEN_CREATE) == 0 {
flags |= OPEN_READWRITE | OPEN_CREATE
@@ -56,8 +55,6 @@ func newConn(filename string, flags OpenFlag) (conn *Conn, err error) {
defer func() {
if conn == nil {
sqlite.close()
} else {
runtime.SetFinalizer(conn, util.Finalizer[Conn](3))
}
}()
@@ -72,12 +69,12 @@ func newConn(filename string, flags OpenFlag) (conn *Conn, err error) {
}
func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
defer c.arena.reset()
defer c.arena.mark()()
connPtr := c.arena.new(ptrlen)
namePtr := c.arena.string(filename)
flags |= OPEN_EXRESCODE
r := c.call(c.api.open, uint64(namePtr), uint64(connPtr), uint64(flags), 0)
r := c.call("sqlite3_open_v2", uint64(namePtr), uint64(connPtr), uint64(flags), 0)
handle := util.ReadUint32(c.mod, connPtr)
if err := c.sqlite.error(r, handle); err != nil {
@@ -92,13 +89,12 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
for _, p := range query["_pragma"] {
pragmas.WriteString(`PRAGMA `)
pragmas.WriteString(p)
pragmas.WriteByte(';')
pragmas.WriteString(`;`)
}
}
c.arena.reset()
pragmaPtr := c.arena.string(pragmas.String())
r := c.call(c.api.exec, uint64(handle), uint64(pragmaPtr), 0, 0, 0)
r := c.call("sqlite3_exec", uint64(handle), uint64(pragmaPtr), 0, 0, 0)
if err := c.sqlite.error(r, handle, pragmas.String()); err != nil {
if errors.Is(err, ERROR) {
err = fmt.Errorf("sqlite3: invalid _pragma: %w", err)
@@ -112,7 +108,7 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
}
func (c *Conn) closeDB(handle uint32) {
r := c.call(c.api.closeZombie, uint64(handle))
r := c.call("sqlite3_close_v2", uint64(handle))
if err := c.sqlite.error(r, handle); err != nil {
panic(err)
}
@@ -126,7 +122,7 @@ func (c *Conn) closeDB(handle uint32) {
//
// It is safe to close a nil, zero or closed Conn.
//
// https://www.sqlite.org/c3ref/close.html
// https://sqlite.org/c3ref/close.html
func (c *Conn) Close() error {
if c == nil || c.handle == 0 {
return nil
@@ -135,27 +131,26 @@ func (c *Conn) Close() error {
c.pending.Close()
c.pending = nil
r := c.call(c.api.close, uint64(c.handle))
r := c.call("sqlite3_close", uint64(c.handle))
if err := c.error(r); err != nil {
return err
}
c.handle = 0
runtime.SetFinalizer(c, nil)
return c.close()
}
// Exec is a convenience function that allows an application to run
// multiple statements of SQL without having to use a lot of code.
//
// https://www.sqlite.org/c3ref/exec.html
// https://sqlite.org/c3ref/exec.html
func (c *Conn) Exec(sql string) error {
c.checkInterrupt()
defer c.arena.reset()
defer c.arena.mark()()
sqlPtr := c.arena.string(sql)
r := c.call(c.api.exec, uint64(c.handle), uint64(sqlPtr), 0, 0, 0)
return c.error(r)
r := c.call("sqlite3_exec", uint64(c.handle), uint64(sqlPtr), 0, 0, 0)
return c.error(r, sql)
}
// Prepare calls [Conn.PrepareFlags] with no flags.
@@ -168,25 +163,26 @@ func (c *Conn) Prepare(sql string) (stmt *Stmt, tail string, err error) {
// If the input text contains no SQL (if the input is an empty string or a comment),
// both stmt and err will be nil.
//
// https://www.sqlite.org/c3ref/prepare.html
// https://sqlite.org/c3ref/prepare.html
func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail string, err error) {
if emptyStatement(sql) {
return nil, "", nil
if len(sql) > _MAX_LENGTH {
return nil, "", TOOBIG
}
defer c.arena.reset()
defer c.arena.mark()()
stmtPtr := c.arena.new(ptrlen)
tailPtr := c.arena.new(ptrlen)
sqlPtr := c.arena.string(sql)
r := c.call(c.api.prepare, uint64(c.handle),
r := c.call("sqlite3_prepare_v3", uint64(c.handle),
uint64(sqlPtr), uint64(len(sql)+1), uint64(flags),
uint64(stmtPtr), uint64(tailPtr))
stmt = &Stmt{c: c}
stmt.handle = util.ReadUint32(c.mod, stmtPtr)
i := util.ReadUint32(c.mod, tailPtr)
tail = sql[i-sqlPtr:]
if sql := sql[util.ReadUint32(c.mod, tailPtr)-sqlPtr:]; sql != "" {
tail = sql
}
if err := c.error(r, sql); err != nil {
return nil, "", err
@@ -194,23 +190,23 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
if stmt.handle == 0 {
return nil, "", nil
}
return
return stmt, tail, nil
}
// GetAutocommit tests the connection for auto-commit mode.
//
// https://www.sqlite.org/c3ref/get_autocommit.html
// https://sqlite.org/c3ref/get_autocommit.html
func (c *Conn) GetAutocommit() bool {
r := c.call(c.api.autocommit, uint64(c.handle))
r := c.call("sqlite3_get_autocommit", uint64(c.handle))
return r != 0
}
// LastInsertRowID returns the rowid of the most recent successful INSERT
// on the database connection.
//
// https://www.sqlite.org/c3ref/last_insert_rowid.html
// https://sqlite.org/c3ref/last_insert_rowid.html
func (c *Conn) LastInsertRowID() int64 {
r := c.call(c.api.lastRowid, uint64(c.handle))
r := c.call("sqlite3_last_insert_rowid", uint64(c.handle))
return int64(r)
}
@@ -218,9 +214,9 @@ func (c *Conn) LastInsertRowID() int64 {
// by the most recently completed INSERT, UPDATE or DELETE statement
// on the database connection.
//
// https://www.sqlite.org/c3ref/changes.html
// https://sqlite.org/c3ref/changes.html
func (c *Conn) Changes() int64 {
r := c.call(c.api.changes, uint64(c.handle))
r := c.call("sqlite3_changes64", uint64(c.handle))
return int64(r)
}
@@ -237,7 +233,7 @@ func (c *Conn) Changes() int64 {
//
// SetInterrupt returns the old context assigned to the connection.
//
// https://www.sqlite.org/c3ref/interrupt.html
// https://sqlite.org/c3ref/interrupt.html
func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
// Is it the same context?
if ctx == c.interrupt {
@@ -256,16 +252,16 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
c.interrupt = ctx
// Remove the handler if the context can't be canceled.
if ctx == nil || ctx.Done() == nil {
c.call(c.api.progressHandler, uint64(c.handle), 0)
c.call("sqlite3_progress_handler_go", uint64(c.handle), 0)
return old
}
c.pending.Step()
c.call(c.api.progressHandler, uint64(c.handle), 100)
c.call("sqlite3_progress_handler_go", uint64(c.handle), 100)
return old
}
func callbackProgress(ctx context.Context, mod api.Module, _ uint32) uint32 {
func progressCallback(ctx context.Context, mod api.Module, _ uint32) uint32 {
if c, ok := ctx.Value(connKey{}).(*Conn); ok {
if c.interrupt != nil && c.interrupt.Err() != nil {
return 1
@@ -276,13 +272,13 @@ func callbackProgress(ctx context.Context, mod api.Module, _ uint32) uint32 {
func (c *Conn) checkInterrupt() {
if c.interrupt != nil && c.interrupt.Err() != nil {
c.call(c.api.interrupt, uint64(c.handle))
c.call("sqlite3_interrupt", uint64(c.handle))
}
}
// Pragma executes a PRAGMA statement and returns any results.
//
// https://www.sqlite.org/pragma.html
// https://sqlite.org/pragma.html
func (c *Conn) Pragma(str string) ([]string, error) {
stmt, _, err := c.Prepare(`PRAGMA ` + str)
if err != nil {
@@ -305,7 +301,7 @@ func (c *Conn) error(rc uint64, sql ...string) error {
//
// It can be used to access SQLite features like [online backup].
//
// [online backup]: https://www.sqlite.org/backup.html
// [online backup]: https://sqlite.org/backup.html
type DriverConn interface {
Raw() *Conn
}

View File

@@ -9,8 +9,9 @@ const (
_UTF8 = 1
_MAX_STRING = 512 // Used for short strings: names, error messages…
_MAX_NAME = 512 // Used for short strings: names, error messages…
_MAX_LENGTH = 1e9
_MAX_SQL_LENGTH = 1e9
_MAX_ALLOCATION_SIZE = 0x7ffffeff
ptrlen = 4
@@ -18,7 +19,7 @@ const (
// ErrorCode is a result code that [Error.Code] might return.
//
// https://www.sqlite.org/rescode.html
// https://sqlite.org/rescode.html
type ErrorCode uint8
const (
@@ -54,7 +55,7 @@ const (
// ExtendedErrorCode is a result code that [Error.ExtendedCode] might return.
//
// https://www.sqlite.org/rescode.html
// https://sqlite.org/rescode.html
type (
ExtendedErrorCode uint16
xErrorCode = ExtendedErrorCode
@@ -140,7 +141,7 @@ const (
// OpenFlag is a flag for the [OpenFlags] function.
//
// https://www.sqlite.org/c3ref/c_open_autoproxy.html
// https://sqlite.org/c3ref/c_open_autoproxy.html
type OpenFlag uint32
const (
@@ -159,7 +160,7 @@ const (
// PrepareFlag is a flag that can be passed to [Conn.PrepareFlags].
//
// https://www.sqlite.org/c3ref/c_prepare_normalize.html
// https://sqlite.org/c3ref/c_prepare_normalize.html
type PrepareFlag uint32
const (
@@ -168,9 +169,10 @@ const (
PREPARE_NO_VTAB PrepareFlag = 0x04
)
// FunctionFlag is a flag that can be passed to [Conn.PrepareFlags].
// FunctionFlag is a flag that can be passed to
// [Conn.CreateFunction] and [Conn.CreateWindowFunction].
//
// https://www.sqlite.org/c3ref/c_deterministic.html
// https://sqlite.org/c3ref/c_deterministic.html
type FunctionFlag uint32
const (
@@ -180,9 +182,26 @@ const (
INNOCUOUS FunctionFlag = 0x000200000
)
// StmtStatus name counter values associated with the [Stmt.Status] method.
//
// https://sqlite.org/c3ref/c_stmtstatus_counter.html
type StmtStatus uint32
const (
STMTSTATUS_FULLSCAN_STEP StmtStatus = 1
STMTSTATUS_SORT StmtStatus = 2
STMTSTATUS_AUTOINDEX StmtStatus = 3
STMTSTATUS_VM_STEP StmtStatus = 4
STMTSTATUS_REPREPARE StmtStatus = 5
STMTSTATUS_RUN StmtStatus = 6
STMTSTATUS_FILTER_MISS StmtStatus = 7
STMTSTATUS_FILTER_HIT StmtStatus = 8
STMTSTATUS_MEMUSED StmtStatus = 99
)
// Datatype is a fundamental datatype of SQLite.
//
// https://www.sqlite.org/c3ref/c_blob.html
// https://sqlite.org/c3ref/c_blob.html
type Datatype uint32
const (

View File

@@ -12,7 +12,7 @@ import (
// Context is the context in which an SQL function executes.
// An SQLite [Context] is in no way related to a Go [context.Context].
//
// https://www.sqlite.org/c3ref/context.html
// https://sqlite.org/c3ref/context.html
type Context struct {
c *Conn
handle uint32
@@ -29,17 +29,17 @@ func (ctx Context) Conn() *Conn {
// SetAuxData saves metadata for argument n of the function.
//
// https://www.sqlite.org/c3ref/get_auxdata.html
// https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) SetAuxData(n int, data any) {
ptr := util.AddHandle(ctx.c.ctx, data)
ctx.c.call(ctx.c.api.setAuxData, uint64(ctx.handle), uint64(n), uint64(ptr))
ctx.c.call("sqlite3_set_auxdata_go", uint64(ctx.handle), uint64(n), uint64(ptr))
}
// GetAuxData returns metadata for argument n of the function.
//
// https://www.sqlite.org/c3ref/get_auxdata.html
// https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) GetAuxData(n int) any {
ptr := uint32(ctx.c.call(ctx.c.api.getAuxData, uint64(ctx.handle), uint64(n)))
ptr := uint32(ctx.c.call("sqlite3_get_auxdata", uint64(ctx.handle), uint64(n)))
return util.GetHandle(ctx.c.ctx, ptr)
}
@@ -47,7 +47,7 @@ func (ctx Context) GetAuxData(n int) any {
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are stored as integers 0 (false) and 1 (true).
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultBool(value bool) {
var i int64
if value {
@@ -58,67 +58,77 @@ func (ctx Context) ResultBool(value bool) {
// ResultInt sets the result of the function to an int.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultInt(value int) {
ctx.ResultInt64(int64(value))
}
// ResultInt64 sets the result of the function to an int64.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultInt64(value int64) {
ctx.c.call(ctx.c.api.resultInteger,
ctx.c.call("sqlite3_result_int64",
uint64(ctx.handle), uint64(value))
}
// ResultFloat sets the result of the function to a float64.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultFloat(value float64) {
ctx.c.call(ctx.c.api.resultFloat,
ctx.c.call("sqlite3_result_double",
uint64(ctx.handle), math.Float64bits(value))
}
// ResultText sets the result of the function to a string.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultText(value string) {
ptr := ctx.c.newString(value)
ctx.c.call(ctx.c.api.resultText,
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.api.destructor), _UTF8)
uint64(ctx.c.freer), _UTF8)
}
// ResultRawText sets the text result of the function to a []byte.
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultRawText(value []byte) {
ptr := ctx.c.newBytes(value)
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.freer), _UTF8)
}
// ResultBlob sets the result of the function to a []byte.
// Returning a nil slice is the same as calling [Context.ResultNull].
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultBlob(value []byte) {
ptr := ctx.c.newBytes(value)
ctx.c.call(ctx.c.api.resultBlob,
ctx.c.call("sqlite3_result_blob64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.api.destructor))
uint64(ctx.c.freer))
}
// BindZeroBlob sets the result of the function to a zero-filled, length n BLOB.
// ResultZeroBlob sets the result of the function to a zero-filled, length n BLOB.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultZeroBlob(n int64) {
ctx.c.call(ctx.c.api.resultZeroBlob,
ctx.c.call("sqlite3_result_zeroblob64",
uint64(ctx.handle), uint64(n))
}
// ResultNull sets the result of the function to NULL.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultNull() {
ctx.c.call(ctx.c.api.resultNull,
ctx.c.call("sqlite3_result_null",
uint64(ctx.handle))
}
// ResultTime sets the result of the function to a [time.Time].
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultTime(value time.Time, format TimeFormat) {
if format == TimeFormatDefault {
ctx.resultRFC3339Nano(value)
@@ -143,77 +153,68 @@ func (ctx Context) resultRFC3339Nano(value time.Time) {
buf := util.View(ctx.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
ctx.c.call(ctx.c.api.resultText,
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(buf)),
uint64(ctx.c.api.destructor), _UTF8)
uint64(ctx.c.freer), _UTF8)
}
// ResultPointer sets the result of the function to NULL, just like [Context.ResultNull],
// except that it also associates ptr with that NULL value such that it can be retrieved
// within an application-defined SQL function using [Value.Pointer].
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultPointer(ptr any) {
valPtr := util.AddHandle(ctx.c.ctx, ptr)
ctx.c.call(ctx.c.api.resultPointer, uint64(valPtr))
ctx.c.call("sqlite3_result_pointer_go", uint64(valPtr))
}
// ResultJSON sets the result of the function to the JSON encoding of value.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultJSON(value any) {
data, err := json.Marshal(value)
if err != nil {
ctx.ResultError(err)
return
}
ptr := ctx.c.newBytes(data)
ctx.c.call(ctx.c.api.resultText,
uint64(ctx.handle), uint64(ptr), uint64(len(data)),
uint64(ctx.c.api.destructor))
ctx.ResultRawText(data)
}
// ResultValue sets the result of the function a copy of [Value].
// ResultValue sets the result of the function to a copy of [Value].
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultValue(value Value) {
if value.sqlite != ctx.c.sqlite {
ctx.ResultError(MISUSE)
return
}
ctx.c.call(ctx.c.api.resultValue,
ctx.c.call("sqlite3_result_value",
uint64(ctx.handle), uint64(value.handle))
}
// ResultError sets the result of the function an error.
//
// https://www.sqlite.org/c3ref/result_blob.html
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultError(err error) {
if errors.Is(err, NOMEM) {
ctx.c.call(ctx.c.api.resultErrorMem, uint64(ctx.handle))
ctx.c.call("sqlite3_result_error_nomem", uint64(ctx.handle))
return
}
if errors.Is(err, TOOBIG) {
ctx.c.call(ctx.c.api.resultErrorBig, uint64(ctx.handle))
ctx.c.call("sqlite3_result_error_toobig", uint64(ctx.handle))
return
}
str := err.Error()
ptr := ctx.c.newString(str)
ctx.c.call(ctx.c.api.resultError,
uint64(ctx.handle), uint64(ptr), uint64(len(str)))
ctx.c.free(ptr)
var code uint64
var ecode ErrorCode
var xcode xErrorCode
switch {
case errors.As(err, &xcode):
code = uint64(xcode)
case errors.As(err, &ecode):
code = uint64(ecode)
msg, code := errorCode(err, _OK)
if msg != "" {
defer ctx.c.arena.mark()()
ptr := ctx.c.arena.string(msg)
ctx.c.call("sqlite3_result_error",
uint64(ctx.handle), uint64(ptr), uint64(len(msg)))
}
if code != 0 {
ctx.c.call(ctx.c.api.resultErrorCode,
uint64(ctx.handle), code)
if code != _OK {
ctx.c.call("sqlite3_result_error_code",
uint64(ctx.handle), uint64(code))
}
}

View File

@@ -12,6 +12,18 @@
//
// sql.Open("sqlite3", "file:demo.db?_txlock=immediate")
//
// Possible values are: "deferred", "immediate", "exclusive".
// A [read-only] transaction is always "deferred", regardless of "_txlock".
//
// The time encoding/decoding format can be specified using "_timefmt":
//
// sql.Open("sqlite3", "file:demo.db?_timefmt=sqlite")
//
// Possible values are: "auto" (the default), "sqlite", "rfc3339";
// "auto" encodes as RFC 3339 and decodes any [format] supported by SQLite;
// "sqlite" encodes as SQLite and decodes any [format] supported by SQLite;
// "rfc3339" encodes and decodes RFC 3339 only.
//
// [PRAGMA] statements can be specified using "_pragma":
//
// sql.Open("sqlite3", "file:demo.db?_pragma=busy_timeout(10000)")
@@ -21,16 +33,17 @@
// Order matters:
// busy timeout and locking mode should be the first PRAGMAs set, in that order.
//
// [URI]: https://www.sqlite.org/uri.html
// [PRAGMA]: https://www.sqlite.org/pragma.html
// [TRANSACTION]: https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
// [URI]: https://sqlite.org/uri.html
// [PRAGMA]: https://sqlite.org/pragma.html
// [format]: https://sqlite.org/lang_datefunc.html#time_values
// [TRANSACTION]: https://sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
// [read-only]: https://pkg.go.dev/database/sql#TxOptions
package driver
import (
"context"
"database/sql"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"io"
@@ -44,7 +57,7 @@ import (
// This variable can be replaced with -ldflags:
//
// go build -ldflags="-X github.com/ncruces/go-sqlite3.driverName=sqlite"
// go build -ldflags="-X github.com/ncruces/go-sqlite3/driver.driverName=sqlite"
var driverName = "sqlite3"
func init() {
@@ -82,23 +95,52 @@ func (sqlite) OpenConnector(name string) (driver.Connector, error) {
func newConnector(name string, init func(*sqlite3.Conn) error) (*connector, error) {
c := connector{name: name, init: init}
var txlock, timefmt string
if strings.HasPrefix(name, "file:") {
if _, after, ok := strings.Cut(name, "?"); ok {
query, err := url.ParseQuery(after)
if err != nil {
return nil, err
}
c.txlock = query.Get("_txlock")
c.pragmas = len(query["_pragma"]) > 0
txlock = query.Get("_txlock")
timefmt = query.Get("_timefmt")
c.pragmas = query.Has("_pragma")
}
}
switch txlock {
case "":
c.txBegin = "BEGIN"
case "deferred", "immediate", "exclusive":
c.txBegin = "BEGIN " + txlock
default:
return nil, fmt.Errorf("sqlite3: invalid _txlock: %s", txlock)
}
switch timefmt {
case "":
c.tmRead = sqlite3.TimeFormatAuto
c.tmWrite = sqlite3.TimeFormatDefault
case "sqlite":
c.tmRead = sqlite3.TimeFormatAuto
c.tmWrite = sqlite3.TimeFormat3
case "rfc3339":
c.tmRead = sqlite3.TimeFormatDefault
c.tmWrite = sqlite3.TimeFormatDefault
default:
c.tmRead = sqlite3.TimeFormat(timefmt)
c.tmWrite = sqlite3.TimeFormat(timefmt)
}
return &c, nil
}
type connector struct {
init func(*sqlite3.Conn) error
name string
txlock string
txBegin string
tmRead sqlite3.TimeFormat
tmWrite sqlite3.TimeFormat
pragmas bool
}
@@ -107,7 +149,12 @@ func (n *connector) Driver() driver.Driver {
}
func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
var c conn
c := &conn{
txBegin: n.txBegin,
tmRead: n.tmRead,
tmWrite: n.tmWrite,
}
c.Conn, err = sqlite3.Open(n.name)
if err != nil {
return nil, err
@@ -121,14 +168,6 @@ func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
old := c.Conn.SetInterrupt(ctx)
defer c.Conn.SetInterrupt(old)
switch n.txlock {
case "":
c.txBegin = "BEGIN"
case "deferred", "immediate", "exclusive":
c.txBegin = "BEGIN " + n.txlock
default:
return nil, fmt.Errorf("sqlite3: invalid _txlock: %s", n.txlock)
}
if !n.pragmas {
err = c.Conn.Exec(`PRAGMA busy_timeout=60000`)
if err != nil {
@@ -156,7 +195,7 @@ func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
return nil, err
}
}
return &c, nil
return c, nil
}
type conn struct {
@@ -164,6 +203,8 @@ type conn struct {
txBegin string
txCommit string
txRollback string
tmRead sqlite3.TimeFormat
tmWrite sqlite3.TimeFormat
readOnly byte
}
@@ -248,19 +289,10 @@ func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, e
return nil, err
}
if tail != "" {
// Check if the tail contains any SQL.
st, _, err := c.Conn.Prepare(tail)
if err != nil {
s.Close()
return nil, err
}
if st != nil {
s.Close()
st.Close()
return nil, util.TailErr
}
s.Close()
return nil, util.TailErr
}
return &stmt{s, c.Conn}, nil
return &stmt{Stmt: s, tmRead: c.tmRead, tmWrite: c.tmWrite}, nil
}
func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
@@ -271,7 +303,7 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []driver.Name
if savept, ok := ctx.(*saveptCtx); ok {
// Called from driver.Savepoint.
savept.Savepoint = c.Savepoint()
savept.Savepoint = c.Conn.Savepoint()
return resultRowsAffected(0), nil
}
@@ -291,8 +323,9 @@ func (*conn) CheckNamedValue(arg *driver.NamedValue) error {
}
type stmt struct {
Stmt *sqlite3.Stmt
Conn *sqlite3.Conn
*sqlite3.Stmt
tmWrite sqlite3.TimeFormat
tmRead sqlite3.TimeFormat
}
var (
@@ -302,10 +335,6 @@ var (
_ driver.NamedValueChecker = &stmt{}
)
func (s *stmt) Close() error {
return s.Stmt.Close()
}
func (s *stmt) NumInput() int {
n := s.Stmt.BindCount()
for i := 1; i <= n; i++ {
@@ -332,15 +361,15 @@ func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (drive
return nil, err
}
old := s.Conn.SetInterrupt(ctx)
defer s.Conn.SetInterrupt(old)
old := s.Stmt.Conn().SetInterrupt(ctx)
defer s.Stmt.Conn().SetInterrupt(old)
err = s.Stmt.Exec()
if err != nil {
return nil, err
}
return newResult(s.Conn), nil
return newResult(s.Stmt.Conn()), nil
}
func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
@@ -348,7 +377,7 @@ func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driv
if err != nil {
return nil, err
}
return &rows{ctx, s.Stmt, s.Conn}, nil
return &rows{s, ctx}, nil
}
func (s *stmt) setupBindings(args []driver.NamedValue) error {
@@ -386,12 +415,12 @@ func (s *stmt) setupBindings(args []driver.NamedValue) error {
err = s.Stmt.BindBlob(id, a)
case sqlite3.ZeroBlob:
err = s.Stmt.BindZeroBlob(id, int64(a))
case interface{ Value() any }:
err = s.Stmt.BindPointer(id, a.Value())
case time.Time:
err = s.Stmt.BindTime(id, a, sqlite3.TimeFormatDefault)
case json.Marshaler:
err = s.Stmt.BindJSON(id, a)
err = s.Stmt.BindTime(id, a, s.tmWrite)
case interface{ Pointer() any }:
err = s.Stmt.BindPointer(id, a.Pointer())
case interface{ JSON() any }:
err = s.Stmt.BindJSON(id, a.JSON())
case nil:
err = s.Stmt.BindNull(id)
default:
@@ -408,8 +437,10 @@ func (s *stmt) setupBindings(args []driver.NamedValue) error {
func (s *stmt) CheckNamedValue(arg *driver.NamedValue) error {
switch arg.Value.(type) {
case bool, int, int64, float64, string, []byte,
sqlite3.ZeroBlob, interface{ Value() any },
time.Time, json.Marshaler, nil:
sqlite3.ZeroBlob, time.Time,
interface{ Pointer() any },
interface{ JSON() any },
nil:
return nil
default:
return driver.ErrSkip
@@ -448,12 +479,12 @@ func (r resultRowsAffected) RowsAffected() (int64, error) {
}
type rows struct {
ctx context.Context
Stmt *sqlite3.Stmt
Conn *sqlite3.Conn
*stmt
ctx context.Context
}
func (r *rows) Close() error {
r.Stmt.ClearBindings()
return r.Stmt.Reset()
}
@@ -466,9 +497,19 @@ func (r *rows) Columns() []string {
return columns
}
func (r *rows) ColumnTypeDatabaseTypeName(index int) string {
decltype := r.Stmt.ColumnDeclType(index)
if len := len(decltype); len > 0 && decltype[len-1] == ')' {
if i := strings.LastIndexByte(decltype, '('); i >= 0 {
decltype = decltype[:i]
}
}
return strings.ToUpper(strings.TrimSpace(decltype))
}
func (r *rows) Next(dest []driver.Value) error {
old := r.Conn.SetInterrupt(r.ctx)
defer r.Conn.SetInterrupt(old)
old := r.Stmt.Conn().SetInterrupt(r.ctx)
defer r.Stmt.Conn().SetInterrupt(old)
if !r.Stmt.Step() {
if err := r.Stmt.Err(); err != nil {
@@ -478,6 +519,10 @@ func (r *rows) Next(dest []driver.Value) error {
}
for i := range dest {
if t, ok := r.decodeTime(i); ok {
dest[i] = t
continue
}
switch r.Stmt.ColumnType(i) {
case sqlite3.INTEGER:
dest[i] = r.Stmt.ColumnInt64(i)
@@ -496,3 +541,22 @@ func (r *rows) Next(dest []driver.Value) error {
return r.Stmt.Err()
}
func (s *stmt) decodeTime(i int) (_ time.Time, _ bool) {
if s.tmRead == "" {
return
}
switch s.Stmt.ColumnType(i) {
case sqlite3.INTEGER, sqlite3.FLOAT, sqlite3.TEXT:
// maybe
default:
return
}
switch strings.ToUpper(s.Stmt.ColumnDeclType(i)) {
case "DATE", "TIME", "DATETIME", "TIMESTAMP":
// maybe
default:
return
}
return s.Stmt.ColumnTime(i, s.tmRead), s.Stmt.Err() == nil
}

View File

@@ -11,6 +11,7 @@ import (
"time"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/internal/util"
)
@@ -113,13 +114,7 @@ func Test_Open_txLock(t *testing.T) {
func Test_Open_txLock_invalid(t *testing.T) {
t.Parallel()
db, err := sql.Open("sqlite3", "file::memory:?_txlock=xclusive")
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Conn(context.TODO())
_, err := sql.Open("sqlite3", "file::memory:?_txlock=xclusive")
if err == nil {
t.Fatal("want error")
}
@@ -185,12 +180,6 @@ func Test_Prepare(t *testing.T) {
}
defer db.Close()
stmt, err := db.Prepare(`SELECT 1; -- HERE`)
if err != nil {
t.Error(err)
}
defer stmt.Close()
var serr *sqlite3.Error
_, err = db.Prepare(`SELECT`)
if err == nil {
@@ -206,18 +195,14 @@ func Test_Prepare(t *testing.T) {
t.Error("got message:", got)
}
_, err = db.Prepare(`SELECT 1; `)
if err.Error() != string(util.TailErr) {
t.Error("want tailErr")
}
_, err = db.Prepare(`SELECT 1; SELECT`)
if err == nil {
t.Error("want error")
}
if !errors.As(err, &serr) {
t.Fatalf("got %T, want sqlite3.Error", err)
}
if rc := serr.Code(); rc != sqlite3.ERROR {
t.Errorf("got %d, want sqlite3.ERROR", rc)
}
if got := err.Error(); got != `sqlite3: SQL logic error: incomplete input` {
t.Error("got message:", got)
if err.Error() != string(util.TailErr) {
t.Error("want tailErr")
}
_, err = db.Prepare(`SELECT 1; SELECT 2`)
@@ -296,6 +281,7 @@ func Test_QueryRow_blob_null(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer rows.Close()
want := [][]byte{nil, {0xca, 0xfe}, {0xba, 0xbe}, nil}
for i := 0; rows.Next(); i++ {

View File

@@ -18,7 +18,7 @@ func Example_json() {
defer db.Close()
_, err = db.Exec(`
CREATE TABLE orders (
CREATE TABLE IF NOT EXISTS orders (
cart_id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
cart TEXT

View File

@@ -9,7 +9,7 @@ import (
// Savepoint establishes a new transaction savepoint.
//
// https://www.sqlite.org/lang_savepoint.html
// https://sqlite.org/lang_savepoint.html
func Savepoint(tx *sql.Tx) sqlite3.Savepoint {
var ctx saveptCtx
tx.ExecContext(&ctx, "")

View File

@@ -5,6 +5,7 @@ import (
"log"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
)

View File

@@ -49,16 +49,16 @@ func Fuzz_stringOrTime_1(f *testing.F) {
// This checks that any [time.Time] can be recovered as a [time.Time],
// with nanosecond accuracy, and preserving any timezone offset.
func Fuzz_stringOrTime_2(f *testing.F) {
f.Add(0, 0)
f.Add(0, 1)
f.Add(0, -1)
f.Add(0, 999_999_999)
f.Add(0, 1_000_000_000)
f.Add(7956915742, 222_222_222) // twosday
f.Add(639095955742, 222_222_222) // twosday, year 22222AD
f.Add(-763421161058, 222_222_222) // twosday, year 22222BC
f.Add(int64(0), int64(0))
f.Add(int64(0), int64(1))
f.Add(int64(0), int64(-1))
f.Add(int64(0), int64(999_999_999))
f.Add(int64(0), int64(1_000_000_000))
f.Add(int64(7956915742), int64(222_222_222)) // twosday
f.Add(int64(639095955742), int64(222_222_222)) // twosday, year 22222AD
f.Add(int64(-763421161058), int64(222_222_222)) // twosday, year 22222BC
checkTime := func(t *testing.T, date time.Time) {
checkTime := func(t testing.TB, date time.Time) {
value := stringOrTime([]byte(date.Format(time.RFC3339Nano)))
switch v := value.(type) {
@@ -80,7 +80,7 @@ func Fuzz_stringOrTime_2(f *testing.F) {
}
}
f.Fuzz(func(t *testing.T, sec, nsec int) {
f.Fuzz(func(t *testing.T, sec, nsec int64) {
// Reduce the search space.
if 1e12 < sec || sec < -1e12 {
// Dates before 29000BC and after 33000AD; I think we're safe.
@@ -91,7 +91,7 @@ func Fuzz_stringOrTime_2(f *testing.F) {
return
}
unix := time.Unix(int64(sec), int64(nsec))
unix := time.Unix(sec, nsec)
checkTime(t, unix)
checkTime(t, unix.UTC())
checkTime(t, unix.In(time.FixedZone("", -8*3600)))

View File

@@ -1,15 +1,15 @@
# Embeddable WASM build of SQLite
This folder includes an embeddable WASM build of SQLite 3.44.0 for use with
This folder includes an embeddable WASM build of SQLite 3.44.2 for use with
[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
The following optional features are compiled in:
- [math functions](https://www.sqlite.org/lang_mathfunc.html)
- [FTS3/4](https://www.sqlite.org/fts3.html)/[5](https://www.sqlite.org/fts5.html)
- [JSON](https://www.sqlite.org/json1.html)
- [R*Tree](https://www.sqlite.org/rtree.html)
- [GeoPoly](https://www.sqlite.org/geopoly.html)
- [soundex](https://www.sqlite.org/lang_corefunc.html#soundex)
- [math functions](https://sqlite.org/lang_mathfunc.html)
- [FTS3/4](https://sqlite.org/fts3.html)/[5](https://sqlite.org/fts5.html)
- [JSON](https://sqlite.org/json1.html)
- [R*Tree](https://sqlite.org/rtree.html)
- [GeoPoly](https://sqlite.org/geopoly.html)
- [soundex](https://sqlite.org/lang_corefunc.html#soundex)
- [base64](https://github.com/sqlite/sqlite/blob/master/ext/misc/base64.c)
- [decimal](https://github.com/sqlite/sqlite/blob/master/ext/misc/decimal.c)
- [regexp](https://github.com/sqlite/sqlite/blob/master/ext/misc/regexp.c)

View File

@@ -23,7 +23,7 @@ WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin"
trap 'rm -f sqlite3.tmp' EXIT
"$BINARYEN/wasm-ctor-eval" -g -c _initialize sqlite3.wasm -o sqlite3.tmp
"$BINARYEN/wasm-opt" -g --strip -c -O3 \
"$BINARYEN/wasm-opt" -g --strip --strip-producers -c -O3 \
sqlite3.tmp -o sqlite3.wasm \
--enable-simd --enable-mutable-globals --enable-multivalue \
--enable-bulk-memory --enable-reference-types \

View File

@@ -1,80 +1,101 @@
free
malloc
malloc_destructor
sqlite3_errcode
sqlite3_errstr
sqlite3_errmsg
sqlite3_error_offset
sqlite3_open_v2
sqlite3_close
sqlite3_close_v2
sqlite3_prepare_v3
sqlite3_finalize
sqlite3_reset
sqlite3_step
sqlite3_exec
sqlite3_interrupt
sqlite3_progress_handler_go
sqlite3_clear_bindings
sqlite3_aggregate_context
sqlite3_anycollseq_init
sqlite3_backup_finish
sqlite3_backup_init
sqlite3_backup_pagecount
sqlite3_backup_remaining
sqlite3_backup_step
sqlite3_bind_blob64
sqlite3_bind_double
sqlite3_bind_int64
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
sqlite3_bind_null
sqlite3_bind_int64
sqlite3_bind_double
sqlite3_bind_text64
sqlite3_bind_blob64
sqlite3_bind_zeroblob64
sqlite3_bind_pointer_go
sqlite3_column_count
sqlite3_column_name
sqlite3_column_type
sqlite3_column_int64
sqlite3_column_double
sqlite3_column_text
sqlite3_bind_text64
sqlite3_bind_value
sqlite3_bind_zeroblob64
sqlite3_blob_bytes
sqlite3_blob_close
sqlite3_blob_open
sqlite3_blob_read
sqlite3_blob_reopen
sqlite3_blob_write
sqlite3_changes64
sqlite3_clear_bindings
sqlite3_close
sqlite3_close_v2
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_blob_open
sqlite3_blob_close
sqlite3_blob_reopen
sqlite3_blob_bytes
sqlite3_blob_read
sqlite3_blob_write
sqlite3_backup_init
sqlite3_backup_step
sqlite3_backup_finish
sqlite3_backup_remaining
sqlite3_backup_pagecount
sqlite3_uri_parameter
sqlite3_uri_key
sqlite3_changes64
sqlite3_last_insert_rowid
sqlite3_get_autocommit
sqlite3_anycollseq_init
sqlite3_column_count
sqlite3_column_decltype
sqlite3_column_double
sqlite3_column_int64
sqlite3_column_name
sqlite3_column_text
sqlite3_column_type
sqlite3_column_value
sqlite3_create_aggregate_function_go
sqlite3_create_collation_go
sqlite3_create_function_go
sqlite3_create_aggregate_function_go
sqlite3_create_module_go
sqlite3_create_window_function_go
sqlite3_aggregate_context
sqlite3_user_data
sqlite3_set_auxdata_go
sqlite3_declare_vtab
sqlite3_errcode
sqlite3_errmsg
sqlite3_error_offset
sqlite3_errstr
sqlite3_exec
sqlite3_finalize
sqlite3_get_autocommit
sqlite3_get_auxdata
sqlite3_value_type
sqlite3_value_int64
sqlite3_value_double
sqlite3_value_text
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_pointer_go
sqlite3_result_null
sqlite3_result_int64
sqlite3_result_double
sqlite3_result_text64
sqlite3_interrupt
sqlite3_last_insert_rowid
sqlite3_open_v2
sqlite3_overload_function
sqlite3_prepare_v3
sqlite3_progress_handler_go
sqlite3_reset
sqlite3_result_blob64
sqlite3_result_zeroblob64
sqlite3_result_pointer_go
sqlite3_result_value
sqlite3_result_double
sqlite3_result_error
sqlite3_result_error_code
sqlite3_result_error_nomem
sqlite3_result_error_toobig
sqlite3_result_error_toobig
sqlite3_result_int64
sqlite3_result_null
sqlite3_result_pointer_go
sqlite3_result_text64
sqlite3_result_value
sqlite3_result_zeroblob64
sqlite3_set_auxdata_go
sqlite3_step
sqlite3_stmt_busy
sqlite3_stmt_readonly
sqlite3_stmt_status
sqlite3_uri_key
sqlite3_uri_parameter
sqlite3_user_data
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_double
sqlite3_value_dup
sqlite3_value_free
sqlite3_value_int64
sqlite3_value_nochange
sqlite3_value_pointer_go
sqlite3_value_text
sqlite3_value_type
sqlite3_vtab_collation
sqlite3_vtab_config_go
sqlite3_vtab_distinct
sqlite3_vtab_in
sqlite3_vtab_in_first
sqlite3_vtab_in_next
sqlite3_vtab_nochange
sqlite3_vtab_on_conflict
sqlite3_vtab_rhs_value

Binary file not shown.

View File

@@ -1,6 +1,7 @@
package sqlite3
import (
"errors"
"strconv"
"strings"
@@ -9,7 +10,7 @@ import (
// Error wraps an SQLite Error Code.
//
// https://www.sqlite.org/c3ref/errcode.html
// https://sqlite.org/c3ref/errcode.html
type Error struct {
str string
msg string
@@ -19,14 +20,14 @@ type Error struct {
// Code returns the primary error code for this error.
//
// https://www.sqlite.org/rescode.html
// https://sqlite.org/rescode.html
func (e *Error) Code() ErrorCode {
return ErrorCode(e.code)
}
// ExtendedCode returns the extended error code for this error.
//
// https://www.sqlite.org/rescode.html
// https://sqlite.org/rescode.html
func (e *Error) ExtendedCode() ExtendedErrorCode {
return ExtendedErrorCode(e.code)
}
@@ -43,8 +44,7 @@ func (e *Error) Error() string {
}
if e.msg != "" {
b.WriteByte(':')
b.WriteByte(' ')
b.WriteString(": ")
b.WriteString(e.msg)
}
@@ -135,3 +135,28 @@ func (e ExtendedErrorCode) Temporary() bool {
func (e ExtendedErrorCode) Timeout() bool {
return e == BUSY_TIMEOUT
}
func errorCode(err error, def ErrorCode) (msg string, code uint32) {
switch code := err.(type) {
case ErrorCode:
return "", uint32(code)
case ExtendedErrorCode:
return "", uint32(code)
case *Error:
return code.msg, uint32(code.code)
case nil:
return "", _OK
}
var ecode ErrorCode
var xcode xErrorCode
switch {
case errors.As(err, &xcode):
code = uint32(xcode)
case errors.As(err, &ecode):
code = uint32(ecode)
default:
code = uint32(def)
}
return err.Error(), code
}

View File

@@ -135,8 +135,8 @@ func Test_ErrorCode_Error(t *testing.T) {
// Test all error codes.
for i := 0; i == int(ErrorCode(i)); i++ {
want := "sqlite3: "
r := db.call(db.api.errstr, uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_STRING)
r := db.call("sqlite3_errstr", uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_NAME)
got := ErrorCode(i).Error()
if got != want {
@@ -157,8 +157,8 @@ func Test_ExtendedErrorCode_Error(t *testing.T) {
// Test all extended error codes.
for i := 0; i == int(ExtendedErrorCode(i)); i++ {
want := "sqlite3: "
r := db.call(db.api.errstr, uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_STRING)
r := db.call("sqlite3_errstr", uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_NAME)
got := ExtendedErrorCode(i).Error()
if got != want {

135
ext/array/array.go Normal file
View File

@@ -0,0 +1,135 @@
// Package array provides the array table-valued SQL function.
package array
import (
"fmt"
"reflect"
"github.com/ncruces/go-sqlite3"
)
// Register registers the array single-argument, table-valued SQL function.
// The argument must be an [sqlite3.Pointer] to a Go slice or array
// of ints, floats, bools, strings or blobs.
//
// https://sqlite.org/carray.html
func Register(db *sqlite3.Conn) {
sqlite3.CreateModule[array](db, "array", nil,
func(db *sqlite3.Conn, _, _, _ string, _ ...string) (array, error) {
err := db.DeclareVtab(`CREATE TABLE x(value, array HIDDEN)`)
return array{}, err
})
}
type array struct{}
func (array) BestIndex(idx *sqlite3.IndexInfo) error {
for i, cst := range idx.Constraint {
if cst.Column == 1 && cst.Op == sqlite3.INDEX_CONSTRAINT_EQ && cst.Usable {
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
Omit: true,
ArgvIndex: 1,
}
idx.EstimatedCost = 1
idx.EstimatedRows = 100
return nil
}
}
return sqlite3.CONSTRAINT
}
func (array) Open() (sqlite3.VTabCursor, error) {
return &cursor{}, nil
}
type cursor struct {
array reflect.Value
rowID int
}
func (c *cursor) EOF() bool {
return c.rowID >= c.array.Len()
}
func (c *cursor) Next() error {
c.rowID++
return nil
}
func (c *cursor) RowID() (int64, error) {
return int64(c.rowID), nil
}
func (c *cursor) Column(ctx *sqlite3.Context, n int) error {
if n != 0 {
return nil
}
v := c.array.Index(c.rowID)
k := v.Kind()
if k == reflect.Interface {
if v.IsNil() {
ctx.ResultNull()
return nil
}
v = v.Elem()
k = v.Kind()
}
switch {
case v.CanInt():
ctx.ResultInt64(v.Int())
case v.CanUint():
i64 := int64(v.Uint())
if i64 < 0 {
return fmt.Errorf("array: integer element overflow:%.0w %d", sqlite3.MISMATCH, v.Uint())
}
ctx.ResultInt64(i64)
case v.CanFloat():
ctx.ResultFloat(v.Float())
case k == reflect.Bool:
ctx.ResultBool(v.Bool())
case k == reflect.String:
ctx.ResultText(v.String())
case (k == reflect.Slice || k == reflect.Array && v.CanAddr()) &&
v.Type().Elem().Kind() == reflect.Uint8:
ctx.ResultBlob(v.Bytes())
default:
return fmt.Errorf("array: unsupported element:%.0w %v", sqlite3.MISMATCH, v.Type())
}
return nil
}
func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
array := reflect.ValueOf(arg[0].Pointer())
array, err := indexable(array)
if err != nil {
return err
}
c.array = array
c.rowID = 0
return nil
}
func indexable(v reflect.Value) (reflect.Value, error) {
if v.Kind() == reflect.Slice {
return v, nil
}
if v.Kind() == reflect.Array {
return v, nil
}
if v.Kind() == reflect.Pointer {
if v := v.Elem(); v.Kind() == reflect.Array {
return v, nil
}
}
return v, fmt.Errorf("array: unsupported argument:%.0w %v", sqlite3.MISMATCH, v.Type())
}

94
ext/array/array_test.go Normal file
View File

@@ -0,0 +1,94 @@
package array_test
import (
"fmt"
"log"
"math"
"reflect"
"testing"
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/array"
)
func Example() {
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
array.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query(`
SELECT name
FROM pragma_function_list
WHERE name like 'geopoly%' AND narg IN array(?)`,
sqlite3.Pointer([]int{2, 3, 4}))
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name string
err := rows.Scan(&name)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", name)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
// Unordered output:
// geopoly_regular
// geopoly_overlap
// geopoly_contains_point
// geopoly_within
}
func Test_cursor_Column(t *testing.T) {
t.Parallel()
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
array.Register(c)
return nil
})
if err != nil {
t.Fatal(err)
}
defer db.Close()
rows, err := db.Query(`
SELECT rowid, value FROM array(?)`,
sqlite3.Pointer(&[...]any{nil, true, 1, uint(2), math.Pi, "text", []byte{1, 2, 3}}))
if err != nil {
t.Fatal(err)
}
defer rows.Close()
want := []string{"nil", "int64", "int64", "int64", "float64", "string", "[]uint8"}
for rows.Next() {
var id, val any
err := rows.Scan(&id, &val)
if err != nil {
t.Fatal(err)
}
if want := want[0]; val == nil {
if want != "nil" {
t.Errorf("got nil, want %s", want)
}
} else if got := reflect.TypeOf(val).String(); got != want {
t.Errorf("got %s, want %s", got, want)
}
want = want[1:]
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}

View File

@@ -5,9 +5,18 @@ import (
"errors"
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/internal/util"
)
// Register registers the blob_open SQL function.
// Register registers the blob_open SQL function:
//
// blob_open(schema, table, column, rowid, flags, callback, args...)
//
// The callback must be an [sqlite3.Pointer] to an [OpenCallback].
// Any optional args will be passed to the callback,
// along with the [sqlite3.Blob] handle.
//
// https://sqlite.org/c3ref/blob.html
func Register(db *sqlite3.Conn) {
db.CreateFunction("blob_open", -1,
sqlite3.DETERMINISTIC|sqlite3.DIRECTONLY, openBlob)
@@ -15,7 +24,7 @@ func Register(db *sqlite3.Conn) {
func openBlob(ctx sqlite3.Context, arg ...sqlite3.Value) {
if len(arg) < 6 {
ctx.ResultError(errors.New("wrong number of arguments to function blob_open()"))
ctx.ResultError(util.ErrorString("blob_open: wrong number of arguments"))
return
}
@@ -26,7 +35,7 @@ func openBlob(ctx sqlite3.Context, arg ...sqlite3.Value) {
if ok {
err = blob.Reopen(row)
if errors.Is(err, sqlite3.MISUSE) {
// Blob was closed (db, table or column changed).
// Blob was closed (db, table, column or write changed).
ok = false
}
}
@@ -50,10 +59,12 @@ func openBlob(ctx sqlite3.Context, arg ...sqlite3.Value) {
return
}
// This ensures the blob is closed if db, table or column change.
ctx.SetAuxData(0, blob)
ctx.SetAuxData(1, blob)
ctx.SetAuxData(2, blob)
// This ensures the blob is closed if db, table, column or write change.
ctx.SetAuxData(0, blob) // db
ctx.SetAuxData(1, blob) // table
ctx.SetAuxData(2, blob) // column
ctx.SetAuxData(4, blob) // write
}
// OpenCallback is the type for the blob_open callback.
type OpenCallback func(*sqlite3.Blob, ...sqlite3.Value) error

View File

@@ -4,10 +4,13 @@ import (
"io"
"log"
"os"
"reflect"
"testing"
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/array"
"github.com/ncruces/go-sqlite3/ext/blob"
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
)
@@ -59,3 +62,67 @@ func Example() {
// Output:
// Hello BLOB!
}
func TestRegister(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
blob.Register(db)
array.Register(db)
err = db.Exec(`SELECT blob_open()`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`
CREATE TABLE IF NOT EXISTS test1 (col);
CREATE TABLE IF NOT EXISTS test2 (col);
INSERT INTO test1 VALUES (x'cafe');
INSERT INTO test2 VALUES (x'babe');
`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT blob_open('main', value, 'col', 1, false, ?) FROM array(?)`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
var got []string
err = stmt.BindPointer(1, blob.OpenCallback(func(b *sqlite3.Blob, _ ...sqlite3.Value) error {
d, err := io.ReadAll(b)
if err != nil {
return err
}
got = append(got, string(d))
return nil
}))
if err != nil {
t.Fatal(err)
}
err = stmt.BindPointer(2, []string{"test1", "test2"})
if err != nil {
t.Fatal(err)
}
err = stmt.Exec()
if err != nil {
t.Fatal(err)
}
want := []string{"\xca\xfe", "\xba\xbe"}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}

211
ext/csv/csv.go Normal file
View File

@@ -0,0 +1,211 @@
// Package csv provides a CSV virtual table.
//
// The CSV virtual table reads RFC 4180 formatted comma-separated values,
// and returns that content as if it were rows and columns of an SQL table.
//
// https://sqlite.org/csv.html
package csv
import (
"encoding/csv"
"fmt"
"io"
"math"
"os"
"strings"
"github.com/ncruces/go-sqlite3"
)
// Register registers the CSV virtual table.
// If a filename is specified, `os.Open` is used to read it from disk.
func Register(db *sqlite3.Conn) {
RegisterOpen(db, func(name string) (io.ReaderAt, error) {
return os.Open(name)
})
}
// RegisterOpen registers the CSV virtual table.
// If a filename is specified, open is used to open the file.
func RegisterOpen(db *sqlite3.Conn, open func(name string) (io.ReaderAt, error)) {
declare := func(db *sqlite3.Conn, _, _, _ string, arg ...string) (_ *table, err error) {
var (
filename string
data string
schema string
header bool
columns int = -1
comma rune = ','
done = map[string]struct{}{}
)
for _, arg := range arg {
key, val := getParam(arg)
if _, ok := done[key]; ok {
return nil, fmt.Errorf("csv: more than one %q parameter", key)
}
switch key {
case "filename":
filename = unquoteParam(val)
case "data":
data = unquoteParam(val)
case "schema":
schema = unquoteParam(val)
case "header":
header, err = boolParam(key, val)
case "columns":
columns, err = uintParam(key, val)
case "comma":
comma, err = runeParam(key, val)
default:
return nil, fmt.Errorf("csv: unknown %q parameter", key)
}
if err != nil {
return nil, err
}
done[key] = struct{}{}
}
if (filename == "") == (data == "") {
return nil, fmt.Errorf(`csv: must specify either "filename" or "data" but not both`)
}
var r io.ReaderAt
if filename != "" {
r, err = open(filename)
} else {
r = strings.NewReader(data)
}
if err != nil {
return nil, err
}
table := &table{
r: r,
comma: comma,
header: header,
bom: -1,
}
defer func() {
if err != nil {
table.Close()
}
}()
if schema == "" {
var row []string
if header || columns < 0 {
row, err = table.newReader().Read()
if err != nil {
return nil, err
}
}
schema = getSchema(header, columns, row)
}
err = db.DeclareVtab(schema)
if err != nil {
return nil, err
}
err = db.VtabConfig(sqlite3.VTAB_DIRECTONLY)
if err != nil {
return nil, err
}
return table, nil
}
sqlite3.CreateModule(db, "csv", declare, declare)
}
type table struct {
r io.ReaderAt
comma rune
header bool
bom int8
}
func (t *table) Close() error {
if c, ok := t.r.(io.Closer); ok {
err := c.Close()
t.r = nil
return err
}
return nil
}
func (t *table) BestIndex(idx *sqlite3.IndexInfo) error {
idx.EstimatedCost = 1e6
return nil
}
func (t *table) Open() (sqlite3.VTabCursor, error) {
return &cursor{table: t}, nil
}
func (t *table) Rename(new string) error {
return nil
}
func (t *table) Integrity(schema, table string, flags int) (err error) {
if flags&1 == 0 {
_, err = t.newReader().ReadAll()
}
return err
}
func (t *table) newReader() *csv.Reader {
if t.bom < 0 {
var bom [3]byte
t.r.ReadAt(bom[:], 0)
if string(bom[:]) == "\xEF\xBB\xBF" {
t.bom = 3
} else {
t.bom = 0
}
}
csv := csv.NewReader(io.NewSectionReader(t.r, int64(t.bom), math.MaxInt64))
csv.ReuseRecord = true
csv.Comma = t.comma
return csv
}
type cursor struct {
table *table
csv *csv.Reader
row []string
rowID int64
}
func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
c.csv = c.table.newReader()
if c.table.header {
c.Next() // skip header
}
c.rowID = 0
return c.Next()
}
func (c *cursor) Next() (err error) {
c.rowID++
c.row, err = c.csv.Read()
if err != io.EOF {
return err
}
return nil
}
func (c *cursor) EOF() bool {
return c.row == nil
}
func (c *cursor) RowID() (int64, error) {
return c.rowID, nil
}
func (c *cursor) Column(ctx *sqlite3.Context, col int) error {
if col < len(c.row) {
ctx.ResultText(c.row[col])
}
return nil
}

155
ext/csv/csv_test.go Normal file
View File

@@ -0,0 +1,155 @@
package csv_test
import (
"fmt"
"log"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/csv"
)
func Example() {
db, err := sqlite3.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
csv.Register(db)
err = db.Exec(`
CREATE VIRTUAL TABLE IF NOT EXISTS eurofxref USING csv(
filename = 'testdata/eurofxref.csv',
header = YES,
columns = 42,
)`)
if err != nil {
log.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT USD FROM eurofxref WHERE Date = '2022-02-22'`)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
if stmt.Step() {
fmt.Printf("On Twosday, 1€ = $%g", stmt.ColumnFloat(0))
}
if err := stmt.Reset(); err != nil {
log.Fatal(err)
}
err = db.Exec(`DROP TABLE eurofxref`)
if err != nil {
log.Fatal(err)
}
// Output:
// On Twosday, 1€ = $1.1342
}
func TestRegister(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
csv.Register(db)
const data = "\xEF\xBB\xBF" + `
"Rob" "Pike" rob
"Ken" Thompson ken
Robert "Griesemer" "gri"`
err = db.Exec(`
CREATE VIRTUAL TABLE temp.users USING csv(
data = ` + sqlite3.Quote(data) + `,
schema = 'CREATE TABLE x(first_name, last_name, username)',
comma = '\t'
)`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT * FROM temp.users WHERE rowid = 1 ORDER BY username`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if !stmt.Step() {
t.Fatal("no rows")
}
if got := stmt.ColumnText(1); got != "Pike" {
t.Errorf("got %q want Pike", got)
}
if stmt.Step() {
t.Fatal("more rows")
}
err = db.Exec(`ALTER TABLE temp.users RENAME TO csv`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`PRAGMA integrity_check`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`DROP TABLE temp.csv`)
if err != nil {
log.Fatal(err)
}
}
func TestRegister_errors(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
csv.Register(db)
err = db.Exec(`CREATE VIRTUAL TABLE temp.users USING csv()`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE temp.users USING csv(data='abc', data='abc')`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE temp.users USING csv(data='abc', xpto='abc')`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE temp.users USING csv(data='abc', comma='"')`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE temp.users USING csv(data='abc', header=tru)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
}

65
ext/csv/params.go Normal file
View File

@@ -0,0 +1,65 @@
package csv
import (
"fmt"
"strconv"
"strings"
)
func getParam(arg string) (key, val string) {
key, val, _ = strings.Cut(arg, "=")
key = strings.TrimSpace(key)
val = strings.TrimSpace(val)
return
}
func uintParam(key, val string) (int, error) {
i, err := strconv.ParseUint(val, 10, 15)
if err != nil {
return 0, fmt.Errorf("csv: invalid %q parameter: %s", key, val)
}
return int(i), nil
}
func boolParam(key, val string) (bool, error) {
if val == "" || val == "1" ||
strings.EqualFold(val, "true") ||
strings.EqualFold(val, "yes") ||
strings.EqualFold(val, "on") {
return true, nil
}
if val == "0" ||
strings.EqualFold(val, "false") ||
strings.EqualFold(val, "no") ||
strings.EqualFold(val, "off") {
return false, nil
}
return false, fmt.Errorf("csv: invalid %q parameter: %s", key, val)
}
func runeParam(key, val string) (rune, error) {
r, _, tail, err := strconv.UnquoteChar(unquoteParam(val), 0)
if tail != "" || err != nil {
return 0, fmt.Errorf("csv: invalid %q parameter: %s", key, val)
}
return r, nil
}
func unquoteParam(val string) string {
if len(val) < 2 {
return val
}
if val[0] != val[len(val)-1] {
return val
}
var old, new string
switch val[0] {
default:
return val
case '"':
old, new = `""`, `"`
case '\'':
old, new = `''`, `'`
}
return strings.ReplaceAll(val[1:len(val)-1], old, new)
}

104
ext/csv/params_test.go Normal file
View File

@@ -0,0 +1,104 @@
package csv
import "testing"
func Test_uintParam(t *testing.T) {
t.Parallel()
tests := []struct {
arg string
key string
val int
err bool
}{
{"columns 1", "columns 1", 0, true},
{"columns = 1", "columns", 1, false},
{"columns\t= 2", "columns", 2, false},
{" columns = 3", "columns", 3, false},
{" columns = -1", "columns", 0, true},
{" columns = 32768", "columns", 0, true},
}
for _, tt := range tests {
t.Run(tt.arg, func(t *testing.T) {
key, val := getParam(tt.arg)
if key != tt.key {
t.Errorf("getParam() %v, want err %v", key, tt.key)
}
got, err := uintParam(key, val)
if (err != nil) != tt.err {
t.Fatalf("uintParam() error = %v, want err %v", err, tt.err)
}
if got != tt.val {
t.Errorf("uintParam() = %v, want %v", got, tt.val)
}
})
}
}
func Test_boolParam(t *testing.T) {
tests := []struct {
arg string
key string
val bool
err bool
}{
{"header", "header", true, false},
{"header\t= 1", "header", true, false},
{" header = 0", "header", false, false},
{" header = TrUe", "header", true, false},
{" header = FaLsE", "header", false, false},
{" header = Yes", "header", true, false},
{" header = nO", "header", false, false},
{" header = On", "header", true, false},
{" header = Off", "header", false, false},
{" header = T", "header", false, true},
{" header = f", "header", false, true},
}
for _, tt := range tests {
t.Run(tt.arg, func(t *testing.T) {
key, val := getParam(tt.arg)
if key != tt.key {
t.Errorf("getParam() %v, want err %v", key, tt.key)
}
got, err := boolParam(key, val)
if (err != nil) != tt.err {
t.Fatalf("boolParam() error = %v, want err %v", err, tt.err)
}
if got != tt.val {
t.Errorf("boolParam() = %v, want %v", got, tt.val)
}
})
}
}
func Test_runeParam(t *testing.T) {
tests := []struct {
arg string
key string
val rune
err bool
}{
{"comma", "comma", 0, true},
{"comma\t= ,", "comma", ',', false},
{" comma = ;", "comma", ';', false},
{" comma = ;;", "comma", 0, true},
{` comma = '\t`, "comma", 0, true},
{` comma = '\t'`, "comma", '\t', false},
{` comma = "\t"`, "comma", '\t', false},
}
for _, tt := range tests {
t.Run(tt.arg, func(t *testing.T) {
key, val := getParam(tt.arg)
if key != tt.key {
t.Errorf("getParam() %v, want err %v", key, tt.key)
}
got, err := runeParam(key, val)
if (err != nil) != tt.err {
t.Fatalf("runeParam() error = %v, want err %v", err, tt.err)
}
if got != tt.val {
t.Errorf("runeParam() = %v, want %v", got, tt.val)
}
})
}
}

39
ext/csv/schema.go Normal file
View File

@@ -0,0 +1,39 @@
package csv
import (
"strconv"
"strings"
"github.com/ncruces/go-sqlite3"
)
func getSchema(header bool, columns int, row []string) string {
var sep string
var str strings.Builder
str.WriteString("CREATE TABLE x(")
if 0 <= columns && columns < len(row) {
row = row[:columns]
}
for i, f := range row {
str.WriteString(sep)
if header && f != "" {
str.WriteString(sqlite3.QuoteIdentifier(f))
} else {
str.WriteString("c")
str.WriteString(strconv.Itoa(i + 1))
}
str.WriteString(" TEXT")
sep = ","
}
for i := len(row); i < columns; i++ {
str.WriteString(sep)
str.WriteString("c")
str.WriteString(strconv.Itoa(i + 1))
str.WriteString(" TEXT")
sep = ","
}
str.WriteByte(')')
return str.String()
}

28
ext/csv/schema_test.go Normal file
View File

@@ -0,0 +1,28 @@
package csv
import "testing"
func Test_getSchema(t *testing.T) {
t.Parallel()
tests := []struct {
header bool
columns int
row []string
want string
}{
{true, 2, nil, `CREATE TABLE x(c1 TEXT,c2 TEXT)`},
{false, 2, nil, `CREATE TABLE x(c1 TEXT,c2 TEXT)`},
{false, -1, []string{"abc", ""}, `CREATE TABLE x(c1 TEXT,c2 TEXT)`},
{true, 3, []string{"abc", ""}, `CREATE TABLE x("abc" TEXT,c2 TEXT,c3 TEXT)`},
{true, -1, []string{"abc", "def"}, `CREATE TABLE x("abc" TEXT,"def" TEXT)`},
{true, 1, []string{"abc", "def"}, `CREATE TABLE x("abc" TEXT)`},
}
for _, tt := range tests {
t.Run(tt.want, func(t *testing.T) {
if got := getSchema(tt.header, tt.columns, tt.row); got != tt.want {
t.Errorf("getSchema() = %v, want %v", got, tt.want)
}
})
}
}

258
ext/csv/testdata/eurofxref.csv vendored Normal file
View File

@@ -0,0 +1,258 @@
Date,USD,JPY,BGN,CYP,CZK,DKK,EEK,GBP,HUF,LTL,LVL,MTL,PLN,ROL,RON,SEK,SIT,SKK,CHF,ISK,NOK,HRK,RUB,TRL,TRY,AUD,BRL,CAD,CNY,HKD,IDR,ILS,INR,KRW,MXN,MYR,NZD,PHP,SGD,THB,ZAR,
2022-12-30,1.0666,140.66,1.9558,N/A,24.116,7.4365,N/A,0.88693,400.87,N/A,N/A,N/A,4.6808,N/A,4.9495,11.1218,N/A,N/A,0.9847,151.5,10.5138,7.5365,N/A,N/A,19.9649,1.5693,5.6386,1.444,7.3582,8.3163,16519.82,3.7554,88.171,1344.09,20.856,4.6984,1.6798,59.32,1.43,36.835,18.0986,
2022-12-29,1.0649,142.24,1.9558,N/A,24.191,7.4365,N/A,0.88549,399.6,N/A,N/A,N/A,4.6855,N/A,4.9493,11.158,N/A,N/A,0.984,152.5,10.55,7.5365,N/A,N/A,19.934,1.5859,5.5351,1.4475,7.4151,8.2994,16680.38,3.7575,88.2295,1350.18,20.651,4.7106,1.6887,59.367,1.436,36.877,18.1967,
2022-12-28,1.064,142.21,1.9558,N/A,24.252,7.4365,N/A,0.88058,403.3,N/A,N/A,N/A,4.7008,N/A,4.946,11.1038,N/A,N/A,0.9863,151.9,10.4495,7.5365,N/A,N/A,19.9144,1.566,5.6109,1.4361,7.4224,8.2931,16765.93,3.7526,88.0943,1348.59,20.6856,4.7055,1.6772,59.613,1.4323,36.953,18.289,
2022-12-27,1.0624,141.68,1.9558,N/A,24.26,7.4366,N/A,0.88333,401.65,N/A,N/A,N/A,4.6683,N/A,4.927,11.1285,N/A,N/A,0.9885,152.3,10.4895,7.5375,N/A,N/A,19.8799,1.577,5.6035,1.4384,7.3994,8.2874,16620.58,3.7278,88.0808,1349.85,20.5515,4.699,1.6916,59.356,1.43,36.775,18.3181,
2022-12-23,1.0622,140.86,1.9558,N/A,24.247,7.4364,N/A,0.8803,400.68,N/A,N/A,N/A,4.6423,N/A,4.9056,11.1045,N/A,N/A,0.9867,152.3,10.4448,7.537,N/A,N/A,19.843,1.5857,5.4834,1.4433,7.4198,8.2878,16569.18,3.704,87.958,1359.5,20.7115,4.7002,1.6887,58.623,1.4337,36.842,18.1048,
2022-12-22,1.0633,140.42,1.9558,N/A,24.215,7.4367,N/A,0.88243,402.13,N/A,N/A,N/A,4.6443,N/A,4.8993,11.05,N/A,N/A,0.9852,153.3,10.4123,7.538,N/A,N/A,19.8553,1.5804,5.5386,1.4484,7.4229,8.2883,16525.91,3.6942,88.0365,1361.75,20.8485,4.7051,1.6918,58.705,1.4356,36.849,18.2238,
2022-12-21,1.0636,140.29,1.9558,N/A,24.218,7.438,N/A,0.87651,402.93,N/A,N/A,N/A,4.6665,N/A,4.8937,11.0623,N/A,N/A,0.9836,152.1,10.4309,7.5419,N/A,N/A,19.8541,1.5859,5.4913,1.4475,7.4219,8.2902,16573.77,3.6989,88.109,1367.63,20.9919,4.7197,1.685,58.556,1.4366,36.907,18.3529,
2022-12-20,1.0599,140.58,1.9558,N/A,24.181,7.4388,N/A,0.8753,403.88,N/A,N/A,N/A,4.6757,N/A,4.9125,11.0615,N/A,N/A,0.9854,151.5,10.5098,7.5471,N/A,N/A,19.7744,1.5972,5.6234,1.4451,7.39,8.2488,16537.09,3.6759,87.6649,1363.73,20.9355,4.6991,1.6816,58.549,1.4347,36.853,18.4239,
2022-12-19,1.0598,144.65,1.9558,N/A,24.233,7.4382,N/A,0.87118,403.18,N/A,N/A,N/A,4.6853,N/A,4.9107,11.0063,N/A,N/A,0.9884,151.9,10.5025,7.5395,N/A,N/A,19.7676,1.5794,5.6327,1.4472,7.3901,8.2428,16506.72,3.6551,87.5321,1377.17,20.9743,4.6912,1.6632,58.649,1.4378,36.923,18.3074,
2022-12-16,1.0619,145.53,1.9558,N/A,24.262,7.4379,N/A,0.87233,407.1,N/A,N/A,N/A,4.6925,N/A,4.9213,11.0153,N/A,N/A,0.9879,150.1,10.4833,7.5385,N/A,N/A,19.8039,1.5866,5.6233,1.4506,7.4037,8.2632,16575.47,3.6689,87.824,1389.7,21.0634,4.6984,1.6687,58.967,1.4413,37.145,18.6708,
2022-12-15,1.0621,145.07,1.9558,N/A,24.27,7.4387,N/A,0.86194,406.4,N/A,N/A,N/A,4.689,N/A,4.922,10.898,N/A,N/A,0.9862,150.9,10.4013,7.5395,N/A,N/A,19.806,1.5695,5.6247,1.4443,7.4007,8.2551,16591.4,3.6388,87.9355,1393.97,20.9431,4.6918,1.6628,59.297,1.4406,37.12,18.3599,
2022-12-14,1.0649,143.68,1.9558,N/A,24.276,7.4392,N/A,0.86118,406.63,N/A,N/A,N/A,4.681,N/A,4.9248,10.8638,N/A,N/A,0.9865,150.9,10.362,7.538,N/A,N/A,19.8579,1.551,5.6842,1.4441,7.4009,8.2751,16599.51,3.6327,87.8435,1379.99,20.8635,4.6765,1.6508,59.326,1.4349,36.851,18.2563,
2022-12-13,1.0545,144.85,1.9558,N/A,24.287,7.4391,N/A,0.85753,409.65,N/A,N/A,N/A,4.6938,N/A,4.9298,10.8965,N/A,N/A,0.9869,151.1,10.4679,7.5495,N/A,N/A,19.6649,1.5553,5.5784,1.4341,7.3637,8.2033,16521.81,3.6266,87.2965,1378.75,20.9435,4.6704,1.6464,58.852,1.4288,36.707,18.6855,
2022-12-12,1.0562,144.86,1.9558,N/A,24.307,7.4379,N/A,0.86006,416.78,N/A,N/A,N/A,4.6923,N/A,4.9318,10.9075,N/A,N/A,0.9855,150.7,10.5548,7.554,N/A,N/A,19.6913,1.5625,5.556,1.4428,7.367,8.2103,16524.63,3.6232,87.253,1377.93,20.9047,4.6652,1.6523,58.788,1.4284,36.708,18.4697,
2022-12-09,1.0559,143.3,1.9558,N/A,24.293,7.4379,N/A,0.8595,417.53,N/A,N/A,N/A,4.6869,N/A,4.9224,10.9188,N/A,N/A,0.9856,149.5,10.5345,7.555,N/A,N/A,19.6872,1.5553,5.5457,1.438,7.3475,8.2169,16453.46,3.6128,86.9535,1373.94,20.849,4.6512,1.6482,58.47,1.426,36.656,18.2358,
2022-12-08,1.0519,143.75,1.9558,N/A,24.324,7.4382,N/A,0.86258,417.66,N/A,N/A,N/A,4.6853,N/A,4.9131,10.906,N/A,N/A,0.9889,149.5,10.488,7.5553,N/A,N/A,19.6114,1.559,5.488,1.4307,7.3324,8.1889,16423.92,3.6206,86.6755,1387.06,20.6989,4.6257,1.6547,58.233,1.4256,36.559,18.0225,
2022-12-07,1.0529,144.44,1.9558,N/A,24.322,7.4382,N/A,0.86408,410.63,N/A,N/A,N/A,4.7003,N/A,4.918,10.919,N/A,N/A,0.9893,148.7,10.5255,7.5525,N/A,N/A,19.6256,1.5728,5.5023,1.4387,7.3476,8.1997,16465.17,3.626,86.692,1390.87,20.7534,4.6301,1.6573,58.432,1.4286,36.904,18.1353,
2022-12-06,1.0516,143.33,1.9558,N/A,24.316,7.438,N/A,0.8617,415.08,N/A,N/A,N/A,4.6975,N/A,4.913,10.889,N/A,N/A,0.9872,148.9,10.4408,7.5563,N/A,N/A,19.601,1.5625,5.5113,1.4326,7.3494,8.1813,16441.49,3.5831,86.6485,1386.39,20.6884,4.6223,1.6583,58.782,1.4263,36.827,18.2068,
2022-12-05,1.0587,143.07,1.9558,N/A,24.351,7.4369,N/A,0.86085,412.13,N/A,N/A,N/A,4.695,N/A,4.9215,10.8931,N/A,N/A,0.9893,148.9,10.3366,7.551,N/A,N/A,19.7326,1.5542,5.5491,1.4198,7.3573,8.2236,16332.36,3.5856,86.5249,1370.87,20.7295,4.6255,1.6498,59.245,1.4271,36.732,18.2038,
2022-12-02,1.0538,141.32,1.9558,N/A,24.377,7.4373,N/A,0.85855,410,N/A,N/A,N/A,4.684,N/A,4.9298,10.902,N/A,N/A,0.9834,148.7,10.2615,7.5503,N/A,N/A,19.6392,1.5457,5.4657,1.416,7.3971,8.2035,16179.78,3.5769,85.6435,1366.67,20.187,4.6241,1.6453,58.734,1.4227,36.614,18.2749,
2022-12-01,1.0454,142.48,1.9558,N/A,24.361,7.4373,N/A,0.85715,413.5,N/A,N/A,N/A,4.6998,N/A,4.9303,10.8984,N/A,N/A,0.9868,148.7,10.2495,7.55,N/A,N/A,19.4778,1.5377,5.4508,1.4059,7.3965,8.1371,16160.84,3.5642,84.933,1363.81,20.1472,4.605,1.6446,58.793,1.4195,36.526,18.5393,
2022-11-30,1.0376,144.28,1.9558,N/A,24.338,7.4366,N/A,0.86488,408.4,N/A,N/A,N/A,4.6635,N/A,4.9245,10.9345,N/A,N/A,0.9854,147.1,10.2648,7.549,N/A,N/A,19.3333,1.5425,5.5063,1.4021,7.3437,8.0944,16271.81,3.5691,84.4215,1365.14,20.0111,4.6147,1.6634,58.697,1.418,36.588,17.5768,
2022-11-29,1.0366,143.36,1.9558,N/A,24.334,7.4367,N/A,0.86218,406.5,N/A,N/A,N/A,4.673,N/A,4.9193,10.901,N/A,N/A,0.9862,147.1,10.3313,7.55,N/A,N/A,19.3181,1.5414,5.5126,1.4005,7.4289,8.0965,16301.58,3.5581,84.6548,1375.7,19.8075,4.6735,1.6639,58.64,1.4237,36.706,17.6027,
2022-11-28,1.0463,144.9,1.9558,N/A,24.348,7.4367,N/A,0.86606,408.87,N/A,N/A,N/A,4.6938,N/A,4.9246,10.8973,N/A,N/A,0.9872,146.7,10.364,7.5488,N/A,N/A,19.4844,1.5632,5.6354,1.4062,7.5326,8.1782,16440.45,3.6002,85.437,1396.56,20.22,4.6874,1.6827,59.21,1.4375,37.285,17.9376,
2022-11-25,1.0375,144.62,1.9558,N/A,24.367,7.4365,N/A,0.85885,411.33,N/A,N/A,N/A,4.6875,N/A,4.9255,10.8183,N/A,N/A,0.9836,146.5,10.2985,7.5473,N/A,N/A,19.3333,1.5404,5.5476,1.3864,7.4425,8.1084,16282.44,3.5551,84.7145,1383.2,20.1069,4.648,1.6651,58.795,1.4277,37.153,17.7677,
2022-11-24,1.0413,143.9,1.9558,N/A,24.392,7.4369,N/A,0.85933,413.33,N/A,N/A,N/A,4.6958,N/A,4.9205,10.8573,N/A,N/A,0.9818,146.5,10.3435,7.547,N/A,N/A,19.3969,1.5414,5.5504,1.3894,7.4442,8.1324,16295.35,3.5607,85.0295,1382.28,20.1501,4.6806,1.6598,58.992,1.4319,37.258,17.7246,
2022-11-23,1.0325,145.75,1.9558,N/A,24.356,7.437,N/A,0.86369,405.75,N/A,N/A,N/A,4.7033,N/A,4.937,10.8933,N/A,N/A,0.9795,146.7,10.3659,7.5435,N/A,N/A,19.2316,1.5522,5.565,1.3856,7.3982,8.0708,16189.81,3.5681,84.466,1397.42,20.001,4.7237,1.6718,58.914,1.4295,37.423,17.7103,
2022-11-22,1.0274,145.2,1.9558,N/A,24.351,7.4377,N/A,0.86358,408.23,N/A,N/A,N/A,4.7125,N/A,4.9269,10.9653,N/A,N/A,0.9791,145.7,10.4445,7.5438,N/A,N/A,19.1221,1.5473,5.4578,1.3765,7.3344,8.0313,16106.79,3.5615,83.8768,1392.68,20.0951,4.7055,1.6707,58.942,1.4167,37.11,17.7568,
2022-11-21,1.0246,145.33,1.9558,N/A,24.356,7.4377,N/A,0.86793,409.43,N/A,N/A,N/A,4.7075,N/A,4.9413,10.9873,N/A,N/A,0.9817,147.9,10.4898,7.5425,N/A,N/A,19.0822,1.5471,5.4401,1.377,7.3419,7.9989,16116.76,3.5515,83.7375,1395,19.9357,4.6927,1.6766,58.822,1.4162,37.121,17.7858,
2022-11-18,1.0366,145.12,1.9558,N/A,24.351,7.4385,N/A,0.87063,407.41,N/A,N/A,N/A,4.7033,N/A,4.9413,10.9805,N/A,N/A,0.9881,148.9,10.486,7.5415,N/A,N/A,19.3009,1.5433,5.547,1.3841,7.379,8.1092,16224.36,3.591,84.6875,1389.02,20.162,4.7202,1.6757,59.41,1.4229,37.069,17.908,
2022-11-17,1.0319,144.8,1.9558,N/A,24.399,7.4383,N/A,0.87475,415.6,N/A,N/A,N/A,4.7153,N/A,4.9254,10.9871,N/A,N/A,0.9818,148.9,10.498,7.541,N/A,N/A,19.2124,1.5526,5.6535,1.382,7.3859,8.077,16224.01,3.5796,84.394,1394.06,20.062,4.7122,1.6986,59.293,1.4221,37.123,18.0961,
2022-11-16,1.0412,145.29,1.9558,N/A,24.355,7.4386,N/A,0.87483,408.18,N/A,N/A,N/A,4.7065,N/A,4.9206,10.8754,N/A,N/A,0.9795,148.9,10.3675,7.5443,N/A,N/A,19.3783,1.54,5.5438,1.3801,7.372,8.1444,16248.37,3.5684,84.5905,1378.1,20.1227,4.7323,1.6897,59.678,1.425,37.103,18.0195,
2022-11-15,1.0404,144.84,1.9558,N/A,24.326,7.4388,N/A,0.87455,405.45,N/A,N/A,N/A,4.7073,N/A,4.9116,10.8081,N/A,N/A,0.979,149.9,10.357,7.5459,N/A,N/A,19.3608,1.5415,5.548,1.3816,7.3299,8.143,16164.78,3.5694,84.1304,1365.61,20.0795,4.7208,1.6897,59.532,1.4238,36.939,17.8822,
2022-11-14,1.0319,144.86,1.9558,N/A,24.289,7.4382,N/A,0.87513,407.28,N/A,N/A,N/A,4.6898,N/A,4.9043,10.7713,N/A,N/A,0.9751,150.3,10.3143,7.5465,N/A,N/A,19.1923,1.5427,5.4605,1.3706,7.2906,8.0852,16052.12,3.541,83.7779,1369.32,20.0985,4.7429,1.6957,59.04,1.4177,36.978,17.8393,
2022-11-11,1.0308,143.89,1.9558,N/A,24.278,7.4384,N/A,0.87538,402.08,N/A,N/A,N/A,4.6765,N/A,4.894,10.7241,N/A,N/A,0.9844,148.7,10.2635,7.5445,N/A,N/A,19.0987,1.5459,5.5147,1.3698,7.3267,8.0758,15979.45,3.5255,83.2253,1359.2,20.0239,4.77,1.702,59.106,1.4199,37.088,17.7944,
2022-11-10,0.9954,145.47,1.9558,N/A,24.361,7.4381,N/A,0.87298,400.95,N/A,N/A,N/A,4.706,N/A,4.8913,10.8743,N/A,N/A,0.9834,147.5,10.3615,7.5427,N/A,N/A,18.51,1.5525,5.286,1.3467,7.2184,7.8128,15615.6,3.5453,81.3058,1373.96,19.4562,4.6789,1.6984,57.793,1.3963,36.7,17.6882,
2022-11-09,1.0039,146.82,1.9558,N/A,24.337,7.4382,N/A,0.87774,403.53,N/A,N/A,N/A,4.701,N/A,4.9045,10.845,N/A,N/A,0.988,146.7,10.322,7.5425,N/A,N/A,18.6728,1.5538,5.1947,1.3501,7.2813,7.8801,15717.07,3.5621,81.6575,1369.73,19.6554,4.7098,1.7033,58.236,1.4061,36.999,17.877,
2022-11-08,0.9996,146.25,1.9558,N/A,24.326,7.4378,N/A,0.87378,400.75,N/A,N/A,N/A,4.6918,N/A,4.8978,10.8373,N/A,N/A,0.9911,146.3,10.2795,7.539,N/A,N/A,18.5991,1.5435,5.203,1.3489,7.2495,7.8468,15652.76,3.5436,81.518,1377.94,19.4495,4.7346,1.686,58.187,1.4022,37.22,17.8397,
2022-11-07,0.9993,146.18,1.9558,N/A,24.301,7.4393,N/A,0.87135,401.03,N/A,N/A,N/A,4.6865,N/A,4.8855,10.832,N/A,N/A,0.9874,145.9,10.2555,7.5375,N/A,N/A,18.5875,1.5428,5.07,1.3464,7.2189,7.8444,15648.95,3.5402,81.8407,1391.25,19.4395,4.7362,1.6834,58.361,1.4022,37.284,17.7583,
2022-11-04,0.9872,145.19,1.9558,N/A,24.422,7.4419,N/A,0.87478,401.15,N/A,N/A,N/A,4.6825,N/A,4.8893,10.8538,N/A,N/A,0.9863,145.5,10.2019,7.5353,N/A,N/A,18.3845,1.5311,4.9682,1.3351,7.0894,7.7493,15491.81,3.5065,81.02,1397.7,19.2611,4.6872,1.6769,57.672,1.3891,36.906,17.7983,
2022-11-03,0.9753,144.58,1.9558,N/A,24.539,7.4433,N/A,0.87228,407.87,N/A,N/A,N/A,4.709,N/A,4.9013,10.932,N/A,N/A,0.9889,144.9,10.3543,7.5375,N/A,N/A,18.1602,1.5517,5.0262,1.3452,7.1367,7.656,15400.2,3.4847,80.8845,1391.75,19.2363,4.6271,1.6957,57.463,1.3878,37.091,18.0173,
2022-11-02,0.9908,145.75,1.9558,N/A,24.506,7.4431,N/A,0.861,407,N/A,N/A,N/A,4.7035,N/A,4.912,10.9065,N/A,N/A,0.9861,143.7,10.2388,7.5335,N/A,N/A,18.4488,1.5426,5.0964,1.347,7.2156,7.7774,15492.57,3.4987,81.992,1402.01,19.4921,4.6944,1.6844,57.841,1.3983,37.314,17.9608,
2022-11-01,0.9947,146.35,1.9558,N/A,24.484,7.4438,N/A,0.86058,406.9,N/A,N/A,N/A,4.7053,N/A,4.9138,10.874,N/A,N/A,0.9878,143.3,10.1835,7.5342,N/A,N/A,18.5216,1.5409,5.1337,1.3469,7.2165,7.8079,15534.6,3.4922,82.084,1404.63,19.5984,4.7119,1.6876,57.786,1.4017,37.45,17.9802,
2022-10-31,0.9914,147.4,1.9558,N/A,24.488,7.4444,N/A,0.86115,409.65,N/A,N/A,N/A,4.7085,N/A,4.9143,10.901,N/A,N/A,0.9925,143.3,10.3028,7.531,N/A,N/A,18.4562,1.5529,5.2694,1.3553,7.238,7.7822,15489.55,3.4933,82.1035,1416.12,19.7122,4.6873,1.7099,57.8,1.4038,37.748,18.1736,
2022-10-28,0.9951,146.79,1.9558,N/A,24.465,7.4423,N/A,0.8612,411.7,N/A,N/A,N/A,4.7275,N/A,4.9189,10.9403,N/A,N/A,0.992,143.3,10.2695,7.532,N/A,N/A,18.5219,1.5511,5.327,1.3542,7.2159,7.8107,15481.88,3.5215,82.0565,1417.7,19.7718,4.6994,1.7151,57.739,1.4055,37.724,18.053,
2022-10-27,1.0037,147.37,1.9558,N/A,24.53,7.4387,N/A,0.86745,412.15,N/A,N/A,N/A,4.7585,N/A,4.8893,10.9583,N/A,N/A,0.9949,143.1,10.342,7.533,N/A,N/A,18.681,1.561,5.3889,1.3672,7.2552,7.8782,15629.06,3.5376,82.656,1428.57,20.015,4.7324,1.7316,58.441,1.4154,37.975,18.1521,
2022-10-26,1.0023,147.32,1.9558,N/A,24.535,7.4381,N/A,0.86603,408.09,N/A,N/A,N/A,4.7548,N/A,4.8806,10.953,N/A,N/A,0.9917,143.5,10.3408,7.532,N/A,N/A,18.6461,1.5466,5.2944,1.3568,7.1948,7.8678,15589.27,3.5145,82.206,1422.11,19.8501,4.7262,1.7249,58.493,1.4104,37.862,18.0212,
2022-10-25,0.9861,146.84,1.9558,N/A,24.472,7.4387,N/A,0.87143,413.7,N/A,N/A,N/A,4.777,N/A,4.9036,10.9728,N/A,N/A,0.9888,142.9,10.391,7.5315,N/A,N/A,18.3508,1.5599,5.2254,1.3537,7.2072,7.7407,15407.12,3.506,81.653,1417.5,19.6353,4.6697,1.7321,57.988,1.405,37.758,18.2211,
2022-10-24,0.9851,146.76,1.9558,N/A,24.482,7.4385,N/A,0.8707,411.88,N/A,N/A,N/A,4.7908,N/A,4.9128,11.0795,N/A,N/A,0.9856,142.5,10.392,7.5337,N/A,N/A,18.3298,1.5631,5.1461,1.3502,7.1544,7.7329,15362.63,3.4997,81.5451,1418.4,19.6514,4.6674,1.7343,58.021,1.4008,37.6,18.0625,
2022-10-21,0.973,147.59,1.9558,N/A,24.511,7.4382,N/A,0.87728,412.88,N/A,N/A,N/A,4.7885,N/A,4.9125,11.0868,N/A,N/A,0.9855,141.1,10.4315,7.5325,N/A,N/A,18.0988,1.5646,5.1117,1.3465,7.0504,7.6376,15199.12,3.4803,80.739,1404.32,19.5521,4.6101,1.7347,57.287,1.3917,37.349,18.0021,
2022-10-20,0.9811,146.99,1.9558,N/A,24.525,7.4389,N/A,0.87258,411.2,N/A,N/A,N/A,4.7728,N/A,4.9203,10.982,N/A,N/A,0.9836,141.1,10.402,7.5353,N/A,N/A,18.2257,1.5554,5.1387,1.3461,7.0858,7.7008,15250.05,3.4754,81.1755,1400.3,19.7005,4.6396,1.7206,57.742,1.3959,37.36,17.9106,
2022-10-19,0.9778,146.34,1.9558,N/A,24.563,7.439,N/A,0.86993,413.78,N/A,N/A,N/A,4.7878,N/A,4.9248,10.9448,N/A,N/A,0.981,141.1,10.3823,7.5325,N/A,N/A,18.1793,1.5568,5.1755,1.3479,7.0672,7.6757,15185.1,3.4628,81.1955,1398.35,19.6845,4.6152,1.7264,57.741,1.3931,37.469,17.8339,
2022-10-18,0.9835,146.65,1.9558,N/A,24.593,7.4393,N/A,0.86928,413.08,N/A,N/A,N/A,4.804,N/A,4.9359,10.906,N/A,N/A,0.9792,141.5,10.3528,7.5298,N/A,N/A,18.2813,1.5557,5.1795,1.3495,7.0805,7.72,15214.98,3.464,80.9195,1400.92,19.664,4.6382,1.7251,57.897,1.3963,37.422,17.7904,
2022-10-17,0.9739,145,1.9558,N/A,24.562,7.4379,N/A,0.8625,418.3,N/A,N/A,N/A,4.8143,N/A,4.937,10.9893,N/A,N/A,0.9762,140.9,10.342,7.5265,N/A,N/A,18.1043,1.5599,5.1497,1.3452,7.013,7.6448,15061.8,3.4486,80.128,1399.41,19.5,4.5934,1.7404,57.433,1.3896,37.169,17.6769,
2022-10-14,0.9717,143.63,1.9558,N/A,24.587,7.4378,N/A,0.86823,418.24,N/A,N/A,N/A,4.8328,N/A,4.9335,11.0035,N/A,N/A,0.9757,140.5,10.3323,7.5266,N/A,N/A,18.0614,1.5493,5.1177,1.3426,6.9952,7.6278,15031.5,3.444,79.9695,1398.5,19.5032,4.5689,1.7302,57.375,1.3852,37.109,17.6932,
2022-10-13,0.9739,142.94,1.9558,N/A,24.569,7.4385,N/A,0.86513,430.65,N/A,N/A,N/A,4.8303,N/A,4.9355,11.0098,N/A,N/A,0.9725,140.5,10.3525,7.531,N/A,N/A,18.1041,1.5495,5.1214,1.3443,6.9945,7.644,14952.86,3.4731,79.9981,1392.71,19.4442,4.5691,1.7314,57.352,1.3949,36.843,17.8173,
2022-10-12,0.9706,142.34,1.9558,N/A,24.561,7.4399,N/A,0.8784,429.65,N/A,N/A,N/A,4.8495,N/A,4.94,11.02,N/A,N/A,0.9664,140.1,10.4145,7.529,N/A,N/A,18.0427,1.5525,5.1378,1.3395,6.9603,7.6192,14907.04,3.4623,79.8955,1384.66,19.4522,4.5448,1.7372,57.148,1.3941,36.902,17.6876,
2022-10-11,0.9723,141.54,1.9558,N/A,24.535,7.439,N/A,0.87703,428.73,N/A,N/A,N/A,4.869,N/A,4.9394,11.0015,N/A,N/A,0.9675,140.7,10.4235,7.5293,N/A,N/A,18.0686,1.545,5.0456,1.3402,6.9669,7.6325,14930.83,3.4776,79.9555,1392.84,19.4115,4.5436,1.7323,57.243,1.3967,37.03,17.6153,
2022-10-10,0.9697,141.16,1.9558,N/A,24.521,7.4384,N/A,0.8773,428.2,N/A,N/A,N/A,4.8655,N/A,4.94,10.9502,N/A,N/A,0.968,139.9,10.3378,7.528,N/A,N/A,18.0131,1.536,5.0328,1.3312,6.9344,7.612,14872.51,3.4463,79.9678,1384.26,19.3588,4.5091,1.7369,57.197,1.3939,36.81,17.5866,
2022-10-07,0.9797,141.92,1.9558,N/A,24.517,7.4381,N/A,0.87383,423.85,N/A,N/A,N/A,4.8595,N/A,4.9415,10.8555,N/A,N/A,0.97,140.7,10.4498,7.527,N/A,N/A,18.209,1.5266,5.1075,1.3437,6.9715,7.6906,14933.14,3.4477,80.546,1381.42,19.643,4.5556,1.7328,57.747,1.3996,36.602,17.6222,
2022-10-06,0.986,142.68,1.9558,N/A,24.479,7.439,N/A,0.87583,422.59,N/A,N/A,N/A,4.8505,N/A,4.9364,10.8728,N/A,N/A,0.9709,139.9,10.4278,7.5288,N/A,N/A,18.3191,1.5263,5.1185,1.3475,7.0164,7.74,15021.24,3.4846,81.0615,1388.39,19.817,4.5726,1.728,57.949,1.4057,36.827,17.5769,
2022-10-05,0.9915,143.18,1.9558,N/A,24.524,7.4388,N/A,0.8734,423.6,N/A,N/A,N/A,4.791,N/A,4.9385,10.8376,N/A,N/A,0.9756,141.3,10.4858,7.5255,N/A,N/A,18.4201,1.538,5.1575,1.3493,7.0555,7.7831,15061.81,3.503,80.909,1406.71,19.8625,4.5911,1.7419,58.212,1.4124,37.102,17.6228,
2022-10-04,0.9891,143.3,1.9558,N/A,24.544,7.4374,N/A,0.87273,417.68,N/A,N/A,N/A,4.8193,N/A,4.9418,10.8166,N/A,N/A,0.9767,141.9,10.4915,7.523,N/A,N/A,18.3374,1.5318,5.0589,1.3503,7.0384,7.7644,15080.18,3.4885,80.6995,1412.2,19.777,4.5939,1.7368,58.104,1.4148,37.16,17.5437,
2022-10-03,0.9764,141.49,1.9558,N/A,24.527,7.4366,N/A,0.8707,424.86,N/A,N/A,N/A,4.832,N/A,4.9479,10.8743,N/A,N/A,0.9658,141.7,10.5655,7.5275,N/A,N/A,18.124,1.5128,5.178,1.3412,6.9481,7.6647,14969.79,3.498,79.898,1408.25,19.604,4.5383,1.7263,57.599,1.4015,37.181,17.5871,
2022-09-30,0.9748,141.01,1.9558,N/A,24.549,7.4365,N/A,0.883,422.18,N/A,N/A,N/A,4.8483,N/A,4.949,10.8993,N/A,N/A,0.9561,140.9,10.5838,7.524,N/A,N/A,18.0841,1.5076,5.2584,1.3401,6.9368,7.6521,14863.26,3.4759,79.425,1400.69,19.6393,4.5201,1.7177,57.276,1.4001,36.823,17.5353,
2022-09-29,0.9706,140.46,1.9558,N/A,24.687,7.4365,N/A,0.89485,421.93,N/A,N/A,N/A,4.857,N/A,4.9481,10.958,N/A,N/A,0.9538,140.1,10.4518,7.528,N/A,N/A,18,1.4982,5.2521,1.3294,6.9223,7.6192,14735.97,3.4422,79.314,1388.34,19.5779,4.4992,1.704,56.86,1.3961,36.946,17.4466,
2022-09-28,0.9565,138.39,1.9558,N/A,24.65,7.4368,N/A,0.90268,411.72,N/A,N/A,N/A,4.8043,N/A,4.9485,10.9194,N/A,N/A,0.9437,139.7,10.4576,7.5313,N/A,N/A,17.7311,1.4924,5.1728,1.3157,6.9199,7.5084,14622.96,3.3931,78.2655,1378.84,19.5294,4.4281,1.6998,56.528,1.3846,36.687,17.2916,
2022-09-27,0.9644,139.28,1.9558,N/A,24.661,7.4366,N/A,0.89275,406.65,N/A,N/A,N/A,4.764,N/A,4.9444,10.8533,N/A,N/A,0.9503,139.3,10.3473,7.528,N/A,N/A,17.824,1.4859,5.1235,1.3196,6.9156,7.5704,14604.52,3.3714,78.574,1370.06,19.5832,4.4466,1.6921,56.933,1.3838,36.565,17.2361,
2022-09-26,0.9646,139.07,1.9558,N/A,24.64,7.4365,N/A,0.89404,408.83,N/A,N/A,N/A,4.7608,N/A,4.9418,10.9275,N/A,N/A,0.9555,138.9,10.3585,7.5278,N/A,N/A,17.8001,1.4858,5.1504,1.3195,6.9075,7.572,14620.74,3.4069,78.704,1379.4,19.6066,4.4401,1.6886,56.908,1.3842,36.496,17.4247,
2022-09-23,0.9754,139.43,1.9558,N/A,24.658,7.4365,N/A,0.88201,406.3,N/A,N/A,N/A,4.7543,N/A,4.9433,10.9328,N/A,N/A,0.9565,139.9,10.2335,7.5228,N/A,N/A,17.9515,1.4828,5.0456,1.3177,6.9442,7.6567,14697.3,3.4152,79.0705,1381.97,19.5708,4.4659,1.6846,57.217,1.3897,36.636,17.3853,
2022-09-22,0.9884,139.18,1.9558,N/A,24.657,7.4365,N/A,0.87256,405.25,N/A,N/A,N/A,4.7592,N/A,4.9411,10.8724,N/A,N/A,0.9684,139.9,10.235,7.5235,N/A,N/A,18.1559,1.484,5.0677,1.3278,6.9804,7.7583,14824.28,3.4216,79.897,1384.79,19.6129,4.514,1.6832,57.721,1.3998,36.803,17.3514,
2022-09-21,0.9906,142.66,1.9558,N/A,24.637,7.4364,N/A,0.87335,405.1,N/A,N/A,N/A,4.7505,N/A,4.9443,10.9214,N/A,N/A,0.9549,140.3,10.2858,7.5205,N/A,N/A,18.149,1.4851,5.0924,1.3262,6.9821,7.7761,14866.28,3.4298,79.1555,1381.38,19.7847,4.5097,1.6844,57.285,1.4006,36.786,17.4879,
2022-09-20,0.9986,143.34,1.9558,N/A,24.556,7.4368,N/A,0.87395,398.58,N/A,N/A,N/A,4.7208,N/A,4.934,10.8338,N/A,N/A,0.9644,140.9,10.273,7.5198,N/A,N/A,18.2833,1.4893,5.2139,1.3268,7.003,7.8382,14997.82,3.4406,79.6095,1390.71,19.9667,4.5516,1.6908,57.497,1.4074,36.968,17.7261,
2022-09-19,0.999,143.42,1.9558,N/A,24.494,7.4373,N/A,0.87785,400.85,N/A,N/A,N/A,4.7058,N/A,4.93,10.7993,N/A,N/A,0.9658,139.9,10.2826,7.5215,N/A,N/A,18.2738,1.495,5.2886,1.3294,7.0066,7.8416,14975.43,3.446,79.653,1391.82,20.113,4.5455,1.6807,57.347,1.4082,36.983,17.7267,
2022-09-16,0.9954,142.53,1.9558,N/A,24.497,7.4366,N/A,0.874,403.98,N/A,N/A,N/A,4.7143,N/A,4.9238,10.7541,N/A,N/A,0.9579,138.3,10.1985,7.5235,N/A,N/A,18.1923,1.4894,5.2279,1.3226,6.9787,7.8133,14904.67,3.4267,79.3605,1383.58,20.0028,4.5141,1.6717,57.111,1.4025,36.8,17.6004,
2022-09-15,0.9992,143.43,1.9558,N/A,24.518,7.4366,N/A,0.86934,407.15,N/A,N/A,N/A,4.7273,N/A,4.9238,10.69,N/A,N/A,0.9572,138.7,10.1203,7.5258,N/A,N/A,18.2477,1.4853,5.1837,1.3172,6.9852,7.8423,14925.35,3.4384,79.7119,1397.18,20.0021,4.5314,1.6689,57.258,1.4062,36.816,17.5283,
2022-09-14,0.999,143.08,1.9558,N/A,24.527,7.4366,N/A,0.86498,402.9,N/A,N/A,N/A,4.7163,N/A,4.9297,10.675,N/A,N/A,0.9612,139.7,10.1125,7.5195,N/A,N/A,18.2397,1.4873,5.1827,1.3177,6.955,7.8405,14903.93,3.4339,79.422,1391.97,20.028,4.5225,1.6675,57.054,1.4039,36.608,17.4342,
2022-09-13,1.0175,144.5,1.9558,N/A,24.551,7.4366,N/A,0.86793,396.83,N/A,N/A,N/A,4.705,N/A,4.921,10.6108,N/A,N/A,0.9669,140.1,9.9988,7.5255,N/A,N/A,18.564,1.4736,5.1764,1.32,7.0467,7.9855,15099.17,3.4125,80.5453,1397.3,20.1615,4.5869,1.6555,57.665,1.4186,36.859,17.3112,
2022-09-12,1.0155,144.49,1.9558,N/A,24.546,7.4365,N/A,0.86778,395.73,N/A,N/A,N/A,4.6965,N/A,4.9135,10.6368,N/A,N/A,0.9667,140.9,9.9718,7.5195,N/A,N/A,18.5232,1.4749,5.1933,1.3194,7.0348,7.9709,15083.83,3.4346,80.692,1397.58,20.1025,4.5733,1.6499,57.701,1.4168,36.873,17.322,
2022-09-09,1.0049,143.3,1.9558,N/A,24.536,7.4365,N/A,0.8686,396.3,N/A,N/A,N/A,4.721,N/A,4.9019,10.6643,N/A,N/A,0.9657,140.9,9.9836,7.5245,N/A,N/A,18.3282,1.4704,5.2087,1.307,6.9543,7.8871,14905.33,3.4416,79.9685,1384.64,19.991,4.52,1.6463,57.098,1.4063,36.508,17.3753,
2022-09-08,1.0009,143.65,1.9558,N/A,24.543,7.4365,N/A,0.86656,395.48,N/A,N/A,N/A,4.7155,N/A,4.8756,10.7075,N/A,N/A,0.9739,140.3,10.0615,7.515,N/A,N/A,18.2546,1.4824,5.2042,1.3134,6.9564,7.8568,14891.86,3.429,79.7375,1381.7,20.013,4.5051,1.6491,57.031,1.4054,36.418,17.3797,
2022-09-07,0.9885,143.2,1.9558,N/A,24.631,7.4365,N/A,0.8651,401.83,N/A,N/A,N/A,4.729,N/A,4.8585,10.6888,N/A,N/A,0.975,141.3,9.9483,7.5143,N/A,N/A,18.0262,1.4748,5.1881,1.3037,6.8968,7.7596,14779.47,3.4053,79.028,1374.44,19.9225,4.4497,1.6459,56.532,1.3931,36.322,17.2582,
2022-09-06,0.9928,140.91,1.9558,N/A,24.55,7.4365,N/A,0.85743,402.65,N/A,N/A,N/A,4.7068,N/A,4.8424,10.6825,N/A,N/A,0.9745,141.9,9.8945,7.5133,N/A,N/A,18.0938,1.4651,5.13,1.3029,6.9091,7.7932,14783.94,3.39,79.2305,1366.65,19.8545,4.4676,1.6313,56.655,1.3947,36.242,17.0805,
2022-09-05,0.992,139.47,1.9558,N/A,24.622,7.4364,N/A,0.86358,403.9,N/A,N/A,N/A,4.736,N/A,4.8198,10.729,N/A,N/A,0.9747,142.7,9.9188,7.5173,N/A,N/A,18.0792,1.4616,5.1407,1.3043,6.8768,7.7867,14782.83,3.3826,79.2332,1359.98,19.8192,4.4563,1.6289,56.477,1.3932,36.263,17.088,
2022-09-02,0.9993,140.36,1.9558,N/A,24.481,7.437,N/A,0.86478,398.38,N/A,N/A,N/A,4.7063,N/A,4.8335,10.7498,N/A,N/A,0.9839,141.5,10.0035,7.5225,N/A,N/A,18.2072,1.4671,5.2153,1.3131,6.9031,7.8439,14895.92,3.396,79.8096,1360.84,20.1024,4.4809,1.6394,56.854,1.4013,36.624,17.2791,
2022-09-01,1.0004,139.34,1.9558,N/A,24.488,7.4372,N/A,0.86473,399.58,N/A,N/A,N/A,4.7128,N/A,4.8447,10.7415,N/A,N/A,0.9802,141.7,10.013,7.521,N/A,N/A,18.2149,1.4651,5.2239,1.3169,6.9017,7.8511,14878,3.3644,79.6195,1353.69,20.1954,4.4828,1.6389,56.609,1.4002,36.71,17.1524,
2022-08-31,1,138.72,1.9558,N/A,24.55,7.4371,N/A,0.86035,402.8,N/A,N/A,N/A,4.7283,N/A,4.8595,10.6788,N/A,N/A,0.9796,141.7,9.9388,7.5148,N/A,N/A,18.1849,1.4591,5.1482,1.3111,6.8947,7.8488,14849.93,3.3399,79.5465,1342.79,20.2044,4.4755,1.6322,56.153,1.3969,36.45,17.0667,
2022-08-30,1.0034,138.71,1.9558,N/A,24.577,7.4376,N/A,0.85645,406.38,N/A,N/A,N/A,4.7323,N/A,4.8657,10.65,N/A,N/A,0.9741,142.1,9.7553,7.5103,N/A,N/A,18.239,1.4472,5.0286,1.3047,6.9233,7.8751,14875,3.3168,79.8025,1350.92,20.0077,4.4907,1.6245,56.393,1.3997,36.494,16.8567,
2022-08-29,0.9986,138.49,1.9558,N/A,24.592,7.4379,N/A,0.8542,409.9,N/A,N/A,N/A,4.745,N/A,4.8699,10.628,N/A,N/A,0.967,141.1,9.7675,7.5119,N/A,N/A,18.1605,1.4529,5.0663,1.3026,6.9044,7.8368,14871.09,3.3146,79.8295,1347.47,19.9876,4.4837,1.6305,56.187,1.395,36.399,16.8891,
2022-08-26,1.0007,137.02,1.9558,N/A,24.635,7.4379,N/A,0.8459,410.48,N/A,N/A,N/A,4.7485,N/A,4.8729,10.5703,N/A,N/A,0.9642,140.3,9.667,7.5135,N/A,N/A,18.1923,1.4333,5.1069,1.2944,6.8671,7.8521,14825.57,3.2537,79.9025,1333.46,19.924,4.4706,1.6112,56.109,1.3906,36.035,16.7995,
2022-08-25,0.997,136.07,1.9558,N/A,24.648,7.4374,N/A,0.84293,408.93,N/A,N/A,N/A,4.7578,N/A,4.8758,10.5525,N/A,N/A,0.9616,140.3,9.64,7.514,N/A,N/A,18.112,1.4306,5.0879,1.2881,6.8317,7.8234,14753.15,3.2791,79.6555,1331.98,19.8132,4.4586,1.6006,55.842,1.3857,35.732,16.7903,
2022-08-24,0.9934,135.74,1.9558,N/A,24.629,7.4381,N/A,0.84283,410.93,N/A,N/A,N/A,4.7668,N/A,4.88,10.586,N/A,N/A,0.9576,139.5,9.636,7.5125,N/A,N/A,18.0362,1.4389,5.0606,1.2908,6.822,7.795,14757.6,3.2599,79.3006,1332.84,19.7781,4.4559,1.6065,55.7,1.3857,35.906,16.8976,
2022-08-23,0.9927,136.34,1.9558,N/A,24.658,7.4374,N/A,0.84343,410.55,N/A,N/A,N/A,4.7788,N/A,4.8839,10.6063,N/A,N/A,0.9602,140.1,9.7438,7.5128,N/A,N/A,17.983,1.4437,5.0984,1.2928,6.7952,7.79,14743.28,3.2598,79.2805,1332.1,19.9152,4.4557,1.6071,55.661,1.386,35.856,16.9568,
2022-08-22,1.0001,137.08,1.9558,N/A,24.651,7.437,N/A,0.84658,408,N/A,N/A,N/A,4.764,N/A,4.8853,10.65,N/A,N/A,0.958,140.9,9.7719,7.5113,N/A,N/A,18.1268,1.4478,5.1752,1.2989,6.8457,7.8468,14895.47,3.2778,79.8615,1344.21,20.1583,4.4854,1.6125,56.218,1.3958,36.099,17.0766,
2022-08-19,1.0054,137.67,1.9558,N/A,24.625,7.4373,N/A,0.84938,407.35,N/A,N/A,N/A,4.751,N/A,4.8811,10.6095,N/A,N/A,0.9616,140.5,9.8418,7.5155,N/A,N/A,18.2028,1.4584,5.2334,1.3062,6.8531,7.8877,14951.91,3.2879,80.2988,1343.39,20.3273,4.5007,1.6203,56.325,1.3979,35.988,17.1007,
2022-08-18,1.0178,137.17,1.9558,N/A,24.611,7.4389,N/A,0.84391,405.13,N/A,N/A,N/A,4.724,N/A,4.8808,10.5903,N/A,N/A,0.9683,140.5,9.8283,7.5215,N/A,N/A,18.4095,1.4617,5.2326,1.3118,6.906,7.9844,15092.62,3.2993,81.042,1344.81,20.313,4.5536,1.6145,56.776,1.4053,36.254,17.0004,
2022-08-17,1.0164,137.36,1.9558,N/A,24.566,7.4377,N/A,0.84208,404.28,N/A,N/A,N/A,4.7078,N/A,4.8825,10.5617,N/A,N/A,0.9686,140.3,9.8428,7.5071,N/A,N/A,18.2568,1.4655,5.2838,1.3117,6.8917,7.9705,15015.81,3.311,80.7555,1337.02,20.3825,4.5413,1.6165,56.772,1.4051,36.052,16.9125,
2022-08-16,1.0131,136.11,1.9558,N/A,24.54,7.4368,N/A,0.84218,406.2,N/A,N/A,N/A,4.7043,N/A,4.882,10.5365,N/A,N/A,0.9625,140.3,9.8428,7.51,N/A,N/A,18.1994,1.4463,5.1835,1.3076,6.8767,7.9449,14968.68,3.3087,80.3745,1329.66,20.1595,4.5245,1.6012,56.602,1.398,35.93,16.6556,
2022-08-15,1.0195,135.61,1.9558,N/A,24.46,7.4373,N/A,0.84375,398.6,N/A,N/A,N/A,4.6858,N/A,4.8849,10.498,N/A,N/A,0.9631,140.3,9.871,7.5028,N/A,N/A,18.3143,1.4508,5.2268,1.3167,6.905,7.9899,15042.36,3.3294,81.061,1336.35,20.3914,4.5465,1.6002,57.122,1.4036,36.218,16.7375,
2022-08-12,1.0285,137.47,1.9558,N/A,24.38,7.4395,N/A,0.84715,392.3,N/A,N/A,N/A,4.6773,N/A,4.8915,10.4515,N/A,N/A,0.9689,140.3,9.813,7.5138,N/A,N/A,18.4733,1.4496,5.3007,1.3148,6.9352,8.06,15104.2,3.345,81.9935,1342.59,20.4925,4.5709,1.5985,57.246,1.4106,36.393,16.7318,
2022-08-11,1.0338,136.57,1.9558,N/A,24.346,7.4395,N/A,0.84575,394.18,N/A,N/A,N/A,4.6828,N/A,4.9055,10.36,N/A,N/A,0.9712,139.7,9.804,7.515,N/A,N/A,18.5674,1.4532,5.2447,1.3202,6.9668,8.1118,15215.93,3.3505,82.2845,1344.62,20.6398,4.5952,1.6045,57.225,1.4151,36.343,16.7083,
2022-08-10,1.0252,138.16,1.9558,N/A,24.397,7.4397,N/A,0.84608,397.65,N/A,N/A,N/A,4.7063,N/A,4.9138,10.3773,N/A,N/A,0.9713,139.7,9.9118,7.5158,N/A,N/A,18.4099,1.4682,5.251,1.3207,6.9222,8.046,15218.87,3.3773,81.468,1344.16,20.713,4.5693,1.6211,57.061,1.4107,36.42,16.8788,
2022-08-09,1.0234,138.26,1.9558,N/A,24.532,7.4407,N/A,0.8452,397.35,N/A,N/A,N/A,4.7085,N/A,4.9038,10.3875,N/A,N/A,0.9763,140.1,9.9365,7.514,N/A,N/A,18.3342,1.4687,5.2478,1.3163,6.9106,8.0334,15197.09,3.3865,81.406,1336.74,20.7145,4.5592,1.6304,56.939,1.411,36.264,17.05,
2022-08-08,1.0199,137.62,1.9558,N/A,24.515,7.4405,N/A,0.84165,394.27,N/A,N/A,N/A,4.7043,N/A,4.9163,10.365,N/A,N/A,0.9763,140.1,9.9405,7.5123,N/A,N/A,18.3175,1.4607,5.238,1.3134,6.8931,8.0061,15147.65,3.3895,81.166,1329.93,20.681,4.5477,1.6202,56.554,1.4058,36.38,16.9694,
2022-08-05,1.0233,136.22,1.9558,N/A,24.581,7.4415,N/A,0.84268,393.78,N/A,N/A,N/A,4.7085,N/A,4.9251,10.3573,N/A,N/A,0.9776,138.9,9.982,7.5148,N/A,N/A,18.3853,1.4713,5.3348,1.3185,6.9068,8.0328,15236.2,3.4033,81.0469,1324.53,20.8367,4.5598,1.6248,56.524,1.4077,36.373,17.0342,
2022-08-04,1.0181,135.81,1.9558,N/A,24.659,7.4425,N/A,0.84231,395.98,N/A,N/A,N/A,4.7233,N/A,4.9261,10.374,N/A,N/A,0.9765,138.7,9.9065,7.515,N/A,N/A,18.2922,1.4607,5.3614,1.307,6.8769,7.9919,15200.94,3.4101,80.7715,1333.7,20.756,4.5387,1.6172,56.633,1.4037,36.606,17.0352,
2022-08-03,1.0194,136.18,1.9558,N/A,24.65,7.4427,N/A,0.83629,395.03,N/A,N/A,N/A,4.691,N/A,4.9245,10.3913,N/A,N/A,0.9773,139.3,9.8743,7.5178,N/A,N/A,18.3112,1.4681,5.3547,1.3085,6.883,8.0022,15184.35,3.4362,80.6895,1336.03,21.0788,4.5435,1.6266,56.855,1.4069,36.963,17.1283,
2022-08-02,1.0224,133.9,1.9558,N/A,24.644,7.4432,N/A,0.83665,396.82,N/A,N/A,N/A,4.7063,N/A,4.9298,10.3995,N/A,N/A,0.9744,139.3,9.9305,7.5195,N/A,N/A,18.3564,1.4745,5.3175,1.315,6.9117,8.0257,15204.85,3.4486,80.3243,1339.16,20.952,4.5531,1.6254,56.834,1.4103,36.914,16.982,
2022-08-01,1.0233,135.38,1.9558,N/A,24.628,7.4457,N/A,0.837,401.35,N/A,N/A,N/A,4.734,N/A,4.9283,10.3668,N/A,N/A,0.9717,138.7,9.8638,7.521,N/A,N/A,18.3475,1.4535,5.2723,1.3076,6.9105,8.0329,15203.21,3.4546,80.9335,1333.3,20.7635,4.5568,1.616,56.734,1.4087,36.977,16.8613,
2022-07-29,1.0198,136.42,1.9558,N/A,24.61,7.4438,N/A,0.8399,404.8,N/A,N/A,N/A,4.7375,N/A,4.9343,10.3875,N/A,N/A,0.9744,138.3,9.8773,7.518,N/A,N/A,18.2472,1.4646,5.2739,1.31,6.8705,8.0054,15155.56,3.4714,80.882,1329.4,20.6745,4.5386,1.6283,56.375,1.4088,36.978,16.8627,
2022-07-28,1.0122,137.26,1.9558,N/A,24.609,7.4442,N/A,0.83586,407.3,N/A,N/A,N/A,4.7908,N/A,4.9342,10.449,N/A,N/A,0.9745,138.7,9.8983,7.52,N/A,N/A,18.1417,1.4535,5.33,1.2986,6.8325,7.9456,15107.59,3.4701,80.6535,1320.45,20.676,4.5071,1.6172,56.592,1.4009,37.097,17.0011,
2022-07-27,1.0152,138.89,1.9558,N/A,24.575,7.4446,N/A,0.84138,404.67,N/A,N/A,N/A,4.7978,N/A,4.9334,10.4545,N/A,N/A,0.9768,139.1,9.9558,7.514,N/A,N/A,18.1859,1.462,5.4039,1.3049,6.8534,7.9692,15213.07,3.4855,81.135,1333.99,20.753,4.5263,1.6306,56.455,1.4088,37.4,17.1347,
2022-07-26,1.0124,138.35,1.9558,N/A,24.607,7.4449,N/A,0.84558,400.99,N/A,N/A,N/A,4.742,N/A,4.9324,10.4445,N/A,N/A,0.9765,139.1,10.0105,7.5145,N/A,N/A,18.0705,1.4605,5.4437,1.3035,6.8451,7.9466,15185.27,3.4891,80.805,1326.65,20.7845,4.5113,1.6235,56.16,1.4066,37.18,17.087,
2022-07-25,1.0236,139.84,1.9558,N/A,24.535,7.4449,N/A,0.84813,396.5,N/A,N/A,N/A,4.708,N/A,4.9339,10.3973,N/A,N/A,0.9869,139.5,10.0704,7.5195,N/A,N/A,18.2653,1.4707,5.5976,1.3168,6.9094,8.0345,15303.87,3.5201,81.6675,1341.25,20.9376,4.5586,1.6325,57.209,1.4176,37.525,17.1502,
2022-07-22,1.019,139.51,1.9558,N/A,24.514,7.4443,N/A,0.85141,398.3,N/A,N/A,N/A,4.7508,N/A,4.9321,10.4328,N/A,N/A,0.9832,139.5,10.1498,7.5234,N/A,N/A,18.094,1.4677,5.5821,1.3105,6.8852,7.9985,15275.69,3.5083,81.384,1335.66,20.9595,4.5366,1.6265,57.24,1.4151,37.392,17.2009,
2022-07-21,1.0199,141.46,1.9558,N/A,24.496,7.4446,N/A,0.85545,400.13,N/A,N/A,N/A,4.761,N/A,4.9391,10.426,N/A,N/A,0.9924,139.7,10.175,7.52,N/A,N/A,18.0327,1.4848,5.5777,1.3178,6.904,8.0056,15342.25,3.5203,81.451,1337.47,20.941,4.5457,1.6479,57.512,1.4218,37.66,17.5195,
2022-07-20,1.0199,140.92,1.9558,N/A,24.493,7.4452,N/A,0.85178,399.5,N/A,N/A,N/A,4.782,N/A,4.9396,10.4606,N/A,N/A,0.9896,139.5,10.1323,7.5143,N/A,N/A,17.9444,1.4767,5.5427,1.3132,6.8892,8.0062,15275.82,3.5147,81.599,1337.61,20.8967,4.5406,1.6308,57.398,1.4204,37.405,17.3924,
2022-07-19,1.0245,141.01,1.9558,N/A,24.555,7.4449,N/A,0.85303,397.45,N/A,N/A,N/A,4.7598,N/A,4.9395,10.4964,N/A,N/A,0.9918,138.9,10.176,7.5093,N/A,N/A,18.018,1.4869,5.5454,1.3264,6.9064,8.0423,15344.49,3.5295,81.898,1340.33,20.8552,4.559,1.6456,57.583,1.4269,37.492,17.457,
2022-07-18,1.0131,140.16,1.9558,N/A,24.508,7.4435,N/A,0.84708,402.05,N/A,N/A,N/A,4.776,N/A,4.9389,10.5265,N/A,N/A,0.9911,138.9,10.2553,7.513,N/A,N/A,17.7225,1.4839,5.4505,1.3151,6.8266,7.9528,15157.63,3.5004,81.034,1333.33,20.7095,4.5113,1.6432,57.056,1.4153,37.13,17.383,
2022-07-15,1.0059,139.49,1.9558,N/A,24.561,7.443,N/A,0.84988,403.73,N/A,N/A,N/A,4.7953,N/A,4.9407,10.5943,N/A,N/A,0.9849,138.9,10.2763,7.516,N/A,N/A,17.5451,1.4886,5.4434,1.3147,6.7943,7.8963,15081.58,3.5044,80.316,1333.79,20.9209,4.4752,1.6377,56.678,1.4113,36.866,17.2875,
2022-07-14,1.0005,139.04,1.9558,N/A,24.417,7.4425,N/A,0.8456,408.78,N/A,N/A,N/A,4.8146,N/A,4.942,10.6019,N/A,N/A,0.9841,138.89,10.2536,7.5122,N/A,N/A,17.494,1.4893,5.4586,1.3162,6.7618,7.8539,15119.56,3.4915,80.0752,1322.29,20.9585,4.4462,1.6437,56.565,1.4065,36.632,17.202,
2022-07-13,1.0067,138.02,1.9558,N/A,24.397,7.4416,N/A,0.84371,409.35,N/A,N/A,N/A,4.824,N/A,4.9414,10.602,N/A,N/A,0.9829,138.3,10.2428,7.5155,N/A,N/A,17.5629,1.4802,5.4533,1.3073,6.7722,7.9025,15117.08,3.4864,80.1285,1311.4,20.9029,4.4667,1.635,56.669,1.4134,36.377,17.0527,
2022-07-12,1.0042,137.31,1.9558,N/A,24.582,7.4408,N/A,0.84823,409.98,N/A,N/A,N/A,4.819,N/A,4.9413,10.629,N/A,N/A,0.9883,139.1,10.2754,7.517,N/A,N/A,17.4392,1.49,5.4009,1.3094,6.7518,7.8828,15054.05,3.4987,79.8965,1315.1,20.8883,4.4556,1.6395,56.648,1.4127,36.392,17.1509,
2022-07-11,1.0098,138.77,1.9558,N/A,24.592,7.4414,N/A,0.8454,408.22,N/A,N/A,N/A,4.7968,N/A,4.943,10.6943,N/A,N/A,0.9908,139.3,10.299,7.518,N/A,N/A,17.5447,1.491,5.3673,1.314,6.7793,7.9265,15131.92,3.5108,80.2435,1320.36,20.7845,4.4704,1.6466,56.574,1.4178,36.585,17.1634,
2022-07-08,1.0163,138.05,1.9558,N/A,24.614,7.4424,N/A,0.84585,402.45,N/A,N/A,N/A,4.763,N/A,4.9431,10.6665,N/A,N/A,0.9913,139.5,10.263,7.519,N/A,N/A,17.6026,1.4871,5.4345,1.3201,6.8095,7.9769,15210.73,3.5325,80.528,1321.61,20.8477,4.4992,1.6464,56.882,1.4228,36.602,17.1922,
2022-07-07,1.018,138.11,1.9558,N/A,24.779,7.4405,N/A,0.85105,410.04,N/A,N/A,N/A,4.7721,N/A,4.9448,10.723,N/A,N/A,0.9906,139.3,10.291,7.5193,N/A,N/A,17.5551,1.4883,5.4983,1.3227,6.823,7.9893,15265.27,3.5548,80.6,1324.66,20.9675,4.5077,1.6461,56.939,1.4255,36.74,17.0372,
2022-07-06,1.0177,137.71,1.9558,N/A,24.778,7.4403,N/A,0.85676,411.8,N/A,N/A,N/A,4.771,N/A,4.944,10.745,N/A,N/A,0.9896,138.5,10.2803,7.5198,N/A,N/A,17.5505,1.4961,5.5116,1.3274,6.8289,7.9864,15287.49,3.5884,80.5321,1331.69,21.0194,4.5028,1.6505,56.779,1.4305,36.78,17.0246,
2022-07-05,1.029,139.77,1.9558,N/A,24.751,7.4396,N/A,0.85845,407.38,N/A,N/A,N/A,4.7448,N/A,4.9438,10.8031,N/A,N/A,0.9932,139.1,10.285,7.5246,N/A,N/A,17.5049,1.518,5.5141,1.3364,6.9029,8.0748,15487.93,3.6343,81.673,1348.97,21.0171,4.5477,1.6772,57.009,1.4455,36.879,16.9143,
2022-07-04,1.0455,141.51,1.9558,N/A,24.745,7.4391,N/A,0.8596,401.52,N/A,N/A,N/A,4.71,N/A,4.944,10.7658,N/A,N/A,1.0037,139.3,10.2958,7.5301,N/A,N/A,17.5994,1.5205,5.5663,1.3435,6.9977,8.2033,15684.13,3.6655,82.5067,1353.4,21.1972,4.6138,1.6748,57.487,1.4587,37.298,17.0275,
2022-07-01,1.0425,141.05,1.9558,N/A,24.753,7.4391,N/A,0.86648,401.11,N/A,N/A,N/A,4.7168,N/A,4.9457,10.7783,N/A,N/A,1.0027,138.7,10.3651,7.531,N/A,N/A,17.4608,1.5382,5.5117,1.3492,6.987,8.1801,15621.64,3.6717,82.3747,1352.58,21.115,4.5943,1.6929,57.452,1.4565,37.186,17.1323,
2022-06-30,1.0387,141.54,1.9558,N/A,24.739,7.4392,N/A,0.8582,397.04,N/A,N/A,N/A,4.6904,N/A,4.9464,10.73,N/A,N/A,0.996,138.9,10.3485,7.5307,N/A,N/A,17.322,1.5099,5.4229,1.3425,6.9624,8.1493,15552,3.6392,82.113,1351.6,20.9641,4.5781,1.6705,57.15,1.4483,36.754,17.0143,
2022-06-29,1.0517,143.53,1.9558,N/A,24.739,7.4392,N/A,0.86461,394.28,N/A,N/A,N/A,4.6869,N/A,4.9419,10.6848,N/A,N/A,1.0005,139.9,10.3065,7.5285,N/A,N/A,17.4998,1.5256,5.5163,1.3513,7.0382,8.2532,15612.61,3.6344,83.037,1364.02,21.1375,4.6272,1.6871,57.773,1.4607,36.925,16.9295,
2022-06-28,1.0561,143.67,1.9558,N/A,24.726,7.4394,N/A,0.8635,398.55,N/A,N/A,N/A,4.6905,N/A,4.9443,10.6543,N/A,N/A,1.0101,139.5,10.337,7.532,N/A,N/A,17.5891,1.521,5.5308,1.3565,7.0775,8.288,15669.91,3.6267,83.408,1361.75,21.088,4.6432,1.6822,57.85,1.4645,37.154,16.9072,
2022-06-27,1.0572,143.25,1.9558,N/A,24.724,7.4408,N/A,0.862,402.62,N/A,N/A,N/A,4.699,N/A,4.944,10.6713,N/A,N/A,1.0143,139.7,10.408,7.5333,N/A,N/A,17.4794,1.5278,5.5446,1.3639,7.0737,8.2946,15635.36,3.6009,82.9325,1357.68,21.041,4.6559,1.6801,57.9,1.4641,37.361,16.7967,
2022-06-24,1.0524,142.19,1.9558,N/A,24.731,7.4398,N/A,0.85773,401.34,N/A,N/A,N/A,4.7023,N/A,4.9463,10.694,N/A,N/A,1.0072,139.7,10.4345,7.5295,N/A,N/A,18.2856,1.5248,5.4851,1.3657,7.0478,8.2609,15633.96,3.621,82.3985,1364.09,20.9901,4.6327,1.6731,57.83,1.462,37.36,16.7137,
2022-06-23,1.0493,142.11,1.9558,N/A,24.75,7.4388,N/A,0.85818,399.6,N/A,N/A,N/A,4.7085,N/A,4.9468,10.705,N/A,N/A,1.013,139.9,10.475,7.5286,N/A,N/A,18.2199,1.5212,5.4515,1.36,7.0367,8.236,15594.75,3.6192,82.1489,1367.21,21.0924,4.623,1.6713,57.44,1.4589,37.261,16.817,
2022-06-22,1.0521,143.11,1.9558,N/A,24.712,7.4387,N/A,0.85885,396,N/A,N/A,N/A,4.6905,N/A,4.9467,10.6688,N/A,N/A,1.0153,138.7,10.5045,7.5228,N/A,N/A,18.255,1.5254,5.4349,1.366,7.0604,8.2589,15618.98,3.6432,82.4075,1369.29,21.1491,4.6345,1.6835,57.174,1.4615,37.281,16.7985,
2022-06-21,1.055,143.75,1.9558,N/A,24.69,7.4393,N/A,0.8601,396.48,N/A,N/A,N/A,4.6435,N/A,4.9462,10.646,N/A,N/A,1.0214,138.7,10.3283,7.5205,N/A,N/A,18.3049,1.5177,5.442,1.366,7.068,8.2817,15639.62,3.6505,82.423,1365.09,21.2485,4.6399,1.6675,57.304,1.4612,37.294,16.7881,
2022-06-20,1.0517,141.94,1.9558,N/A,24.728,7.4387,N/A,0.85748,397.85,N/A,N/A,N/A,4.652,N/A,4.9453,10.6375,N/A,N/A,1.0162,137.3,10.4085,7.5175,N/A,N/A,18.2239,1.5061,5.4117,1.3662,7.0346,8.2558,15589.89,3.639,81.994,1357.54,21.3016,4.6291,1.6549,56.872,1.4589,37.157,16.8603,
2022-06-17,1.0486,141.21,1.9558,N/A,24.742,7.4384,N/A,0.855,400.53,N/A,N/A,N/A,4.7003,N/A,4.9469,10.6748,N/A,N/A,1.0105,137.7,10.4525,7.5155,N/A,N/A,18.1495,1.5039,5.3824,1.3631,7.0308,8.2314,15537.05,3.6112,81.871,1356.27,21.4474,4.6159,1.6601,56.371,1.4547,36.974,16.7133,
2022-06-16,1.04,138.24,1.9558,N/A,24.742,7.4386,N/A,0.8555,398.1,N/A,N/A,N/A,4.7138,N/A,4.9443,10.6942,N/A,N/A,1.0142,137.5,10.4588,7.5245,N/A,N/A,18.0126,1.4939,5.2559,1.3446,6.9844,8.1638,15427.31,3.5934,81.1945,1346.88,21.4115,4.5786,1.6608,55.7,1.4451,36.566,16.6052,
2022-06-15,1.0431,140.49,1.9558,N/A,24.703,7.4392,N/A,0.86328,397.96,N/A,N/A,N/A,4.669,N/A,4.9427,10.6278,N/A,N/A,1.0435,137.5,10.3868,7.5245,N/A,N/A,18.0465,1.5051,5.3164,1.3498,7.0013,8.1883,15361.97,3.6007,81.5142,1346.86,21.4763,4.6037,1.6706,55.627,1.4519,36.529,16.7111,
2022-06-14,1.0452,140.62,1.9558,N/A,24.749,7.4403,N/A,0.86578,398.68,N/A,N/A,N/A,4.6563,N/A,4.9443,10.622,N/A,N/A,1.0394,138.3,10.3945,7.5238,N/A,N/A,18.06,1.5174,5.3329,1.3522,7.0417,8.2048,15400.02,3.6208,81.559,1346.72,21.4832,4.6224,1.6755,55.669,1.4541,36.566,16.7959,
2022-06-13,1.0455,140.51,1.9558,N/A,24.724,7.4397,N/A,0.8585,399.3,N/A,N/A,N/A,4.6373,N/A,4.9459,10.616,N/A,N/A,1.0375,138.7,10.3222,7.5215,N/A,N/A,18.0495,1.4998,5.2785,1.3435,7.0434,8.2071,15376.17,3.5994,81.606,1349.93,21.2102,4.6195,1.6635,55.72,1.4538,36.425,16.807,
2022-06-10,1.0578,141.69,1.9558,N/A,24.705,7.4389,N/A,0.85048,398.48,N/A,N/A,N/A,4.6053,N/A,4.9442,10.5255,N/A,N/A,1.0404,137.7,10.1495,7.5225,N/A,N/A,18.0116,1.4845,5.1718,1.3484,7.0868,8.3031,15393.27,3.5626,82.3355,1344.25,20.8285,4.6564,1.6482,56.101,1.462,36.774,16.5209,
2022-06-09,1.0743,143.93,1.9558,N/A,24.689,7.4391,N/A,0.85653,396.45,N/A,N/A,N/A,4.5925,N/A,4.9453,10.5045,N/A,N/A,1.0495,138.7,10.1818,7.5223,N/A,N/A,18.5104,1.4985,5.2506,1.3506,7.1722,8.4317,15646.25,3.5859,83.526,1348.99,21.0248,4.7199,1.6673,56.872,1.4779,37.079,16.4132,
2022-06-08,1.0739,143.92,1.9558,N/A,24.622,7.4386,N/A,0.85575,391.25,N/A,N/A,N/A,4.5698,N/A,4.945,10.4938,N/A,N/A,1.0486,138.9,10.1395,7.5215,N/A,N/A,18.453,1.4917,5.2447,1.3467,7.1785,8.4275,15577.86,3.5848,83.414,1349.34,21.0458,4.7187,1.6644,56.799,1.4769,37.076,16.4626,
2022-06-07,1.0662,141.66,1.9558,N/A,24.739,7.4395,N/A,0.85365,389.33,N/A,N/A,N/A,4.5813,N/A,4.9426,10.5039,N/A,N/A,1.0423,138.9,10.1843,7.5244,N/A,N/A,17.8702,1.4884,5.1256,1.3437,7.1146,8.3656,15412.37,3.5661,82.873,1340.75,20.8435,4.6865,1.6582,56.421,1.4685,36.768,16.4059,
2022-06-06,1.0726,140.16,1.9558,N/A,24.715,7.439,N/A,0.85415,388.05,N/A,N/A,N/A,4.5808,N/A,4.9424,10.452,N/A,N/A,1.032,138.3,10.0853,7.5222,N/A,N/A,17.796,1.4842,5.0986,1.3463,7.1223,8.4154,15464.73,3.5697,83.245,1341.13,20.9078,4.7076,1.6428,56.67,1.4732,36.774,16.4142,
2022-06-03,1.073,139.59,1.9558,N/A,24.708,7.4388,N/A,0.8542,394.78,N/A,N/A,N/A,4.5955,N/A,4.9428,10.4589,N/A,N/A,1.0296,137.9,10.103,7.522,N/A,N/A,17.738,1.4805,5.1643,1.3484,7.1465,8.4167,15498.1,3.5751,83.273,1337.4,20.985,4.7094,1.6409,56.738,1.4741,36.777,16.6153,
2022-06-02,1.0692,138.72,1.9558,N/A,24.702,7.4391,N/A,0.85195,394.9,N/A,N/A,N/A,4.5787,N/A,4.9398,10.4705,N/A,N/A,1.0264,136.9,10.0845,7.5325,N/A,N/A,17.6175,1.4829,5.1335,1.352,7.135,8.3896,15481.86,3.5705,82.922,1334.06,20.9831,4.6949,1.6413,56.467,1.4701,36.754,16.6143,
2022-06-01,1.0712,138.68,1.9558,N/A,24.748,7.4393,N/A,0.85158,395.03,N/A,N/A,N/A,4.5913,N/A,4.9428,10.4758,N/A,N/A,1.0305,137.1,10.0438,7.5345,N/A,N/A,17.6223,1.4861,5.0646,1.3536,7.1586,8.4057,15574.33,3.5682,83.051,1331.44,21.0678,4.6951,1.6442,56.182,1.47,36.801,16.609,
2022-05-31,1.0713,137.36,1.9558,N/A,24.714,7.4394,N/A,0.85138,396.2,N/A,N/A,N/A,4.5805,N/A,4.9408,10.5053,N/A,N/A,1.0281,136.3,10.0983,7.541,N/A,N/A,17.5817,1.4933,5.0965,1.3573,7.1402,8.4063,15580.15,3.5746,83.231,1329.32,20.987,4.6907,1.6459,56.323,1.4687,36.751,16.745,
2022-05-30,1.0764,137.25,1.9558,N/A,24.712,7.4391,N/A,0.8515,392.18,N/A,N/A,N/A,4.5855,N/A,4.9441,10.518,N/A,N/A,1.0327,136.9,10.1256,7.5305,N/A,N/A,17.6416,1.4982,5.0629,1.3647,7.1735,8.449,15682.41,3.5722,83.475,1331.66,20.8994,4.6998,1.6439,56.322,1.4719,36.7,16.648,
2022-05-27,1.0722,136.05,1.9558,N/A,24.7,7.4392,N/A,0.84875,392.83,N/A,N/A,N/A,4.5858,N/A,4.9427,10.5293,N/A,N/A,1.0258,137.9,10.179,7.5379,N/A,N/A,17.582,1.4995,5.0959,1.3661,7.1831,8.4165,15583.97,3.597,83.1915,1343.63,21.136,4.6952,1.6426,56.02,1.4679,36.589,16.746,
2022-05-26,1.0697,135.95,1.9558,N/A,24.676,7.4409,N/A,0.85073,391.72,N/A,N/A,N/A,4.6083,N/A,4.9423,10.5983,N/A,N/A,1.0283,138.1,10.2715,7.5355,N/A,N/A,17.5588,1.511,5.1741,1.3715,7.2024,8.397,15628.91,3.5935,83.0065,1352.69,21.1935,4.7045,1.6541,55.975,1.4709,36.589,16.9312,
2022-05-25,1.0656,135.34,1.9558,N/A,24.648,7.4405,N/A,0.85295,388.25,N/A,N/A,N/A,4.621,N/A,4.9416,10.5419,N/A,N/A,1.0269,138.3,10.2704,7.5355,N/A,N/A,17.3954,1.5126,5.1736,1.372,7.1334,8.3647,15587.59,3.585,82.6666,1354.61,21.2213,4.6833,1.6539,55.787,1.4676,36.55,16.7628,
2022-05-24,1.072,136.49,1.9558,N/A,24.663,7.4411,N/A,0.8575,383.33,N/A,N/A,N/A,4.6015,N/A,4.9446,10.5013,N/A,N/A,1.0334,139.3,10.289,7.5285,N/A,N/A,17.2572,1.5152,5.1793,1.3714,7.1449,8.4143,15711.88,3.5848,83.185,1353.65,21.2456,4.7076,1.6656,56.152,1.4722,36.609,16.7814,
2022-05-23,1.0659,136.05,1.9558,N/A,24.594,7.4413,N/A,0.84783,381.65,N/A,N/A,N/A,4.621,N/A,4.947,10.4918,N/A,N/A,1.031,139.1,10.252,7.5275,N/A,N/A,16.8672,1.4982,5.1623,1.3626,7.085,8.3664,15609,3.5745,82.6795,1344.19,21.1273,4.6782,1.6463,55.686,1.4639,36.41,16.7437,
2022-05-20,1.0577,135.34,1.9558,N/A,24.67,7.4424,N/A,0.8482,382.93,N/A,N/A,N/A,4.6365,N/A,4.9477,10.4915,N/A,N/A,1.028,138.5,10.262,7.5335,N/A,N/A,16.8201,1.498,5.1989,1.3526,7.0638,8.2999,15501.99,3.533,82.1617,1340.58,21.0314,4.6422,1.6518,55.181,1.4588,36.284,16.7131,
2022-05-19,1.0525,134.46,1.9558,N/A,24.7,7.4423,N/A,0.84728,385.83,N/A,N/A,N/A,4.6423,N/A,4.9474,10.5098,N/A,N/A,1.0265,139.5,10.3102,7.5395,N/A,N/A,16.8037,1.5036,5.2094,1.349,7.1028,8.2594,15416.76,3.5623,81.7115,1343.21,21.0043,4.6363,1.6551,55.14,1.4576,36.343,16.8315,
2022-05-18,1.0523,135.76,1.9558,N/A,24.647,7.4419,N/A,0.8467,382.88,N/A,N/A,N/A,4.6443,N/A,4.9473,10.4675,N/A,N/A,1.0486,138.9,10.2125,7.535,N/A,N/A,16.7811,1.498,5.1974,1.3488,7.0972,8.2591,15446,3.526,81.6455,1332.76,20.9204,4.6254,1.6548,55.077,1.4598,36.399,16.7313,
2022-05-17,1.0541,136.32,1.9558,N/A,24.712,7.4414,N/A,0.844,386.3,N/A,N/A,N/A,4.6488,N/A,4.9478,10.4393,N/A,N/A,1.0457,138.7,10.178,7.5245,N/A,N/A,16.6027,1.4993,5.2621,1.3517,7.0899,8.2744,15433.23,3.5387,81.6515,1333.66,21.0273,4.6211,1.6561,55.137,1.4589,36.361,16.844,
2022-05-16,1.0422,135.01,1.9558,N/A,24.71,7.4418,N/A,0.85045,385.85,N/A,N/A,N/A,4.6675,N/A,4.9469,10.4978,N/A,N/A,1.0479,138.3,10.2188,7.5225,N/A,N/A,16.3121,1.5057,5.2819,1.3473,7.0786,8.1812,15294.29,3.5474,81.081,1337.9,20.9324,4.5836,1.6601,54.705,1.4531,36.274,16.9195,
2022-05-13,1.0385,133.91,1.9558,N/A,24.74,7.4412,N/A,0.85115,385,N/A,N/A,N/A,4.6883,N/A,4.9455,10.4905,N/A,N/A,1.0385,140.1,10.2043,7.52,N/A,N/A,16.0687,1.5067,5.3204,1.3505,7.0513,8.1522,15193.55,3.5586,80.4315,1330.83,20.988,4.5673,1.6633,54.449,1.45,36.109,16.7789,
2022-05-12,1.0408,133.85,1.9558,N/A,24.925,7.4413,N/A,0.85293,382.2,N/A,N/A,N/A,4.668,N/A,4.947,10.5648,N/A,N/A,1.0377,139.7,10.2898,7.5235,N/A,N/A,16.0132,1.5163,5.4161,1.3569,7.0691,8.1702,15255.73,3.5981,80.667,1341.98,21.2531,4.5725,1.6692,54.589,1.4529,36.15,16.8806,
2022-05-11,1.0553,137.07,1.9558,N/A,25.365,7.4393,N/A,0.85393,379.13,N/A,N/A,N/A,4.6575,N/A,4.947,10.526,N/A,N/A,1.0446,139.3,10.1793,7.5365,N/A,N/A,16.1851,1.5055,5.3859,1.3685,7.0893,8.2839,15308.87,3.6148,81.4935,1343.99,21.387,4.6185,1.6645,54.992,1.4622,36.492,16.9275,
2022-05-10,1.0554,137.38,1.9558,N/A,25.014,7.4386,N/A,0.85595,380.15,N/A,N/A,N/A,4.6763,N/A,4.9458,10.6075,N/A,N/A,1.0479,139.5,10.2315,7.5385,N/A,N/A,16.0883,1.5162,5.4232,1.3707,7.0967,8.2847,15349.06,3.6587,81.5425,1346.56,21.4716,4.6248,1.6707,55.289,1.4667,36.448,17.005,
2022-05-09,1.0559,138.1,1.9558,N/A,25.055,7.4385,N/A,0.85235,383.23,N/A,N/A,N/A,4.6985,N/A,4.9467,10.5818,N/A,N/A,1.0462,139.5,10.0583,7.5335,N/A,N/A,15.8941,1.5048,5.4321,1.3656,7.0886,8.2887,15367.67,3.6239,81.7415,1345.48,21.4341,4.6285,1.6584,55.67,1.4676,36.497,17.1332,
2022-05-06,1.057,137.9,1.9558,N/A,24.665,7.44,N/A,0.85625,381.47,N/A,N/A,N/A,4.7028,N/A,4.949,10.4686,N/A,N/A,1.0419,138.3,9.9808,7.5336,N/A,N/A,15.8078,1.4888,5.3183,1.356,7.0506,8.2969,15312.44,3.5965,81.298,1343.9,21.3555,4.6191,1.644,55.467,1.4642,36.303,16.9614,
2022-05-05,1.0568,137.18,1.9558,N/A,24.606,7.4405,N/A,0.8519,378.65,N/A,N/A,N/A,4.6673,N/A,4.9485,10.3748,N/A,N/A,1.0355,138,9.8463,7.5398,N/A,N/A,15.7051,1.4669,5.2192,1.3483,6.9944,8.2948,15250.92,3.5916,80.6185,1330.89,21.2069,4.5955,1.6273,55.364,1.4561,36.026,16.5862,
2022-05-04,1.0531,136.84,1.9558,N/A,24.644,7.4409,N/A,0.84194,377.55,N/A,N/A,N/A,4.6875,N/A,4.947,10.3968,N/A,N/A,1.0324,137.2,9.9042,7.5499,N/A,N/A,15.5769,1.478,5.24,1.3498,6.9594,8.2655,15201.44,3.5487,80.4035,1331.45,21.2947,4.5847,1.6333,55.26,1.4559,36.137,16.6489,
2022-05-03,1.0556,137.06,1.9558,N/A,24.662,7.4403,N/A,0.8413,382.15,N/A,N/A,N/A,4.6925,N/A,4.9475,10.3978,N/A,N/A,1.0272,137.6,9.909,7.5555,N/A,N/A,15.6941,1.4825,5.3143,1.357,6.9759,8.2838,15288.47,3.5597,80.842,1335.64,21.5025,4.5956,1.6366,55.455,1.4605,36.387,16.8303,
2022-05-02,1.0524,136.63,1.9558,N/A,24.671,7.4391,N/A,0.8381,378.51,N/A,N/A,N/A,4.685,N/A,4.9478,10.4035,N/A,N/A,1.0253,137.2,9.9248,7.561,N/A,N/A,15.6697,1.4913,5.248,1.356,6.9548,8.2581,15293.41,3.5277,80.497,1333.71,21.4758,4.5816,1.6362,55.229,1.4585,36.208,16.7383,
2022-04-29,1.054,137.01,1.9558,N/A,24.605,7.4415,N/A,0.83908,378.71,N/A,N/A,N/A,4.678,N/A,4.9479,10.2958,N/A,N/A,1.0229,137.8,9.7525,7.5667,N/A,N/A,15.6385,1.4699,5.1608,1.3426,6.9441,8.2703,15301.52,3.4993,80.638,1326.71,21.4181,4.5886,1.6119,55.2,1.4545,36.026,16.6473,
2022-04-28,1.0485,137.13,1.9558,N/A,24.526,7.4421,N/A,0.8435,377.06,N/A,N/A,N/A,4.6891,N/A,4.9479,10.3594,N/A,N/A,1.0216,137.8,9.899,7.5703,N/A,N/A,15.5362,1.4814,5.2465,1.3498,6.9381,8.2267,15222.05,3.5096,80.367,1337.82,21.4531,4.5741,1.6221,54.845,1.4556,36.152,16.7472,
2022-04-27,1.0583,135.57,1.9558,N/A,24.55,7.441,N/A,0.84215,379.74,N/A,N/A,N/A,4.7043,N/A,4.948,10.4035,N/A,N/A,1.0229,138.2,9.7838,7.565,N/A,N/A,15.6857,1.4828,5.3045,1.3572,6.9377,8.3045,15259.86,3.5178,81.0705,1341.98,21.6259,4.6142,1.6118,55.195,1.4602,36.331,16.8406,
2022-04-26,1.0674,136.15,1.9558,N/A,24.423,7.4393,N/A,0.84135,374.46,N/A,N/A,N/A,4.6466,N/A,4.9458,10.3935,N/A,N/A,1.0229,138.4,9.7943,7.5625,N/A,N/A,15.7944,1.4828,5.249,1.3613,6.9837,8.3735,15365.76,3.5147,81.7265,1340.02,21.6538,4.6485,1.6102,55.681,1.4666,36.596,16.7787,
2022-04-25,1.0746,137.73,1.9558,N/A,24.418,7.4391,N/A,0.8433,374.08,N/A,N/A,N/A,4.6398,N/A,4.9455,10.3476,N/A,N/A,1.0267,139.2,9.7018,7.562,N/A,N/A,15.864,1.4972,5.1953,1.3709,7.0398,8.4325,15533.84,3.5306,82.321,1344.49,21.8989,4.6815,1.624,56.259,1.4757,36.542,16.8549,
2022-04-22,1.0817,138.83,1.9558,N/A,24.32,7.4402,N/A,0.83925,370.35,N/A,N/A,N/A,4.6336,N/A,4.9455,10.278,N/A,N/A,1.0336,139.8,9.6255,7.5625,N/A,N/A,15.9446,1.4816,5.0926,1.3714,7.0332,8.4859,15603.47,3.5288,82.6943,1344.04,22.0034,4.6784,1.6193,56.721,1.4784,36.724,16.8652,
2022-04-21,1.0887,139.61,1.9558,N/A,24.38,7.4403,N/A,0.83523,370.6,N/A,N/A,N/A,4.63,N/A,4.945,10.2553,N/A,N/A,1.0335,139,9.5788,7.5635,N/A,N/A,15.9983,1.4653,5.0324,1.36,7.0228,8.5406,15624.02,3.5153,82.965,1348.33,21.8836,4.6716,1.6053,57.081,1.482,36.891,16.5996,
2022-04-20,1.083,138.53,1.9558,N/A,24.409,7.4405,N/A,0.82965,371.36,N/A,N/A,N/A,4.6338,N/A,4.9436,10.23,N/A,N/A,1.0254,139.2,9.5443,7.561,N/A,N/A,15.8892,1.4581,5.0481,1.3579,6.9448,8.494,15537.05,3.4908,82.6348,1337.89,21.6392,4.6415,1.595,56.747,1.4779,36.567,16.3019,
2022-04-19,1.0803,138.4,1.9558,N/A,24.424,7.4391,N/A,0.82955,374.12,N/A,N/A,N/A,4.6553,N/A,4.9411,10.3408,N/A,N/A,1.0208,139.8,9.5228,7.562,N/A,N/A,15.8416,1.4663,5.0261,1.3631,6.9008,8.4698,15498.35,3.5038,82.6038,1339.46,21.4725,4.5961,1.6016,56.683,1.4763,36.466,16.0401,
2022-04-14,1.0878,136.32,1.9558,N/A,24.42,7.4389,N/A,0.82908,376.57,N/A,N/A,N/A,4.6478,N/A,4.9459,10.3008,N/A,N/A,1.0189,140.4,9.5313,7.5587,N/A,N/A,15.9046,1.4612,5.1226,1.3663,6.932,8.5298,15621.3,3.4896,82.814,1334.71,21.5941,4.603,1.5957,56.759,1.4732,36.615,15.9331,
2022-04-13,1.0826,136.26,1.9558,N/A,24.45,7.4377,N/A,0.8328,378.45,N/A,N/A,N/A,4.6453,N/A,4.9415,10.3323,N/A,N/A,1.0116,140.2,9.5693,7.5538,N/A,N/A,15.7992,1.4603,5.0449,1.37,6.8939,8.4867,15549.1,3.4782,82.478,1328.47,21.417,4.5799,1.5991,56.446,1.4769,36.305,15.682,
2022-04-12,1.0861,136.29,1.9558,N/A,24.45,7.4379,N/A,0.83455,377.78,N/A,N/A,N/A,4.6552,N/A,4.9417,10.332,N/A,N/A,1.0131,139.6,9.5395,7.5513,N/A,N/A,15.9548,1.4599,5.0944,1.3724,6.9199,8.5112,15609.66,3.4972,82.7285,1335.49,21.5616,4.5972,1.5874,56.574,1.4803,36.531,15.849,
2022-04-11,1.09,137.01,1.9558,N/A,24.429,7.4375,N/A,0.83693,378.27,N/A,N/A,N/A,4.6456,N/A,4.9397,10.3128,N/A,N/A,1.018,140,9.5478,7.5519,N/A,N/A,16.0485,1.4654,5.155,1.3738,6.9405,8.544,15658.28,3.501,82.7085,1345.23,21.8653,4.6112,1.5938,56.753,1.4874,36.613,15.9127,
2022-04-08,1.0861,134.87,1.9558,N/A,24.479,7.4372,N/A,0.83355,375.66,N/A,N/A,N/A,4.6437,N/A,4.9425,10.2768,N/A,N/A,1.0155,139.6,9.508,7.549,N/A,N/A,16.0237,1.4552,5.1583,1.3675,6.9115,8.5134,15601.96,3.501,82.389,1333.12,21.8729,4.585,1.5849,55.99,1.4801,36.488,15.9968,
2022-04-07,1.0916,135.32,1.9558,N/A,24.512,7.4378,N/A,0.8345,379.26,N/A,N/A,N/A,4.637,N/A,4.9419,10.313,N/A,N/A,1.0185,141,9.5595,7.5562,N/A,N/A,16.0929,1.4578,5.146,1.3704,6.9448,8.5554,15692.35,3.5259,82.951,1330.92,21.9806,4.6046,1.5816,56.114,1.4848,36.541,16.052,
2022-04-06,1.0923,135.3,1.9558,N/A,24.441,7.4378,N/A,0.83473,377.77,N/A,N/A,N/A,4.6328,N/A,4.9433,10.2855,N/A,N/A,1.0187,141.4,9.5523,7.547,N/A,N/A,16.0998,1.4431,5.0996,1.3647,6.9498,8.5617,15683.36,3.5199,82.8343,1330.44,21.8759,4.604,1.5718,56.167,1.4844,36.701,15.9934,
2022-04-05,1.0969,134.76,1.9558,N/A,24.338,7.4378,N/A,0.8349,370.93,N/A,N/A,N/A,4.6265,N/A,4.9438,10.2593,N/A,N/A,1.0141,141.6,9.5398,7.5399,N/A,N/A,16.15,1.4374,5.0384,1.3647,6.9783,8.5917,15732.77,3.5152,82.635,1330.81,21.7474,4.6185,1.5657,56.194,1.4867,36.697,15.9529,
2022-04-04,1.1005,135.08,1.9558,N/A,24.32,7.4385,N/A,0.8389,369.15,N/A,N/A,N/A,4.6375,N/A,4.9432,10.3849,N/A,N/A,1.0203,141.8,9.5489,7.5455,N/A,N/A,16.183,1.4651,5.1162,1.3749,7.0026,8.6226,15783.89,3.5312,83.118,1338.41,21.82,4.643,1.586,56.521,1.4938,36.894,16.0957,
2022-04-01,1.1052,135.35,1.9558,N/A,24.376,7.4388,N/A,0.84145,368.12,N/A,N/A,N/A,4.6401,N/A,4.9452,10.332,N/A,N/A,1.0217,142,9.6628,7.5675,N/A,N/A,16.2411,1.4696,5.2188,1.3805,7.0311,8.6596,15887.5,3.5315,83.9847,1345.61,21.9087,4.6534,1.5911,57.084,1.4985,36.941,16.1685,
2022-03-31,1.1101,135.17,1.9558,N/A,24.375,7.4379,N/A,0.84595,369.77,N/A,N/A,N/A,4.6531,N/A,4.9463,10.337,N/A,N/A,1.0267,142,9.711,7.574,N/A,N/A,16.2823,1.4829,5.3009,1.3896,7.0403,8.6918,15947,3.5243,84.134,1347.37,22.0903,4.6677,1.6014,57.514,1.5028,36.911,16.1727,
2022-03-30,1.1126,135.47,1.9558,N/A,24.45,7.4391,N/A,0.84563,368.13,N/A,N/A,N/A,4.6679,N/A,4.9477,10.3498,N/A,N/A,1.0309,142.2,9.6398,7.572,N/A,N/A,16.3296,1.4809,5.2808,1.3891,7.0666,8.7081,15957.24,3.5399,84.38,1346.97,22.1557,4.6779,1.5947,57.906,1.5064,37.144,16.1288,
2022-03-29,1.1085,136.66,1.9558,N/A,24.464,7.4388,N/A,0.8444,369.8,N/A,N/A,N/A,4.6594,N/A,4.9478,10.329,N/A,N/A,1.0362,142.2,9.5995,7.5815,N/A,N/A,16.3275,1.4795,5.2434,1.387,7.055,8.6767,15896.31,3.5505,83.9685,1345.62,22.1561,4.6707,1.6054,57.602,1.5051,37.29,16.1804,
2022-03-28,1.0966,135.93,1.9558,N/A,24.65,7.4393,N/A,0.83643,374.13,N/A,N/A,N/A,4.718,N/A,4.9483,10.4225,N/A,N/A,1.0257,142.8,9.5123,7.5735,N/A,N/A,16.275,1.459,5.2133,1.3702,6.9862,8.5861,15737.77,3.5313,83.4825,1342.49,21.9841,4.6238,1.5838,57.08,1.4921,37.027,15.9925,
2022-03-25,1.1002,134.07,1.9558,N/A,24.645,7.4404,N/A,0.8338,373.81,N/A,N/A,N/A,4.7307,N/A,4.9487,10.3505,N/A,N/A,1.0207,142.2,9.5205,7.5754,N/A,N/A,16.3304,1.4624,5.2634,1.3781,7.0007,8.6117,15777.69,3.5351,83.8235,1343.32,21.9908,4.6324,1.5787,57.322,1.4919,36.906,16.0386,
2022-03-24,1.0978,133.71,1.9558,N/A,24.72,7.4397,N/A,0.83288,374.44,N/A,N/A,N/A,4.7421,N/A,4.9489,10.3555,N/A,N/A,1.0225,141.2,9.4923,7.5745,N/A,N/A,16.2917,1.4668,5.3057,1.3806,6.9933,8.5897,15778.31,3.5461,83.879,1342.53,22.177,4.6396,1.5812,57.426,1.4912,36.837,16.1478,
2022-03-23,1.0985,132.65,1.9558,N/A,24.605,7.4381,N/A,0.8328,372.25,N/A,N/A,N/A,4.7052,N/A,4.9463,10.4005,N/A,N/A,1.0269,141.4,9.6425,7.571,N/A,N/A,16.3108,1.4728,5.3903,1.384,7.0003,8.5948,15792.11,3.5407,83.9675,1337.76,22.1978,4.6401,1.5822,57.565,1.4919,36.965,16.2501,
2022-03-22,1.1024,132.96,1.9558,N/A,24.679,7.4402,N/A,0.83228,371.23,N/A,N/A,N/A,4.6851,N/A,4.9463,10.3822,N/A,N/A,1.0275,142.7,9.6233,7.575,N/A,N/A,16.3432,1.4802,5.4105,1.3867,7.0137,8.6285,15808.01,3.5521,83.9145,1343.81,22.3667,4.6483,1.586,57.749,1.4957,36.881,16.343,
2022-03-21,1.1038,131.57,1.9558,N/A,24.683,7.4411,N/A,0.83775,374.48,N/A,N/A,N/A,4.696,N/A,4.947,10.4088,N/A,N/A,1.0278,142.7,9.6575,7.5733,N/A,N/A,16.3773,1.4897,5.502,1.3898,7.0152,8.6387,15826.61,3.5637,84.1835,1342.62,22.48,4.6415,1.5997,57.817,1.496,37.038,16.4543,
2022-03-18,1.1008,131.4,1.9558,N/A,24.837,7.4423,N/A,0.83925,375.33,N/A,N/A,N/A,4.7135,N/A,4.9483,10.4303,N/A,N/A,1.0314,142.9,9.694,7.5685,N/A,N/A,16.3054,1.4945,5.5784,1.3911,7.0031,8.6101,15782.11,3.5761,83.7825,1337.31,22.5905,4.6157,1.6026,57.622,1.4952,36.745,16.5347,
2022-03-17,1.1051,131.27,1.9558,N/A,24.777,7.4439,N/A,0.84315,372.05,N/A,N/A,N/A,4.6889,N/A,4.9465,10.4503,N/A,N/A,1.0385,142.1,9.78,7.573,N/A,N/A,16.3123,1.5055,5.6339,1.3998,7.0176,8.6391,15835.97,3.5777,83.8435,1340.02,22.788,4.6364,1.613,57.69,1.498,36.767,16.5286,
2022-03-16,1.0994,130.05,1.9558,N/A,24.687,7.4412,N/A,0.83988,371.18,N/A,N/A,N/A,4.6765,N/A,4.9473,10.4205,N/A,N/A,1.0336,143.5,9.7988,7.5725,N/A,N/A,16.1783,1.5165,5.6523,1.3967,6.9817,8.5996,15690.36,3.5872,83.7805,1353.77,22.854,4.6147,1.6168,57.433,1.4966,36.681,16.5574,
2022-03-15,1.0991,129.67,1.9558,N/A,24.867,7.441,N/A,0.84053,371.41,N/A,N/A,N/A,4.7355,N/A,4.9482,10.526,N/A,N/A,1.0322,144.9,9.849,7.575,N/A,N/A,16.0968,1.5234,5.6385,1.4099,7.0117,8.6026,15710.44,3.6088,83.9555,1366.05,22.9352,4.6239,1.6216,57.536,1.4993,36.842,16.6249,
2022-03-14,1.096,129.3,1.9558,N/A,24.89,7.4405,N/A,0.83915,373.88,N/A,N/A,N/A,4.7218,N/A,4.949,10.5368,N/A,N/A,1.0249,145.1,9.8588,7.5745,N/A,N/A,16.2,1.5137,5.5286,1.3978,6.9738,8.5815,15678.53,3.586,83.931,1357.77,22.8311,4.6087,1.613,57.398,1.4947,36.59,16.5029,
2022-03-11,1.099,128.46,1.9558,N/A,25.213,7.4402,N/A,0.8397,380.92,N/A,N/A,N/A,4.782,N/A,4.949,10.646,N/A,N/A,1.023,144.9,9.8033,7.5713,N/A,N/A,16.2554,1.5017,5.5077,1.4024,6.9633,8.6007,15696.64,3.5683,83.9875,1354.04,22.9524,4.6098,1.6053,57.461,1.4949,36.542,16.4896,
2022-03-10,1.1084,128.54,1.9558,N/A,25.316,7.4401,N/A,0.84175,381.63,N/A,N/A,N/A,4.8239,N/A,4.9491,10.7073,N/A,N/A,1.027,145.5,9.919,7.5665,N/A,N/A,16.574,1.5109,5.5958,1.4189,7.0063,8.6688,15824.95,3.6219,84.607,1360.48,23.3153,4.6414,1.6185,57.825,1.5058,36.71,16.7264,
2022-03-09,1.0993,127.31,1.9558,N/A,25.364,7.444,N/A,0.8357,379.66,N/A,N/A,N/A,4.8196,N/A,4.9485,10.734,N/A,N/A,1.0198,145.3,9.798,7.5625,N/A,N/A,16.1323,1.4991,5.5201,1.4108,6.9454,8.5974,15710.06,3.5978,84.2025,1357.08,23.2145,4.6028,1.6055,57.259,1.4966,36.326,16.656,
2022-03-08,1.0892,126.03,1.9558,N/A,25.642,7.4441,N/A,0.83185,388.28,N/A,N/A,N/A,4.9103,N/A,4.9494,10.8803,N/A,N/A,1.0111,145.9,9.7925,7.5715,N/A,N/A,15.8183,1.4971,5.5346,1.3978,6.8805,8.5183,15639.76,3.6022,83.924,1344.71,23.2866,4.5556,1.5958,56.9,1.4856,36.156,16.7051,
2022-03-07,1.0895,125.55,1.9558,N/A,25.584,7.4406,N/A,0.82625,393.25,N/A,N/A,N/A,4.9525,N/A,4.9494,10.8573,N/A,N/A,1.0069,145.8,9.8325,7.56,N/A,N/A,15.6577,1.4751,5.5065,1.3864,6.8846,8.5154,15685.76,3.5653,83.8125,1338.45,23.0249,4.5426,1.5861,56.832,1.4831,35.866,16.6951,
2022-03-04,1.0929,126.17,1.9558,N/A,25.737,7.4394,N/A,0.82388,386.54,N/A,N/A,N/A,4.853,N/A,4.9495,10.7935,N/A,N/A,1.0056,144.2,9.8358,7.5584,N/A,N/A,15.5681,1.4872,5.5313,1.3937,6.9065,8.5411,15725.3,3.5603,83.4354,1332.23,22.7543,4.5661,1.6005,56.814,1.4872,35.776,16.8044,
2022-03-03,1.1076,128.18,1.9558,N/A,25.634,7.4399,N/A,0.82773,378.64,N/A,N/A,N/A,4.7691,N/A,4.9496,10.7688,N/A,N/A,1.0192,143.4,9.8418,7.57,N/A,N/A,15.6897,1.5139,5.6041,1.3992,6.9996,8.6547,15934.42,3.5872,84.174,1334.2,22.8945,4.637,1.6329,57.293,1.5042,36.063,16.8798,
2022-03-02,1.1106,128.08,1.9558,N/A,25.866,7.4387,N/A,0.83316,382.31,N/A,N/A,N/A,4.8021,N/A,4.9493,10.788,N/A,N/A,1.0216,143,9.8826,7.574,N/A,N/A,15.628,1.5272,5.7313,1.4088,7.0153,8.6785,15980.03,3.5954,84.1765,1338.99,22.999,4.6595,1.6404,57.206,1.5059,36.339,17.1904,
2022-03-01,1.1162,128.15,1.9558,N/A,25.465,7.4377,N/A,0.8329,379.6,N/A,N/A,N/A,4.7947,N/A,4.949,10.6893,N/A,N/A,1.0247,142,9.8598,7.567,117.201,N/A,15.5509,1.5365,5.7598,1.4158,7.0462,8.7234,16033.36,3.6152,84.5015,1342.6,22.8558,4.6802,1.6484,57.295,1.515,36.505,17.2145,
2022-02-28,1.1199,129.31,1.9558,N/A,24.997,7.4404,N/A,0.8355,369.72,N/A,N/A,N/A,4.6835,N/A,4.9484,10.6055,N/A,N/A,1.0336,141.8,9.9465,7.5655,115.4842,N/A,15.4532,1.5508,5.7828,1.4264,7.067,8.7514,16100.72,3.63,84.554,1347.62,22.9011,4.7019,1.6628,57.432,1.5201,36.593,17.2863,
2022-02-25,1.1216,129.64,1.9558,N/A,24.66,7.4418,N/A,0.8374,365.28,N/A,N/A,N/A,4.6369,N/A,4.9479,10.5848,N/A,N/A,1.0398,140.8,9.9756,7.5535,92.5673,N/A,15.4799,1.5541,5.738,1.4325,7.0828,8.7578,16088.71,3.6389,84.347,1346.44,22.9145,4.7107,1.6651,57.549,1.5176,36.441,17.0315,
2022-02-24,1.1163,128.28,1.9558,N/A,25.09,7.4405,N/A,0.83463,368.63,N/A,N/A,N/A,4.6554,N/A,4.9501,10.7338,N/A,N/A,1.032,142,10.0878,7.552,95.7175,N/A,16.0525,1.5593,5.6874,1.4316,7.0601,8.7178,16074,3.6618,84.296,1347.7,22.9355,4.6896,1.6692,57.45,1.5125,36.514,17.1634,
2022-02-23,1.1344,130.58,1.9558,N/A,24.473,7.4388,N/A,0.83463,357.25,N/A,N/A,N/A,4.5481,N/A,4.9468,10.5658,N/A,N/A,1.0431,141.2,10.0335,7.5362,90.8791,N/A,15.6871,1.5592,5.6808,1.4394,7.1669,8.8529,16270.12,3.6515,84.6135,1350.23,22.9079,4.748,1.6679,57.98,1.5253,36.601,17.0508,
2022-02-22,1.1342,130.54,1.9558,N/A,24.496,7.4392,N/A,0.83685,355.89,N/A,N/A,N/A,4.5447,N/A,4.9464,10.5996,N/A,N/A,1.0422,141.2,10.1018,7.537,89.8055,N/A,15.6959,1.5739,5.7677,1.4441,7.1771,8.8495,16293.92,3.6584,84.758,1353.34,23.033,4.7472,1.6848,58.208,1.5268,36.748,17.1768,
2022-02-21,1.1338,130.2,1.9558,N/A,24.345,7.4397,N/A,0.83298,357.54,N/A,N/A,N/A,4.5351,N/A,4.9448,10.6535,N/A,N/A,1.0387,141.4,10.1738,7.536,89.0866,N/A,15.4689,1.5751,5.8045,1.4454,7.1831,8.8443,16276.34,3.6433,84.677,1353.02,22.9951,4.7387,1.687,58.3,1.5265,36.588,17.1895,
2022-02-18,1.1354,130.59,1.9558,N/A,24.337,7.4382,N/A,0.83425,356.37,N/A,N/A,N/A,4.5201,N/A,4.9453,10.5796,N/A,N/A,1.0452,140.8,10.1465,7.5355,86.2815,N/A,15.4678,1.5754,5.8435,1.4424,7.184,8.8566,16304.49,3.6276,84.6525,1356.45,23.027,4.7528,1.6896,58.403,1.5255,36.435,17.0858,
2022-02-17,1.137,130.84,1.9558,N/A,24.383,7.4398,N/A,0.83493,356.08,N/A,N/A,N/A,4.5065,N/A,4.9432,10.593,N/A,N/A,1.0466,141.6,10.1225,7.533,86.388,N/A,15.4945,1.5786,5.8495,1.4439,7.206,8.8692,16291.53,3.6231,85.2935,1360.7,23.0367,4.7612,1.695,58.314,1.5278,36.537,16.9893,
2022-02-16,1.1372,131.56,1.9558,N/A,24.365,7.441,N/A,0.8394,355.65,N/A,N/A,N/A,4.4961,N/A,4.9436,10.5363,N/A,N/A,1.0516,141.4,10.1095,7.5295,85.3679,N/A,15.481,1.5859,5.8765,1.4416,7.2101,8.8712,16232.55,3.6256,85.3885,1361.31,23.1718,4.7595,1.7108,58.346,1.5291,36.771,17.214,
2022-02-15,1.1345,131.18,1.9558,N/A,24.419,7.4422,N/A,0.83765,355.33,N/A,N/A,N/A,4.5036,N/A,4.941,10.5739,N/A,N/A,1.0483,141.2,10.0893,7.529,85.5025,N/A,15.4716,1.5888,5.8977,1.4433,7.1969,8.8527,16187.89,3.6596,85.443,1357.5,23.1113,4.7493,1.7143,58.144,1.5265,36.724,17.1767,
2022-02-14,1.1316,130.6,1.9558,N/A,24.527,7.4411,N/A,0.8372,357.06,N/A,N/A,N/A,4.54,N/A,4.9457,10.6158,N/A,N/A,1.0472,142.6,10.0693,7.5293,86.348,N/A,15.351,1.5902,5.8965,1.4431,7.1937,8.8283,16190.53,3.6835,85.4715,1354.5,23.1331,4.742,1.7112,58.114,1.5247,36.8,17.131,
2022-02-11,1.1417,132.24,1.9558,N/A,24.405,7.44,N/A,0.83958,353.38,N/A,N/A,N/A,4.5204,N/A,4.9458,10.553,N/A,N/A,1.0557,141.8,10.0732,7.5312,85.855,N/A,15.4066,1.5927,5.9263,1.4498,7.2564,8.9054,16339.46,3.6958,85.8535,1363.68,23.3183,4.7832,1.7085,58.482,1.5339,37.282,17.2736,
2022-02-10,1.1439,132.42,1.9558,N/A,24.35,7.4404,N/A,0.84248,354.02,N/A,N/A,N/A,4.4921,N/A,4.9451,10.5275,N/A,N/A,1.0571,141.8,10.0693,7.5275,85.0187,N/A,15.4838,1.5894,5.9668,1.4498,7.2722,8.9142,16390.21,3.6796,85.9373,1367.52,23.3584,4.7855,1.7076,58.583,1.5345,37.331,17.3078,
2022-02-09,1.1435,132.04,1.9558,N/A,24.288,7.4437,N/A,0.84255,352.94,N/A,N/A,N/A,4.5135,N/A,4.9449,10.4075,N/A,N/A,1.0555,142.2,10.0585,7.5285,85.5289,N/A,15.551,1.5933,6.0198,1.4514,7.2759,8.9106,16390.99,3.6817,85.5765,1365.72,23.4719,4.7853,1.7107,58.603,1.5349,37.404,17.5281,
2022-02-08,1.1408,131.68,1.9558,N/A,24.259,7.4437,N/A,0.84363,353.09,N/A,N/A,N/A,4.5312,N/A,4.945,10.4433,N/A,N/A,1.0545,142.4,10.0758,7.5215,85.7797,N/A,15.5558,1.6025,6.0209,1.4505,7.2636,8.8923,16418.4,3.6753,85.2545,1367.88,23.5601,4.774,1.7196,58.715,1.5349,37.606,17.638,
2022-02-07,1.1447,131.59,1.9558,N/A,24.222,7.4443,N/A,0.84685,353.48,N/A,N/A,N/A,4.5432,N/A,4.9461,10.4483,N/A,N/A,1.0571,143.4,10.0658,7.52,86.5824,N/A,15.5235,1.6097,6.0541,1.4546,7.2807,8.9202,16478.97,3.6547,85.5345,1371.76,23.575,4.7909,1.7278,58.978,1.5389,37.735,17.7,
2022-02-04,1.1464,131.72,1.9558,N/A,24.36,7.4432,N/A,0.84593,352.92,N/A,N/A,N/A,4.5474,N/A,4.9466,10.4465,N/A,N/A,1.0567,142.8,10.0483,7.5275,87.3095,N/A,15.5072,1.6165,6.083,1.4583,7.2923,8.9286,16493.16,3.6741,85.6445,1374.04,23.5856,4.7914,1.7287,58.754,1.5419,37.797,17.5875,
2022-02-03,1.1286,129.63,1.9558,N/A,24.135,7.4388,N/A,0.83208,353.94,N/A,N/A,N/A,4.5315,N/A,4.9461,10.387,N/A,N/A,1.0407,142.4,9.9545,7.5295,86.1788,N/A,15.3047,1.5849,5.9843,1.4334,7.1795,8.7966,16243.28,3.5949,84.518,1358.42,23.2359,4.7215,1.7001,57.608,1.5212,37.424,17.2864,
2022-02-02,1.1323,129.37,1.9558,N/A,24.298,7.4383,N/A,0.83395,354.45,N/A,N/A,N/A,4.5449,N/A,4.9463,10.385,N/A,N/A,1.0399,143.2,9.9228,7.526,85.815,N/A,15.3011,1.5828,5.9677,1.433,7.2026,8.8245,16243.98,3.5777,84.613,1359.23,23.2134,4.7392,1.701,57.785,1.5254,37.575,17.3459,
2022-02-01,1.126,129.12,1.9558,N/A,24.335,7.4407,N/A,0.83498,356.38,N/A,N/A,N/A,4.5804,N/A,4.9465,10.4438,N/A,N/A,1.0374,143.8,9.9638,7.5275,86.3238,N/A,15.0644,1.5868,5.9572,1.4299,7.1625,8.7779,16126.29,3.566,84.197,1353.61,23.1296,4.7129,1.7032,57.516,1.5199,37.378,17.1633,
2022-01-31,1.1156,128.79,1.9558,N/A,24.372,7.4419,N/A,0.83153,357.19,N/A,N/A,N/A,4.5892,N/A,4.9475,10.489,N/A,N/A,1.0404,143.2,10.0085,7.5293,86.7251,N/A,14.931,1.582,6.003,1.4233,7.0963,8.6994,16036.76,3.564,83.3655,1349.08,23.1856,4.6693,1.6983,56.985,1.511,37.144,17.3734,
2022-01-28,1.1138,128.68,1.9558,N/A,24.443,7.4432,N/A,0.83178,358.42,N/A,N/A,N/A,4.5755,N/A,4.9463,10.552,N/A,N/A,1.0378,144,10.026,7.529,86.6113,N/A,15.1424,1.5971,6.0147,1.4239,7.0857,8.681,16047.76,3.5697,83.6015,1349.47,23.1854,4.6668,1.7031,57.028,1.5109,37.229,17.3844,
2022-01-27,1.116,128.74,1.9558,N/A,24.427,7.4428,N/A,0.83368,358.09,N/A,N/A,N/A,4.5592,N/A,4.9466,10.445,N/A,N/A,1.0391,145.2,9.9903,7.5328,87.139,N/A,15.1946,1.5771,6.0159,1.4161,7.1061,8.6951,16052.42,3.5695,83.7893,1344.5,23.143,4.6844,1.6872,57.295,1.5089,37.124,17.1112,
2022-01-26,1.1277,128.86,1.9558,N/A,24.531,7.442,N/A,0.83458,359.67,N/A,N/A,N/A,4.5864,N/A,4.9451,10.4493,N/A,N/A,1.0386,145.6,10.0115,7.529,89.265,N/A,15.2877,1.5727,6.1084,1.4173,7.1293,8.7791,16185.31,3.5834,84.4288,1350.03,23.1845,4.7268,1.6865,57.728,1.5162,37.169,17.0858,
2022-01-25,1.1268,128.49,1.9558,N/A,24.5,7.4437,N/A,0.83713,359.44,N/A,N/A,N/A,4.5751,N/A,4.9448,10.502,N/A,N/A,1.0364,146,10.1385,7.5295,88.7384,N/A,15.2723,1.5814,6.2049,1.4247,7.1325,8.7725,16169.54,3.5898,84.277,1350.71,23.2909,4.7213,1.6911,57.753,1.5157,37.28,17.2669,
2022-01-24,1.1304,128.62,1.9558,N/A,24.528,7.4431,N/A,0.83803,359.84,N/A,N/A,N/A,4.5572,N/A,4.9453,10.5038,N/A,N/A,1.0308,145.6,10.1638,7.529,88.649,N/A,15.1621,1.5866,6.1901,1.4269,7.1533,8.8003,16213.69,3.5846,84.3495,1352.41,23.2566,4.7352,1.6901,58.045,1.5216,37.382,17.2509,
2022-01-21,1.1348,129.14,1.9558,N/A,24.347,7.4431,N/A,0.83633,358.19,N/A,N/A,N/A,4.5318,N/A,4.9453,10.414,N/A,N/A,1.0353,145.6,10.0523,7.528,86.838,N/A,15.223,1.5774,6.2063,1.4211,7.1946,8.837,16244.2,3.5668,84.419,1351.89,23.2229,4.7508,1.6884,58.171,1.526,37.358,17.1546,
2022-01-20,1.1338,129.53,1.9558,N/A,24.263,7.4424,N/A,0.83265,355.81,N/A,N/A,N/A,4.5228,N/A,4.9453,10.3708,N/A,N/A,1.0382,145.4,9.9578,7.525,86.8952,N/A,15.2094,1.5662,6.1621,1.4158,7.1936,8.8274,16267.5,3.5564,84.362,1349.16,23.1684,4.7489,1.6731,58.285,1.5261,37.319,17.2531,
2022-01-19,1.1345,129.86,1.9558,N/A,24.313,7.4419,N/A,0.83168,355.88,N/A,N/A,N/A,4.5229,N/A,4.9449,10.3428,N/A,N/A,1.0383,145.2,9.9368,7.5238,86.48,N/A,15.4207,1.5709,6.2657,1.4144,7.2003,8.8392,16283.78,3.5529,84.4135,1347.1,23.0922,4.757,1.6684,58.429,1.5293,37.467,17.3889,
2022-01-18,1.1367,130.39,1.9558,N/A,24.426,7.4425,N/A,0.83673,357,N/A,N/A,N/A,4.526,N/A,4.9449,10.3185,N/A,N/A,1.0414,146,9.9638,7.5225,86.7325,N/A,15.4447,1.5833,6.2797,1.4228,7.2212,8.8576,16318.64,3.5557,84.813,1355.33,23.1443,4.7554,1.6798,58.553,1.5349,37.635,17.5398,
2022-01-17,1.1403,130.64,1.9558,N/A,24.467,7.4417,N/A,0.83573,356.09,N/A,N/A,N/A,4.5256,N/A,4.9443,10.305,N/A,N/A,1.0429,146.8,9.9623,7.5275,87.3907,N/A,15.2757,1.5811,6.2808,1.4287,7.2402,8.8844,16337.73,3.5479,84.7295,1359.89,23.1901,4.7704,1.6765,58.496,1.5374,37.761,17.601,
2022-01-14,1.1447,130.17,1.9558,N/A,24.493,7.4414,N/A,0.83508,356.1,N/A,N/A,N/A,4.5414,N/A,4.9429,10.2684,N/A,N/A,1.0429,147,9.9863,7.5205,88.0011,N/A,15.5256,1.5803,6.3361,1.433,7.2728,8.9119,16388.85,3.5565,84.9445,1361.27,23.2684,4.7831,1.6745,58.727,1.5418,38.033,17.6043,
2022-01-13,1.1463,130.98,1.9558,N/A,24.458,7.4409,N/A,0.83545,355.24,N/A,N/A,N/A,4.5361,N/A,4.944,10.238,N/A,N/A,1.0453,147,9.9333,7.5202,86.603,N/A,15.5744,1.5709,6.3518,1.4304,7.2913,8.9289,16379.02,3.5638,84.717,1359.24,23.3894,4.7875,1.6676,58.572,1.5427,38.08,17.6381,
2022-01-12,1.137,131.19,1.9558,N/A,24.423,7.4414,N/A,0.83338,355.98,N/A,N/A,N/A,4.5359,N/A,4.9453,10.264,N/A,N/A,1.0486,147,9.927,7.524,84.7559,N/A,15.5922,1.5762,6.3458,1.4261,7.2379,8.863,16295.93,3.5406,84.0285,1353.27,23.1852,4.7595,1.6775,58.08,1.5358,37.936,17.5645,
2022-01-11,1.1336,130.95,1.9558,N/A,24.412,7.4404,N/A,0.83475,357.45,N/A,N/A,N/A,4.5438,N/A,4.945,10.3075,N/A,N/A,1.0502,147,10.0165,7.5236,84.8663,N/A,15.696,1.5804,6.389,1.4329,7.2255,8.8384,16221.39,3.549,83.7481,1352.85,23.0888,4.7515,1.6772,57.979,1.5342,37.862,17.7094,
2022-01-10,1.1318,130.45,1.9558,N/A,24.357,7.4381,N/A,0.83398,358.4,N/A,N/A,N/A,4.5334,N/A,4.9449,10.3038,N/A,N/A,1.0446,146.2,10.0253,7.5278,84.9825,N/A,15.7183,1.5774,6.3969,1.4327,7.2128,8.8233,16181.9,3.5303,83.8,1355.68,23.0597,4.7536,1.6753,58.141,1.5344,38.074,17.6999,
2022-01-07,1.1298,130.9,1.9558,N/A,24.439,7.438,N/A,0.8343,358.68,N/A,N/A,N/A,4.5496,N/A,4.9451,10.2839,N/A,N/A,1.0422,146,10.0288,7.5214,85.298,N/A,15.7206,1.5804,6.4343,1.4374,7.206,8.8133,16188.43,3.5135,83.978,1359.96,23.1109,4.7553,1.6748,58.046,1.5356,38.074,17.6701,
2022-01-06,1.1315,131.05,1.9558,N/A,24.528,7.4393,N/A,0.83593,359.84,N/A,N/A,N/A,4.5614,N/A,4.9435,10.3265,N/A,N/A,1.0395,146.8,10.035,7.5197,86.5088,N/A,15.5504,1.5778,6.442,1.4451,7.2187,8.8272,16291.88,3.5247,84.2475,1362.06,23.2549,4.767,1.6752,57.943,1.5388,37.962,17.7932,
2022-01-05,1.1319,131.03,1.9558,N/A,24.581,7.4384,N/A,0.83546,362.15,N/A,N/A,N/A,4.5666,N/A,4.946,10.2545,N/A,N/A,1.0364,146.8,9.9672,7.519,85.7275,N/A,15.2446,1.56,6.4146,1.4399,7.2087,8.8227,16263.02,3.4989,84.161,1354.61,23.1422,4.7466,1.6597,57.713,1.534,37.607,17.9369,
2022-01-04,1.1279,131.17,1.9558,N/A,24.745,7.4378,N/A,0.83618,365.12,N/A,N/A,N/A,4.5667,N/A,4.9481,10.2808,N/A,N/A,1.0355,147.8,10.0138,7.5185,84.9202,N/A,15.1384,1.5682,6.4174,1.4382,7.1924,8.7919,16199.73,3.4909,84.2055,1352.91,23.1808,4.7214,1.6668,57.988,1.531,37.582,18.108,
2022-01-03,1.1355,130.56,1.9558,N/A,24.818,7.4382,N/A,0.84135,367.71,N/A,N/A,N/A,4.5895,N/A,4.9483,10.2958,N/A,N/A,1.0372,147.6,10.0013,7.519,84.5313,N/A,15.0777,1.5691,6.3539,1.442,7.2174,8.8541,16202.02,3.5139,84.3949,1354.4,23.2259,4.7379,1.6651,58.051,1.5333,37.665,17.9661,
1 Date USD JPY BGN CYP CZK DKK EEK GBP HUF LTL LVL MTL PLN ROL RON SEK SIT SKK CHF ISK NOK HRK RUB TRL TRY AUD BRL CAD CNY HKD IDR ILS INR KRW MXN MYR NZD PHP SGD THB ZAR
2 2022-12-30 1.0666 140.66 1.9558 N/A 24.116 7.4365 N/A 0.88693 400.87 N/A N/A N/A 4.6808 N/A 4.9495 11.1218 N/A N/A 0.9847 151.5 10.5138 7.5365 N/A N/A 19.9649 1.5693 5.6386 1.444 7.3582 8.3163 16519.82 3.7554 88.171 1344.09 20.856 4.6984 1.6798 59.32 1.43 36.835 18.0986
3 2022-12-29 1.0649 142.24 1.9558 N/A 24.191 7.4365 N/A 0.88549 399.6 N/A N/A N/A 4.6855 N/A 4.9493 11.158 N/A N/A 0.984 152.5 10.55 7.5365 N/A N/A 19.934 1.5859 5.5351 1.4475 7.4151 8.2994 16680.38 3.7575 88.2295 1350.18 20.651 4.7106 1.6887 59.367 1.436 36.877 18.1967
4 2022-12-28 1.064 142.21 1.9558 N/A 24.252 7.4365 N/A 0.88058 403.3 N/A N/A N/A 4.7008 N/A 4.946 11.1038 N/A N/A 0.9863 151.9 10.4495 7.5365 N/A N/A 19.9144 1.566 5.6109 1.4361 7.4224 8.2931 16765.93 3.7526 88.0943 1348.59 20.6856 4.7055 1.6772 59.613 1.4323 36.953 18.289
5 2022-12-27 1.0624 141.68 1.9558 N/A 24.26 7.4366 N/A 0.88333 401.65 N/A N/A N/A 4.6683 N/A 4.927 11.1285 N/A N/A 0.9885 152.3 10.4895 7.5375 N/A N/A 19.8799 1.577 5.6035 1.4384 7.3994 8.2874 16620.58 3.7278 88.0808 1349.85 20.5515 4.699 1.6916 59.356 1.43 36.775 18.3181
6 2022-12-23 1.0622 140.86 1.9558 N/A 24.247 7.4364 N/A 0.8803 400.68 N/A N/A N/A 4.6423 N/A 4.9056 11.1045 N/A N/A 0.9867 152.3 10.4448 7.537 N/A N/A 19.843 1.5857 5.4834 1.4433 7.4198 8.2878 16569.18 3.704 87.958 1359.5 20.7115 4.7002 1.6887 58.623 1.4337 36.842 18.1048
7 2022-12-22 1.0633 140.42 1.9558 N/A 24.215 7.4367 N/A 0.88243 402.13 N/A N/A N/A 4.6443 N/A 4.8993 11.05 N/A N/A 0.9852 153.3 10.4123 7.538 N/A N/A 19.8553 1.5804 5.5386 1.4484 7.4229 8.2883 16525.91 3.6942 88.0365 1361.75 20.8485 4.7051 1.6918 58.705 1.4356 36.849 18.2238
8 2022-12-21 1.0636 140.29 1.9558 N/A 24.218 7.438 N/A 0.87651 402.93 N/A N/A N/A 4.6665 N/A 4.8937 11.0623 N/A N/A 0.9836 152.1 10.4309 7.5419 N/A N/A 19.8541 1.5859 5.4913 1.4475 7.4219 8.2902 16573.77 3.6989 88.109 1367.63 20.9919 4.7197 1.685 58.556 1.4366 36.907 18.3529
9 2022-12-20 1.0599 140.58 1.9558 N/A 24.181 7.4388 N/A 0.8753 403.88 N/A N/A N/A 4.6757 N/A 4.9125 11.0615 N/A N/A 0.9854 151.5 10.5098 7.5471 N/A N/A 19.7744 1.5972 5.6234 1.4451 7.39 8.2488 16537.09 3.6759 87.6649 1363.73 20.9355 4.6991 1.6816 58.549 1.4347 36.853 18.4239
10 2022-12-19 1.0598 144.65 1.9558 N/A 24.233 7.4382 N/A 0.87118 403.18 N/A N/A N/A 4.6853 N/A 4.9107 11.0063 N/A N/A 0.9884 151.9 10.5025 7.5395 N/A N/A 19.7676 1.5794 5.6327 1.4472 7.3901 8.2428 16506.72 3.6551 87.5321 1377.17 20.9743 4.6912 1.6632 58.649 1.4378 36.923 18.3074
11 2022-12-16 1.0619 145.53 1.9558 N/A 24.262 7.4379 N/A 0.87233 407.1 N/A N/A N/A 4.6925 N/A 4.9213 11.0153 N/A N/A 0.9879 150.1 10.4833 7.5385 N/A N/A 19.8039 1.5866 5.6233 1.4506 7.4037 8.2632 16575.47 3.6689 87.824 1389.7 21.0634 4.6984 1.6687 58.967 1.4413 37.145 18.6708
12 2022-12-15 1.0621 145.07 1.9558 N/A 24.27 7.4387 N/A 0.86194 406.4 N/A N/A N/A 4.689 N/A 4.922 10.898 N/A N/A 0.9862 150.9 10.4013 7.5395 N/A N/A 19.806 1.5695 5.6247 1.4443 7.4007 8.2551 16591.4 3.6388 87.9355 1393.97 20.9431 4.6918 1.6628 59.297 1.4406 37.12 18.3599
13 2022-12-14 1.0649 143.68 1.9558 N/A 24.276 7.4392 N/A 0.86118 406.63 N/A N/A N/A 4.681 N/A 4.9248 10.8638 N/A N/A 0.9865 150.9 10.362 7.538 N/A N/A 19.8579 1.551 5.6842 1.4441 7.4009 8.2751 16599.51 3.6327 87.8435 1379.99 20.8635 4.6765 1.6508 59.326 1.4349 36.851 18.2563
14 2022-12-13 1.0545 144.85 1.9558 N/A 24.287 7.4391 N/A 0.85753 409.65 N/A N/A N/A 4.6938 N/A 4.9298 10.8965 N/A N/A 0.9869 151.1 10.4679 7.5495 N/A N/A 19.6649 1.5553 5.5784 1.4341 7.3637 8.2033 16521.81 3.6266 87.2965 1378.75 20.9435 4.6704 1.6464 58.852 1.4288 36.707 18.6855
15 2022-12-12 1.0562 144.86 1.9558 N/A 24.307 7.4379 N/A 0.86006 416.78 N/A N/A N/A 4.6923 N/A 4.9318 10.9075 N/A N/A 0.9855 150.7 10.5548 7.554 N/A N/A 19.6913 1.5625 5.556 1.4428 7.367 8.2103 16524.63 3.6232 87.253 1377.93 20.9047 4.6652 1.6523 58.788 1.4284 36.708 18.4697
16 2022-12-09 1.0559 143.3 1.9558 N/A 24.293 7.4379 N/A 0.8595 417.53 N/A N/A N/A 4.6869 N/A 4.9224 10.9188 N/A N/A 0.9856 149.5 10.5345 7.555 N/A N/A 19.6872 1.5553 5.5457 1.438 7.3475 8.2169 16453.46 3.6128 86.9535 1373.94 20.849 4.6512 1.6482 58.47 1.426 36.656 18.2358
17 2022-12-08 1.0519 143.75 1.9558 N/A 24.324 7.4382 N/A 0.86258 417.66 N/A N/A N/A 4.6853 N/A 4.9131 10.906 N/A N/A 0.9889 149.5 10.488 7.5553 N/A N/A 19.6114 1.559 5.488 1.4307 7.3324 8.1889 16423.92 3.6206 86.6755 1387.06 20.6989 4.6257 1.6547 58.233 1.4256 36.559 18.0225
18 2022-12-07 1.0529 144.44 1.9558 N/A 24.322 7.4382 N/A 0.86408 410.63 N/A N/A N/A 4.7003 N/A 4.918 10.919 N/A N/A 0.9893 148.7 10.5255 7.5525 N/A N/A 19.6256 1.5728 5.5023 1.4387 7.3476 8.1997 16465.17 3.626 86.692 1390.87 20.7534 4.6301 1.6573 58.432 1.4286 36.904 18.1353
19 2022-12-06 1.0516 143.33 1.9558 N/A 24.316 7.438 N/A 0.8617 415.08 N/A N/A N/A 4.6975 N/A 4.913 10.889 N/A N/A 0.9872 148.9 10.4408 7.5563 N/A N/A 19.601 1.5625 5.5113 1.4326 7.3494 8.1813 16441.49 3.5831 86.6485 1386.39 20.6884 4.6223 1.6583 58.782 1.4263 36.827 18.2068
20 2022-12-05 1.0587 143.07 1.9558 N/A 24.351 7.4369 N/A 0.86085 412.13 N/A N/A N/A 4.695 N/A 4.9215 10.8931 N/A N/A 0.9893 148.9 10.3366 7.551 N/A N/A 19.7326 1.5542 5.5491 1.4198 7.3573 8.2236 16332.36 3.5856 86.5249 1370.87 20.7295 4.6255 1.6498 59.245 1.4271 36.732 18.2038
21 2022-12-02 1.0538 141.32 1.9558 N/A 24.377 7.4373 N/A 0.85855 410 N/A N/A N/A 4.684 N/A 4.9298 10.902 N/A N/A 0.9834 148.7 10.2615 7.5503 N/A N/A 19.6392 1.5457 5.4657 1.416 7.3971 8.2035 16179.78 3.5769 85.6435 1366.67 20.187 4.6241 1.6453 58.734 1.4227 36.614 18.2749
22 2022-12-01 1.0454 142.48 1.9558 N/A 24.361 7.4373 N/A 0.85715 413.5 N/A N/A N/A 4.6998 N/A 4.9303 10.8984 N/A N/A 0.9868 148.7 10.2495 7.55 N/A N/A 19.4778 1.5377 5.4508 1.4059 7.3965 8.1371 16160.84 3.5642 84.933 1363.81 20.1472 4.605 1.6446 58.793 1.4195 36.526 18.5393
23 2022-11-30 1.0376 144.28 1.9558 N/A 24.338 7.4366 N/A 0.86488 408.4 N/A N/A N/A 4.6635 N/A 4.9245 10.9345 N/A N/A 0.9854 147.1 10.2648 7.549 N/A N/A 19.3333 1.5425 5.5063 1.4021 7.3437 8.0944 16271.81 3.5691 84.4215 1365.14 20.0111 4.6147 1.6634 58.697 1.418 36.588 17.5768
24 2022-11-29 1.0366 143.36 1.9558 N/A 24.334 7.4367 N/A 0.86218 406.5 N/A N/A N/A 4.673 N/A 4.9193 10.901 N/A N/A 0.9862 147.1 10.3313 7.55 N/A N/A 19.3181 1.5414 5.5126 1.4005 7.4289 8.0965 16301.58 3.5581 84.6548 1375.7 19.8075 4.6735 1.6639 58.64 1.4237 36.706 17.6027
25 2022-11-28 1.0463 144.9 1.9558 N/A 24.348 7.4367 N/A 0.86606 408.87 N/A N/A N/A 4.6938 N/A 4.9246 10.8973 N/A N/A 0.9872 146.7 10.364 7.5488 N/A N/A 19.4844 1.5632 5.6354 1.4062 7.5326 8.1782 16440.45 3.6002 85.437 1396.56 20.22 4.6874 1.6827 59.21 1.4375 37.285 17.9376
26 2022-11-25 1.0375 144.62 1.9558 N/A 24.367 7.4365 N/A 0.85885 411.33 N/A N/A N/A 4.6875 N/A 4.9255 10.8183 N/A N/A 0.9836 146.5 10.2985 7.5473 N/A N/A 19.3333 1.5404 5.5476 1.3864 7.4425 8.1084 16282.44 3.5551 84.7145 1383.2 20.1069 4.648 1.6651 58.795 1.4277 37.153 17.7677
27 2022-11-24 1.0413 143.9 1.9558 N/A 24.392 7.4369 N/A 0.85933 413.33 N/A N/A N/A 4.6958 N/A 4.9205 10.8573 N/A N/A 0.9818 146.5 10.3435 7.547 N/A N/A 19.3969 1.5414 5.5504 1.3894 7.4442 8.1324 16295.35 3.5607 85.0295 1382.28 20.1501 4.6806 1.6598 58.992 1.4319 37.258 17.7246
28 2022-11-23 1.0325 145.75 1.9558 N/A 24.356 7.437 N/A 0.86369 405.75 N/A N/A N/A 4.7033 N/A 4.937 10.8933 N/A N/A 0.9795 146.7 10.3659 7.5435 N/A N/A 19.2316 1.5522 5.565 1.3856 7.3982 8.0708 16189.81 3.5681 84.466 1397.42 20.001 4.7237 1.6718 58.914 1.4295 37.423 17.7103
29 2022-11-22 1.0274 145.2 1.9558 N/A 24.351 7.4377 N/A 0.86358 408.23 N/A N/A N/A 4.7125 N/A 4.9269 10.9653 N/A N/A 0.9791 145.7 10.4445 7.5438 N/A N/A 19.1221 1.5473 5.4578 1.3765 7.3344 8.0313 16106.79 3.5615 83.8768 1392.68 20.0951 4.7055 1.6707 58.942 1.4167 37.11 17.7568
30 2022-11-21 1.0246 145.33 1.9558 N/A 24.356 7.4377 N/A 0.86793 409.43 N/A N/A N/A 4.7075 N/A 4.9413 10.9873 N/A N/A 0.9817 147.9 10.4898 7.5425 N/A N/A 19.0822 1.5471 5.4401 1.377 7.3419 7.9989 16116.76 3.5515 83.7375 1395 19.9357 4.6927 1.6766 58.822 1.4162 37.121 17.7858
31 2022-11-18 1.0366 145.12 1.9558 N/A 24.351 7.4385 N/A 0.87063 407.41 N/A N/A N/A 4.7033 N/A 4.9413 10.9805 N/A N/A 0.9881 148.9 10.486 7.5415 N/A N/A 19.3009 1.5433 5.547 1.3841 7.379 8.1092 16224.36 3.591 84.6875 1389.02 20.162 4.7202 1.6757 59.41 1.4229 37.069 17.908
32 2022-11-17 1.0319 144.8 1.9558 N/A 24.399 7.4383 N/A 0.87475 415.6 N/A N/A N/A 4.7153 N/A 4.9254 10.9871 N/A N/A 0.9818 148.9 10.498 7.541 N/A N/A 19.2124 1.5526 5.6535 1.382 7.3859 8.077 16224.01 3.5796 84.394 1394.06 20.062 4.7122 1.6986 59.293 1.4221 37.123 18.0961
33 2022-11-16 1.0412 145.29 1.9558 N/A 24.355 7.4386 N/A 0.87483 408.18 N/A N/A N/A 4.7065 N/A 4.9206 10.8754 N/A N/A 0.9795 148.9 10.3675 7.5443 N/A N/A 19.3783 1.54 5.5438 1.3801 7.372 8.1444 16248.37 3.5684 84.5905 1378.1 20.1227 4.7323 1.6897 59.678 1.425 37.103 18.0195
34 2022-11-15 1.0404 144.84 1.9558 N/A 24.326 7.4388 N/A 0.87455 405.45 N/A N/A N/A 4.7073 N/A 4.9116 10.8081 N/A N/A 0.979 149.9 10.357 7.5459 N/A N/A 19.3608 1.5415 5.548 1.3816 7.3299 8.143 16164.78 3.5694 84.1304 1365.61 20.0795 4.7208 1.6897 59.532 1.4238 36.939 17.8822
35 2022-11-14 1.0319 144.86 1.9558 N/A 24.289 7.4382 N/A 0.87513 407.28 N/A N/A N/A 4.6898 N/A 4.9043 10.7713 N/A N/A 0.9751 150.3 10.3143 7.5465 N/A N/A 19.1923 1.5427 5.4605 1.3706 7.2906 8.0852 16052.12 3.541 83.7779 1369.32 20.0985 4.7429 1.6957 59.04 1.4177 36.978 17.8393
36 2022-11-11 1.0308 143.89 1.9558 N/A 24.278 7.4384 N/A 0.87538 402.08 N/A N/A N/A 4.6765 N/A 4.894 10.7241 N/A N/A 0.9844 148.7 10.2635 7.5445 N/A N/A 19.0987 1.5459 5.5147 1.3698 7.3267 8.0758 15979.45 3.5255 83.2253 1359.2 20.0239 4.77 1.702 59.106 1.4199 37.088 17.7944
37 2022-11-10 0.9954 145.47 1.9558 N/A 24.361 7.4381 N/A 0.87298 400.95 N/A N/A N/A 4.706 N/A 4.8913 10.8743 N/A N/A 0.9834 147.5 10.3615 7.5427 N/A N/A 18.51 1.5525 5.286 1.3467 7.2184 7.8128 15615.6 3.5453 81.3058 1373.96 19.4562 4.6789 1.6984 57.793 1.3963 36.7 17.6882
38 2022-11-09 1.0039 146.82 1.9558 N/A 24.337 7.4382 N/A 0.87774 403.53 N/A N/A N/A 4.701 N/A 4.9045 10.845 N/A N/A 0.988 146.7 10.322 7.5425 N/A N/A 18.6728 1.5538 5.1947 1.3501 7.2813 7.8801 15717.07 3.5621 81.6575 1369.73 19.6554 4.7098 1.7033 58.236 1.4061 36.999 17.877
39 2022-11-08 0.9996 146.25 1.9558 N/A 24.326 7.4378 N/A 0.87378 400.75 N/A N/A N/A 4.6918 N/A 4.8978 10.8373 N/A N/A 0.9911 146.3 10.2795 7.539 N/A N/A 18.5991 1.5435 5.203 1.3489 7.2495 7.8468 15652.76 3.5436 81.518 1377.94 19.4495 4.7346 1.686 58.187 1.4022 37.22 17.8397
40 2022-11-07 0.9993 146.18 1.9558 N/A 24.301 7.4393 N/A 0.87135 401.03 N/A N/A N/A 4.6865 N/A 4.8855 10.832 N/A N/A 0.9874 145.9 10.2555 7.5375 N/A N/A 18.5875 1.5428 5.07 1.3464 7.2189 7.8444 15648.95 3.5402 81.8407 1391.25 19.4395 4.7362 1.6834 58.361 1.4022 37.284 17.7583
41 2022-11-04 0.9872 145.19 1.9558 N/A 24.422 7.4419 N/A 0.87478 401.15 N/A N/A N/A 4.6825 N/A 4.8893 10.8538 N/A N/A 0.9863 145.5 10.2019 7.5353 N/A N/A 18.3845 1.5311 4.9682 1.3351 7.0894 7.7493 15491.81 3.5065 81.02 1397.7 19.2611 4.6872 1.6769 57.672 1.3891 36.906 17.7983
42 2022-11-03 0.9753 144.58 1.9558 N/A 24.539 7.4433 N/A 0.87228 407.87 N/A N/A N/A 4.709 N/A 4.9013 10.932 N/A N/A 0.9889 144.9 10.3543 7.5375 N/A N/A 18.1602 1.5517 5.0262 1.3452 7.1367 7.656 15400.2 3.4847 80.8845 1391.75 19.2363 4.6271 1.6957 57.463 1.3878 37.091 18.0173
43 2022-11-02 0.9908 145.75 1.9558 N/A 24.506 7.4431 N/A 0.861 407 N/A N/A N/A 4.7035 N/A 4.912 10.9065 N/A N/A 0.9861 143.7 10.2388 7.5335 N/A N/A 18.4488 1.5426 5.0964 1.347 7.2156 7.7774 15492.57 3.4987 81.992 1402.01 19.4921 4.6944 1.6844 57.841 1.3983 37.314 17.9608
44 2022-11-01 0.9947 146.35 1.9558 N/A 24.484 7.4438 N/A 0.86058 406.9 N/A N/A N/A 4.7053 N/A 4.9138 10.874 N/A N/A 0.9878 143.3 10.1835 7.5342 N/A N/A 18.5216 1.5409 5.1337 1.3469 7.2165 7.8079 15534.6 3.4922 82.084 1404.63 19.5984 4.7119 1.6876 57.786 1.4017 37.45 17.9802
45 2022-10-31 0.9914 147.4 1.9558 N/A 24.488 7.4444 N/A 0.86115 409.65 N/A N/A N/A 4.7085 N/A 4.9143 10.901 N/A N/A 0.9925 143.3 10.3028 7.531 N/A N/A 18.4562 1.5529 5.2694 1.3553 7.238 7.7822 15489.55 3.4933 82.1035 1416.12 19.7122 4.6873 1.7099 57.8 1.4038 37.748 18.1736
46 2022-10-28 0.9951 146.79 1.9558 N/A 24.465 7.4423 N/A 0.8612 411.7 N/A N/A N/A 4.7275 N/A 4.9189 10.9403 N/A N/A 0.992 143.3 10.2695 7.532 N/A N/A 18.5219 1.5511 5.327 1.3542 7.2159 7.8107 15481.88 3.5215 82.0565 1417.7 19.7718 4.6994 1.7151 57.739 1.4055 37.724 18.053
47 2022-10-27 1.0037 147.37 1.9558 N/A 24.53 7.4387 N/A 0.86745 412.15 N/A N/A N/A 4.7585 N/A 4.8893 10.9583 N/A N/A 0.9949 143.1 10.342 7.533 N/A N/A 18.681 1.561 5.3889 1.3672 7.2552 7.8782 15629.06 3.5376 82.656 1428.57 20.015 4.7324 1.7316 58.441 1.4154 37.975 18.1521
48 2022-10-26 1.0023 147.32 1.9558 N/A 24.535 7.4381 N/A 0.86603 408.09 N/A N/A N/A 4.7548 N/A 4.8806 10.953 N/A N/A 0.9917 143.5 10.3408 7.532 N/A N/A 18.6461 1.5466 5.2944 1.3568 7.1948 7.8678 15589.27 3.5145 82.206 1422.11 19.8501 4.7262 1.7249 58.493 1.4104 37.862 18.0212
49 2022-10-25 0.9861 146.84 1.9558 N/A 24.472 7.4387 N/A 0.87143 413.7 N/A N/A N/A 4.777 N/A 4.9036 10.9728 N/A N/A 0.9888 142.9 10.391 7.5315 N/A N/A 18.3508 1.5599 5.2254 1.3537 7.2072 7.7407 15407.12 3.506 81.653 1417.5 19.6353 4.6697 1.7321 57.988 1.405 37.758 18.2211
50 2022-10-24 0.9851 146.76 1.9558 N/A 24.482 7.4385 N/A 0.8707 411.88 N/A N/A N/A 4.7908 N/A 4.9128 11.0795 N/A N/A 0.9856 142.5 10.392 7.5337 N/A N/A 18.3298 1.5631 5.1461 1.3502 7.1544 7.7329 15362.63 3.4997 81.5451 1418.4 19.6514 4.6674 1.7343 58.021 1.4008 37.6 18.0625
51 2022-10-21 0.973 147.59 1.9558 N/A 24.511 7.4382 N/A 0.87728 412.88 N/A N/A N/A 4.7885 N/A 4.9125 11.0868 N/A N/A 0.9855 141.1 10.4315 7.5325 N/A N/A 18.0988 1.5646 5.1117 1.3465 7.0504 7.6376 15199.12 3.4803 80.739 1404.32 19.5521 4.6101 1.7347 57.287 1.3917 37.349 18.0021
52 2022-10-20 0.9811 146.99 1.9558 N/A 24.525 7.4389 N/A 0.87258 411.2 N/A N/A N/A 4.7728 N/A 4.9203 10.982 N/A N/A 0.9836 141.1 10.402 7.5353 N/A N/A 18.2257 1.5554 5.1387 1.3461 7.0858 7.7008 15250.05 3.4754 81.1755 1400.3 19.7005 4.6396 1.7206 57.742 1.3959 37.36 17.9106
53 2022-10-19 0.9778 146.34 1.9558 N/A 24.563 7.439 N/A 0.86993 413.78 N/A N/A N/A 4.7878 N/A 4.9248 10.9448 N/A N/A 0.981 141.1 10.3823 7.5325 N/A N/A 18.1793 1.5568 5.1755 1.3479 7.0672 7.6757 15185.1 3.4628 81.1955 1398.35 19.6845 4.6152 1.7264 57.741 1.3931 37.469 17.8339
54 2022-10-18 0.9835 146.65 1.9558 N/A 24.593 7.4393 N/A 0.86928 413.08 N/A N/A N/A 4.804 N/A 4.9359 10.906 N/A N/A 0.9792 141.5 10.3528 7.5298 N/A N/A 18.2813 1.5557 5.1795 1.3495 7.0805 7.72 15214.98 3.464 80.9195 1400.92 19.664 4.6382 1.7251 57.897 1.3963 37.422 17.7904
55 2022-10-17 0.9739 145 1.9558 N/A 24.562 7.4379 N/A 0.8625 418.3 N/A N/A N/A 4.8143 N/A 4.937 10.9893 N/A N/A 0.9762 140.9 10.342 7.5265 N/A N/A 18.1043 1.5599 5.1497 1.3452 7.013 7.6448 15061.8 3.4486 80.128 1399.41 19.5 4.5934 1.7404 57.433 1.3896 37.169 17.6769
56 2022-10-14 0.9717 143.63 1.9558 N/A 24.587 7.4378 N/A 0.86823 418.24 N/A N/A N/A 4.8328 N/A 4.9335 11.0035 N/A N/A 0.9757 140.5 10.3323 7.5266 N/A N/A 18.0614 1.5493 5.1177 1.3426 6.9952 7.6278 15031.5 3.444 79.9695 1398.5 19.5032 4.5689 1.7302 57.375 1.3852 37.109 17.6932
57 2022-10-13 0.9739 142.94 1.9558 N/A 24.569 7.4385 N/A 0.86513 430.65 N/A N/A N/A 4.8303 N/A 4.9355 11.0098 N/A N/A 0.9725 140.5 10.3525 7.531 N/A N/A 18.1041 1.5495 5.1214 1.3443 6.9945 7.644 14952.86 3.4731 79.9981 1392.71 19.4442 4.5691 1.7314 57.352 1.3949 36.843 17.8173
58 2022-10-12 0.9706 142.34 1.9558 N/A 24.561 7.4399 N/A 0.8784 429.65 N/A N/A N/A 4.8495 N/A 4.94 11.02 N/A N/A 0.9664 140.1 10.4145 7.529 N/A N/A 18.0427 1.5525 5.1378 1.3395 6.9603 7.6192 14907.04 3.4623 79.8955 1384.66 19.4522 4.5448 1.7372 57.148 1.3941 36.902 17.6876
59 2022-10-11 0.9723 141.54 1.9558 N/A 24.535 7.439 N/A 0.87703 428.73 N/A N/A N/A 4.869 N/A 4.9394 11.0015 N/A N/A 0.9675 140.7 10.4235 7.5293 N/A N/A 18.0686 1.545 5.0456 1.3402 6.9669 7.6325 14930.83 3.4776 79.9555 1392.84 19.4115 4.5436 1.7323 57.243 1.3967 37.03 17.6153
60 2022-10-10 0.9697 141.16 1.9558 N/A 24.521 7.4384 N/A 0.8773 428.2 N/A N/A N/A 4.8655 N/A 4.94 10.9502 N/A N/A 0.968 139.9 10.3378 7.528 N/A N/A 18.0131 1.536 5.0328 1.3312 6.9344 7.612 14872.51 3.4463 79.9678 1384.26 19.3588 4.5091 1.7369 57.197 1.3939 36.81 17.5866
61 2022-10-07 0.9797 141.92 1.9558 N/A 24.517 7.4381 N/A 0.87383 423.85 N/A N/A N/A 4.8595 N/A 4.9415 10.8555 N/A N/A 0.97 140.7 10.4498 7.527 N/A N/A 18.209 1.5266 5.1075 1.3437 6.9715 7.6906 14933.14 3.4477 80.546 1381.42 19.643 4.5556 1.7328 57.747 1.3996 36.602 17.6222
62 2022-10-06 0.986 142.68 1.9558 N/A 24.479 7.439 N/A 0.87583 422.59 N/A N/A N/A 4.8505 N/A 4.9364 10.8728 N/A N/A 0.9709 139.9 10.4278 7.5288 N/A N/A 18.3191 1.5263 5.1185 1.3475 7.0164 7.74 15021.24 3.4846 81.0615 1388.39 19.817 4.5726 1.728 57.949 1.4057 36.827 17.5769
63 2022-10-05 0.9915 143.18 1.9558 N/A 24.524 7.4388 N/A 0.8734 423.6 N/A N/A N/A 4.791 N/A 4.9385 10.8376 N/A N/A 0.9756 141.3 10.4858 7.5255 N/A N/A 18.4201 1.538 5.1575 1.3493 7.0555 7.7831 15061.81 3.503 80.909 1406.71 19.8625 4.5911 1.7419 58.212 1.4124 37.102 17.6228
64 2022-10-04 0.9891 143.3 1.9558 N/A 24.544 7.4374 N/A 0.87273 417.68 N/A N/A N/A 4.8193 N/A 4.9418 10.8166 N/A N/A 0.9767 141.9 10.4915 7.523 N/A N/A 18.3374 1.5318 5.0589 1.3503 7.0384 7.7644 15080.18 3.4885 80.6995 1412.2 19.777 4.5939 1.7368 58.104 1.4148 37.16 17.5437
65 2022-10-03 0.9764 141.49 1.9558 N/A 24.527 7.4366 N/A 0.8707 424.86 N/A N/A N/A 4.832 N/A 4.9479 10.8743 N/A N/A 0.9658 141.7 10.5655 7.5275 N/A N/A 18.124 1.5128 5.178 1.3412 6.9481 7.6647 14969.79 3.498 79.898 1408.25 19.604 4.5383 1.7263 57.599 1.4015 37.181 17.5871
66 2022-09-30 0.9748 141.01 1.9558 N/A 24.549 7.4365 N/A 0.883 422.18 N/A N/A N/A 4.8483 N/A 4.949 10.8993 N/A N/A 0.9561 140.9 10.5838 7.524 N/A N/A 18.0841 1.5076 5.2584 1.3401 6.9368 7.6521 14863.26 3.4759 79.425 1400.69 19.6393 4.5201 1.7177 57.276 1.4001 36.823 17.5353
67 2022-09-29 0.9706 140.46 1.9558 N/A 24.687 7.4365 N/A 0.89485 421.93 N/A N/A N/A 4.857 N/A 4.9481 10.958 N/A N/A 0.9538 140.1 10.4518 7.528 N/A N/A 18 1.4982 5.2521 1.3294 6.9223 7.6192 14735.97 3.4422 79.314 1388.34 19.5779 4.4992 1.704 56.86 1.3961 36.946 17.4466
68 2022-09-28 0.9565 138.39 1.9558 N/A 24.65 7.4368 N/A 0.90268 411.72 N/A N/A N/A 4.8043 N/A 4.9485 10.9194 N/A N/A 0.9437 139.7 10.4576 7.5313 N/A N/A 17.7311 1.4924 5.1728 1.3157 6.9199 7.5084 14622.96 3.3931 78.2655 1378.84 19.5294 4.4281 1.6998 56.528 1.3846 36.687 17.2916
69 2022-09-27 0.9644 139.28 1.9558 N/A 24.661 7.4366 N/A 0.89275 406.65 N/A N/A N/A 4.764 N/A 4.9444 10.8533 N/A N/A 0.9503 139.3 10.3473 7.528 N/A N/A 17.824 1.4859 5.1235 1.3196 6.9156 7.5704 14604.52 3.3714 78.574 1370.06 19.5832 4.4466 1.6921 56.933 1.3838 36.565 17.2361
70 2022-09-26 0.9646 139.07 1.9558 N/A 24.64 7.4365 N/A 0.89404 408.83 N/A N/A N/A 4.7608 N/A 4.9418 10.9275 N/A N/A 0.9555 138.9 10.3585 7.5278 N/A N/A 17.8001 1.4858 5.1504 1.3195 6.9075 7.572 14620.74 3.4069 78.704 1379.4 19.6066 4.4401 1.6886 56.908 1.3842 36.496 17.4247
71 2022-09-23 0.9754 139.43 1.9558 N/A 24.658 7.4365 N/A 0.88201 406.3 N/A N/A N/A 4.7543 N/A 4.9433 10.9328 N/A N/A 0.9565 139.9 10.2335 7.5228 N/A N/A 17.9515 1.4828 5.0456 1.3177 6.9442 7.6567 14697.3 3.4152 79.0705 1381.97 19.5708 4.4659 1.6846 57.217 1.3897 36.636 17.3853
72 2022-09-22 0.9884 139.18 1.9558 N/A 24.657 7.4365 N/A 0.87256 405.25 N/A N/A N/A 4.7592 N/A 4.9411 10.8724 N/A N/A 0.9684 139.9 10.235 7.5235 N/A N/A 18.1559 1.484 5.0677 1.3278 6.9804 7.7583 14824.28 3.4216 79.897 1384.79 19.6129 4.514 1.6832 57.721 1.3998 36.803 17.3514
73 2022-09-21 0.9906 142.66 1.9558 N/A 24.637 7.4364 N/A 0.87335 405.1 N/A N/A N/A 4.7505 N/A 4.9443 10.9214 N/A N/A 0.9549 140.3 10.2858 7.5205 N/A N/A 18.149 1.4851 5.0924 1.3262 6.9821 7.7761 14866.28 3.4298 79.1555 1381.38 19.7847 4.5097 1.6844 57.285 1.4006 36.786 17.4879
74 2022-09-20 0.9986 143.34 1.9558 N/A 24.556 7.4368 N/A 0.87395 398.58 N/A N/A N/A 4.7208 N/A 4.934 10.8338 N/A N/A 0.9644 140.9 10.273 7.5198 N/A N/A 18.2833 1.4893 5.2139 1.3268 7.003 7.8382 14997.82 3.4406 79.6095 1390.71 19.9667 4.5516 1.6908 57.497 1.4074 36.968 17.7261
75 2022-09-19 0.999 143.42 1.9558 N/A 24.494 7.4373 N/A 0.87785 400.85 N/A N/A N/A 4.7058 N/A 4.93 10.7993 N/A N/A 0.9658 139.9 10.2826 7.5215 N/A N/A 18.2738 1.495 5.2886 1.3294 7.0066 7.8416 14975.43 3.446 79.653 1391.82 20.113 4.5455 1.6807 57.347 1.4082 36.983 17.7267
76 2022-09-16 0.9954 142.53 1.9558 N/A 24.497 7.4366 N/A 0.874 403.98 N/A N/A N/A 4.7143 N/A 4.9238 10.7541 N/A N/A 0.9579 138.3 10.1985 7.5235 N/A N/A 18.1923 1.4894 5.2279 1.3226 6.9787 7.8133 14904.67 3.4267 79.3605 1383.58 20.0028 4.5141 1.6717 57.111 1.4025 36.8 17.6004
77 2022-09-15 0.9992 143.43 1.9558 N/A 24.518 7.4366 N/A 0.86934 407.15 N/A N/A N/A 4.7273 N/A 4.9238 10.69 N/A N/A 0.9572 138.7 10.1203 7.5258 N/A N/A 18.2477 1.4853 5.1837 1.3172 6.9852 7.8423 14925.35 3.4384 79.7119 1397.18 20.0021 4.5314 1.6689 57.258 1.4062 36.816 17.5283
78 2022-09-14 0.999 143.08 1.9558 N/A 24.527 7.4366 N/A 0.86498 402.9 N/A N/A N/A 4.7163 N/A 4.9297 10.675 N/A N/A 0.9612 139.7 10.1125 7.5195 N/A N/A 18.2397 1.4873 5.1827 1.3177 6.955 7.8405 14903.93 3.4339 79.422 1391.97 20.028 4.5225 1.6675 57.054 1.4039 36.608 17.4342
79 2022-09-13 1.0175 144.5 1.9558 N/A 24.551 7.4366 N/A 0.86793 396.83 N/A N/A N/A 4.705 N/A 4.921 10.6108 N/A N/A 0.9669 140.1 9.9988 7.5255 N/A N/A 18.564 1.4736 5.1764 1.32 7.0467 7.9855 15099.17 3.4125 80.5453 1397.3 20.1615 4.5869 1.6555 57.665 1.4186 36.859 17.3112
80 2022-09-12 1.0155 144.49 1.9558 N/A 24.546 7.4365 N/A 0.86778 395.73 N/A N/A N/A 4.6965 N/A 4.9135 10.6368 N/A N/A 0.9667 140.9 9.9718 7.5195 N/A N/A 18.5232 1.4749 5.1933 1.3194 7.0348 7.9709 15083.83 3.4346 80.692 1397.58 20.1025 4.5733 1.6499 57.701 1.4168 36.873 17.322
81 2022-09-09 1.0049 143.3 1.9558 N/A 24.536 7.4365 N/A 0.8686 396.3 N/A N/A N/A 4.721 N/A 4.9019 10.6643 N/A N/A 0.9657 140.9 9.9836 7.5245 N/A N/A 18.3282 1.4704 5.2087 1.307 6.9543 7.8871 14905.33 3.4416 79.9685 1384.64 19.991 4.52 1.6463 57.098 1.4063 36.508 17.3753
82 2022-09-08 1.0009 143.65 1.9558 N/A 24.543 7.4365 N/A 0.86656 395.48 N/A N/A N/A 4.7155 N/A 4.8756 10.7075 N/A N/A 0.9739 140.3 10.0615 7.515 N/A N/A 18.2546 1.4824 5.2042 1.3134 6.9564 7.8568 14891.86 3.429 79.7375 1381.7 20.013 4.5051 1.6491 57.031 1.4054 36.418 17.3797
83 2022-09-07 0.9885 143.2 1.9558 N/A 24.631 7.4365 N/A 0.8651 401.83 N/A N/A N/A 4.729 N/A 4.8585 10.6888 N/A N/A 0.975 141.3 9.9483 7.5143 N/A N/A 18.0262 1.4748 5.1881 1.3037 6.8968 7.7596 14779.47 3.4053 79.028 1374.44 19.9225 4.4497 1.6459 56.532 1.3931 36.322 17.2582
84 2022-09-06 0.9928 140.91 1.9558 N/A 24.55 7.4365 N/A 0.85743 402.65 N/A N/A N/A 4.7068 N/A 4.8424 10.6825 N/A N/A 0.9745 141.9 9.8945 7.5133 N/A N/A 18.0938 1.4651 5.13 1.3029 6.9091 7.7932 14783.94 3.39 79.2305 1366.65 19.8545 4.4676 1.6313 56.655 1.3947 36.242 17.0805
85 2022-09-05 0.992 139.47 1.9558 N/A 24.622 7.4364 N/A 0.86358 403.9 N/A N/A N/A 4.736 N/A 4.8198 10.729 N/A N/A 0.9747 142.7 9.9188 7.5173 N/A N/A 18.0792 1.4616 5.1407 1.3043 6.8768 7.7867 14782.83 3.3826 79.2332 1359.98 19.8192 4.4563 1.6289 56.477 1.3932 36.263 17.088
86 2022-09-02 0.9993 140.36 1.9558 N/A 24.481 7.437 N/A 0.86478 398.38 N/A N/A N/A 4.7063 N/A 4.8335 10.7498 N/A N/A 0.9839 141.5 10.0035 7.5225 N/A N/A 18.2072 1.4671 5.2153 1.3131 6.9031 7.8439 14895.92 3.396 79.8096 1360.84 20.1024 4.4809 1.6394 56.854 1.4013 36.624 17.2791
87 2022-09-01 1.0004 139.34 1.9558 N/A 24.488 7.4372 N/A 0.86473 399.58 N/A N/A N/A 4.7128 N/A 4.8447 10.7415 N/A N/A 0.9802 141.7 10.013 7.521 N/A N/A 18.2149 1.4651 5.2239 1.3169 6.9017 7.8511 14878 3.3644 79.6195 1353.69 20.1954 4.4828 1.6389 56.609 1.4002 36.71 17.1524
88 2022-08-31 1 138.72 1.9558 N/A 24.55 7.4371 N/A 0.86035 402.8 N/A N/A N/A 4.7283 N/A 4.8595 10.6788 N/A N/A 0.9796 141.7 9.9388 7.5148 N/A N/A 18.1849 1.4591 5.1482 1.3111 6.8947 7.8488 14849.93 3.3399 79.5465 1342.79 20.2044 4.4755 1.6322 56.153 1.3969 36.45 17.0667
89 2022-08-30 1.0034 138.71 1.9558 N/A 24.577 7.4376 N/A 0.85645 406.38 N/A N/A N/A 4.7323 N/A 4.8657 10.65 N/A N/A 0.9741 142.1 9.7553 7.5103 N/A N/A 18.239 1.4472 5.0286 1.3047 6.9233 7.8751 14875 3.3168 79.8025 1350.92 20.0077 4.4907 1.6245 56.393 1.3997 36.494 16.8567
90 2022-08-29 0.9986 138.49 1.9558 N/A 24.592 7.4379 N/A 0.8542 409.9 N/A N/A N/A 4.745 N/A 4.8699 10.628 N/A N/A 0.967 141.1 9.7675 7.5119 N/A N/A 18.1605 1.4529 5.0663 1.3026 6.9044 7.8368 14871.09 3.3146 79.8295 1347.47 19.9876 4.4837 1.6305 56.187 1.395 36.399 16.8891
91 2022-08-26 1.0007 137.02 1.9558 N/A 24.635 7.4379 N/A 0.8459 410.48 N/A N/A N/A 4.7485 N/A 4.8729 10.5703 N/A N/A 0.9642 140.3 9.667 7.5135 N/A N/A 18.1923 1.4333 5.1069 1.2944 6.8671 7.8521 14825.57 3.2537 79.9025 1333.46 19.924 4.4706 1.6112 56.109 1.3906 36.035 16.7995
92 2022-08-25 0.997 136.07 1.9558 N/A 24.648 7.4374 N/A 0.84293 408.93 N/A N/A N/A 4.7578 N/A 4.8758 10.5525 N/A N/A 0.9616 140.3 9.64 7.514 N/A N/A 18.112 1.4306 5.0879 1.2881 6.8317 7.8234 14753.15 3.2791 79.6555 1331.98 19.8132 4.4586 1.6006 55.842 1.3857 35.732 16.7903
93 2022-08-24 0.9934 135.74 1.9558 N/A 24.629 7.4381 N/A 0.84283 410.93 N/A N/A N/A 4.7668 N/A 4.88 10.586 N/A N/A 0.9576 139.5 9.636 7.5125 N/A N/A 18.0362 1.4389 5.0606 1.2908 6.822 7.795 14757.6 3.2599 79.3006 1332.84 19.7781 4.4559 1.6065 55.7 1.3857 35.906 16.8976
94 2022-08-23 0.9927 136.34 1.9558 N/A 24.658 7.4374 N/A 0.84343 410.55 N/A N/A N/A 4.7788 N/A 4.8839 10.6063 N/A N/A 0.9602 140.1 9.7438 7.5128 N/A N/A 17.983 1.4437 5.0984 1.2928 6.7952 7.79 14743.28 3.2598 79.2805 1332.1 19.9152 4.4557 1.6071 55.661 1.386 35.856 16.9568
95 2022-08-22 1.0001 137.08 1.9558 N/A 24.651 7.437 N/A 0.84658 408 N/A N/A N/A 4.764 N/A 4.8853 10.65 N/A N/A 0.958 140.9 9.7719 7.5113 N/A N/A 18.1268 1.4478 5.1752 1.2989 6.8457 7.8468 14895.47 3.2778 79.8615 1344.21 20.1583 4.4854 1.6125 56.218 1.3958 36.099 17.0766
96 2022-08-19 1.0054 137.67 1.9558 N/A 24.625 7.4373 N/A 0.84938 407.35 N/A N/A N/A 4.751 N/A 4.8811 10.6095 N/A N/A 0.9616 140.5 9.8418 7.5155 N/A N/A 18.2028 1.4584 5.2334 1.3062 6.8531 7.8877 14951.91 3.2879 80.2988 1343.39 20.3273 4.5007 1.6203 56.325 1.3979 35.988 17.1007
97 2022-08-18 1.0178 137.17 1.9558 N/A 24.611 7.4389 N/A 0.84391 405.13 N/A N/A N/A 4.724 N/A 4.8808 10.5903 N/A N/A 0.9683 140.5 9.8283 7.5215 N/A N/A 18.4095 1.4617 5.2326 1.3118 6.906 7.9844 15092.62 3.2993 81.042 1344.81 20.313 4.5536 1.6145 56.776 1.4053 36.254 17.0004
98 2022-08-17 1.0164 137.36 1.9558 N/A 24.566 7.4377 N/A 0.84208 404.28 N/A N/A N/A 4.7078 N/A 4.8825 10.5617 N/A N/A 0.9686 140.3 9.8428 7.5071 N/A N/A 18.2568 1.4655 5.2838 1.3117 6.8917 7.9705 15015.81 3.311 80.7555 1337.02 20.3825 4.5413 1.6165 56.772 1.4051 36.052 16.9125
99 2022-08-16 1.0131 136.11 1.9558 N/A 24.54 7.4368 N/A 0.84218 406.2 N/A N/A N/A 4.7043 N/A 4.882 10.5365 N/A N/A 0.9625 140.3 9.8428 7.51 N/A N/A 18.1994 1.4463 5.1835 1.3076 6.8767 7.9449 14968.68 3.3087 80.3745 1329.66 20.1595 4.5245 1.6012 56.602 1.398 35.93 16.6556
100 2022-08-15 1.0195 135.61 1.9558 N/A 24.46 7.4373 N/A 0.84375 398.6 N/A N/A N/A 4.6858 N/A 4.8849 10.498 N/A N/A 0.9631 140.3 9.871 7.5028 N/A N/A 18.3143 1.4508 5.2268 1.3167 6.905 7.9899 15042.36 3.3294 81.061 1336.35 20.3914 4.5465 1.6002 57.122 1.4036 36.218 16.7375
101 2022-08-12 1.0285 137.47 1.9558 N/A 24.38 7.4395 N/A 0.84715 392.3 N/A N/A N/A 4.6773 N/A 4.8915 10.4515 N/A N/A 0.9689 140.3 9.813 7.5138 N/A N/A 18.4733 1.4496 5.3007 1.3148 6.9352 8.06 15104.2 3.345 81.9935 1342.59 20.4925 4.5709 1.5985 57.246 1.4106 36.393 16.7318
102 2022-08-11 1.0338 136.57 1.9558 N/A 24.346 7.4395 N/A 0.84575 394.18 N/A N/A N/A 4.6828 N/A 4.9055 10.36 N/A N/A 0.9712 139.7 9.804 7.515 N/A N/A 18.5674 1.4532 5.2447 1.3202 6.9668 8.1118 15215.93 3.3505 82.2845 1344.62 20.6398 4.5952 1.6045 57.225 1.4151 36.343 16.7083
103 2022-08-10 1.0252 138.16 1.9558 N/A 24.397 7.4397 N/A 0.84608 397.65 N/A N/A N/A 4.7063 N/A 4.9138 10.3773 N/A N/A 0.9713 139.7 9.9118 7.5158 N/A N/A 18.4099 1.4682 5.251 1.3207 6.9222 8.046 15218.87 3.3773 81.468 1344.16 20.713 4.5693 1.6211 57.061 1.4107 36.42 16.8788
104 2022-08-09 1.0234 138.26 1.9558 N/A 24.532 7.4407 N/A 0.8452 397.35 N/A N/A N/A 4.7085 N/A 4.9038 10.3875 N/A N/A 0.9763 140.1 9.9365 7.514 N/A N/A 18.3342 1.4687 5.2478 1.3163 6.9106 8.0334 15197.09 3.3865 81.406 1336.74 20.7145 4.5592 1.6304 56.939 1.411 36.264 17.05
105 2022-08-08 1.0199 137.62 1.9558 N/A 24.515 7.4405 N/A 0.84165 394.27 N/A N/A N/A 4.7043 N/A 4.9163 10.365 N/A N/A 0.9763 140.1 9.9405 7.5123 N/A N/A 18.3175 1.4607 5.238 1.3134 6.8931 8.0061 15147.65 3.3895 81.166 1329.93 20.681 4.5477 1.6202 56.554 1.4058 36.38 16.9694
106 2022-08-05 1.0233 136.22 1.9558 N/A 24.581 7.4415 N/A 0.84268 393.78 N/A N/A N/A 4.7085 N/A 4.9251 10.3573 N/A N/A 0.9776 138.9 9.982 7.5148 N/A N/A 18.3853 1.4713 5.3348 1.3185 6.9068 8.0328 15236.2 3.4033 81.0469 1324.53 20.8367 4.5598 1.6248 56.524 1.4077 36.373 17.0342
107 2022-08-04 1.0181 135.81 1.9558 N/A 24.659 7.4425 N/A 0.84231 395.98 N/A N/A N/A 4.7233 N/A 4.9261 10.374 N/A N/A 0.9765 138.7 9.9065 7.515 N/A N/A 18.2922 1.4607 5.3614 1.307 6.8769 7.9919 15200.94 3.4101 80.7715 1333.7 20.756 4.5387 1.6172 56.633 1.4037 36.606 17.0352
108 2022-08-03 1.0194 136.18 1.9558 N/A 24.65 7.4427 N/A 0.83629 395.03 N/A N/A N/A 4.691 N/A 4.9245 10.3913 N/A N/A 0.9773 139.3 9.8743 7.5178 N/A N/A 18.3112 1.4681 5.3547 1.3085 6.883 8.0022 15184.35 3.4362 80.6895 1336.03 21.0788 4.5435 1.6266 56.855 1.4069 36.963 17.1283
109 2022-08-02 1.0224 133.9 1.9558 N/A 24.644 7.4432 N/A 0.83665 396.82 N/A N/A N/A 4.7063 N/A 4.9298 10.3995 N/A N/A 0.9744 139.3 9.9305 7.5195 N/A N/A 18.3564 1.4745 5.3175 1.315 6.9117 8.0257 15204.85 3.4486 80.3243 1339.16 20.952 4.5531 1.6254 56.834 1.4103 36.914 16.982
110 2022-08-01 1.0233 135.38 1.9558 N/A 24.628 7.4457 N/A 0.837 401.35 N/A N/A N/A 4.734 N/A 4.9283 10.3668 N/A N/A 0.9717 138.7 9.8638 7.521 N/A N/A 18.3475 1.4535 5.2723 1.3076 6.9105 8.0329 15203.21 3.4546 80.9335 1333.3 20.7635 4.5568 1.616 56.734 1.4087 36.977 16.8613
111 2022-07-29 1.0198 136.42 1.9558 N/A 24.61 7.4438 N/A 0.8399 404.8 N/A N/A N/A 4.7375 N/A 4.9343 10.3875 N/A N/A 0.9744 138.3 9.8773 7.518 N/A N/A 18.2472 1.4646 5.2739 1.31 6.8705 8.0054 15155.56 3.4714 80.882 1329.4 20.6745 4.5386 1.6283 56.375 1.4088 36.978 16.8627
112 2022-07-28 1.0122 137.26 1.9558 N/A 24.609 7.4442 N/A 0.83586 407.3 N/A N/A N/A 4.7908 N/A 4.9342 10.449 N/A N/A 0.9745 138.7 9.8983 7.52 N/A N/A 18.1417 1.4535 5.33 1.2986 6.8325 7.9456 15107.59 3.4701 80.6535 1320.45 20.676 4.5071 1.6172 56.592 1.4009 37.097 17.0011
113 2022-07-27 1.0152 138.89 1.9558 N/A 24.575 7.4446 N/A 0.84138 404.67 N/A N/A N/A 4.7978 N/A 4.9334 10.4545 N/A N/A 0.9768 139.1 9.9558 7.514 N/A N/A 18.1859 1.462 5.4039 1.3049 6.8534 7.9692 15213.07 3.4855 81.135 1333.99 20.753 4.5263 1.6306 56.455 1.4088 37.4 17.1347
114 2022-07-26 1.0124 138.35 1.9558 N/A 24.607 7.4449 N/A 0.84558 400.99 N/A N/A N/A 4.742 N/A 4.9324 10.4445 N/A N/A 0.9765 139.1 10.0105 7.5145 N/A N/A 18.0705 1.4605 5.4437 1.3035 6.8451 7.9466 15185.27 3.4891 80.805 1326.65 20.7845 4.5113 1.6235 56.16 1.4066 37.18 17.087
115 2022-07-25 1.0236 139.84 1.9558 N/A 24.535 7.4449 N/A 0.84813 396.5 N/A N/A N/A 4.708 N/A 4.9339 10.3973 N/A N/A 0.9869 139.5 10.0704 7.5195 N/A N/A 18.2653 1.4707 5.5976 1.3168 6.9094 8.0345 15303.87 3.5201 81.6675 1341.25 20.9376 4.5586 1.6325 57.209 1.4176 37.525 17.1502
116 2022-07-22 1.019 139.51 1.9558 N/A 24.514 7.4443 N/A 0.85141 398.3 N/A N/A N/A 4.7508 N/A 4.9321 10.4328 N/A N/A 0.9832 139.5 10.1498 7.5234 N/A N/A 18.094 1.4677 5.5821 1.3105 6.8852 7.9985 15275.69 3.5083 81.384 1335.66 20.9595 4.5366 1.6265 57.24 1.4151 37.392 17.2009
117 2022-07-21 1.0199 141.46 1.9558 N/A 24.496 7.4446 N/A 0.85545 400.13 N/A N/A N/A 4.761 N/A 4.9391 10.426 N/A N/A 0.9924 139.7 10.175 7.52 N/A N/A 18.0327 1.4848 5.5777 1.3178 6.904 8.0056 15342.25 3.5203 81.451 1337.47 20.941 4.5457 1.6479 57.512 1.4218 37.66 17.5195
118 2022-07-20 1.0199 140.92 1.9558 N/A 24.493 7.4452 N/A 0.85178 399.5 N/A N/A N/A 4.782 N/A 4.9396 10.4606 N/A N/A 0.9896 139.5 10.1323 7.5143 N/A N/A 17.9444 1.4767 5.5427 1.3132 6.8892 8.0062 15275.82 3.5147 81.599 1337.61 20.8967 4.5406 1.6308 57.398 1.4204 37.405 17.3924
119 2022-07-19 1.0245 141.01 1.9558 N/A 24.555 7.4449 N/A 0.85303 397.45 N/A N/A N/A 4.7598 N/A 4.9395 10.4964 N/A N/A 0.9918 138.9 10.176 7.5093 N/A N/A 18.018 1.4869 5.5454 1.3264 6.9064 8.0423 15344.49 3.5295 81.898 1340.33 20.8552 4.559 1.6456 57.583 1.4269 37.492 17.457
120 2022-07-18 1.0131 140.16 1.9558 N/A 24.508 7.4435 N/A 0.84708 402.05 N/A N/A N/A 4.776 N/A 4.9389 10.5265 N/A N/A 0.9911 138.9 10.2553 7.513 N/A N/A 17.7225 1.4839 5.4505 1.3151 6.8266 7.9528 15157.63 3.5004 81.034 1333.33 20.7095 4.5113 1.6432 57.056 1.4153 37.13 17.383
121 2022-07-15 1.0059 139.49 1.9558 N/A 24.561 7.443 N/A 0.84988 403.73 N/A N/A N/A 4.7953 N/A 4.9407 10.5943 N/A N/A 0.9849 138.9 10.2763 7.516 N/A N/A 17.5451 1.4886 5.4434 1.3147 6.7943 7.8963 15081.58 3.5044 80.316 1333.79 20.9209 4.4752 1.6377 56.678 1.4113 36.866 17.2875
122 2022-07-14 1.0005 139.04 1.9558 N/A 24.417 7.4425 N/A 0.8456 408.78 N/A N/A N/A 4.8146 N/A 4.942 10.6019 N/A N/A 0.9841 138.89 10.2536 7.5122 N/A N/A 17.494 1.4893 5.4586 1.3162 6.7618 7.8539 15119.56 3.4915 80.0752 1322.29 20.9585 4.4462 1.6437 56.565 1.4065 36.632 17.202
123 2022-07-13 1.0067 138.02 1.9558 N/A 24.397 7.4416 N/A 0.84371 409.35 N/A N/A N/A 4.824 N/A 4.9414 10.602 N/A N/A 0.9829 138.3 10.2428 7.5155 N/A N/A 17.5629 1.4802 5.4533 1.3073 6.7722 7.9025 15117.08 3.4864 80.1285 1311.4 20.9029 4.4667 1.635 56.669 1.4134 36.377 17.0527
124 2022-07-12 1.0042 137.31 1.9558 N/A 24.582 7.4408 N/A 0.84823 409.98 N/A N/A N/A 4.819 N/A 4.9413 10.629 N/A N/A 0.9883 139.1 10.2754 7.517 N/A N/A 17.4392 1.49 5.4009 1.3094 6.7518 7.8828 15054.05 3.4987 79.8965 1315.1 20.8883 4.4556 1.6395 56.648 1.4127 36.392 17.1509
125 2022-07-11 1.0098 138.77 1.9558 N/A 24.592 7.4414 N/A 0.8454 408.22 N/A N/A N/A 4.7968 N/A 4.943 10.6943 N/A N/A 0.9908 139.3 10.299 7.518 N/A N/A 17.5447 1.491 5.3673 1.314 6.7793 7.9265 15131.92 3.5108 80.2435 1320.36 20.7845 4.4704 1.6466 56.574 1.4178 36.585 17.1634
126 2022-07-08 1.0163 138.05 1.9558 N/A 24.614 7.4424 N/A 0.84585 402.45 N/A N/A N/A 4.763 N/A 4.9431 10.6665 N/A N/A 0.9913 139.5 10.263 7.519 N/A N/A 17.6026 1.4871 5.4345 1.3201 6.8095 7.9769 15210.73 3.5325 80.528 1321.61 20.8477 4.4992 1.6464 56.882 1.4228 36.602 17.1922
127 2022-07-07 1.018 138.11 1.9558 N/A 24.779 7.4405 N/A 0.85105 410.04 N/A N/A N/A 4.7721 N/A 4.9448 10.723 N/A N/A 0.9906 139.3 10.291 7.5193 N/A N/A 17.5551 1.4883 5.4983 1.3227 6.823 7.9893 15265.27 3.5548 80.6 1324.66 20.9675 4.5077 1.6461 56.939 1.4255 36.74 17.0372
128 2022-07-06 1.0177 137.71 1.9558 N/A 24.778 7.4403 N/A 0.85676 411.8 N/A N/A N/A 4.771 N/A 4.944 10.745 N/A N/A 0.9896 138.5 10.2803 7.5198 N/A N/A 17.5505 1.4961 5.5116 1.3274 6.8289 7.9864 15287.49 3.5884 80.5321 1331.69 21.0194 4.5028 1.6505 56.779 1.4305 36.78 17.0246
129 2022-07-05 1.029 139.77 1.9558 N/A 24.751 7.4396 N/A 0.85845 407.38 N/A N/A N/A 4.7448 N/A 4.9438 10.8031 N/A N/A 0.9932 139.1 10.285 7.5246 N/A N/A 17.5049 1.518 5.5141 1.3364 6.9029 8.0748 15487.93 3.6343 81.673 1348.97 21.0171 4.5477 1.6772 57.009 1.4455 36.879 16.9143
130 2022-07-04 1.0455 141.51 1.9558 N/A 24.745 7.4391 N/A 0.8596 401.52 N/A N/A N/A 4.71 N/A 4.944 10.7658 N/A N/A 1.0037 139.3 10.2958 7.5301 N/A N/A 17.5994 1.5205 5.5663 1.3435 6.9977 8.2033 15684.13 3.6655 82.5067 1353.4 21.1972 4.6138 1.6748 57.487 1.4587 37.298 17.0275
131 2022-07-01 1.0425 141.05 1.9558 N/A 24.753 7.4391 N/A 0.86648 401.11 N/A N/A N/A 4.7168 N/A 4.9457 10.7783 N/A N/A 1.0027 138.7 10.3651 7.531 N/A N/A 17.4608 1.5382 5.5117 1.3492 6.987 8.1801 15621.64 3.6717 82.3747 1352.58 21.115 4.5943 1.6929 57.452 1.4565 37.186 17.1323
132 2022-06-30 1.0387 141.54 1.9558 N/A 24.739 7.4392 N/A 0.8582 397.04 N/A N/A N/A 4.6904 N/A 4.9464 10.73 N/A N/A 0.996 138.9 10.3485 7.5307 N/A N/A 17.322 1.5099 5.4229 1.3425 6.9624 8.1493 15552 3.6392 82.113 1351.6 20.9641 4.5781 1.6705 57.15 1.4483 36.754 17.0143
133 2022-06-29 1.0517 143.53 1.9558 N/A 24.739 7.4392 N/A 0.86461 394.28 N/A N/A N/A 4.6869 N/A 4.9419 10.6848 N/A N/A 1.0005 139.9 10.3065 7.5285 N/A N/A 17.4998 1.5256 5.5163 1.3513 7.0382 8.2532 15612.61 3.6344 83.037 1364.02 21.1375 4.6272 1.6871 57.773 1.4607 36.925 16.9295
134 2022-06-28 1.0561 143.67 1.9558 N/A 24.726 7.4394 N/A 0.8635 398.55 N/A N/A N/A 4.6905 N/A 4.9443 10.6543 N/A N/A 1.0101 139.5 10.337 7.532 N/A N/A 17.5891 1.521 5.5308 1.3565 7.0775 8.288 15669.91 3.6267 83.408 1361.75 21.088 4.6432 1.6822 57.85 1.4645 37.154 16.9072
135 2022-06-27 1.0572 143.25 1.9558 N/A 24.724 7.4408 N/A 0.862 402.62 N/A N/A N/A 4.699 N/A 4.944 10.6713 N/A N/A 1.0143 139.7 10.408 7.5333 N/A N/A 17.4794 1.5278 5.5446 1.3639 7.0737 8.2946 15635.36 3.6009 82.9325 1357.68 21.041 4.6559 1.6801 57.9 1.4641 37.361 16.7967
136 2022-06-24 1.0524 142.19 1.9558 N/A 24.731 7.4398 N/A 0.85773 401.34 N/A N/A N/A 4.7023 N/A 4.9463 10.694 N/A N/A 1.0072 139.7 10.4345 7.5295 N/A N/A 18.2856 1.5248 5.4851 1.3657 7.0478 8.2609 15633.96 3.621 82.3985 1364.09 20.9901 4.6327 1.6731 57.83 1.462 37.36 16.7137
137 2022-06-23 1.0493 142.11 1.9558 N/A 24.75 7.4388 N/A 0.85818 399.6 N/A N/A N/A 4.7085 N/A 4.9468 10.705 N/A N/A 1.013 139.9 10.475 7.5286 N/A N/A 18.2199 1.5212 5.4515 1.36 7.0367 8.236 15594.75 3.6192 82.1489 1367.21 21.0924 4.623 1.6713 57.44 1.4589 37.261 16.817
138 2022-06-22 1.0521 143.11 1.9558 N/A 24.712 7.4387 N/A 0.85885 396 N/A N/A N/A 4.6905 N/A 4.9467 10.6688 N/A N/A 1.0153 138.7 10.5045 7.5228 N/A N/A 18.255 1.5254 5.4349 1.366 7.0604 8.2589 15618.98 3.6432 82.4075 1369.29 21.1491 4.6345 1.6835 57.174 1.4615 37.281 16.7985
139 2022-06-21 1.055 143.75 1.9558 N/A 24.69 7.4393 N/A 0.8601 396.48 N/A N/A N/A 4.6435 N/A 4.9462 10.646 N/A N/A 1.0214 138.7 10.3283 7.5205 N/A N/A 18.3049 1.5177 5.442 1.366 7.068 8.2817 15639.62 3.6505 82.423 1365.09 21.2485 4.6399 1.6675 57.304 1.4612 37.294 16.7881
140 2022-06-20 1.0517 141.94 1.9558 N/A 24.728 7.4387 N/A 0.85748 397.85 N/A N/A N/A 4.652 N/A 4.9453 10.6375 N/A N/A 1.0162 137.3 10.4085 7.5175 N/A N/A 18.2239 1.5061 5.4117 1.3662 7.0346 8.2558 15589.89 3.639 81.994 1357.54 21.3016 4.6291 1.6549 56.872 1.4589 37.157 16.8603
141 2022-06-17 1.0486 141.21 1.9558 N/A 24.742 7.4384 N/A 0.855 400.53 N/A N/A N/A 4.7003 N/A 4.9469 10.6748 N/A N/A 1.0105 137.7 10.4525 7.5155 N/A N/A 18.1495 1.5039 5.3824 1.3631 7.0308 8.2314 15537.05 3.6112 81.871 1356.27 21.4474 4.6159 1.6601 56.371 1.4547 36.974 16.7133
142 2022-06-16 1.04 138.24 1.9558 N/A 24.742 7.4386 N/A 0.8555 398.1 N/A N/A N/A 4.7138 N/A 4.9443 10.6942 N/A N/A 1.0142 137.5 10.4588 7.5245 N/A N/A 18.0126 1.4939 5.2559 1.3446 6.9844 8.1638 15427.31 3.5934 81.1945 1346.88 21.4115 4.5786 1.6608 55.7 1.4451 36.566 16.6052
143 2022-06-15 1.0431 140.49 1.9558 N/A 24.703 7.4392 N/A 0.86328 397.96 N/A N/A N/A 4.669 N/A 4.9427 10.6278 N/A N/A 1.0435 137.5 10.3868 7.5245 N/A N/A 18.0465 1.5051 5.3164 1.3498 7.0013 8.1883 15361.97 3.6007 81.5142 1346.86 21.4763 4.6037 1.6706 55.627 1.4519 36.529 16.7111
144 2022-06-14 1.0452 140.62 1.9558 N/A 24.749 7.4403 N/A 0.86578 398.68 N/A N/A N/A 4.6563 N/A 4.9443 10.622 N/A N/A 1.0394 138.3 10.3945 7.5238 N/A N/A 18.06 1.5174 5.3329 1.3522 7.0417 8.2048 15400.02 3.6208 81.559 1346.72 21.4832 4.6224 1.6755 55.669 1.4541 36.566 16.7959
145 2022-06-13 1.0455 140.51 1.9558 N/A 24.724 7.4397 N/A 0.8585 399.3 N/A N/A N/A 4.6373 N/A 4.9459 10.616 N/A N/A 1.0375 138.7 10.3222 7.5215 N/A N/A 18.0495 1.4998 5.2785 1.3435 7.0434 8.2071 15376.17 3.5994 81.606 1349.93 21.2102 4.6195 1.6635 55.72 1.4538 36.425 16.807
146 2022-06-10 1.0578 141.69 1.9558 N/A 24.705 7.4389 N/A 0.85048 398.48 N/A N/A N/A 4.6053 N/A 4.9442 10.5255 N/A N/A 1.0404 137.7 10.1495 7.5225 N/A N/A 18.0116 1.4845 5.1718 1.3484 7.0868 8.3031 15393.27 3.5626 82.3355 1344.25 20.8285 4.6564 1.6482 56.101 1.462 36.774 16.5209
147 2022-06-09 1.0743 143.93 1.9558 N/A 24.689 7.4391 N/A 0.85653 396.45 N/A N/A N/A 4.5925 N/A 4.9453 10.5045 N/A N/A 1.0495 138.7 10.1818 7.5223 N/A N/A 18.5104 1.4985 5.2506 1.3506 7.1722 8.4317 15646.25 3.5859 83.526 1348.99 21.0248 4.7199 1.6673 56.872 1.4779 37.079 16.4132
148 2022-06-08 1.0739 143.92 1.9558 N/A 24.622 7.4386 N/A 0.85575 391.25 N/A N/A N/A 4.5698 N/A 4.945 10.4938 N/A N/A 1.0486 138.9 10.1395 7.5215 N/A N/A 18.453 1.4917 5.2447 1.3467 7.1785 8.4275 15577.86 3.5848 83.414 1349.34 21.0458 4.7187 1.6644 56.799 1.4769 37.076 16.4626
149 2022-06-07 1.0662 141.66 1.9558 N/A 24.739 7.4395 N/A 0.85365 389.33 N/A N/A N/A 4.5813 N/A 4.9426 10.5039 N/A N/A 1.0423 138.9 10.1843 7.5244 N/A N/A 17.8702 1.4884 5.1256 1.3437 7.1146 8.3656 15412.37 3.5661 82.873 1340.75 20.8435 4.6865 1.6582 56.421 1.4685 36.768 16.4059
150 2022-06-06 1.0726 140.16 1.9558 N/A 24.715 7.439 N/A 0.85415 388.05 N/A N/A N/A 4.5808 N/A 4.9424 10.452 N/A N/A 1.032 138.3 10.0853 7.5222 N/A N/A 17.796 1.4842 5.0986 1.3463 7.1223 8.4154 15464.73 3.5697 83.245 1341.13 20.9078 4.7076 1.6428 56.67 1.4732 36.774 16.4142
151 2022-06-03 1.073 139.59 1.9558 N/A 24.708 7.4388 N/A 0.8542 394.78 N/A N/A N/A 4.5955 N/A 4.9428 10.4589 N/A N/A 1.0296 137.9 10.103 7.522 N/A N/A 17.738 1.4805 5.1643 1.3484 7.1465 8.4167 15498.1 3.5751 83.273 1337.4 20.985 4.7094 1.6409 56.738 1.4741 36.777 16.6153
152 2022-06-02 1.0692 138.72 1.9558 N/A 24.702 7.4391 N/A 0.85195 394.9 N/A N/A N/A 4.5787 N/A 4.9398 10.4705 N/A N/A 1.0264 136.9 10.0845 7.5325 N/A N/A 17.6175 1.4829 5.1335 1.352 7.135 8.3896 15481.86 3.5705 82.922 1334.06 20.9831 4.6949 1.6413 56.467 1.4701 36.754 16.6143
153 2022-06-01 1.0712 138.68 1.9558 N/A 24.748 7.4393 N/A 0.85158 395.03 N/A N/A N/A 4.5913 N/A 4.9428 10.4758 N/A N/A 1.0305 137.1 10.0438 7.5345 N/A N/A 17.6223 1.4861 5.0646 1.3536 7.1586 8.4057 15574.33 3.5682 83.051 1331.44 21.0678 4.6951 1.6442 56.182 1.47 36.801 16.609
154 2022-05-31 1.0713 137.36 1.9558 N/A 24.714 7.4394 N/A 0.85138 396.2 N/A N/A N/A 4.5805 N/A 4.9408 10.5053 N/A N/A 1.0281 136.3 10.0983 7.541 N/A N/A 17.5817 1.4933 5.0965 1.3573 7.1402 8.4063 15580.15 3.5746 83.231 1329.32 20.987 4.6907 1.6459 56.323 1.4687 36.751 16.745
155 2022-05-30 1.0764 137.25 1.9558 N/A 24.712 7.4391 N/A 0.8515 392.18 N/A N/A N/A 4.5855 N/A 4.9441 10.518 N/A N/A 1.0327 136.9 10.1256 7.5305 N/A N/A 17.6416 1.4982 5.0629 1.3647 7.1735 8.449 15682.41 3.5722 83.475 1331.66 20.8994 4.6998 1.6439 56.322 1.4719 36.7 16.648
156 2022-05-27 1.0722 136.05 1.9558 N/A 24.7 7.4392 N/A 0.84875 392.83 N/A N/A N/A 4.5858 N/A 4.9427 10.5293 N/A N/A 1.0258 137.9 10.179 7.5379 N/A N/A 17.582 1.4995 5.0959 1.3661 7.1831 8.4165 15583.97 3.597 83.1915 1343.63 21.136 4.6952 1.6426 56.02 1.4679 36.589 16.746
157 2022-05-26 1.0697 135.95 1.9558 N/A 24.676 7.4409 N/A 0.85073 391.72 N/A N/A N/A 4.6083 N/A 4.9423 10.5983 N/A N/A 1.0283 138.1 10.2715 7.5355 N/A N/A 17.5588 1.511 5.1741 1.3715 7.2024 8.397 15628.91 3.5935 83.0065 1352.69 21.1935 4.7045 1.6541 55.975 1.4709 36.589 16.9312
158 2022-05-25 1.0656 135.34 1.9558 N/A 24.648 7.4405 N/A 0.85295 388.25 N/A N/A N/A 4.621 N/A 4.9416 10.5419 N/A N/A 1.0269 138.3 10.2704 7.5355 N/A N/A 17.3954 1.5126 5.1736 1.372 7.1334 8.3647 15587.59 3.585 82.6666 1354.61 21.2213 4.6833 1.6539 55.787 1.4676 36.55 16.7628
159 2022-05-24 1.072 136.49 1.9558 N/A 24.663 7.4411 N/A 0.8575 383.33 N/A N/A N/A 4.6015 N/A 4.9446 10.5013 N/A N/A 1.0334 139.3 10.289 7.5285 N/A N/A 17.2572 1.5152 5.1793 1.3714 7.1449 8.4143 15711.88 3.5848 83.185 1353.65 21.2456 4.7076 1.6656 56.152 1.4722 36.609 16.7814
160 2022-05-23 1.0659 136.05 1.9558 N/A 24.594 7.4413 N/A 0.84783 381.65 N/A N/A N/A 4.621 N/A 4.947 10.4918 N/A N/A 1.031 139.1 10.252 7.5275 N/A N/A 16.8672 1.4982 5.1623 1.3626 7.085 8.3664 15609 3.5745 82.6795 1344.19 21.1273 4.6782 1.6463 55.686 1.4639 36.41 16.7437
161 2022-05-20 1.0577 135.34 1.9558 N/A 24.67 7.4424 N/A 0.8482 382.93 N/A N/A N/A 4.6365 N/A 4.9477 10.4915 N/A N/A 1.028 138.5 10.262 7.5335 N/A N/A 16.8201 1.498 5.1989 1.3526 7.0638 8.2999 15501.99 3.533 82.1617 1340.58 21.0314 4.6422 1.6518 55.181 1.4588 36.284 16.7131
162 2022-05-19 1.0525 134.46 1.9558 N/A 24.7 7.4423 N/A 0.84728 385.83 N/A N/A N/A 4.6423 N/A 4.9474 10.5098 N/A N/A 1.0265 139.5 10.3102 7.5395 N/A N/A 16.8037 1.5036 5.2094 1.349 7.1028 8.2594 15416.76 3.5623 81.7115 1343.21 21.0043 4.6363 1.6551 55.14 1.4576 36.343 16.8315
163 2022-05-18 1.0523 135.76 1.9558 N/A 24.647 7.4419 N/A 0.8467 382.88 N/A N/A N/A 4.6443 N/A 4.9473 10.4675 N/A N/A 1.0486 138.9 10.2125 7.535 N/A N/A 16.7811 1.498 5.1974 1.3488 7.0972 8.2591 15446 3.526 81.6455 1332.76 20.9204 4.6254 1.6548 55.077 1.4598 36.399 16.7313
164 2022-05-17 1.0541 136.32 1.9558 N/A 24.712 7.4414 N/A 0.844 386.3 N/A N/A N/A 4.6488 N/A 4.9478 10.4393 N/A N/A 1.0457 138.7 10.178 7.5245 N/A N/A 16.6027 1.4993 5.2621 1.3517 7.0899 8.2744 15433.23 3.5387 81.6515 1333.66 21.0273 4.6211 1.6561 55.137 1.4589 36.361 16.844
165 2022-05-16 1.0422 135.01 1.9558 N/A 24.71 7.4418 N/A 0.85045 385.85 N/A N/A N/A 4.6675 N/A 4.9469 10.4978 N/A N/A 1.0479 138.3 10.2188 7.5225 N/A N/A 16.3121 1.5057 5.2819 1.3473 7.0786 8.1812 15294.29 3.5474 81.081 1337.9 20.9324 4.5836 1.6601 54.705 1.4531 36.274 16.9195
166 2022-05-13 1.0385 133.91 1.9558 N/A 24.74 7.4412 N/A 0.85115 385 N/A N/A N/A 4.6883 N/A 4.9455 10.4905 N/A N/A 1.0385 140.1 10.2043 7.52 N/A N/A 16.0687 1.5067 5.3204 1.3505 7.0513 8.1522 15193.55 3.5586 80.4315 1330.83 20.988 4.5673 1.6633 54.449 1.45 36.109 16.7789
167 2022-05-12 1.0408 133.85 1.9558 N/A 24.925 7.4413 N/A 0.85293 382.2 N/A N/A N/A 4.668 N/A 4.947 10.5648 N/A N/A 1.0377 139.7 10.2898 7.5235 N/A N/A 16.0132 1.5163 5.4161 1.3569 7.0691 8.1702 15255.73 3.5981 80.667 1341.98 21.2531 4.5725 1.6692 54.589 1.4529 36.15 16.8806
168 2022-05-11 1.0553 137.07 1.9558 N/A 25.365 7.4393 N/A 0.85393 379.13 N/A N/A N/A 4.6575 N/A 4.947 10.526 N/A N/A 1.0446 139.3 10.1793 7.5365 N/A N/A 16.1851 1.5055 5.3859 1.3685 7.0893 8.2839 15308.87 3.6148 81.4935 1343.99 21.387 4.6185 1.6645 54.992 1.4622 36.492 16.9275
169 2022-05-10 1.0554 137.38 1.9558 N/A 25.014 7.4386 N/A 0.85595 380.15 N/A N/A N/A 4.6763 N/A 4.9458 10.6075 N/A N/A 1.0479 139.5 10.2315 7.5385 N/A N/A 16.0883 1.5162 5.4232 1.3707 7.0967 8.2847 15349.06 3.6587 81.5425 1346.56 21.4716 4.6248 1.6707 55.289 1.4667 36.448 17.005
170 2022-05-09 1.0559 138.1 1.9558 N/A 25.055 7.4385 N/A 0.85235 383.23 N/A N/A N/A 4.6985 N/A 4.9467 10.5818 N/A N/A 1.0462 139.5 10.0583 7.5335 N/A N/A 15.8941 1.5048 5.4321 1.3656 7.0886 8.2887 15367.67 3.6239 81.7415 1345.48 21.4341 4.6285 1.6584 55.67 1.4676 36.497 17.1332
171 2022-05-06 1.057 137.9 1.9558 N/A 24.665 7.44 N/A 0.85625 381.47 N/A N/A N/A 4.7028 N/A 4.949 10.4686 N/A N/A 1.0419 138.3 9.9808 7.5336 N/A N/A 15.8078 1.4888 5.3183 1.356 7.0506 8.2969 15312.44 3.5965 81.298 1343.9 21.3555 4.6191 1.644 55.467 1.4642 36.303 16.9614
172 2022-05-05 1.0568 137.18 1.9558 N/A 24.606 7.4405 N/A 0.8519 378.65 N/A N/A N/A 4.6673 N/A 4.9485 10.3748 N/A N/A 1.0355 138 9.8463 7.5398 N/A N/A 15.7051 1.4669 5.2192 1.3483 6.9944 8.2948 15250.92 3.5916 80.6185 1330.89 21.2069 4.5955 1.6273 55.364 1.4561 36.026 16.5862
173 2022-05-04 1.0531 136.84 1.9558 N/A 24.644 7.4409 N/A 0.84194 377.55 N/A N/A N/A 4.6875 N/A 4.947 10.3968 N/A N/A 1.0324 137.2 9.9042 7.5499 N/A N/A 15.5769 1.478 5.24 1.3498 6.9594 8.2655 15201.44 3.5487 80.4035 1331.45 21.2947 4.5847 1.6333 55.26 1.4559 36.137 16.6489
174 2022-05-03 1.0556 137.06 1.9558 N/A 24.662 7.4403 N/A 0.8413 382.15 N/A N/A N/A 4.6925 N/A 4.9475 10.3978 N/A N/A 1.0272 137.6 9.909 7.5555 N/A N/A 15.6941 1.4825 5.3143 1.357 6.9759 8.2838 15288.47 3.5597 80.842 1335.64 21.5025 4.5956 1.6366 55.455 1.4605 36.387 16.8303
175 2022-05-02 1.0524 136.63 1.9558 N/A 24.671 7.4391 N/A 0.8381 378.51 N/A N/A N/A 4.685 N/A 4.9478 10.4035 N/A N/A 1.0253 137.2 9.9248 7.561 N/A N/A 15.6697 1.4913 5.248 1.356 6.9548 8.2581 15293.41 3.5277 80.497 1333.71 21.4758 4.5816 1.6362 55.229 1.4585 36.208 16.7383
176 2022-04-29 1.054 137.01 1.9558 N/A 24.605 7.4415 N/A 0.83908 378.71 N/A N/A N/A 4.678 N/A 4.9479 10.2958 N/A N/A 1.0229 137.8 9.7525 7.5667 N/A N/A 15.6385 1.4699 5.1608 1.3426 6.9441 8.2703 15301.52 3.4993 80.638 1326.71 21.4181 4.5886 1.6119 55.2 1.4545 36.026 16.6473
177 2022-04-28 1.0485 137.13 1.9558 N/A 24.526 7.4421 N/A 0.8435 377.06 N/A N/A N/A 4.6891 N/A 4.9479 10.3594 N/A N/A 1.0216 137.8 9.899 7.5703 N/A N/A 15.5362 1.4814 5.2465 1.3498 6.9381 8.2267 15222.05 3.5096 80.367 1337.82 21.4531 4.5741 1.6221 54.845 1.4556 36.152 16.7472
178 2022-04-27 1.0583 135.57 1.9558 N/A 24.55 7.441 N/A 0.84215 379.74 N/A N/A N/A 4.7043 N/A 4.948 10.4035 N/A N/A 1.0229 138.2 9.7838 7.565 N/A N/A 15.6857 1.4828 5.3045 1.3572 6.9377 8.3045 15259.86 3.5178 81.0705 1341.98 21.6259 4.6142 1.6118 55.195 1.4602 36.331 16.8406
179 2022-04-26 1.0674 136.15 1.9558 N/A 24.423 7.4393 N/A 0.84135 374.46 N/A N/A N/A 4.6466 N/A 4.9458 10.3935 N/A N/A 1.0229 138.4 9.7943 7.5625 N/A N/A 15.7944 1.4828 5.249 1.3613 6.9837 8.3735 15365.76 3.5147 81.7265 1340.02 21.6538 4.6485 1.6102 55.681 1.4666 36.596 16.7787
180 2022-04-25 1.0746 137.73 1.9558 N/A 24.418 7.4391 N/A 0.8433 374.08 N/A N/A N/A 4.6398 N/A 4.9455 10.3476 N/A N/A 1.0267 139.2 9.7018 7.562 N/A N/A 15.864 1.4972 5.1953 1.3709 7.0398 8.4325 15533.84 3.5306 82.321 1344.49 21.8989 4.6815 1.624 56.259 1.4757 36.542 16.8549
181 2022-04-22 1.0817 138.83 1.9558 N/A 24.32 7.4402 N/A 0.83925 370.35 N/A N/A N/A 4.6336 N/A 4.9455 10.278 N/A N/A 1.0336 139.8 9.6255 7.5625 N/A N/A 15.9446 1.4816 5.0926 1.3714 7.0332 8.4859 15603.47 3.5288 82.6943 1344.04 22.0034 4.6784 1.6193 56.721 1.4784 36.724 16.8652
182 2022-04-21 1.0887 139.61 1.9558 N/A 24.38 7.4403 N/A 0.83523 370.6 N/A N/A N/A 4.63 N/A 4.945 10.2553 N/A N/A 1.0335 139 9.5788 7.5635 N/A N/A 15.9983 1.4653 5.0324 1.36 7.0228 8.5406 15624.02 3.5153 82.965 1348.33 21.8836 4.6716 1.6053 57.081 1.482 36.891 16.5996
183 2022-04-20 1.083 138.53 1.9558 N/A 24.409 7.4405 N/A 0.82965 371.36 N/A N/A N/A 4.6338 N/A 4.9436 10.23 N/A N/A 1.0254 139.2 9.5443 7.561 N/A N/A 15.8892 1.4581 5.0481 1.3579 6.9448 8.494 15537.05 3.4908 82.6348 1337.89 21.6392 4.6415 1.595 56.747 1.4779 36.567 16.3019
184 2022-04-19 1.0803 138.4 1.9558 N/A 24.424 7.4391 N/A 0.82955 374.12 N/A N/A N/A 4.6553 N/A 4.9411 10.3408 N/A N/A 1.0208 139.8 9.5228 7.562 N/A N/A 15.8416 1.4663 5.0261 1.3631 6.9008 8.4698 15498.35 3.5038 82.6038 1339.46 21.4725 4.5961 1.6016 56.683 1.4763 36.466 16.0401
185 2022-04-14 1.0878 136.32 1.9558 N/A 24.42 7.4389 N/A 0.82908 376.57 N/A N/A N/A 4.6478 N/A 4.9459 10.3008 N/A N/A 1.0189 140.4 9.5313 7.5587 N/A N/A 15.9046 1.4612 5.1226 1.3663 6.932 8.5298 15621.3 3.4896 82.814 1334.71 21.5941 4.603 1.5957 56.759 1.4732 36.615 15.9331
186 2022-04-13 1.0826 136.26 1.9558 N/A 24.45 7.4377 N/A 0.8328 378.45 N/A N/A N/A 4.6453 N/A 4.9415 10.3323 N/A N/A 1.0116 140.2 9.5693 7.5538 N/A N/A 15.7992 1.4603 5.0449 1.37 6.8939 8.4867 15549.1 3.4782 82.478 1328.47 21.417 4.5799 1.5991 56.446 1.4769 36.305 15.682
187 2022-04-12 1.0861 136.29 1.9558 N/A 24.45 7.4379 N/A 0.83455 377.78 N/A N/A N/A 4.6552 N/A 4.9417 10.332 N/A N/A 1.0131 139.6 9.5395 7.5513 N/A N/A 15.9548 1.4599 5.0944 1.3724 6.9199 8.5112 15609.66 3.4972 82.7285 1335.49 21.5616 4.5972 1.5874 56.574 1.4803 36.531 15.849
188 2022-04-11 1.09 137.01 1.9558 N/A 24.429 7.4375 N/A 0.83693 378.27 N/A N/A N/A 4.6456 N/A 4.9397 10.3128 N/A N/A 1.018 140 9.5478 7.5519 N/A N/A 16.0485 1.4654 5.155 1.3738 6.9405 8.544 15658.28 3.501 82.7085 1345.23 21.8653 4.6112 1.5938 56.753 1.4874 36.613 15.9127
189 2022-04-08 1.0861 134.87 1.9558 N/A 24.479 7.4372 N/A 0.83355 375.66 N/A N/A N/A 4.6437 N/A 4.9425 10.2768 N/A N/A 1.0155 139.6 9.508 7.549 N/A N/A 16.0237 1.4552 5.1583 1.3675 6.9115 8.5134 15601.96 3.501 82.389 1333.12 21.8729 4.585 1.5849 55.99 1.4801 36.488 15.9968
190 2022-04-07 1.0916 135.32 1.9558 N/A 24.512 7.4378 N/A 0.8345 379.26 N/A N/A N/A 4.637 N/A 4.9419 10.313 N/A N/A 1.0185 141 9.5595 7.5562 N/A N/A 16.0929 1.4578 5.146 1.3704 6.9448 8.5554 15692.35 3.5259 82.951 1330.92 21.9806 4.6046 1.5816 56.114 1.4848 36.541 16.052
191 2022-04-06 1.0923 135.3 1.9558 N/A 24.441 7.4378 N/A 0.83473 377.77 N/A N/A N/A 4.6328 N/A 4.9433 10.2855 N/A N/A 1.0187 141.4 9.5523 7.547 N/A N/A 16.0998 1.4431 5.0996 1.3647 6.9498 8.5617 15683.36 3.5199 82.8343 1330.44 21.8759 4.604 1.5718 56.167 1.4844 36.701 15.9934
192 2022-04-05 1.0969 134.76 1.9558 N/A 24.338 7.4378 N/A 0.8349 370.93 N/A N/A N/A 4.6265 N/A 4.9438 10.2593 N/A N/A 1.0141 141.6 9.5398 7.5399 N/A N/A 16.15 1.4374 5.0384 1.3647 6.9783 8.5917 15732.77 3.5152 82.635 1330.81 21.7474 4.6185 1.5657 56.194 1.4867 36.697 15.9529
193 2022-04-04 1.1005 135.08 1.9558 N/A 24.32 7.4385 N/A 0.8389 369.15 N/A N/A N/A 4.6375 N/A 4.9432 10.3849 N/A N/A 1.0203 141.8 9.5489 7.5455 N/A N/A 16.183 1.4651 5.1162 1.3749 7.0026 8.6226 15783.89 3.5312 83.118 1338.41 21.82 4.643 1.586 56.521 1.4938 36.894 16.0957
194 2022-04-01 1.1052 135.35 1.9558 N/A 24.376 7.4388 N/A 0.84145 368.12 N/A N/A N/A 4.6401 N/A 4.9452 10.332 N/A N/A 1.0217 142 9.6628 7.5675 N/A N/A 16.2411 1.4696 5.2188 1.3805 7.0311 8.6596 15887.5 3.5315 83.9847 1345.61 21.9087 4.6534 1.5911 57.084 1.4985 36.941 16.1685
195 2022-03-31 1.1101 135.17 1.9558 N/A 24.375 7.4379 N/A 0.84595 369.77 N/A N/A N/A 4.6531 N/A 4.9463 10.337 N/A N/A 1.0267 142 9.711 7.574 N/A N/A 16.2823 1.4829 5.3009 1.3896 7.0403 8.6918 15947 3.5243 84.134 1347.37 22.0903 4.6677 1.6014 57.514 1.5028 36.911 16.1727
196 2022-03-30 1.1126 135.47 1.9558 N/A 24.45 7.4391 N/A 0.84563 368.13 N/A N/A N/A 4.6679 N/A 4.9477 10.3498 N/A N/A 1.0309 142.2 9.6398 7.572 N/A N/A 16.3296 1.4809 5.2808 1.3891 7.0666 8.7081 15957.24 3.5399 84.38 1346.97 22.1557 4.6779 1.5947 57.906 1.5064 37.144 16.1288
197 2022-03-29 1.1085 136.66 1.9558 N/A 24.464 7.4388 N/A 0.8444 369.8 N/A N/A N/A 4.6594 N/A 4.9478 10.329 N/A N/A 1.0362 142.2 9.5995 7.5815 N/A N/A 16.3275 1.4795 5.2434 1.387 7.055 8.6767 15896.31 3.5505 83.9685 1345.62 22.1561 4.6707 1.6054 57.602 1.5051 37.29 16.1804
198 2022-03-28 1.0966 135.93 1.9558 N/A 24.65 7.4393 N/A 0.83643 374.13 N/A N/A N/A 4.718 N/A 4.9483 10.4225 N/A N/A 1.0257 142.8 9.5123 7.5735 N/A N/A 16.275 1.459 5.2133 1.3702 6.9862 8.5861 15737.77 3.5313 83.4825 1342.49 21.9841 4.6238 1.5838 57.08 1.4921 37.027 15.9925
199 2022-03-25 1.1002 134.07 1.9558 N/A 24.645 7.4404 N/A 0.8338 373.81 N/A N/A N/A 4.7307 N/A 4.9487 10.3505 N/A N/A 1.0207 142.2 9.5205 7.5754 N/A N/A 16.3304 1.4624 5.2634 1.3781 7.0007 8.6117 15777.69 3.5351 83.8235 1343.32 21.9908 4.6324 1.5787 57.322 1.4919 36.906 16.0386
200 2022-03-24 1.0978 133.71 1.9558 N/A 24.72 7.4397 N/A 0.83288 374.44 N/A N/A N/A 4.7421 N/A 4.9489 10.3555 N/A N/A 1.0225 141.2 9.4923 7.5745 N/A N/A 16.2917 1.4668 5.3057 1.3806 6.9933 8.5897 15778.31 3.5461 83.879 1342.53 22.177 4.6396 1.5812 57.426 1.4912 36.837 16.1478
201 2022-03-23 1.0985 132.65 1.9558 N/A 24.605 7.4381 N/A 0.8328 372.25 N/A N/A N/A 4.7052 N/A 4.9463 10.4005 N/A N/A 1.0269 141.4 9.6425 7.571 N/A N/A 16.3108 1.4728 5.3903 1.384 7.0003 8.5948 15792.11 3.5407 83.9675 1337.76 22.1978 4.6401 1.5822 57.565 1.4919 36.965 16.2501
202 2022-03-22 1.1024 132.96 1.9558 N/A 24.679 7.4402 N/A 0.83228 371.23 N/A N/A N/A 4.6851 N/A 4.9463 10.3822 N/A N/A 1.0275 142.7 9.6233 7.575 N/A N/A 16.3432 1.4802 5.4105 1.3867 7.0137 8.6285 15808.01 3.5521 83.9145 1343.81 22.3667 4.6483 1.586 57.749 1.4957 36.881 16.343
203 2022-03-21 1.1038 131.57 1.9558 N/A 24.683 7.4411 N/A 0.83775 374.48 N/A N/A N/A 4.696 N/A 4.947 10.4088 N/A N/A 1.0278 142.7 9.6575 7.5733 N/A N/A 16.3773 1.4897 5.502 1.3898 7.0152 8.6387 15826.61 3.5637 84.1835 1342.62 22.48 4.6415 1.5997 57.817 1.496 37.038 16.4543
204 2022-03-18 1.1008 131.4 1.9558 N/A 24.837 7.4423 N/A 0.83925 375.33 N/A N/A N/A 4.7135 N/A 4.9483 10.4303 N/A N/A 1.0314 142.9 9.694 7.5685 N/A N/A 16.3054 1.4945 5.5784 1.3911 7.0031 8.6101 15782.11 3.5761 83.7825 1337.31 22.5905 4.6157 1.6026 57.622 1.4952 36.745 16.5347
205 2022-03-17 1.1051 131.27 1.9558 N/A 24.777 7.4439 N/A 0.84315 372.05 N/A N/A N/A 4.6889 N/A 4.9465 10.4503 N/A N/A 1.0385 142.1 9.78 7.573 N/A N/A 16.3123 1.5055 5.6339 1.3998 7.0176 8.6391 15835.97 3.5777 83.8435 1340.02 22.788 4.6364 1.613 57.69 1.498 36.767 16.5286
206 2022-03-16 1.0994 130.05 1.9558 N/A 24.687 7.4412 N/A 0.83988 371.18 N/A N/A N/A 4.6765 N/A 4.9473 10.4205 N/A N/A 1.0336 143.5 9.7988 7.5725 N/A N/A 16.1783 1.5165 5.6523 1.3967 6.9817 8.5996 15690.36 3.5872 83.7805 1353.77 22.854 4.6147 1.6168 57.433 1.4966 36.681 16.5574
207 2022-03-15 1.0991 129.67 1.9558 N/A 24.867 7.441 N/A 0.84053 371.41 N/A N/A N/A 4.7355 N/A 4.9482 10.526 N/A N/A 1.0322 144.9 9.849 7.575 N/A N/A 16.0968 1.5234 5.6385 1.4099 7.0117 8.6026 15710.44 3.6088 83.9555 1366.05 22.9352 4.6239 1.6216 57.536 1.4993 36.842 16.6249
208 2022-03-14 1.096 129.3 1.9558 N/A 24.89 7.4405 N/A 0.83915 373.88 N/A N/A N/A 4.7218 N/A 4.949 10.5368 N/A N/A 1.0249 145.1 9.8588 7.5745 N/A N/A 16.2 1.5137 5.5286 1.3978 6.9738 8.5815 15678.53 3.586 83.931 1357.77 22.8311 4.6087 1.613 57.398 1.4947 36.59 16.5029
209 2022-03-11 1.099 128.46 1.9558 N/A 25.213 7.4402 N/A 0.8397 380.92 N/A N/A N/A 4.782 N/A 4.949 10.646 N/A N/A 1.023 144.9 9.8033 7.5713 N/A N/A 16.2554 1.5017 5.5077 1.4024 6.9633 8.6007 15696.64 3.5683 83.9875 1354.04 22.9524 4.6098 1.6053 57.461 1.4949 36.542 16.4896
210 2022-03-10 1.1084 128.54 1.9558 N/A 25.316 7.4401 N/A 0.84175 381.63 N/A N/A N/A 4.8239 N/A 4.9491 10.7073 N/A N/A 1.027 145.5 9.919 7.5665 N/A N/A 16.574 1.5109 5.5958 1.4189 7.0063 8.6688 15824.95 3.6219 84.607 1360.48 23.3153 4.6414 1.6185 57.825 1.5058 36.71 16.7264
211 2022-03-09 1.0993 127.31 1.9558 N/A 25.364 7.444 N/A 0.8357 379.66 N/A N/A N/A 4.8196 N/A 4.9485 10.734 N/A N/A 1.0198 145.3 9.798 7.5625 N/A N/A 16.1323 1.4991 5.5201 1.4108 6.9454 8.5974 15710.06 3.5978 84.2025 1357.08 23.2145 4.6028 1.6055 57.259 1.4966 36.326 16.656
212 2022-03-08 1.0892 126.03 1.9558 N/A 25.642 7.4441 N/A 0.83185 388.28 N/A N/A N/A 4.9103 N/A 4.9494 10.8803 N/A N/A 1.0111 145.9 9.7925 7.5715 N/A N/A 15.8183 1.4971 5.5346 1.3978 6.8805 8.5183 15639.76 3.6022 83.924 1344.71 23.2866 4.5556 1.5958 56.9 1.4856 36.156 16.7051
213 2022-03-07 1.0895 125.55 1.9558 N/A 25.584 7.4406 N/A 0.82625 393.25 N/A N/A N/A 4.9525 N/A 4.9494 10.8573 N/A N/A 1.0069 145.8 9.8325 7.56 N/A N/A 15.6577 1.4751 5.5065 1.3864 6.8846 8.5154 15685.76 3.5653 83.8125 1338.45 23.0249 4.5426 1.5861 56.832 1.4831 35.866 16.6951
214 2022-03-04 1.0929 126.17 1.9558 N/A 25.737 7.4394 N/A 0.82388 386.54 N/A N/A N/A 4.853 N/A 4.9495 10.7935 N/A N/A 1.0056 144.2 9.8358 7.5584 N/A N/A 15.5681 1.4872 5.5313 1.3937 6.9065 8.5411 15725.3 3.5603 83.4354 1332.23 22.7543 4.5661 1.6005 56.814 1.4872 35.776 16.8044
215 2022-03-03 1.1076 128.18 1.9558 N/A 25.634 7.4399 N/A 0.82773 378.64 N/A N/A N/A 4.7691 N/A 4.9496 10.7688 N/A N/A 1.0192 143.4 9.8418 7.57 N/A N/A 15.6897 1.5139 5.6041 1.3992 6.9996 8.6547 15934.42 3.5872 84.174 1334.2 22.8945 4.637 1.6329 57.293 1.5042 36.063 16.8798
216 2022-03-02 1.1106 128.08 1.9558 N/A 25.866 7.4387 N/A 0.83316 382.31 N/A N/A N/A 4.8021 N/A 4.9493 10.788 N/A N/A 1.0216 143 9.8826 7.574 N/A N/A 15.628 1.5272 5.7313 1.4088 7.0153 8.6785 15980.03 3.5954 84.1765 1338.99 22.999 4.6595 1.6404 57.206 1.5059 36.339 17.1904
217 2022-03-01 1.1162 128.15 1.9558 N/A 25.465 7.4377 N/A 0.8329 379.6 N/A N/A N/A 4.7947 N/A 4.949 10.6893 N/A N/A 1.0247 142 9.8598 7.567 117.201 N/A 15.5509 1.5365 5.7598 1.4158 7.0462 8.7234 16033.36 3.6152 84.5015 1342.6 22.8558 4.6802 1.6484 57.295 1.515 36.505 17.2145
218 2022-02-28 1.1199 129.31 1.9558 N/A 24.997 7.4404 N/A 0.8355 369.72 N/A N/A N/A 4.6835 N/A 4.9484 10.6055 N/A N/A 1.0336 141.8 9.9465 7.5655 115.4842 N/A 15.4532 1.5508 5.7828 1.4264 7.067 8.7514 16100.72 3.63 84.554 1347.62 22.9011 4.7019 1.6628 57.432 1.5201 36.593 17.2863
219 2022-02-25 1.1216 129.64 1.9558 N/A 24.66 7.4418 N/A 0.8374 365.28 N/A N/A N/A 4.6369 N/A 4.9479 10.5848 N/A N/A 1.0398 140.8 9.9756 7.5535 92.5673 N/A 15.4799 1.5541 5.738 1.4325 7.0828 8.7578 16088.71 3.6389 84.347 1346.44 22.9145 4.7107 1.6651 57.549 1.5176 36.441 17.0315
220 2022-02-24 1.1163 128.28 1.9558 N/A 25.09 7.4405 N/A 0.83463 368.63 N/A N/A N/A 4.6554 N/A 4.9501 10.7338 N/A N/A 1.032 142 10.0878 7.552 95.7175 N/A 16.0525 1.5593 5.6874 1.4316 7.0601 8.7178 16074 3.6618 84.296 1347.7 22.9355 4.6896 1.6692 57.45 1.5125 36.514 17.1634
221 2022-02-23 1.1344 130.58 1.9558 N/A 24.473 7.4388 N/A 0.83463 357.25 N/A N/A N/A 4.5481 N/A 4.9468 10.5658 N/A N/A 1.0431 141.2 10.0335 7.5362 90.8791 N/A 15.6871 1.5592 5.6808 1.4394 7.1669 8.8529 16270.12 3.6515 84.6135 1350.23 22.9079 4.748 1.6679 57.98 1.5253 36.601 17.0508
222 2022-02-22 1.1342 130.54 1.9558 N/A 24.496 7.4392 N/A 0.83685 355.89 N/A N/A N/A 4.5447 N/A 4.9464 10.5996 N/A N/A 1.0422 141.2 10.1018 7.537 89.8055 N/A 15.6959 1.5739 5.7677 1.4441 7.1771 8.8495 16293.92 3.6584 84.758 1353.34 23.033 4.7472 1.6848 58.208 1.5268 36.748 17.1768
223 2022-02-21 1.1338 130.2 1.9558 N/A 24.345 7.4397 N/A 0.83298 357.54 N/A N/A N/A 4.5351 N/A 4.9448 10.6535 N/A N/A 1.0387 141.4 10.1738 7.536 89.0866 N/A 15.4689 1.5751 5.8045 1.4454 7.1831 8.8443 16276.34 3.6433 84.677 1353.02 22.9951 4.7387 1.687 58.3 1.5265 36.588 17.1895
224 2022-02-18 1.1354 130.59 1.9558 N/A 24.337 7.4382 N/A 0.83425 356.37 N/A N/A N/A 4.5201 N/A 4.9453 10.5796 N/A N/A 1.0452 140.8 10.1465 7.5355 86.2815 N/A 15.4678 1.5754 5.8435 1.4424 7.184 8.8566 16304.49 3.6276 84.6525 1356.45 23.027 4.7528 1.6896 58.403 1.5255 36.435 17.0858
225 2022-02-17 1.137 130.84 1.9558 N/A 24.383 7.4398 N/A 0.83493 356.08 N/A N/A N/A 4.5065 N/A 4.9432 10.593 N/A N/A 1.0466 141.6 10.1225 7.533 86.388 N/A 15.4945 1.5786 5.8495 1.4439 7.206 8.8692 16291.53 3.6231 85.2935 1360.7 23.0367 4.7612 1.695 58.314 1.5278 36.537 16.9893
226 2022-02-16 1.1372 131.56 1.9558 N/A 24.365 7.441 N/A 0.8394 355.65 N/A N/A N/A 4.4961 N/A 4.9436 10.5363 N/A N/A 1.0516 141.4 10.1095 7.5295 85.3679 N/A 15.481 1.5859 5.8765 1.4416 7.2101 8.8712 16232.55 3.6256 85.3885 1361.31 23.1718 4.7595 1.7108 58.346 1.5291 36.771 17.214
227 2022-02-15 1.1345 131.18 1.9558 N/A 24.419 7.4422 N/A 0.83765 355.33 N/A N/A N/A 4.5036 N/A 4.941 10.5739 N/A N/A 1.0483 141.2 10.0893 7.529 85.5025 N/A 15.4716 1.5888 5.8977 1.4433 7.1969 8.8527 16187.89 3.6596 85.443 1357.5 23.1113 4.7493 1.7143 58.144 1.5265 36.724 17.1767
228 2022-02-14 1.1316 130.6 1.9558 N/A 24.527 7.4411 N/A 0.8372 357.06 N/A N/A N/A 4.54 N/A 4.9457 10.6158 N/A N/A 1.0472 142.6 10.0693 7.5293 86.348 N/A 15.351 1.5902 5.8965 1.4431 7.1937 8.8283 16190.53 3.6835 85.4715 1354.5 23.1331 4.742 1.7112 58.114 1.5247 36.8 17.131
229 2022-02-11 1.1417 132.24 1.9558 N/A 24.405 7.44 N/A 0.83958 353.38 N/A N/A N/A 4.5204 N/A 4.9458 10.553 N/A N/A 1.0557 141.8 10.0732 7.5312 85.855 N/A 15.4066 1.5927 5.9263 1.4498 7.2564 8.9054 16339.46 3.6958 85.8535 1363.68 23.3183 4.7832 1.7085 58.482 1.5339 37.282 17.2736
230 2022-02-10 1.1439 132.42 1.9558 N/A 24.35 7.4404 N/A 0.84248 354.02 N/A N/A N/A 4.4921 N/A 4.9451 10.5275 N/A N/A 1.0571 141.8 10.0693 7.5275 85.0187 N/A 15.4838 1.5894 5.9668 1.4498 7.2722 8.9142 16390.21 3.6796 85.9373 1367.52 23.3584 4.7855 1.7076 58.583 1.5345 37.331 17.3078
231 2022-02-09 1.1435 132.04 1.9558 N/A 24.288 7.4437 N/A 0.84255 352.94 N/A N/A N/A 4.5135 N/A 4.9449 10.4075 N/A N/A 1.0555 142.2 10.0585 7.5285 85.5289 N/A 15.551 1.5933 6.0198 1.4514 7.2759 8.9106 16390.99 3.6817 85.5765 1365.72 23.4719 4.7853 1.7107 58.603 1.5349 37.404 17.5281
232 2022-02-08 1.1408 131.68 1.9558 N/A 24.259 7.4437 N/A 0.84363 353.09 N/A N/A N/A 4.5312 N/A 4.945 10.4433 N/A N/A 1.0545 142.4 10.0758 7.5215 85.7797 N/A 15.5558 1.6025 6.0209 1.4505 7.2636 8.8923 16418.4 3.6753 85.2545 1367.88 23.5601 4.774 1.7196 58.715 1.5349 37.606 17.638
233 2022-02-07 1.1447 131.59 1.9558 N/A 24.222 7.4443 N/A 0.84685 353.48 N/A N/A N/A 4.5432 N/A 4.9461 10.4483 N/A N/A 1.0571 143.4 10.0658 7.52 86.5824 N/A 15.5235 1.6097 6.0541 1.4546 7.2807 8.9202 16478.97 3.6547 85.5345 1371.76 23.575 4.7909 1.7278 58.978 1.5389 37.735 17.7
234 2022-02-04 1.1464 131.72 1.9558 N/A 24.36 7.4432 N/A 0.84593 352.92 N/A N/A N/A 4.5474 N/A 4.9466 10.4465 N/A N/A 1.0567 142.8 10.0483 7.5275 87.3095 N/A 15.5072 1.6165 6.083 1.4583 7.2923 8.9286 16493.16 3.6741 85.6445 1374.04 23.5856 4.7914 1.7287 58.754 1.5419 37.797 17.5875
235 2022-02-03 1.1286 129.63 1.9558 N/A 24.135 7.4388 N/A 0.83208 353.94 N/A N/A N/A 4.5315 N/A 4.9461 10.387 N/A N/A 1.0407 142.4 9.9545 7.5295 86.1788 N/A 15.3047 1.5849 5.9843 1.4334 7.1795 8.7966 16243.28 3.5949 84.518 1358.42 23.2359 4.7215 1.7001 57.608 1.5212 37.424 17.2864
236 2022-02-02 1.1323 129.37 1.9558 N/A 24.298 7.4383 N/A 0.83395 354.45 N/A N/A N/A 4.5449 N/A 4.9463 10.385 N/A N/A 1.0399 143.2 9.9228 7.526 85.815 N/A 15.3011 1.5828 5.9677 1.433 7.2026 8.8245 16243.98 3.5777 84.613 1359.23 23.2134 4.7392 1.701 57.785 1.5254 37.575 17.3459
237 2022-02-01 1.126 129.12 1.9558 N/A 24.335 7.4407 N/A 0.83498 356.38 N/A N/A N/A 4.5804 N/A 4.9465 10.4438 N/A N/A 1.0374 143.8 9.9638 7.5275 86.3238 N/A 15.0644 1.5868 5.9572 1.4299 7.1625 8.7779 16126.29 3.566 84.197 1353.61 23.1296 4.7129 1.7032 57.516 1.5199 37.378 17.1633
238 2022-01-31 1.1156 128.79 1.9558 N/A 24.372 7.4419 N/A 0.83153 357.19 N/A N/A N/A 4.5892 N/A 4.9475 10.489 N/A N/A 1.0404 143.2 10.0085 7.5293 86.7251 N/A 14.931 1.582 6.003 1.4233 7.0963 8.6994 16036.76 3.564 83.3655 1349.08 23.1856 4.6693 1.6983 56.985 1.511 37.144 17.3734
239 2022-01-28 1.1138 128.68 1.9558 N/A 24.443 7.4432 N/A 0.83178 358.42 N/A N/A N/A 4.5755 N/A 4.9463 10.552 N/A N/A 1.0378 144 10.026 7.529 86.6113 N/A 15.1424 1.5971 6.0147 1.4239 7.0857 8.681 16047.76 3.5697 83.6015 1349.47 23.1854 4.6668 1.7031 57.028 1.5109 37.229 17.3844
240 2022-01-27 1.116 128.74 1.9558 N/A 24.427 7.4428 N/A 0.83368 358.09 N/A N/A N/A 4.5592 N/A 4.9466 10.445 N/A N/A 1.0391 145.2 9.9903 7.5328 87.139 N/A 15.1946 1.5771 6.0159 1.4161 7.1061 8.6951 16052.42 3.5695 83.7893 1344.5 23.143 4.6844 1.6872 57.295 1.5089 37.124 17.1112
241 2022-01-26 1.1277 128.86 1.9558 N/A 24.531 7.442 N/A 0.83458 359.67 N/A N/A N/A 4.5864 N/A 4.9451 10.4493 N/A N/A 1.0386 145.6 10.0115 7.529 89.265 N/A 15.2877 1.5727 6.1084 1.4173 7.1293 8.7791 16185.31 3.5834 84.4288 1350.03 23.1845 4.7268 1.6865 57.728 1.5162 37.169 17.0858
242 2022-01-25 1.1268 128.49 1.9558 N/A 24.5 7.4437 N/A 0.83713 359.44 N/A N/A N/A 4.5751 N/A 4.9448 10.502 N/A N/A 1.0364 146 10.1385 7.5295 88.7384 N/A 15.2723 1.5814 6.2049 1.4247 7.1325 8.7725 16169.54 3.5898 84.277 1350.71 23.2909 4.7213 1.6911 57.753 1.5157 37.28 17.2669
243 2022-01-24 1.1304 128.62 1.9558 N/A 24.528 7.4431 N/A 0.83803 359.84 N/A N/A N/A 4.5572 N/A 4.9453 10.5038 N/A N/A 1.0308 145.6 10.1638 7.529 88.649 N/A 15.1621 1.5866 6.1901 1.4269 7.1533 8.8003 16213.69 3.5846 84.3495 1352.41 23.2566 4.7352 1.6901 58.045 1.5216 37.382 17.2509
244 2022-01-21 1.1348 129.14 1.9558 N/A 24.347 7.4431 N/A 0.83633 358.19 N/A N/A N/A 4.5318 N/A 4.9453 10.414 N/A N/A 1.0353 145.6 10.0523 7.528 86.838 N/A 15.223 1.5774 6.2063 1.4211 7.1946 8.837 16244.2 3.5668 84.419 1351.89 23.2229 4.7508 1.6884 58.171 1.526 37.358 17.1546
245 2022-01-20 1.1338 129.53 1.9558 N/A 24.263 7.4424 N/A 0.83265 355.81 N/A N/A N/A 4.5228 N/A 4.9453 10.3708 N/A N/A 1.0382 145.4 9.9578 7.525 86.8952 N/A 15.2094 1.5662 6.1621 1.4158 7.1936 8.8274 16267.5 3.5564 84.362 1349.16 23.1684 4.7489 1.6731 58.285 1.5261 37.319 17.2531
246 2022-01-19 1.1345 129.86 1.9558 N/A 24.313 7.4419 N/A 0.83168 355.88 N/A N/A N/A 4.5229 N/A 4.9449 10.3428 N/A N/A 1.0383 145.2 9.9368 7.5238 86.48 N/A 15.4207 1.5709 6.2657 1.4144 7.2003 8.8392 16283.78 3.5529 84.4135 1347.1 23.0922 4.757 1.6684 58.429 1.5293 37.467 17.3889
247 2022-01-18 1.1367 130.39 1.9558 N/A 24.426 7.4425 N/A 0.83673 357 N/A N/A N/A 4.526 N/A 4.9449 10.3185 N/A N/A 1.0414 146 9.9638 7.5225 86.7325 N/A 15.4447 1.5833 6.2797 1.4228 7.2212 8.8576 16318.64 3.5557 84.813 1355.33 23.1443 4.7554 1.6798 58.553 1.5349 37.635 17.5398
248 2022-01-17 1.1403 130.64 1.9558 N/A 24.467 7.4417 N/A 0.83573 356.09 N/A N/A N/A 4.5256 N/A 4.9443 10.305 N/A N/A 1.0429 146.8 9.9623 7.5275 87.3907 N/A 15.2757 1.5811 6.2808 1.4287 7.2402 8.8844 16337.73 3.5479 84.7295 1359.89 23.1901 4.7704 1.6765 58.496 1.5374 37.761 17.601
249 2022-01-14 1.1447 130.17 1.9558 N/A 24.493 7.4414 N/A 0.83508 356.1 N/A N/A N/A 4.5414 N/A 4.9429 10.2684 N/A N/A 1.0429 147 9.9863 7.5205 88.0011 N/A 15.5256 1.5803 6.3361 1.433 7.2728 8.9119 16388.85 3.5565 84.9445 1361.27 23.2684 4.7831 1.6745 58.727 1.5418 38.033 17.6043
250 2022-01-13 1.1463 130.98 1.9558 N/A 24.458 7.4409 N/A 0.83545 355.24 N/A N/A N/A 4.5361 N/A 4.944 10.238 N/A N/A 1.0453 147 9.9333 7.5202 86.603 N/A 15.5744 1.5709 6.3518 1.4304 7.2913 8.9289 16379.02 3.5638 84.717 1359.24 23.3894 4.7875 1.6676 58.572 1.5427 38.08 17.6381
251 2022-01-12 1.137 131.19 1.9558 N/A 24.423 7.4414 N/A 0.83338 355.98 N/A N/A N/A 4.5359 N/A 4.9453 10.264 N/A N/A 1.0486 147 9.927 7.524 84.7559 N/A 15.5922 1.5762 6.3458 1.4261 7.2379 8.863 16295.93 3.5406 84.0285 1353.27 23.1852 4.7595 1.6775 58.08 1.5358 37.936 17.5645
252 2022-01-11 1.1336 130.95 1.9558 N/A 24.412 7.4404 N/A 0.83475 357.45 N/A N/A N/A 4.5438 N/A 4.945 10.3075 N/A N/A 1.0502 147 10.0165 7.5236 84.8663 N/A 15.696 1.5804 6.389 1.4329 7.2255 8.8384 16221.39 3.549 83.7481 1352.85 23.0888 4.7515 1.6772 57.979 1.5342 37.862 17.7094
253 2022-01-10 1.1318 130.45 1.9558 N/A 24.357 7.4381 N/A 0.83398 358.4 N/A N/A N/A 4.5334 N/A 4.9449 10.3038 N/A N/A 1.0446 146.2 10.0253 7.5278 84.9825 N/A 15.7183 1.5774 6.3969 1.4327 7.2128 8.8233 16181.9 3.5303 83.8 1355.68 23.0597 4.7536 1.6753 58.141 1.5344 38.074 17.6999
254 2022-01-07 1.1298 130.9 1.9558 N/A 24.439 7.438 N/A 0.8343 358.68 N/A N/A N/A 4.5496 N/A 4.9451 10.2839 N/A N/A 1.0422 146 10.0288 7.5214 85.298 N/A 15.7206 1.5804 6.4343 1.4374 7.206 8.8133 16188.43 3.5135 83.978 1359.96 23.1109 4.7553 1.6748 58.046 1.5356 38.074 17.6701
255 2022-01-06 1.1315 131.05 1.9558 N/A 24.528 7.4393 N/A 0.83593 359.84 N/A N/A N/A 4.5614 N/A 4.9435 10.3265 N/A N/A 1.0395 146.8 10.035 7.5197 86.5088 N/A 15.5504 1.5778 6.442 1.4451 7.2187 8.8272 16291.88 3.5247 84.2475 1362.06 23.2549 4.767 1.6752 57.943 1.5388 37.962 17.7932
256 2022-01-05 1.1319 131.03 1.9558 N/A 24.581 7.4384 N/A 0.83546 362.15 N/A N/A N/A 4.5666 N/A 4.946 10.2545 N/A N/A 1.0364 146.8 9.9672 7.519 85.7275 N/A 15.2446 1.56 6.4146 1.4399 7.2087 8.8227 16263.02 3.4989 84.161 1354.61 23.1422 4.7466 1.6597 57.713 1.534 37.607 17.9369
257 2022-01-04 1.1279 131.17 1.9558 N/A 24.745 7.4378 N/A 0.83618 365.12 N/A N/A N/A 4.5667 N/A 4.9481 10.2808 N/A N/A 1.0355 147.8 10.0138 7.5185 84.9202 N/A 15.1384 1.5682 6.4174 1.4382 7.1924 8.7919 16199.73 3.4909 84.2055 1352.91 23.1808 4.7214 1.6668 57.988 1.531 37.582 18.108
258 2022-01-03 1.1355 130.56 1.9558 N/A 24.818 7.4382 N/A 0.84135 367.71 N/A N/A N/A 4.5895 N/A 4.9483 10.2958 N/A N/A 1.0372 147.6 10.0013 7.519 84.5313 N/A 15.0777 1.5691 6.3539 1.442 7.2174 8.8541 16202.02 3.5139 84.3949 1354.4 23.2259 4.7379 1.6651 58.051 1.5333 37.665 17.9661

128
ext/lines/lines.go Normal file
View File

@@ -0,0 +1,128 @@
// Package lines provides a virtual table to read large files line-by-line.
package lines
import (
"bufio"
"bytes"
"fmt"
"io"
"math"
"os"
"github.com/ncruces/go-sqlite3"
)
// Register registers the lines and lines_read virtual tables.
// The lines virtual table reads from a database blob or text.
// The lines_read virtual table reads from a file or an [io.ReaderAt].
func Register(db *sqlite3.Conn) {
sqlite3.CreateModule[lines](db, "lines", nil,
func(db *sqlite3.Conn, _, _, _ string, _ ...string) (lines, error) {
err := db.DeclareVtab(`CREATE TABLE x(line TEXT, data HIDDEN)`)
db.VtabConfig(sqlite3.VTAB_INNOCUOUS)
return false, err
})
sqlite3.CreateModule[lines](db, "lines_read", nil,
func(db *sqlite3.Conn, _, _, _ string, _ ...string) (lines, error) {
err := db.DeclareVtab(`CREATE TABLE x(line TEXT, data HIDDEN)`)
db.VtabConfig(sqlite3.VTAB_DIRECTONLY)
return true, err
})
}
type lines bool
func (l lines) BestIndex(idx *sqlite3.IndexInfo) error {
for i, cst := range idx.Constraint {
if cst.Column == 1 && cst.Op == sqlite3.INDEX_CONSTRAINT_EQ && cst.Usable {
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
Omit: true,
ArgvIndex: 1,
}
idx.EstimatedCost = 1e6
idx.EstimatedRows = 100
return nil
}
}
return sqlite3.CONSTRAINT
}
func (l lines) Open() (sqlite3.VTabCursor, error) {
return &cursor{reader: bool(l)}, nil
}
type cursor struct {
scanner *bufio.Scanner
closer io.Closer
rowID int64
eof bool
reader bool
}
func (c *cursor) Close() (err error) {
if c.closer != nil {
err = c.closer.Close()
c.closer = nil
}
return err
}
func (c *cursor) EOF() bool {
return c.eof
}
func (c *cursor) Next() error {
c.rowID++
c.eof = !c.scanner.Scan()
return c.scanner.Err()
}
func (c *cursor) RowID() (int64, error) {
return c.rowID, nil
}
func (c *cursor) Column(ctx *sqlite3.Context, n int) error {
if n == 0 {
ctx.ResultRawText(c.scanner.Bytes())
}
return nil
}
func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
if err := c.Close(); err != nil {
return err
}
var r io.Reader
data := arg[0]
typ := data.Type()
if c.reader {
switch typ {
case sqlite3.NULL:
if p, ok := data.Pointer().(io.ReaderAt); ok {
r = io.NewSectionReader(p, 0, math.MaxInt64)
}
case sqlite3.TEXT:
f, err := os.Open(data.Text())
if err != nil {
return err
}
c.closer = f
r = f
}
} else {
switch typ {
case sqlite3.TEXT:
r = bytes.NewReader(data.RawText())
case sqlite3.BLOB:
r = bytes.NewReader(data.RawBlob())
}
}
if r == nil {
return fmt.Errorf("lines: unsupported argument:%.0w %v", sqlite3.MISMATCH, typ)
}
c.scanner = bufio.NewScanner(r)
c.rowID = 0
return c.Next()
}

186
ext/lines/lines_test.go Normal file
View File

@@ -0,0 +1,186 @@
package lines_test
import (
"database/sql"
"errors"
"fmt"
"log"
"os"
"strings"
"testing"
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/lines"
)
func Example() {
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
lines.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
// https://storage.googleapis.com/quickdraw_dataset/full/simplified/calendar.ndjson
f, err := os.Open("calendar.ndjson")
if err != nil {
log.Fatal(err)
}
defer f.Close()
rows, err := db.Query(`
SELECT
line ->> '$.countrycode' as countrycode,
COUNT(*)
FROM lines_read(?)
GROUP BY 1
ORDER BY 2 DESC
LIMIT 5`,
sqlite3.Pointer(f))
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var countrycode sql.RawBytes
var count int
for rows.Next() {
err := rows.Scan(&countrycode, &count)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %d\n", countrycode, count)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
// Sample output:
// US: 141001
// GB: 22560
// CA: 11759
// RU: 9250
// DE: 8748
}
func Test_lines(t *testing.T) {
t.Parallel()
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
lines.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
const data = "line 1\nline 2\nline 3"
rows, err := db.Query(`SELECT rowid, line FROM lines(?)`, data)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int64
var line string
err := rows.Scan(&id, &line)
if err != nil {
t.Fatal(err)
}
}
}
func Test_lines_error(t *testing.T) {
t.Parallel()
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
lines.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`SELECT rowid, line FROM lines(?)`, nil)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
_, err = db.Exec(`SELECT rowid, line FROM lines_read(?)`, "xpto")
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
}
func Test_lines_read(t *testing.T) {
t.Parallel()
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
lines.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
const data = "line 1\nline 2\nline 3"
rows, err := db.Query(`SELECT rowid, line FROM lines_read(?)`,
sqlite3.Pointer(strings.NewReader(data)))
if err != nil {
t.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int64
var line string
err := rows.Scan(&id, &line)
if err != nil {
t.Fatal(err)
}
}
}
func Test_lines_test(t *testing.T) {
t.Parallel()
db, err := driver.Open(":memory:", func(c *sqlite3.Conn) error {
lines.Register(c)
return nil
})
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query(`SELECT rowid, line FROM lines_read(?)`, "lines_test.go")
if errors.Is(err, os.ErrNotExist) {
t.Skip(err)
}
if err != nil {
t.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int64
var line string
err := rows.Scan(&id, &line)
if err != nil {
t.Fatal(err)
}
}
}

267
ext/pivot/pivot.go Normal file
View File

@@ -0,0 +1,267 @@
// Package pivot implements a pivot virtual table.
//
// https://github.com/jakethaw/pivot_vtab
package pivot
import (
"errors"
"fmt"
"strings"
"github.com/ncruces/go-sqlite3"
)
// Register registers the pivot virtual table.
func Register(db *sqlite3.Conn) {
sqlite3.CreateModule(db, "pivot", declare, declare)
}
type table struct {
db *sqlite3.Conn
scan string
cell string
keys []string
cols []*sqlite3.Value
}
func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (_ *table, err error) {
if len(arg) != 3 {
return nil, fmt.Errorf("pivot: wrong number of arguments")
}
table := &table{db: db}
defer func() {
if err != nil {
table.Close()
}
}()
var sep string
var create strings.Builder
create.WriteString("CREATE TABLE x(")
// Row key query.
table.scan = "SELECT * FROM\n" + arg[0]
stmt, _, err := db.Prepare(table.scan)
if err != nil {
return nil, err
}
defer stmt.Close()
table.keys = make([]string, stmt.ColumnCount())
for i := range table.keys {
name := sqlite3.QuoteIdentifier(stmt.ColumnName(i))
table.keys[i] = name
create.WriteString(sep)
create.WriteString(name)
sep = ","
}
stmt.Close()
// Column definition query.
stmt, _, err = db.Prepare("SELECT * FROM\n" + arg[1])
if err != nil {
return nil, err
}
if stmt.ColumnCount() != 2 {
return nil, fmt.Errorf("pivot: column definition query expects 2 result columns")
}
for stmt.Step() {
name := sqlite3.QuoteIdentifier(stmt.ColumnText(1))
table.cols = append(table.cols, stmt.ColumnValue(0).Dup())
create.WriteString(",")
create.WriteString(name)
}
stmt.Close()
// Pivot cell query.
table.cell = "SELECT * FROM\n" + arg[2]
stmt, _, err = db.Prepare(table.cell)
if err != nil {
return nil, err
}
if stmt.ColumnCount() != 1 {
return nil, fmt.Errorf("pivot: cell query expects 1 result columns")
}
if stmt.BindCount() != len(table.keys)+1 {
return nil, fmt.Errorf("pivot: cell query expects %d bound parameters", len(table.keys)+1)
}
create.WriteByte(')')
err = db.DeclareVtab(create.String())
if err != nil {
return nil, err
}
return table, nil
}
func (t *table) Close() error {
for i := range t.cols {
t.cols[i].Close()
}
return nil
}
func (t *table) BestIndex(idx *sqlite3.IndexInfo) error {
var idxStr strings.Builder
idxStr.WriteString(t.scan)
argvIndex := 1
sep := " WHERE "
for i, cst := range idx.Constraint {
if !cst.Usable || !(0 <= cst.Column && cst.Column < len(t.keys)) {
continue
}
var op string
switch cst.Op {
case sqlite3.INDEX_CONSTRAINT_EQ:
op = "="
case sqlite3.INDEX_CONSTRAINT_LT:
op = "<"
case sqlite3.INDEX_CONSTRAINT_GT:
op = ">"
case sqlite3.INDEX_CONSTRAINT_LE:
op = "<="
case sqlite3.INDEX_CONSTRAINT_GE:
op = ">="
case sqlite3.INDEX_CONSTRAINT_NE:
op = "<>"
case sqlite3.INDEX_CONSTRAINT_MATCH:
op = "MATCH"
case sqlite3.INDEX_CONSTRAINT_LIKE:
op = "LIKE"
case sqlite3.INDEX_CONSTRAINT_GLOB:
op = "GLOB"
case sqlite3.INDEX_CONSTRAINT_REGEXP:
op = "REGEXP"
case sqlite3.INDEX_CONSTRAINT_IS, sqlite3.INDEX_CONSTRAINT_ISNULL:
op = "IS"
case sqlite3.INDEX_CONSTRAINT_ISNOT, sqlite3.INDEX_CONSTRAINT_ISNOTNULL:
op = "IS NOT"
default:
continue
}
idxStr.WriteString(sep)
idxStr.WriteString(t.keys[cst.Column])
idxStr.WriteString(" ")
idxStr.WriteString(op)
idxStr.WriteString(" ?")
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
ArgvIndex: argvIndex,
Omit: true,
}
sep = " AND "
argvIndex++
}
sep = " ORDER BY "
idx.OrderByConsumed = true
for _, ord := range idx.OrderBy {
if !(0 <= ord.Column && ord.Column < len(t.keys)) {
idx.OrderByConsumed = false
continue
}
idxStr.WriteString(sep)
idxStr.WriteString(t.keys[ord.Column])
if ord.Desc {
idxStr.WriteString(" DESC")
}
sep = ","
}
idx.EstimatedCost = 1e9 / float64(argvIndex)
idx.IdxStr = idxStr.String()
return nil
}
func (t *table) Open() (sqlite3.VTabCursor, error) {
return &cursor{table: t}, nil
}
func (t *table) Rename(new string) error {
return nil
}
type cursor struct {
table *table
scan *sqlite3.Stmt
cell *sqlite3.Stmt
rowID int64
}
func (c *cursor) Close() error {
return errors.Join(c.scan.Close(), c.cell.Close())
}
func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
err := c.scan.Close()
if err != nil {
return err
}
c.scan, _, err = c.table.db.Prepare(idxStr)
if err != nil {
return err
}
for i, arg := range arg {
err := c.scan.BindValue(i+1, arg)
if err != nil {
return err
}
}
if c.cell == nil {
c.cell, _, err = c.table.db.Prepare(c.table.cell)
if err != nil {
return err
}
}
c.rowID = 0
return c.Next()
}
func (c *cursor) Next() error {
if c.scan.Step() {
count := c.scan.ColumnCount()
for i := 0; i < count; i++ {
err := c.cell.BindValue(i+1, c.scan.ColumnValue(i))
if err != nil {
return err
}
}
c.rowID++
}
return c.scan.Err()
}
func (c *cursor) EOF() bool {
return !c.scan.Busy()
}
func (c *cursor) RowID() (int64, error) {
return c.rowID, nil
}
func (c *cursor) Column(ctx *sqlite3.Context, col int) error {
count := c.scan.ColumnCount()
if col < count {
ctx.ResultValue(c.scan.ColumnValue(col))
return nil
}
err := c.cell.BindValue(count+1, *c.table.cols[col-count])
if err != nil {
return err
}
if c.cell.Step() {
ctx.ResultValue(c.cell.ColumnValue(0))
}
return c.cell.Reset()
}

219
ext/pivot/pivot_test.go Normal file
View File

@@ -0,0 +1,219 @@
package pivot_test
import (
"fmt"
"log"
"strings"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/pivot"
)
// https://antonz.org/sqlite-pivot-table/
func Example() {
db, err := sqlite3.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
pivot.Register(db)
err = db.Exec(`
CREATE TABLE sales(product TEXT, year INT, income DECIMAL);
INSERT INTO sales(product, year, income) VALUES
('alpha', 2020, 100),
('alpha', 2021, 120),
('alpha', 2022, 130),
('alpha', 2023, 140),
('beta', 2020, 10),
('beta', 2021, 20),
('beta', 2022, 40),
('beta', 2023, 80),
('gamma', 2020, 80),
('gamma', 2021, 75),
('gamma', 2022, 78),
('gamma', 2023, 80);
`)
if err != nil {
log.Fatal(err)
}
err = db.Exec(`
CREATE VIRTUAL TABLE v_sales USING pivot(
-- rows
(SELECT DISTINCT product FROM sales),
-- columns
(SELECT DISTINCT year, year FROM sales),
-- cells
(SELECT sum(income) FROM sales WHERE product = ? AND year = ?)
)`)
if err != nil {
log.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT * FROM v_sales`)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
cols := make([]string, stmt.ColumnCount())
for i := range cols {
cols[i] = stmt.ColumnName(i)
}
fmt.Println(pretty(cols))
for stmt.Step() {
for i := range cols {
cols[i] = stmt.ColumnText(i)
}
fmt.Println(pretty(cols))
}
if err := stmt.Reset(); err != nil {
log.Fatal(err)
}
// Output:
// product 2020 2021 2022 2023
// alpha 100 120 130 140
// beta 10 20 40 80
// gamma 80 75 78 80
}
func TestRegister(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
pivot.Register(db)
err = db.Exec(`
CREATE TABLE r AS
SELECT 1 id UNION SELECT 2 UNION SELECT 3;
CREATE TABLE c(
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO c (name) VALUES
('a'),('b'),('c'),('d');
CREATE TABLE x(
r_id INT,
c_id INT,
val TEXT
);
INSERT INTO x (r_id, c_id, val)
SELECT r.id, c.id, c.name || r.id
FROM c, r;
`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`
CREATE VIRTUAL TABLE v_x USING pivot(
-- rows
(SELECT id r_id FROM r),
-- columns
(SELECT id c_id, name FROM c),
-- cells
(SELECT val FROM x WHERE r_id = ?1 AND c_id = ?2)
)`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT * FROM v_x WHERE rowid <> 0 AND r_id <> 1 ORDER BY rowid, r_id DESC LIMIT 1`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if stmt.Step() {
if got := stmt.ColumnInt(0); got != 3 {
t.Errorf("got %d, want 3", got)
}
}
}
func TestRegister_errors(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
pivot.Register(db)
err = db.Exec(`CREATE VIRTUAL TABLE pivot USING pivot()`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot(SELECT 1, SELECT 2, SELECT 3)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot((SELECT 1), SELECT 2, SELECT 3)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot((SELECT 1), (SELECT 2), SELECT 3)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot((SELECT 1), (SELECT 1, 2), SELECT 3)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot((SELECT 1), (SELECT 1, 2), (SELECT 3, 4))`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING pivot((SELECT 1), (SELECT 1, 2), (SELECT 3))`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
}
func pretty(cols []string) string {
var buf strings.Builder
for i, s := range cols {
if i != 0 {
buf.WriteByte(' ')
}
for buf.Len()%8 != 0 {
buf.WriteByte(' ')
}
buf.WriteString(s)
}
return buf.String()
}

210
ext/statement/stmt.go Normal file
View File

@@ -0,0 +1,210 @@
// Package statement defines table-valued functions natively using SQL.
//
// https://github.com/0x09/sqlite-statement-vtab
package statement
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"unsafe"
"github.com/ncruces/go-sqlite3"
)
// Register registers the statement virtual table.
func Register(db *sqlite3.Conn) {
sqlite3.CreateModule(db, "statement", declare, declare)
}
type table struct {
stmt *sqlite3.Stmt
sql string
inuse bool
}
func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (*table, error) {
if len(arg) != 1 {
return nil, fmt.Errorf("statement: wrong number of arguments")
}
sql := "SELECT * FROM\n" + arg[0]
stmt, _, err := db.Prepare(sql)
if err != nil {
return nil, err
}
var sep string
var str strings.Builder
str.WriteString("CREATE TABLE x(")
outputs := stmt.ColumnCount()
for i := 0; i < outputs; i++ {
name := sqlite3.QuoteIdentifier(stmt.ColumnName(i))
str.WriteString(sep)
str.WriteString(name)
str.WriteString(" ")
str.WriteString(stmt.ColumnDeclType(i))
sep = ","
}
inputs := stmt.BindCount()
for i := 1; i <= inputs; i++ {
str.WriteString(sep)
name := stmt.BindName(i)
if name == "" {
str.WriteString("[")
str.WriteString(strconv.Itoa(i))
str.WriteString("] HIDDEN")
} else {
str.WriteString(sqlite3.QuoteIdentifier(name[1:]))
str.WriteString(" HIDDEN")
}
sep = ","
}
str.WriteByte(')')
err = db.DeclareVtab(str.String())
if err != nil {
stmt.Close()
return nil, err
}
return &table{sql: sql, stmt: stmt}, nil
}
func (t *table) Close() error {
return t.stmt.Close()
}
func (t *table) BestIndex(idx *sqlite3.IndexInfo) error {
idx.EstimatedCost = 1000
var argvIndex = 1
var needIndex bool
var listIndex []int
outputs := t.stmt.ColumnCount()
for i, cst := range idx.Constraint {
// Skip if this is a constraint on one of our output columns.
if cst.Column < outputs {
continue
}
// A given query plan is only usable if all provided input columns
// are usable and have equal constraints only.
if !cst.Usable || cst.Op != sqlite3.INDEX_CONSTRAINT_EQ {
return sqlite3.CONSTRAINT
}
// The non-zero argvIdx values must be contiguous.
// If they're not, build a list and serialize it through IdxStr.
nextIndex := cst.Column - outputs + 1
idx.ConstraintUsage[i] = sqlite3.IndexConstraintUsage{
ArgvIndex: argvIndex,
Omit: true,
}
if nextIndex != argvIndex {
needIndex = true
}
listIndex = append(listIndex, nextIndex)
argvIndex++
}
if needIndex {
buf, err := json.Marshal(listIndex)
if err != nil {
return err
}
idx.IdxStr = unsafe.String(&buf[0], len(buf))
}
return nil
}
func (t *table) Open() (sqlite3.VTabCursor, error) {
stmt := t.stmt
if !t.inuse {
t.inuse = true
} else {
var err error
stmt, _, err = t.stmt.Conn().Prepare(t.sql)
if err != nil {
return nil, err
}
}
return &cursor{table: t, stmt: stmt}, nil
}
func (t *table) Rename(new string) error {
return nil
}
type cursor struct {
table *table
stmt *sqlite3.Stmt
arg []sqlite3.Value
rowID int64
}
func (c *cursor) Close() error {
if c.stmt == c.table.stmt {
c.table.inuse = false
c.stmt.ClearBindings()
return c.stmt.Reset()
}
return c.stmt.Close()
}
func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
c.arg = arg
c.rowID = 0
c.stmt.ClearBindings()
if err := c.stmt.Reset(); err != nil {
return err
}
var list []int
if idxStr != "" {
buf := unsafe.Slice(unsafe.StringData(idxStr), len(idxStr))
err := json.Unmarshal(buf, &list)
if err != nil {
return err
}
}
for i, arg := range arg {
param := i + 1
if list != nil {
param = list[i]
}
err := c.stmt.BindValue(param, arg)
if err != nil {
return err
}
}
return c.Next()
}
func (c *cursor) Next() error {
if c.stmt.Step() {
c.rowID++
}
return c.stmt.Err()
}
func (c *cursor) EOF() bool {
return !c.stmt.Busy()
}
func (c *cursor) RowID() (int64, error) {
return c.rowID, nil
}
func (c *cursor) Column(ctx *sqlite3.Context, col int) error {
switch outputs := c.stmt.ColumnCount(); {
case col < outputs:
ctx.ResultValue(c.stmt.ColumnValue(col))
case col-outputs < len(c.arg):
ctx.ResultValue(c.arg[col-outputs])
}
return nil
}

145
ext/statement/stmt_test.go Normal file
View File

@@ -0,0 +1,145 @@
package statement_test
import (
"fmt"
"log"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/statement"
)
func Example() {
db, err := sqlite3.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
statement.Register(db)
err = db.Exec(`
CREATE VIRTUAL TABLE split_date USING statement((
SELECT
strftime('%Y', :date) AS year,
strftime('%m', :date) AS month,
strftime('%d', :date) AS day
))`)
if err != nil {
log.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT * FROM split_date('2022-02-22')`)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
if stmt.Step() {
fmt.Printf("Twosday was %d-%d-%d", stmt.ColumnInt(0), stmt.ColumnInt(1), stmt.ColumnInt(2))
}
if err := stmt.Reset(); err != nil {
log.Fatal(err)
}
// Output:
// Twosday was 2022-2-22
}
func TestRegister(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
statement.Register(db)
err = db.Exec(`
CREATE VIRTUAL TABLE arguments USING statement((SELECT ? AS a, ? AS b, ? AS c))
`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`
SELECT * from arguments WHERE [2] = 'y' AND [3] = 'z'
`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`
CREATE VIRTUAL TABLE hypot USING statement((SELECT sqrt(:x * :x + :y * :y) AS hypotenuse))
`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`
SELECT x, y, * FROM hypot WHERE x = 3 AND y = 4
`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
if stmt.Step() {
x := stmt.ColumnInt(0)
y := stmt.ColumnInt(1)
hypot := stmt.ColumnInt(2)
if x != 3 || y != 4 || hypot != 5 {
t.Errorf("hypot(%d, %d) = %d", x, y, hypot)
}
}
}
func TestRegister_errors(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
statement.Register(db)
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING statement()`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING statement(SELECT 1, SELECT 2)`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING statement((SELECT 1, SELECT 2))`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING statement((SELECT 1; SELECT 2))`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
err = db.Exec(`CREATE VIRTUAL TABLE split_date USING statement((CREATE TABLE x(val)))`)
if err == nil {
t.Fatal("want error")
} else {
t.Log(err)
}
}

View File

@@ -6,6 +6,8 @@ import (
)
func Test_welford(t *testing.T) {
t.Parallel()
var s1, s2 welford
s1.enqueue(4)
@@ -38,6 +40,8 @@ func Test_welford(t *testing.T) {
}
func Test_covar(t *testing.T) {
t.Parallel()
var c1, c2 welford2
c1.enqueue(3, 70)
@@ -64,6 +68,8 @@ func Test_covar(t *testing.T) {
}
func Test_correlation(t *testing.T) {
t.Parallel()
var c welford2
c.enqueue(1, 3)
c.enqueue(2, 2)

View File

@@ -66,7 +66,7 @@ func RegisterCollation(db *sqlite3.Conn, locale, name string) error {
func upper(ctx sqlite3.Context, arg ...sqlite3.Value) {
if len(arg) == 1 {
ctx.ResultBlob(bytes.ToUpper(arg[0].RawBlob()))
ctx.ResultRawText(bytes.ToUpper(arg[0].RawText()))
return
}
cs, ok := ctx.GetAuxData(1).(cases.Caser)
@@ -80,12 +80,12 @@ func upper(ctx sqlite3.Context, arg ...sqlite3.Value) {
ctx.SetAuxData(1, c)
cs = c
}
ctx.ResultBlob(cs.Bytes(arg[0].RawBlob()))
ctx.ResultRawText(cs.Bytes(arg[0].RawText()))
}
func lower(ctx sqlite3.Context, arg ...sqlite3.Value) {
if len(arg) == 1 {
ctx.ResultBlob(bytes.ToLower(arg[0].RawBlob()))
ctx.ResultRawText(bytes.ToLower(arg[0].RawText()))
return
}
cs, ok := ctx.GetAuxData(1).(cases.Caser)
@@ -99,7 +99,7 @@ func lower(ctx sqlite3.Context, arg ...sqlite3.Value) {
ctx.SetAuxData(1, c)
cs = c
}
ctx.ResultBlob(cs.Bytes(arg[0].RawBlob()))
ctx.ResultRawText(cs.Bytes(arg[0].RawText()))
}
func regex(ctx sqlite3.Context, arg ...sqlite3.Value) {
@@ -113,14 +113,14 @@ func regex(ctx sqlite3.Context, arg ...sqlite3.Value) {
re = r
ctx.SetAuxData(0, re)
}
ctx.ResultBool(re.Match(arg[1].RawBlob()))
ctx.ResultBool(re.Match(arg[1].RawText()))
}
func like(ctx sqlite3.Context, arg ...sqlite3.Value) {
escape := rune(-1)
if len(arg) == 3 {
var size int
b := arg[2].RawBlob()
b := arg[2].RawText()
escape, size = utf8.DecodeRune(b)
if size != len(b) {
ctx.ResultError(util.ErrorString("ESCAPE expression must be a single character"))
@@ -141,7 +141,7 @@ func like(ctx sqlite3.Context, arg ...sqlite3.Value) {
}
ctx.SetAuxData(0, re)
}
ctx.ResultBool(re.Match(arg[1].RawBlob()))
ctx.ResultBool(re.Match(arg[1].RawText()))
}
func like2regex(pattern string, escape rune) string {

View File

@@ -189,6 +189,8 @@ func TestRegister_error(t *testing.T) {
}
func Test_like2regex(t *testing.T) {
t.Parallel()
const prefix = `(?is)\A`
const sufix = `\z`
tests := []struct {

82
func.go
View File

@@ -14,47 +14,49 @@ import (
// This can be used to load schemas that contain
// one or more unknown collating sequences.
func (c *Conn) AnyCollationNeeded() {
c.call(c.api.anyCollation, uint64(c.handle), 0, 0)
c.call("sqlite3_anycollseq_init", uint64(c.handle), 0, 0)
}
// CreateCollation defines a new collating sequence.
//
// https://www.sqlite.org/c3ref/create_collation.html
// https://sqlite.org/c3ref/create_collation.html
func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error {
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
r := c.call(c.api.createCollation,
r := c.call("sqlite3_create_collation_go",
uint64(c.handle), uint64(namePtr), uint64(funcPtr))
if err := c.error(r); err != nil {
util.DelHandle(c.ctx, funcPtr)
return err
}
return nil
return c.error(r)
}
// CreateFunction defines a new scalar SQL function.
//
// https://www.sqlite.org/c3ref/create_function.html
func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn func(ctx Context, arg ...Value)) error {
// https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn ScalarFunction) error {
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
r := c.call(c.api.createFunction,
r := c.call("sqlite3_create_function_go",
uint64(c.handle), uint64(namePtr), uint64(nArg),
uint64(flag), uint64(funcPtr))
return c.error(r)
}
// ScalarFunction is the type of a scalar SQL function.
type ScalarFunction func(ctx Context, arg ...Value)
// CreateWindowFunction defines a new aggregate or aggregate window SQL function.
// If fn returns a [WindowFunction], then an aggregate window function is created.
// If fn returns an [io.Closer], it will be called to free resources.
//
// https://www.sqlite.org/c3ref/create_function.html
// https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error {
call := c.api.createAggregate
defer c.arena.mark()()
call := "sqlite3_create_aggregate_function_go"
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
if _, ok := fn().(WindowFunction); ok {
call = c.api.createWindow
call = "sqlite3_create_window_function_go"
}
r := c.call(call,
uint64(c.handle), uint64(namePtr), uint64(nArg),
@@ -64,7 +66,7 @@ func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn
// AggregateFunction is the interface an aggregate function should implement.
//
// https://www.sqlite.org/appfunc.html
// https://sqlite.org/appfunc.html
type AggregateFunction interface {
// Step is invoked to add a row to the current window.
// The function arguments, if any, corresponding to the row being added are passed to Step.
@@ -76,7 +78,7 @@ type AggregateFunction interface {
// WindowFunction is the interface an aggregate window function should implement.
//
// https://www.sqlite.org/windowfunctions.html
// https://sqlite.org/windowfunctions.html
type WindowFunction interface {
AggregateFunction
@@ -85,78 +87,76 @@ type WindowFunction interface {
Inverse(ctx Context, arg ...Value)
}
func callbackDestroy(ctx context.Context, mod api.Module, pApp uint32) {
func destroyCallback(ctx context.Context, mod api.Module, pApp uint32) {
util.DelHandle(ctx, pApp)
}
func callbackCompare(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nKey2, pKey2 uint32) uint32 {
func compareCallback(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nKey2, pKey2 uint32) uint32 {
fn := util.GetHandle(ctx, pApp).(func(a, b []byte) int)
return uint32(fn(util.View(mod, pKey1, uint64(nKey1)), util.View(mod, pKey2, uint64(nKey2))))
}
func callbackFunc(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
func funcCallback(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
db := ctx.Value(connKey{}).(*Conn)
fn := callbackHandle(db, pCtx).(func(ctx Context, arg ...Value))
fn := userDataHandle(db, pCtx).(ScalarFunction)
fn(Context{db, pCtx}, callbackArgs(db, nArg, pArg)...)
}
func callbackStep(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
func stepCallback(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
db := ctx.Value(connKey{}).(*Conn)
fn := callbackAggregate(db, pCtx, nil).(AggregateFunction)
fn := aggregateCtxHandle(db, pCtx, nil)
fn.Step(Context{db, pCtx}, callbackArgs(db, nArg, pArg)...)
}
func callbackFinal(ctx context.Context, mod api.Module, pCtx uint32) {
func finalCallback(ctx context.Context, mod api.Module, pCtx uint32) {
var handle uint32
db := ctx.Value(connKey{}).(*Conn)
fn := callbackAggregate(db, pCtx, &handle).(AggregateFunction)
fn := aggregateCtxHandle(db, pCtx, &handle)
fn.Value(Context{db, pCtx})
if err := util.DelHandle(ctx, handle); err != nil {
Context{db, pCtx}.ResultError(err)
}
}
func callbackValue(ctx context.Context, mod api.Module, pCtx uint32) {
func valueCallback(ctx context.Context, mod api.Module, pCtx uint32) {
db := ctx.Value(connKey{}).(*Conn)
fn := callbackAggregate(db, pCtx, nil).(AggregateFunction)
fn := aggregateCtxHandle(db, pCtx, nil)
fn.Value(Context{db, pCtx})
}
func callbackInverse(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
func inverseCallback(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
db := ctx.Value(connKey{}).(*Conn)
fn := callbackAggregate(db, pCtx, nil).(WindowFunction)
fn := aggregateCtxHandle(db, pCtx, nil).(WindowFunction)
fn.Inverse(Context{db, pCtx}, callbackArgs(db, nArg, pArg)...)
}
func callbackHandle(db *Conn, pCtx uint32) any {
pApp := uint32(db.call(db.api.userData, uint64(pCtx)))
func userDataHandle(db *Conn, pCtx uint32) any {
pApp := uint32(db.call("sqlite3_user_data", uint64(pCtx)))
return util.GetHandle(db.ctx, pApp)
}
func callbackAggregate(db *Conn, pCtx uint32, close *uint32) any {
// On close, we're getting rid of the handle.
func aggregateCtxHandle(db *Conn, pCtx uint32, close *uint32) AggregateFunction {
// On close, we're getting rid of the aggregate.
// Don't allocate space to store it.
var size uint64
if close == nil {
size = ptrlen
}
ptr := uint32(db.call(db.api.aggregateCtx, uint64(pCtx), size))
ptr := uint32(db.call("sqlite3_aggregate_context", uint64(pCtx), size))
// Try loading the handle, if we already have one, or want a new one.
if ptr != 0 || size != 0 {
// If we already have an aggregate, return it.
if ptr != 0 {
if handle := util.ReadUint32(db.mod, ptr); handle != 0 {
fn := util.GetHandle(db.ctx, handle)
fn := util.GetHandle(db.ctx, handle).(AggregateFunction)
if close != nil {
*close = handle
}
if fn != nil {
return fn
}
return fn
}
}
// Create a new aggregate and store the handle.
fn := callbackHandle(db, pCtx).(func() AggregateFunction)()
// Create a new aggregate, and store it if needed.
fn := userDataHandle(db, pCtx).(func() AggregateFunction)()
if ptr != 0 {
util.WriteUint32(db.mod, ptr, util.AddHandle(db.ctx, fn))
}

View File

@@ -74,7 +74,7 @@ func ExampleConn_CreateFunction() {
}
err = db.CreateFunction("upper", 1, sqlite3.DETERMINISTIC|sqlite3.INNOCUOUS, func(ctx sqlite3.Context, arg ...sqlite3.Value) {
ctx.ResultBlob(bytes.ToUpper(arg[0].RawBlob()))
ctx.ResultRawText(bytes.ToUpper(arg[0].RawText()))
})
if err != nil {
log.Fatal(err)
@@ -129,7 +129,7 @@ func ExampleContext_SetAuxData() {
ctx.SetAuxData(0, r)
re = r
}
ctx.ResultBool(re.Match(arg[1].RawBlob()))
ctx.ResultBool(re.Match(arg[1].RawText()))
})
if err != nil {
log.Fatal(err)

2
go.mod
View File

@@ -7,7 +7,7 @@ require (
github.com/psanford/httpreadat v0.1.0
github.com/tetratelabs/wazero v1.5.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.14.0
golang.org/x/sys v0.15.0
golang.org/x/text v0.14.0
)

4
go.sum
View File

@@ -6,7 +6,7 @@ github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08q
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=

View File

@@ -1,4 +1,3 @@
github.com/ncruces/go-sqlite3 v0.9.1/go.mod h1:jFoUbaCDNUS1KN5ZgFxN7bgcWoWfO0EOKeik9QAHZ08=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=

View File

@@ -14,13 +14,4 @@ import (
db, err := gorm.Open(gormlite.Open("gorm.db"), &gorm.Config{})
```
Checkout [https://gorm.io](https://gorm.io) for details.
### Foreign-key constraint activation
Foreign-key constraint is disabled by default in SQLite. To activate it, use connection URL parameter:
```go
db, err := gorm.Open(gormlite.Open(
"file:gorm.db?_pragma=busy_timeout(10000)&_pragma=foreign_keys(1)"),
&gorm.Config{})
```
Checkout [https://gorm.io](https://gorm.io) for details.

View File

@@ -13,7 +13,7 @@ import (
var (
sqliteSeparator = "`|\"|'|\t"
indexRegexp = regexp.MustCompile(fmt.Sprintf(`(?is)CREATE(?: UNIQUE)? INDEX [%v]?[\w\d-]+[%v]? ON (.*)$`, sqliteSeparator, sqliteSeparator))
indexRegexp = regexp.MustCompile(fmt.Sprintf(`(?is)CREATE(?: UNIQUE)? INDEX [%v]?[\w\d-]+[%v]?(?s:.*?)ON (.*)$`, sqliteSeparator, sqliteSeparator))
tableRegexp = regexp.MustCompile(fmt.Sprintf(`(?is)(CREATE TABLE [%v]?[\w\d-]+[%v]?)(?:\s*\((.*)\))?`, sqliteSeparator, sqliteSeparator))
separatorRegexp = regexp.MustCompile(fmt.Sprintf("[%v]", sqliteSeparator))
columnsRegexp = regexp.MustCompile(fmt.Sprintf(`[(,][%v]?(\w+)[%v]?`, sqliteSeparator, sqliteSeparator))

View File

@@ -97,6 +97,24 @@ func TestParseDDL(t *testing.T) {
},
},
},
{
"index with \n from .schema sqlite",
[]string{
"CREATE TABLE `test-d` (`field` integer NOT NULL)",
"CREATE INDEX `idx_uq`\n ON `test-b`(`field`) WHERE field = 0",
},
1,
[]migrator.ColumnType{
{
NameValue: sql.NullString{String: "field", Valid: true},
DataTypeValue: sql.NullString{String: "integer", Valid: true},
ColumnTypeValue: sql.NullString{String: "integer", Valid: true},
PrimaryKeyValue: sql.NullBool{Bool: false, Valid: true},
UniqueValue: sql.NullBool{Bool: false, Valid: true},
NullableValue: sql.NullBool{Bool: false, Valid: true},
},
},
},
}
for _, p := range params {

View File

@@ -3,14 +3,14 @@ module github.com/ncruces/go-sqlite3/gormlite
go 1.21
require (
github.com/ncruces/go-sqlite3 v0.9.1
github.com/ncruces/go-sqlite3 v0.10.5
gorm.io/gorm v1.25.5
)
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/ncruces/julianday v0.1.5 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/tetratelabs/wazero v1.5.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/sys v0.14.0 // indirect
)

View File

@@ -2,15 +2,15 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/ncruces/go-sqlite3 v0.9.1 h1:kV7Zy+ZNyHMfMyZeWc1Yyq+wtgYZDZdp2qAA/wfeMWo=
github.com/ncruces/go-sqlite3 v0.9.1/go.mod h1:jFoUbaCDNUS1KN5ZgFxN7bgcWoWfO0EOKeik9QAHZ08=
github.com/ncruces/julianday v0.1.5 h1:hDJ9ejiMp3DHsoZ5KW4c1lwfMjbARS7u/gbYcd0FBZk=
github.com/ncruces/julianday v0.1.5/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/ncruces/go-sqlite3 v0.10.5 h1:SPnFFYajDfhTuJNjeNwdOhwVCRSAqB1PdSHsGrdfYjw=
github.com/ncruces/go-sqlite3 v0.10.5/go.mod h1:8aGu9/G8lLZbvO6TXA0FXTP2liIefFmbpeXuhG4nJLw=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0=
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=

View File

@@ -50,7 +50,7 @@ func (dialector _Dialector) Initialize(db *gorm.DB) (err error) {
if err := db.ConnPool.QueryRowContext(context.Background(), "select sqlite_version()").Scan(&version); err != nil {
return err
}
// https://www.sqlite.org/releaselog/3_35_0.html
// https://sqlite.org/releaselog/3_35_0.html
if compareVersion(version, "3.35.0") >= 0 {
callbacks.RegisterDefaultCallbacks(db, &callbacks.Config{
CreateClauses: []string{"INSERT", "VALUES", "ON CONFLICT", "RETURNING"},
@@ -199,7 +199,7 @@ func (dialector _Dialector) DataTypeOf(field *schema.Field) string {
case schema.Int, schema.Uint:
if field.AutoIncrement {
// doesn't check `PrimaryKey`, to keep backward compatibility
// https://www.sqlite.org/autoinc.html
// https://sqlite.org/autoinc.html
return "integer PRIMARY KEY AUTOINCREMENT"
} else {
return "integer"

View File

@@ -20,12 +20,3 @@ diff --git a/tests/tests_test.go b/tests/tests_test.go
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
"gorm.io/gorm/logger"
@@ -89,7 +91,7 @@ func OpenTestConnection(cfg *gorm.Config) (db *gorm.DB, err error) {
db, err = gorm.Open(mysql.Open(dbDSN), cfg)
default:
log.Println("testing sqlite3...")
- db, err = gorm.Open(sqlite.Open(filepath.Join(os.TempDir(), "gorm.db?_foreign_keys=on")), cfg)
+ db, err = gorm.Open(sqlite.Open("file:"+filepath.Join(os.TempDir(), "gorm.db")+"?_pragma=busy_timeout(1000)&_pragma=foreign_keys(1)"), cfg)
}
if err != nil {

View File

@@ -1,7 +1,6 @@
package util
import (
"fmt"
"runtime"
"strconv"
)
@@ -15,9 +14,8 @@ const (
OOMErr = ErrorString("sqlite3: out of memory")
RangeErr = ErrorString("sqlite3: index out of range")
NoNulErr = ErrorString("sqlite3: missing NUL terminator")
NoGlobalErr = ErrorString("sqlite3: could not find global: ")
NoFuncErr = ErrorString("sqlite3: could not find function: ")
BinaryErr = ErrorString("sqlite3: no SQLite binary embed/set/loaded")
NoBinaryErr = ErrorString("sqlite3: no SQLite binary embed/set/loaded")
BadBinaryErr = ErrorString("sqlite3: invalid SQLite binary embed/set/loaded")
TimeErr = ErrorString("sqlite3: invalid time value")
WhenceErr = ErrorString("sqlite3: invalid whence")
OffsetErr = ErrorString("sqlite3: invalid offset")
@@ -35,14 +33,6 @@ func AssertErr() ErrorString {
return ErrorString(msg)
}
func Finalizer[T any](skip int) func(*T) {
msg := fmt.Sprintf("sqlite3: %T not closed", new(T))
if _, file, line, ok := runtime.Caller(skip + 1); ok && skip >= 0 {
msg += " (" + file + ":" + strconv.Itoa(line) + ")"
}
return func(*T) { panic(ErrorString(msg)) }
}
func ErrorCodeString(rc uint32) string {
switch rc {
case ABORT_ROLLBACK:

View File

@@ -24,6 +24,17 @@ func View(mod api.Module, ptr uint32, size uint64) []byte {
return buf
}
func ReadUint8(mod api.Module, ptr uint32) uint8 {
if ptr == 0 {
panic(NilErr)
}
v, ok := mod.Memory().ReadByte(ptr)
if !ok {
panic(RangeErr)
}
return v
}
func ReadUint32(mod api.Module, ptr uint32) uint32 {
if ptr == 0 {
panic(NilErr)
@@ -35,6 +46,16 @@ func ReadUint32(mod api.Module, ptr uint32) uint32 {
return v
}
func WriteUint8(mod api.Module, ptr uint32, v uint8) {
if ptr == 0 {
panic(NilErr)
}
ok := mod.Memory().WriteByte(ptr, v)
if !ok {
panic(RangeErr)
}
}
func WriteUint32(mod api.Module, ptr uint32, v uint32) {
if ptr == 0 {
panic(NilErr)

View File

@@ -28,6 +28,20 @@ func TestView_overflow(t *testing.T) {
t.Error("want panic")
}
func TestReadUint8_nil(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))
ReadUint8(mock, 0)
t.Error("want panic")
}
func TestReadUint8_range(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))
ReadUint8(mock, wazerotest.PageSize)
t.Error("want panic")
}
func TestReadUint32_nil(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))
@@ -56,6 +70,20 @@ func TestReadUint64_range(t *testing.T) {
t.Error("want panic")
}
func TestWriteUint8_nil(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))
WriteUint8(mock, 0, 1)
t.Error("want panic")
}
func TestWriteUint8_range(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))
WriteUint8(mock, wazerotest.PageSize, 1)
t.Error("want panic")
}
func TestWriteUint32_nil(t *testing.T) {
defer func() { _ = recover() }()
mock := wazerotest.NewModule(wazerotest.NewFixedMemory(wazerotest.PageSize))

20
json.go
View File

@@ -9,26 +9,16 @@ import (
"github.com/ncruces/go-sqlite3/internal/util"
)
// JSON returns:
// a [json.Marshaler] that can be used as an argument to
// [database/sql.DB.Exec] and similar methods to
// store value as JSON; and
// a [database/sql.Scanner] that can be used as an argument to
// [database/sql.Row.Scan] and similar methods to
// decode JSON into value.
// JSON returns a value that can be used as an argument to
// [database/sql.DB.Exec], [database/sql.Row.Scan] and similar methods to
// store value as JSON, or decode JSON into value.
func JSON(value any) any {
return jsonValue{value}
}
type jsonValue struct{ any }
func (j jsonValue) MarshalJSON() ([]byte, error) {
return json.Marshal(j.any)
}
func (j jsonValue) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, j.any)
}
func (j jsonValue) JSON() any { return j.any }
func (j jsonValue) Scan(value any) error {
var buf []byte
@@ -52,5 +42,5 @@ func (j jsonValue) Scan(value any) error {
panic(util.AssertErr())
}
return j.UnmarshalJSON(buf)
return json.Unmarshal(buf, j.any)
}

View File

@@ -4,11 +4,11 @@ package sqlite3
// that can be used as an argument to
// [database/sql.DB.Exec] and similar methods.
//
// https://www.sqlite.org/bindptr.html
// https://sqlite.org/bindptr.html
func Pointer[T any](val T) any {
return pointer[T]{val}
}
type pointer[T any] struct{ val T }
func (p pointer[T]) Value() any { return p.val }
func (p pointer[T]) Pointer() any { return p.val }

280
sqlite.go
View File

@@ -57,7 +57,7 @@ func compileSQLite() {
}
}
if bin == nil {
instance.err = util.BinaryErr
instance.err = util.NoBinaryErr
return
}
@@ -67,8 +67,9 @@ func compileSQLite() {
type sqlite struct {
ctx context.Context
mod api.Module
api sqliteAPI
funcs [8]api.Function
stack [8]uint64
freer uint32
}
func instantiateSQLite() (sqlt *sqlite, err error) {
@@ -86,104 +87,12 @@ func instantiateSQLite() (sqlt *sqlite, err error) {
return nil, err
}
getFun := func(name string) api.Function {
f := sqlt.mod.ExportedFunction(name)
if f == nil {
err = util.NoFuncErr + util.ErrorString(name)
return nil
}
return f
global := sqlt.mod.ExportedGlobal("malloc_destructor")
if global == nil {
return nil, util.BadBinaryErr
}
getVal := func(name string) uint32 {
g := sqlt.mod.ExportedGlobal(name)
if g == nil {
err = util.NoGlobalErr + util.ErrorString(name)
return 0
}
return util.ReadUint32(sqlt.mod, uint32(g.Get()))
}
sqlt.api = sqliteAPI{
free: getFun("free"),
malloc: getFun("malloc"),
destructor: getVal("malloc_destructor"),
errcode: getFun("sqlite3_errcode"),
errstr: getFun("sqlite3_errstr"),
errmsg: getFun("sqlite3_errmsg"),
erroff: getFun("sqlite3_error_offset"),
open: getFun("sqlite3_open_v2"),
close: getFun("sqlite3_close"),
closeZombie: getFun("sqlite3_close_v2"),
prepare: getFun("sqlite3_prepare_v3"),
finalize: getFun("sqlite3_finalize"),
reset: getFun("sqlite3_reset"),
step: getFun("sqlite3_step"),
exec: getFun("sqlite3_exec"),
interrupt: getFun("sqlite3_interrupt"),
progressHandler: getFun("sqlite3_progress_handler_go"),
clearBindings: getFun("sqlite3_clear_bindings"),
bindCount: getFun("sqlite3_bind_parameter_count"),
bindIndex: getFun("sqlite3_bind_parameter_index"),
bindName: getFun("sqlite3_bind_parameter_name"),
bindNull: getFun("sqlite3_bind_null"),
bindInteger: getFun("sqlite3_bind_int64"),
bindFloat: getFun("sqlite3_bind_double"),
bindText: getFun("sqlite3_bind_text64"),
bindBlob: getFun("sqlite3_bind_blob64"),
bindZeroBlob: getFun("sqlite3_bind_zeroblob64"),
bindPointer: getFun("sqlite3_bind_pointer_go"),
columnCount: getFun("sqlite3_column_count"),
columnName: getFun("sqlite3_column_name"),
columnType: getFun("sqlite3_column_type"),
columnInteger: getFun("sqlite3_column_int64"),
columnFloat: getFun("sqlite3_column_double"),
columnText: getFun("sqlite3_column_text"),
columnBlob: getFun("sqlite3_column_blob"),
columnBytes: getFun("sqlite3_column_bytes"),
blobOpen: getFun("sqlite3_blob_open"),
blobClose: getFun("sqlite3_blob_close"),
blobReopen: getFun("sqlite3_blob_reopen"),
blobBytes: getFun("sqlite3_blob_bytes"),
blobRead: getFun("sqlite3_blob_read"),
blobWrite: getFun("sqlite3_blob_write"),
backupInit: getFun("sqlite3_backup_init"),
backupStep: getFun("sqlite3_backup_step"),
backupFinish: getFun("sqlite3_backup_finish"),
backupRemaining: getFun("sqlite3_backup_remaining"),
backupPageCount: getFun("sqlite3_backup_pagecount"),
changes: getFun("sqlite3_changes64"),
lastRowid: getFun("sqlite3_last_insert_rowid"),
autocommit: getFun("sqlite3_get_autocommit"),
anyCollation: getFun("sqlite3_anycollseq_init"),
createCollation: getFun("sqlite3_create_collation_go"),
createFunction: getFun("sqlite3_create_function_go"),
createAggregate: getFun("sqlite3_create_aggregate_function_go"),
createWindow: getFun("sqlite3_create_window_function_go"),
aggregateCtx: getFun("sqlite3_aggregate_context"),
userData: getFun("sqlite3_user_data"),
setAuxData: getFun("sqlite3_set_auxdata_go"),
getAuxData: getFun("sqlite3_get_auxdata"),
valueType: getFun("sqlite3_value_type"),
valueInteger: getFun("sqlite3_value_int64"),
valueFloat: getFun("sqlite3_value_double"),
valueText: getFun("sqlite3_value_text"),
valueBlob: getFun("sqlite3_value_blob"),
valueBytes: getFun("sqlite3_value_bytes"),
valuePointer: getFun("sqlite3_value_pointer_go"),
resultNull: getFun("sqlite3_result_null"),
resultInteger: getFun("sqlite3_result_int64"),
resultFloat: getFun("sqlite3_result_double"),
resultText: getFun("sqlite3_result_text64"),
resultBlob: getFun("sqlite3_result_blob64"),
resultZeroBlob: getFun("sqlite3_result_zeroblob64"),
resultPointer: getFun("sqlite3_result_pointer_go"),
resultValue: getFun("sqlite3_result_value"),
resultError: getFun("sqlite3_result_error"),
resultErrorCode: getFun("sqlite3_result_error_code"),
resultErrorMem: getFun("sqlite3_result_error_nomem"),
resultErrorBig: getFun("sqlite3_result_error_toobig"),
}
sqlt.freer = util.ReadUint32(sqlt.mod, uint32(global.Get()))
if err != nil {
return nil, err
}
@@ -205,17 +114,17 @@ func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error {
panic(util.OOMErr)
}
if r := sqlt.call(sqlt.api.errstr, rc); r != 0 {
err.str = util.ReadString(sqlt.mod, uint32(r), _MAX_STRING)
if r := sqlt.call("sqlite3_errstr", rc); r != 0 {
err.str = util.ReadString(sqlt.mod, uint32(r), _MAX_NAME)
}
if handle != 0 {
if r := sqlt.call(sqlt.api.errmsg, uint64(handle)); r != 0 {
err.msg = util.ReadString(sqlt.mod, uint32(r), _MAX_STRING)
if r := sqlt.call("sqlite3_errmsg", uint64(handle)); r != 0 {
err.msg = util.ReadString(sqlt.mod, uint32(r), _MAX_NAME)
}
if sql != nil {
if r := sqlt.call(sqlt.api.erroff, uint64(handle)); r != math.MaxUint32 {
if r := sqlt.call("sqlite3_error_offset", uint64(handle)); r != math.MaxUint32 {
err.sql = sql[0][r:]
}
}
@@ -228,12 +137,33 @@ func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error {
return &err
}
func (sqlt *sqlite) call(fn api.Function, params ...uint64) uint64 {
func (sqlt *sqlite) getfn(name string) (api.Function, uint32) {
// https://cr.yp.to/cdb/cdb.txt
hash := func(s string) uint32 {
var hash uint32 = 5381
for _, b := range []byte(s) {
hash = (hash<<5 + hash) ^ uint32(b)
}
return hash
}(name) % uint32(len(sqlt.funcs))
fn := sqlt.funcs[hash]
if fn == nil || name != fn.Definition().Name() {
fn = sqlt.mod.ExportedFunction(name)
} else {
sqlt.funcs[hash] = nil
}
return fn, hash
}
func (sqlt *sqlite) call(name string, params ...uint64) uint64 {
copy(sqlt.stack[:], params)
fn, hash := sqlt.getfn(name)
err := fn.CallWithStack(sqlt.ctx, sqlt.stack[:])
if err != nil {
panic(err)
}
sqlt.funcs[hash] = fn
return sqlt.stack[0]
}
@@ -241,14 +171,14 @@ func (sqlt *sqlite) free(ptr uint32) {
if ptr == 0 {
return
}
sqlt.call(sqlt.api.free, uint64(ptr))
sqlt.call("free", uint64(ptr))
}
func (sqlt *sqlite) new(size uint64) uint32 {
if size > _MAX_ALLOCATION_SIZE {
panic(util.OOMErr)
}
ptr := uint32(sqlt.call(sqlt.api.malloc, size))
ptr := uint32(sqlt.call("malloc", size))
if ptr == 0 && size != 0 {
panic(util.OOMErr)
}
@@ -290,17 +220,23 @@ func (a *arena) free() {
if a.sqlt == nil {
return
}
a.reset()
for _, ptr := range a.ptrs {
a.sqlt.free(ptr)
}
a.sqlt.free(a.base)
a.sqlt = nil
}
func (a *arena) reset() {
for _, ptr := range a.ptrs {
a.sqlt.free(ptr)
func (a *arena) mark() (reset func()) {
ptrs := len(a.ptrs)
next := a.next
return func() {
for _, ptr := range a.ptrs[ptrs:] {
a.sqlt.free(ptr)
}
a.ptrs = a.ptrs[:ptrs]
a.next = next
}
a.ptrs = nil
a.next = 0
}
func (a *arena) new(size uint64) uint32 {
@@ -329,95 +265,37 @@ func (a *arena) string(s string) uint32 {
return ptr
}
type sqliteAPI struct {
free api.Function
malloc api.Function
errcode api.Function
errstr api.Function
errmsg api.Function
erroff api.Function
open api.Function
close api.Function
closeZombie api.Function
prepare api.Function
finalize api.Function
reset api.Function
step api.Function
exec api.Function
interrupt api.Function
progressHandler api.Function
clearBindings api.Function
bindCount api.Function
bindIndex api.Function
bindName api.Function
bindNull api.Function
bindInteger api.Function
bindFloat api.Function
bindText api.Function
bindBlob api.Function
bindZeroBlob api.Function
bindPointer api.Function
columnCount api.Function
columnName api.Function
columnType api.Function
columnInteger api.Function
columnFloat api.Function
columnText api.Function
columnBlob api.Function
columnBytes api.Function
blobOpen api.Function
blobClose api.Function
blobReopen api.Function
blobBytes api.Function
blobRead api.Function
blobWrite api.Function
backupInit api.Function
backupStep api.Function
backupFinish api.Function
backupRemaining api.Function
backupPageCount api.Function
changes api.Function
lastRowid api.Function
autocommit api.Function
anyCollation api.Function
createCollation api.Function
createFunction api.Function
createAggregate api.Function
createWindow api.Function
aggregateCtx api.Function
userData api.Function
setAuxData api.Function
getAuxData api.Function
valueType api.Function
valueInteger api.Function
valueFloat api.Function
valueText api.Function
valueBlob api.Function
valueBytes api.Function
valuePointer api.Function
resultNull api.Function
resultInteger api.Function
resultFloat api.Function
resultText api.Function
resultBlob api.Function
resultZeroBlob api.Function
resultPointer api.Function
resultValue api.Function
resultError api.Function
resultErrorCode api.Function
resultErrorMem api.Function
resultErrorBig api.Function
destructor uint32
}
func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
util.ExportFuncII(env, "go_progress", callbackProgress)
util.ExportFuncVI(env, "go_destroy", callbackDestroy)
util.ExportFuncIIIIII(env, "go_compare", callbackCompare)
util.ExportFuncVIII(env, "go_func", callbackFunc)
util.ExportFuncVIII(env, "go_step", callbackStep)
util.ExportFuncVI(env, "go_final", callbackFinal)
util.ExportFuncVI(env, "go_value", callbackValue)
util.ExportFuncVIII(env, "go_inverse", callbackInverse)
util.ExportFuncII(env, "go_progress", progressCallback)
util.ExportFuncVI(env, "go_destroy", destroyCallback)
util.ExportFuncVIII(env, "go_func", funcCallback)
util.ExportFuncVIII(env, "go_step", stepCallback)
util.ExportFuncVI(env, "go_final", finalCallback)
util.ExportFuncVI(env, "go_value", valueCallback)
util.ExportFuncVIII(env, "go_inverse", inverseCallback)
util.ExportFuncIIIIII(env, "go_compare", compareCallback)
util.ExportFuncIIIIII(env, "go_vtab_create", vtabModuleCallback(0))
util.ExportFuncIIIIII(env, "go_vtab_connect", vtabModuleCallback(1))
util.ExportFuncII(env, "go_vtab_disconnect", vtabDisconnectCallback)
util.ExportFuncII(env, "go_vtab_destroy", vtabDestroyCallback)
util.ExportFuncIII(env, "go_vtab_best_index", vtabBestIndexCallback)
util.ExportFuncIIIII(env, "go_vtab_update", vtabUpdateCallback)
util.ExportFuncIII(env, "go_vtab_rename", vtabRenameCallback)
util.ExportFuncIIIII(env, "go_vtab_find_function", vtabFindFuncCallback)
util.ExportFuncII(env, "go_vtab_begin", vtabBeginCallback)
util.ExportFuncII(env, "go_vtab_sync", vtabSyncCallback)
util.ExportFuncII(env, "go_vtab_commit", vtabCommitCallback)
util.ExportFuncII(env, "go_vtab_rollback", vtabRollbackCallback)
util.ExportFuncIII(env, "go_vtab_savepoint", vtabSavepointCallback)
util.ExportFuncIII(env, "go_vtab_release", vtabReleaseCallback)
util.ExportFuncIII(env, "go_vtab_rollback_to", vtabRollbackToCallback)
util.ExportFuncIIIIII(env, "go_vtab_integrity", vtabIntegrityCallback)
util.ExportFuncIII(env, "go_cur_open", cursorOpenCallback)
util.ExportFuncII(env, "go_cur_close", cursorCloseCallback)
util.ExportFuncIIIIII(env, "go_cur_filter", cursorFilterCallback)
util.ExportFuncII(env, "go_cur_next", cursorNextCallback)
util.ExportFuncII(env, "go_cur_eof", cursorEOFCallback)
util.ExportFuncIIII(env, "go_cur_column", cursorColumnCallback)
util.ExportFuncIII(env, "go_cur_rowid", cursorRowIDCallback)
return env
}

View File

@@ -3,33 +3,33 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
curl -#OL "https://sqlite.org/2023/sqlite-amalgamation-3440000.zip"
curl -#OL "https://sqlite.org/2023/sqlite-amalgamation-3440200.zip"
unzip -d . sqlite-amalgamation-*.zip
mv sqlite-amalgamation-*/sqlite3* .
rm -rf sqlite-amalgamation-*
cat *.patch | patch --posix
cat *.patch | patch --no-backup-if-mismatch
mkdir -p ext/
cd ext/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/decimal.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/uint.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/uuid.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/base64.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/regexp.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/series.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/ext/misc/anycollseq.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/decimal.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/uint.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/uuid.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/base64.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/regexp.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/series.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/ext/misc/anycollseq.c"
cd ~-
cd ../vfs/tests/mptest/testdata/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/mptest.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/config01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/config02.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/crash01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/crash02.subtest"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/mptest/multiwrite01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/mptest.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/config01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/config02.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/crash01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/crash02.subtest"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/mptest/multiwrite01.test"
cd ~-
cd ../vfs/tests/speedtest1/testdata/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.0/test/speedtest1.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.44.2/test/speedtest1.c"
cd ~-

View File

@@ -1,55 +1,44 @@
#include <stddef.h>
#include "include.h"
#include "sqlite3.h"
int go_compare(void *, int, const void *, int, const void *);
void go_func(sqlite3_context *, int, sqlite3_value **);
void go_step(sqlite3_context *, int, sqlite3_value **);
void go_final(sqlite3_context *);
void go_value(sqlite3_context *);
void go_inverse(sqlite3_context *, int, sqlite3_value **);
void go_destroy(void *);
int sqlite3_create_collation_go(sqlite3 *db, const char *zName, void *pApp) {
return sqlite3_create_collation_v2(db, zName, SQLITE_UTF8, pApp, go_compare,
go_destroy);
int go_compare(go_handle, int, const void *, int, const void *);
int sqlite3_create_collation_go(sqlite3 *db, const char *name, go_handle app) {
int rc = sqlite3_create_collation_v2(db, name, SQLITE_UTF8, app, go_compare,
go_destroy);
if (rc) go_destroy(app);
return rc;
}
int sqlite3_create_function_go(sqlite3 *db, const char *zName, int nArg,
int flags, void *pApp) {
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8 | flags, pApp,
int sqlite3_create_function_go(sqlite3 *db, const char *name, int argc,
int flags, go_handle app) {
return sqlite3_create_function_v2(db, name, argc, SQLITE_UTF8 | flags, app,
go_func, /*step=*/NULL, /*final=*/NULL,
go_destroy);
}
int sqlite3_create_aggregate_function_go(sqlite3 *db, const char *zName,
int nArg, int flags, void *pApp) {
return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags,
pApp, go_step, go_final, /*value=*/NULL,
int sqlite3_create_aggregate_function_go(sqlite3 *db, const char *name,
int argc, int flags, go_handle app) {
return sqlite3_create_window_function(db, name, argc, SQLITE_UTF8 | flags,
app, go_step, go_final, /*value=*/NULL,
/*inverse=*/NULL, go_destroy);
}
int sqlite3_create_window_function_go(sqlite3 *db, const char *zName, int nArg,
int flags, void *pApp) {
return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags,
pApp, go_step, go_final, go_value,
int sqlite3_create_window_function_go(sqlite3 *db, const char *name, int argc,
int flags, go_handle app) {
return sqlite3_create_window_function(db, name, argc, SQLITE_UTF8 | flags,
app, go_step, go_final, go_value,
go_inverse, go_destroy);
}
void sqlite3_set_auxdata_go(sqlite3_context *ctx, int iArg, void *pAux) {
sqlite3_set_auxdata(ctx, iArg, pAux, go_destroy);
}
#define GO_POINTER_TYPE "github.com/ncruces/go-sqlite3.Pointer"
int sqlite3_bind_pointer_go(sqlite3_stmt *stmt, int i, void *pApp) {
return sqlite3_bind_pointer(stmt, i, pApp, GO_POINTER_TYPE, go_destroy);
}
void sqlite3_result_pointer_go(sqlite3_context *ctx, void *pApp) {
sqlite3_result_pointer(ctx, pApp, GO_POINTER_TYPE, go_destroy);
}
void *sqlite3_value_pointer_go(sqlite3_value *val) {
return sqlite3_value_pointer(val, GO_POINTER_TYPE);
}
void sqlite3_set_auxdata_go(sqlite3_context *ctx, int i, go_handle aux) {
sqlite3_set_auxdata(ctx, i, aux, go_destroy);
}

12
sqlite3/include.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <assert.h>
#include <stddef.h>
// https://github.com/JuliaLang/julia/blob/v1.9.4/src/julia.h#L67-L68
#define container_of(ptr, type, member) \
((type *)((char *)(ptr)-offsetof(type, member)))
typedef void *go_handle;
void go_destroy(go_handle);
static_assert(sizeof(go_handle) == 4, "Unexpected size");

View File

@@ -1,7 +1,5 @@
// Amalgamation
#include "sqlite3.c"
// VFS
#include "vfs.c"
// Extensions
#include "ext/anycollseq.c"
#include "ext/base64.c"
@@ -10,9 +8,15 @@
#include "ext/series.c"
#include "ext/uint.c"
#include "ext/uuid.c"
// Bindings
#include "func.c"
#include "pointer.c"
#include "progress.c"
#include "time.c"
#include "vfs.c"
#include "vtab.c"
sqlite3_destructor_type malloc_destructor = &free;
__attribute__((constructor)) void init() {
sqlite3_initialize();

17
sqlite3/pointer.c Normal file
View File

@@ -0,0 +1,17 @@
#include "include.h"
#include "sqlite3.h"
#define GO_POINTER_TYPE "github.com/ncruces/go-sqlite3.Pointer"
int sqlite3_bind_pointer_go(sqlite3_stmt *stmt, int i, go_handle app) {
return sqlite3_bind_pointer(stmt, i, app, GO_POINTER_TYPE, go_destroy);
}
void sqlite3_result_pointer_go(sqlite3_context *ctx, go_handle app) {
sqlite3_result_pointer(ctx, app, GO_POINTER_TYPE, go_destroy);
}
go_handle sqlite3_value_pointer_go(sqlite3_value *val) {
return sqlite3_value_pointer(val, GO_POINTER_TYPE);
}

View File

@@ -37,25 +37,33 @@
#define SQLITE_DEFAULT_WAL_SYNCHRONOUS 1
#define SQLITE_LIKE_DOESNT_MATCH_BLOBS
#define SQLITE_MAX_EXPR_DEPTH 0
#define SQLITE_OMIT_DECLTYPE
#define SQLITE_USE_ALLOCA
#define SQLITE_OMIT_DEPRECATED
#define SQLITE_OMIT_SHARED_CACHE
#define SQLITE_OMIT_AUTOINIT
#define SQLITE_USE_ALLOCA
// #define SQLITE_OMIT_DECLTYPE
// #define SQLITE_OMIT_PROGRESS_CALLBACK
// Other Options
#define SQLITE_ALLOW_URI_AUTHORITY
#define SQLITE_ENABLE_BATCH_ATOMIC_WRITE
#define SQLITE_TRUSTED_SCHEMA 0
#define SQLITE_DEFAULT_FOREIGN_KEYS 1
#define SQLITE_ENABLE_ATOMIC_WRITE
#define SQLITE_OMIT_DESERIALIZE
#define SQLITE_ENABLE_BATCH_ATOMIC_WRITE
// Because WASM does not support shared memory,
// SQLite disables WAL for WASM builds.
// We patch SQLite to use exclusive locking mode instead.
// https://www.sqlite.org/wal.html#noshm
// https://sqlite.org/wal.html#noshm
#undef SQLITE_OMIT_WAL
// We have our own memdb VFS.
// To avoid interactions between the two,
// omit sqlite3_serialize/sqlite3_deserialize,
// which we also don't wrap.
#define SQLITE_OMIT_DESERIALIZE
// Amalgamated Extensions
#define SQLITE_ENABLE_MATH_FUNCTIONS 1

View File

@@ -82,7 +82,7 @@ int sqlite3_time_init(sqlite3 *db, char **pzErrMsg,
time_collation,
/*destroy=*/NULL);
sqlite3_create_function_v2(
db, "json_time", -1,
db, "json_time", /*nArg=*/-1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS, /*arg=*/NULL,
json_time_func, /*step=*/NULL, /*final=*/NULL, /*destroy=*/NULL);
return SQLITE_OK;

View File

@@ -2,6 +2,7 @@
#include <stddef.h>
#include <time.h>
#include "include.h"
#include "sqlite3.h"
int go_localtime(struct tm *, sqlite3_int64);
@@ -9,7 +10,6 @@ int go_vfs_find(const char *zVfsName);
int go_randomness(sqlite3_vfs *, int nByte, char *zOut);
int go_sleep(sqlite3_vfs *, int microseconds);
int go_current_time(sqlite3_vfs *, double *);
int go_current_time_64(sqlite3_vfs *, sqlite3_int64 *);
int go_open(sqlite3_vfs *, sqlite3_filename zName, sqlite3_file *, int flags,
@@ -60,7 +60,7 @@ static int go_open_wrapper(sqlite3_vfs *vfs, sqlite3_filename zName,
struct go_file {
sqlite3_file base;
int handle;
go_handle handle;
};
int sqlite3_os_init() {
@@ -77,24 +77,21 @@ int sqlite3_os_init() {
.xRandomness = go_randomness,
.xSleep = go_sleep,
.xCurrentTime = go_current_time,
.xCurrentTimeInt64 = go_current_time_64,
};
return sqlite3_vfs_register(&os_vfs, /*default=*/true);
}
sqlite3_destructor_type malloc_destructor = &free;
int localtime_s(struct tm *const pTm, time_t const *const pTime) {
return go_localtime(pTm, (sqlite3_int64)*pTime);
}
sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName) {
if (zVfsName) {
if (zVfsName && go_vfs_find(zVfsName)) {
static sqlite3_vfs *go_vfs_list;
for (sqlite3_vfs *it = go_vfs_list; it; it = it->pNext) {
if (!strcmp(zVfsName, it->zName) && go_vfs_find(it->zName)) {
if (!strcmp(zVfsName, it->zName)) {
return it;
}
}
@@ -109,30 +106,27 @@ sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName) {
}
}
if (go_vfs_find(zVfsName)) {
sqlite3_vfs *head = go_vfs_list;
go_vfs_list = malloc(sizeof(sqlite3_vfs) + strlen(zVfsName) + 1);
char *name = (char *)(go_vfs_list + 1);
strcpy(name, zVfsName);
*go_vfs_list = (sqlite3_vfs){
.iVersion = 2,
.szOsFile = sizeof(struct go_file),
.mxPathname = 512,
.zName = name,
.pNext = head,
sqlite3_vfs *head = go_vfs_list;
go_vfs_list = malloc(sizeof(sqlite3_vfs) + strlen(zVfsName) + 1);
char *name = (char *)(go_vfs_list + 1);
strcpy(name, zVfsName);
*go_vfs_list = (sqlite3_vfs){
.iVersion = 2,
.szOsFile = sizeof(struct go_file),
.mxPathname = 512,
.zName = name,
.pNext = head,
.xOpen = go_open_wrapper,
.xDelete = go_delete,
.xAccess = go_access,
.xFullPathname = go_full_pathname,
.xOpen = go_open_wrapper,
.xDelete = go_delete,
.xAccess = go_access,
.xFullPathname = go_full_pathname,
.xRandomness = go_randomness,
.xSleep = go_sleep,
.xCurrentTime = go_current_time,
.xCurrentTimeInt64 = go_current_time_64,
};
return go_vfs_list;
}
.xRandomness = go_randomness,
.xSleep = go_sleep,
.xCurrentTimeInt64 = go_current_time_64,
};
return go_vfs_list;
}
return sqlite3_vfs_find_orig(zVfsName);
}

230
sqlite3/vtab.c Normal file
View File

@@ -0,0 +1,230 @@
#include <stddef.h>
#include "include.h"
#include "sqlite3.h"
#define SQLITE_VTAB_CREATOR_GO /******/ 0x01
#define SQLITE_VTAB_DESTROYER_GO /****/ 0x02
#define SQLITE_VTAB_UPDATER_GO /******/ 0x04
#define SQLITE_VTAB_RENAMER_GO /******/ 0x08
#define SQLITE_VTAB_OVERLOADER_GO /***/ 0x10
#define SQLITE_VTAB_CHECKER_GO /******/ 0x20
#define SQLITE_VTAB_TX_GO /***********/ 0x40
#define SQLITE_VTAB_SAVEPOINTER_GO /**/ 0x80
int go_vtab_create(sqlite3_module *, int argc, const char *const *argv,
sqlite3_vtab **, char **pzErr);
int go_vtab_connect(sqlite3_module *, int argc, const char *const *argv,
sqlite3_vtab **, char **pzErr);
int go_vtab_disconnect(sqlite3_vtab *);
int go_vtab_destroy(sqlite3_vtab *);
int go_vtab_best_index(sqlite3_vtab *, sqlite3_index_info *);
int go_cur_open(sqlite3_vtab *, sqlite3_vtab_cursor **);
int go_cur_close(sqlite3_vtab_cursor *);
int go_cur_filter(sqlite3_vtab_cursor *, int idxNum, const char *idxStr,
int argc, sqlite3_value **argv);
int go_cur_next(sqlite3_vtab_cursor *);
int go_cur_eof(sqlite3_vtab_cursor *);
int go_cur_column(sqlite3_vtab_cursor *, sqlite3_context *, int);
int go_cur_rowid(sqlite3_vtab_cursor *, sqlite3_int64 *pRowid);
int go_vtab_update(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
int go_vtab_rename(sqlite3_vtab *, const char *zNew);
int go_vtab_find_function(sqlite3_vtab *, int nArg, const char *zName,
go_handle *pxFunc);
int go_vtab_begin(sqlite3_vtab *);
int go_vtab_sync(sqlite3_vtab *);
int go_vtab_commit(sqlite3_vtab *);
int go_vtab_rollback(sqlite3_vtab *);
int go_vtab_savepoint(sqlite3_vtab *, int);
int go_vtab_release(sqlite3_vtab *, int);
int go_vtab_rollback_to(sqlite3_vtab *, int);
int go_vtab_integrity(sqlite3_vtab *, const char *zSchema, const char *zTabName,
int mFlags, char **pzErr);
struct go_module {
go_handle handle;
sqlite3_module base;
};
struct go_vtab {
go_handle handle;
sqlite3_vtab base;
};
struct go_cursor {
go_handle handle;
sqlite3_vtab_cursor base;
};
static void go_mod_destroy(void *pAux) {
struct go_module *mod = pAux;
void *handle = mod->handle;
free(mod);
go_destroy(handle);
}
static int go_vtab_create_wrapper(sqlite3 *db, void *pAux, int argc,
const char *const *argv,
sqlite3_vtab **ppVTab, char **pzErr) {
struct go_vtab *vtab = calloc(1, sizeof(struct go_vtab));
if (vtab == NULL) return SQLITE_NOMEM;
*ppVTab = &vtab->base;
struct go_module *mod = pAux;
int rc = go_vtab_create(&mod->base, argc, argv, ppVTab, pzErr);
if (rc) {
if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr);
free(vtab);
}
return rc;
}
static int go_vtab_connect_wrapper(sqlite3 *db, void *pAux, int argc,
const char *const *argv,
sqlite3_vtab **ppVTab, char **pzErr) {
struct go_vtab *vtab = calloc(1, sizeof(struct go_vtab));
if (vtab == NULL) return SQLITE_NOMEM;
*ppVTab = &vtab->base;
struct go_module *mod = pAux;
int rc = go_vtab_connect(&mod->base, argc, argv, ppVTab, pzErr);
if (rc) {
free(vtab);
if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr);
}
return rc;
}
static int go_vtab_disconnect_wrapper(sqlite3_vtab *pVTab) {
struct go_vtab *vtab = container_of(pVTab, struct go_vtab, base);
int rc = go_vtab_disconnect(pVTab);
free(vtab);
return rc;
}
static int go_vtab_destroy_wrapper(sqlite3_vtab *pVTab) {
struct go_vtab *vtab = container_of(pVTab, struct go_vtab, base);
int rc = go_vtab_destroy(pVTab);
free(vtab);
return rc;
}
static int go_cur_open_wrapper(sqlite3_vtab *pVTab,
sqlite3_vtab_cursor **ppCursor) {
struct go_cursor *cur = calloc(1, sizeof(struct go_cursor));
if (cur == NULL) return SQLITE_NOMEM;
*ppCursor = &cur->base;
int rc = go_cur_open(pVTab, ppCursor);
if (rc) free(cur);
return rc;
}
static int go_cur_close_wrapper(sqlite3_vtab_cursor *pCursor) {
struct go_cursor *cur = container_of(pCursor, struct go_cursor, base);
int rc = go_cur_close(pCursor);
free(cur);
return rc;
}
static int go_vtab_find_function_wrapper(
sqlite3_vtab *pVTab, int nArg, const char *zName,
void (**pxFunc)(sqlite3_context *, int, sqlite3_value **), void **ppArg) {
struct go_vtab *vtab = container_of(pVTab, struct go_vtab, base);
go_handle handle;
int rc = go_vtab_find_function(pVTab, nArg, zName, &handle);
if (rc) {
*pxFunc = go_func;
*ppArg = handle;
}
return rc;
}
static int go_vtab_integrity_wrapper(sqlite3_vtab *pVTab, const char *zSchema,
const char *zTabName, int mFlags,
char **pzErr) {
int rc = go_vtab_integrity(pVTab, zSchema, zTabName, mFlags, pzErr);
if (rc && *pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr);
return rc;
}
int sqlite3_create_module_go(sqlite3 *db, const char *zName, int flags,
go_handle handle) {
struct go_module *mod = malloc(sizeof(struct go_module));
if (mod == NULL) {
go_destroy(handle);
return SQLITE_NOMEM;
}
mod->handle = handle;
mod->base = (sqlite3_module){
.iVersion = 4,
.xConnect = go_vtab_connect_wrapper,
.xDisconnect = go_vtab_disconnect_wrapper,
.xBestIndex = go_vtab_best_index,
.xOpen = go_cur_open_wrapper,
.xClose = go_cur_close_wrapper,
.xFilter = go_cur_filter,
.xNext = go_cur_next,
.xEof = go_cur_eof,
.xColumn = go_cur_column,
.xRowid = go_cur_rowid,
};
if (flags & SQLITE_VTAB_CREATOR_GO) {
mod->base.xCreate = go_vtab_create_wrapper;
}
if (flags & SQLITE_VTAB_DESTROYER_GO) {
mod->base.xDestroy = go_vtab_destroy_wrapper;
}
if (flags & SQLITE_VTAB_UPDATER_GO) {
mod->base.xUpdate = go_vtab_update;
}
if (flags & SQLITE_VTAB_RENAMER_GO) {
mod->base.xRename = go_vtab_rename;
}
if (flags & SQLITE_VTAB_OVERLOADER_GO) {
mod->base.xFindFunction = go_vtab_find_function_wrapper;
}
if (flags & SQLITE_VTAB_CHECKER_GO) {
mod->base.xIntegrity = go_vtab_integrity_wrapper;
}
if (flags & SQLITE_VTAB_TX_GO) {
mod->base.xBegin = go_vtab_begin;
mod->base.xSync = go_vtab_sync;
mod->base.xCommit = go_vtab_commit;
mod->base.xRollback = go_vtab_rollback;
}
if (flags & SQLITE_VTAB_SAVEPOINTER_GO) {
mod->base.xSavepoint = go_vtab_savepoint;
mod->base.xRelease = go_vtab_release;
mod->base.xRollbackTo = go_vtab_rollback_to;
}
if (mod->base.xCreate && !mod->base.xDestroy) {
mod->base.xDestroy = mod->base.xDisconnect;
}
if (mod->base.xDestroy && !mod->base.xCreate) {
mod->base.xCreate = mod->base.xConnect;
}
return sqlite3_create_module_v2(db, zName, &mod->base, mod, go_mod_destroy);
}
int sqlite3_vtab_config_go(sqlite3 *db, int op, int constraint) {
return sqlite3_vtab_config(db, op, constraint);
}
static_assert(offsetof(struct go_module, base) == 4, "Unexpected offset");
static_assert(offsetof(struct go_vtab, base) == 4, "Unexpected offset");
static_assert(offsetof(struct go_cursor, base) == 4, "Unexpected offset");
static_assert(sizeof(struct sqlite3_index_info) == 72, "Unexpected size");
static_assert(sizeof(struct sqlite3_index_orderby) == 8, "Unexpected size");
static_assert(sizeof(struct sqlite3_index_constraint) == 12, "Unexpected size");
static_assert(sizeof(struct sqlite3_index_constraint_usage) == 8,
"Unexpected size");

View File

@@ -37,7 +37,7 @@ func Test_sqlite_call_closed(t *testing.T) {
sqlite.close()
defer func() { _ = recover() }()
sqlite.call(sqlite.api.free)
sqlite.call("free")
t.Error("want panic")
}

247
stmt.go
View File

@@ -11,7 +11,7 @@ import (
// Stmt is a prepared statement object.
//
// https://www.sqlite.org/c3ref/stmt.html
// https://sqlite.org/c3ref/stmt.html
type Stmt struct {
c *Conn
err error
@@ -22,33 +22,49 @@ type Stmt struct {
//
// It is safe to close a nil, zero or closed Stmt.
//
// https://www.sqlite.org/c3ref/finalize.html
// https://sqlite.org/c3ref/finalize.html
func (s *Stmt) Close() error {
if s == nil || s.handle == 0 {
return nil
}
r := s.c.call(s.c.api.finalize, uint64(s.handle))
r := s.c.call("sqlite3_finalize", uint64(s.handle))
s.handle = 0
return s.c.error(r)
}
// Conn returns the database connection to which the prepared statement belongs.
//
// https://sqlite.org/c3ref/db_handle.html
func (s *Stmt) Conn() *Conn {
return s.c
}
// ReadOnly returns true if and only if the statement
// makes no direct changes to the content of the database file.
//
// https://sqlite.org/c3ref/stmt_readonly.html
func (s *Stmt) ReadOnly() bool {
r := s.c.call("sqlite3_stmt_readonly", uint64(s.handle))
return r != 0
}
// Reset resets the prepared statement object.
//
// https://www.sqlite.org/c3ref/reset.html
// https://sqlite.org/c3ref/reset.html
func (s *Stmt) Reset() error {
r := s.c.call(s.c.api.reset, uint64(s.handle))
r := s.c.call("sqlite3_reset", uint64(s.handle))
s.err = nil
return s.c.error(r)
}
// ClearBindings resets all bindings on the prepared statement.
// Busy determines if a prepared statement has been reset.
//
// https://www.sqlite.org/c3ref/clear_bindings.html
func (s *Stmt) ClearBindings() error {
r := s.c.call(s.c.api.clearBindings, uint64(s.handle))
return s.c.error(r)
// https://sqlite.org/c3ref/stmt_busy.html
func (s *Stmt) Busy() bool {
r := s.c.call("sqlite3_stmt_busy", uint64(s.handle))
return r != 0
}
// Step evaluates the SQL statement.
@@ -59,12 +75,13 @@ func (s *Stmt) ClearBindings() error {
// If an error has occurred, Step returns false;
// call [Stmt.Err] or [Stmt.Reset] to get the error.
//
// https://www.sqlite.org/c3ref/step.html
// https://sqlite.org/c3ref/step.html
func (s *Stmt) Step() bool {
s.c.checkInterrupt()
r := s.c.call(s.c.api.step, uint64(s.handle))
r := s.c.call("sqlite3_step", uint64(s.handle))
switch r {
case _ROW:
s.err = nil
return true
case _DONE:
s.err = nil
@@ -77,7 +94,7 @@ func (s *Stmt) Step() bool {
// Err gets the last error occurred during [Stmt.Step].
// Err returns nil after [Stmt.Reset] is called.
//
// https://www.sqlite.org/c3ref/step.html
// https://sqlite.org/c3ref/step.html
func (s *Stmt) Err() error {
return s.err
}
@@ -90,11 +107,32 @@ func (s *Stmt) Exec() error {
return s.Reset()
}
// Status monitors the performance characteristics of prepared statements.
//
// https://sqlite.org/c3ref/stmt_status.html
func (s *Stmt) Status(op StmtStatus, reset bool) int {
var i uint64
if reset {
i = 1
}
r := s.c.call("sqlite3_stmt_status", uint64(s.handle),
uint64(op), i)
return int(r)
}
// ClearBindings resets all bindings on the prepared statement.
//
// https://sqlite.org/c3ref/clear_bindings.html
func (s *Stmt) ClearBindings() error {
r := s.c.call("sqlite3_clear_bindings", uint64(s.handle))
return s.c.error(r)
}
// BindCount returns the number of SQL parameters in the prepared statement.
//
// https://www.sqlite.org/c3ref/bind_parameter_count.html
// https://sqlite.org/c3ref/bind_parameter_count.html
func (s *Stmt) BindCount() int {
r := s.c.call(s.c.api.bindCount,
r := s.c.call("sqlite3_bind_parameter_count",
uint64(s.handle))
return int(r)
}
@@ -102,11 +140,11 @@ func (s *Stmt) BindCount() int {
// BindIndex returns the index of a parameter in the prepared statement
// given its name.
//
// https://www.sqlite.org/c3ref/bind_parameter_index.html
// https://sqlite.org/c3ref/bind_parameter_index.html
func (s *Stmt) BindIndex(name string) int {
defer s.c.arena.reset()
defer s.c.arena.mark()()
namePtr := s.c.arena.string(name)
r := s.c.call(s.c.api.bindIndex,
r := s.c.call("sqlite3_bind_parameter_index",
uint64(s.handle), uint64(namePtr))
return int(r)
}
@@ -114,16 +152,16 @@ func (s *Stmt) BindIndex(name string) int {
// BindName returns the name of a parameter in the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_parameter_name.html
// https://sqlite.org/c3ref/bind_parameter_name.html
func (s *Stmt) BindName(param int) string {
r := s.c.call(s.c.api.bindName,
r := s.c.call("sqlite3_bind_parameter_name",
uint64(s.handle), uint64(param))
ptr := uint32(r)
if ptr == 0 {
return ""
}
return util.ReadString(s.c.mod, ptr, _MAX_STRING)
return util.ReadString(s.c.mod, ptr, _MAX_NAME)
}
// BindBool binds a bool to the prepared statement.
@@ -131,7 +169,7 @@ func (s *Stmt) BindName(param int) string {
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are stored as integers 0 (false) and 1 (true).
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindBool(param int, value bool) error {
var i int64
if value {
@@ -143,7 +181,7 @@ func (s *Stmt) BindBool(param int, value bool) error {
// BindInt binds an int to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindInt(param int, value int) error {
return s.BindInt64(param, int64(value))
}
@@ -151,9 +189,9 @@ func (s *Stmt) BindInt(param int, value int) error {
// BindInt64 binds an int64 to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindInt64(param int, value int64) error {
r := s.c.call(s.c.api.bindInteger,
r := s.c.call("sqlite3_bind_int64",
uint64(s.handle), uint64(param), uint64(value))
return s.c.error(r)
}
@@ -161,9 +199,9 @@ func (s *Stmt) BindInt64(param int, value int64) error {
// BindFloat binds a float64 to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindFloat(param int, value float64) error {
r := s.c.call(s.c.api.bindFloat,
r := s.c.call("sqlite3_bind_double",
uint64(s.handle), uint64(param), math.Float64bits(value))
return s.c.error(r)
}
@@ -171,13 +209,32 @@ func (s *Stmt) BindFloat(param int, value float64) error {
// BindText binds a string to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindText(param int, value string) error {
if len(value) > _MAX_LENGTH {
return TOOBIG
}
ptr := s.c.newString(value)
r := s.c.call(s.c.api.bindText,
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.api.destructor), _UTF8)
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
// BindRawText binds a []byte to the prepared statement as text.
// The leftmost SQL parameter has an index of 1.
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindRawText(param int, value []byte) error {
if len(value) > _MAX_LENGTH {
return TOOBIG
}
ptr := s.c.newBytes(value)
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
@@ -185,22 +242,25 @@ func (s *Stmt) BindText(param int, value string) error {
// The leftmost SQL parameter has an index of 1.
// Binding a nil slice is the same as calling [Stmt.BindNull].
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindBlob(param int, value []byte) error {
if len(value) > _MAX_LENGTH {
return TOOBIG
}
ptr := s.c.newBytes(value)
r := s.c.call(s.c.api.bindBlob,
r := s.c.call("sqlite3_bind_blob64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.api.destructor))
uint64(s.c.freer))
return s.c.error(r)
}
// BindZeroBlob binds a zero-filled, length n BLOB to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindZeroBlob(param int, n int64) error {
r := s.c.call(s.c.api.bindZeroBlob,
r := s.c.call("sqlite3_bind_zeroblob64",
uint64(s.handle), uint64(param), uint64(n))
return s.c.error(r)
}
@@ -208,9 +268,9 @@ func (s *Stmt) BindZeroBlob(param int, n int64) error {
// BindNull binds a NULL to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindNull(param int) error {
r := s.c.call(s.c.api.bindNull,
r := s.c.call("sqlite3_bind_null",
uint64(s.handle), uint64(param))
return s.c.error(r)
}
@@ -218,7 +278,7 @@ func (s *Stmt) BindNull(param int) error {
// BindTime binds a [time.Time] to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindTime(param int, value time.Time, format TimeFormat) error {
if format == TimeFormatDefault {
return s.bindRFC3339Nano(param, value)
@@ -243,21 +303,22 @@ func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
buf := util.View(s.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
r := s.c.call(s.c.api.bindText,
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(buf)),
uint64(s.c.api.destructor), _UTF8)
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
// BindPointer binds a NULL to the prepared statement, just like [Stmt.BindNull],
// but it also associates ptr with that NULL value such that it can be retrieved
// within an application-defined SQL function using [Value.Pointer].
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindPointer(param int, ptr any) error {
valPtr := util.AddHandle(s.c.ctx, ptr)
r := s.c.call(s.c.api.bindPointer,
r := s.c.call("sqlite3_bind_pointer_go",
uint64(s.handle), uint64(param), uint64(valPtr))
return s.c.error(r)
}
@@ -265,25 +326,33 @@ func (s *Stmt) BindPointer(param int, ptr any) error {
// BindJSON binds the JSON encoding of value to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindJSON(param int, value any) error {
data, err := json.Marshal(value)
if err != nil {
return err
}
ptr := s.c.newBytes(data)
r := s.c.call(s.c.api.bindText,
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(data)),
uint64(s.c.api.destructor), _UTF8)
return s.BindRawText(param, data)
}
// BindValue binds a copy of value to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindValue(param int, value Value) error {
if value.sqlite != s.c.sqlite {
return MISUSE
}
r := s.c.call("sqlite3_bind_value",
uint64(s.handle), uint64(param), uint64(value.handle))
return s.c.error(r)
}
// ColumnCount returns the number of columns in a result set.
//
// https://www.sqlite.org/c3ref/column_count.html
// https://sqlite.org/c3ref/column_count.html
func (s *Stmt) ColumnCount() int {
r := s.c.call(s.c.api.columnCount,
r := s.c.call("sqlite3_column_count",
uint64(s.handle))
return int(r)
}
@@ -291,35 +360,48 @@ func (s *Stmt) ColumnCount() int {
// ColumnName returns the name of the result column.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_name.html
// https://sqlite.org/c3ref/column_name.html
func (s *Stmt) ColumnName(col int) string {
r := s.c.call(s.c.api.columnName,
r := s.c.call("sqlite3_column_name",
uint64(s.handle), uint64(col))
ptr := uint32(r)
if ptr == 0 {
panic(util.OOMErr)
}
return util.ReadString(s.c.mod, ptr, _MAX_STRING)
return util.ReadString(s.c.mod, ptr, _MAX_NAME)
}
// ColumnType returns the initial [Datatype] of the result column.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnType(col int) Datatype {
r := s.c.call(s.c.api.columnType,
r := s.c.call("sqlite3_column_type",
uint64(s.handle), uint64(col))
return Datatype(r)
}
// ColumnDeclType returns the declared datatype of the result column.
// The leftmost column of the result set has the index 0.
//
// https://sqlite.org/c3ref/column_decltype.html
func (s *Stmt) ColumnDeclType(col int) string {
r := s.c.call("sqlite3_column_decltype",
uint64(s.handle), uint64(col))
if r == 0 {
return ""
}
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME)
}
// ColumnBool returns the value of the result column as a bool.
// The leftmost column of the result set has the index 0.
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are retrieved as integers,
// with 0 converted to false and any other value to true.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnBool(col int) bool {
if i := s.ColumnInt64(col); i != 0 {
return true
@@ -330,7 +412,7 @@ func (s *Stmt) ColumnBool(col int) bool {
// ColumnInt returns the value of the result column as an int.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnInt(col int) int {
return int(s.ColumnInt64(col))
}
@@ -338,9 +420,9 @@ func (s *Stmt) ColumnInt(col int) int {
// ColumnInt64 returns the value of the result column as an int64.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnInt64(col int) int64 {
r := s.c.call(s.c.api.columnInteger,
r := s.c.call("sqlite3_column_int64",
uint64(s.handle), uint64(col))
return int64(r)
}
@@ -348,9 +430,9 @@ func (s *Stmt) ColumnInt64(col int) int64 {
// ColumnFloat returns the value of the result column as a float64.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnFloat(col int) float64 {
r := s.c.call(s.c.api.columnFloat,
r := s.c.call("sqlite3_column_double",
uint64(s.handle), uint64(col))
return math.Float64frombits(r)
}
@@ -358,7 +440,7 @@ func (s *Stmt) ColumnFloat(col int) float64 {
// ColumnTime returns the value of the result column as a [time.Time].
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnTime(col int, format TimeFormat) time.Time {
var v any
switch s.ColumnType(col) {
@@ -383,7 +465,7 @@ func (s *Stmt) ColumnTime(col int, format TimeFormat) time.Time {
// ColumnText returns the value of the result column as a string.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnText(col int) string {
return string(s.ColumnRawText(col))
}
@@ -392,7 +474,7 @@ func (s *Stmt) ColumnText(col int) string {
// the value of the result column as a []byte.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
return append(buf, s.ColumnRawBlob(col)...)
}
@@ -402,9 +484,9 @@ func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
// subsequent calls to [Stmt] methods.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawText(col int) []byte {
r := s.c.call(s.c.api.columnText,
r := s.c.call("sqlite3_column_text",
uint64(s.handle), uint64(col))
return s.columnRawBytes(col, uint32(r))
}
@@ -414,21 +496,21 @@ func (s *Stmt) ColumnRawText(col int) []byte {
// subsequent calls to [Stmt] methods.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawBlob(col int) []byte {
r := s.c.call(s.c.api.columnBlob,
r := s.c.call("sqlite3_column_blob",
uint64(s.handle), uint64(col))
return s.columnRawBytes(col, uint32(r))
}
func (s *Stmt) columnRawBytes(col int, ptr uint32) []byte {
if ptr == 0 {
r := s.c.call(s.c.api.errcode, uint64(s.c.handle))
r := s.c.call("sqlite3_errcode", uint64(s.c.handle))
s.err = s.c.error(r)
return nil
}
r := s.c.call(s.c.api.columnBytes,
r := s.c.call("sqlite3_column_bytes",
uint64(s.handle), uint64(col))
return util.View(s.c.mod, ptr, r)
}
@@ -437,7 +519,7 @@ func (s *Stmt) columnRawBytes(col int, ptr uint32) []byte {
// and stores it in the value pointed to by ptr.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnJSON(col int, ptr any) error {
var data []byte
switch s.ColumnType(col) {
@@ -457,17 +539,16 @@ func (s *Stmt) ColumnJSON(col int, ptr any) error {
return json.Unmarshal(data, ptr)
}
// Return true if stmt is an empty SQL statement.
// This is used as an optimization.
// It's OK to always return false here.
func emptyStatement(stmt string) bool {
for _, b := range []byte(stmt) {
switch b {
case ' ', '\n', '\r', '\t', '\v', '\f':
case ';':
default:
return false
}
// ColumnValue returns the unprotected value of the result column.
// The leftmost column of the result set has the index 0.
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnValue(col int) Value {
r := s.c.call("sqlite3_column_value",
uint64(s.handle), uint64(col))
return Value{
unprot: true,
sqlite: s.c.sqlite,
handle: uint32(r),
}
return true
}

View File

@@ -1,60 +0,0 @@
package sqlite3
import (
"testing"
)
func Test_emptyStatement(t *testing.T) {
t.Parallel()
tests := []struct {
name string
stmt string
want bool
}{
{"empty", "", true},
{"space", " ", true},
{"separator", ";\n ", true},
{"begin", "BEGIN", false},
{"select", "SELECT 1;", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := emptyStatement(tt.stmt); got != tt.want {
t.Errorf("got %v, want %v", got, tt.want)
}
})
}
}
func Fuzz_emptyStatement(f *testing.F) {
f.Add("")
f.Add(" ")
f.Add(";\n ")
f.Add("; ;\v")
f.Add("BEGIN")
f.Add("SELECT 1;")
db, err := Open(":memory:")
if err != nil {
f.Fatal(err)
}
defer db.Close()
f.Fuzz(func(t *testing.T, sql string) {
// If empty, SQLite parses it as empty.
if emptyStatement(sql) {
stmt, tail, err := db.Prepare(sql)
if err != nil {
t.Errorf("%q, %v", sql, err)
}
if stmt != nil {
t.Errorf("%q, %v", sql, stmt)
}
if tail != "" {
t.Errorf("%q", sql)
}
stmt.Close()
}
})
}

View File

@@ -75,8 +75,8 @@ func TestConn_Open_modeof(t *testing.T) {
}
func TestConn_Close(t *testing.T) {
var conn *sqlite3.Conn
conn.Close()
var db *sqlite3.Conn
db.Close()
}
func TestConn_Close_BUSY(t *testing.T) {

View File

@@ -15,6 +15,9 @@ import (
//go:embed testdata/wal.db
var waldb []byte
//go:embed testdata/utf16be.db
var utf16db []byte
func TestDB_memory(t *testing.T) {
t.Parallel()
testDB(t, ":memory:")
@@ -34,19 +37,29 @@ func TestDB_nolock(t *testing.T) {
func TestDB_wal(t *testing.T) {
t.Parallel()
wal := filepath.Join(t.TempDir(), "test.db")
err := os.WriteFile(wal, waldb, 0666)
tmp := filepath.Join(t.TempDir(), "test.db")
err := os.WriteFile(tmp, waldb, 0666)
if err != nil {
t.Fatal(err)
}
testDB(t, wal)
testDB(t, tmp)
}
func TestDB_utf16(t *testing.T) {
t.Parallel()
tmp := filepath.Join(t.TempDir(), "test.db")
err := os.WriteFile(tmp, utf16db, 0666)
if err != nil {
t.Fatal(err)
}
testDB(t, tmp)
}
func TestDB_vfs(t *testing.T) {
testDB(t, "file:test.db?vfs=memdb")
}
func testDB(t *testing.T, name string) {
func testDB(t testing.TB, name string) {
db, err := sqlite3.Open(name)
if err != nil {
t.Fatal(err)
@@ -80,6 +93,9 @@ func testDB(t *testing.T, name string) {
id := stmt.ColumnInt(0)
name := stmt.ColumnText(1)
if row >= 3 {
continue
}
if id != ids[row] {
t.Errorf("got %d, want %d", id, ids[row])
}

View File

@@ -72,6 +72,17 @@ func TestDriver(t *testing.T) {
}
defer rows.Close()
typs, err := rows.ColumnTypes()
if err != nil {
t.Fatal(err)
}
if got := typs[0].DatabaseTypeName(); got != "INT" {
t.Errorf("got %s, want INT", got)
}
if got := typs[1].DatabaseTypeName(); got != "VARCHAR" {
t.Errorf("got %s, want INT", got)
}
row := 0
ids := []int{0, 1, 2}
names := []string{"go", "zig", "whatever"}

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func Test_base64(t *testing.T) {

View File

@@ -1,6 +1,7 @@
package tests
import (
"context"
"encoding/json"
"math"
"testing"
@@ -8,26 +9,36 @@ import (
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/julianday"
)
func TestJSON(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
db, err := driver.Open(":memory:", nil)
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS test (col)`)
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
_, err = conn.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS test (col)`)
if err != nil {
t.Fatal(err)
}
reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600))
_, err = db.Exec(
_, err = conn.ExecContext(ctx,
`INSERT INTO test (col) VALUES (?), (?), (?), (?)`,
nil, 1, math.Pi, reference,
)
@@ -35,7 +46,7 @@ func TestJSON(t *testing.T) {
t.Fatal(err)
}
_, err = db.Exec(
_, err = conn.ExecContext(ctx,
`INSERT INTO test (col) VALUES (?), (?), (?), (?)`,
sqlite3.JSON(math.Pi), sqlite3.JSON(false),
julianday.Format(reference), sqlite3.JSON([]string{}))
@@ -43,10 +54,11 @@ func TestJSON(t *testing.T) {
t.Fatal(err)
}
rows, err := db.Query("SELECT * FROM test")
rows, err := conn.QueryContext(ctx, "SELECT * FROM test")
if err != nil {
t.Fatal(err)
}
defer rows.Close()
want := []string{
"null", "1", "3.141592653589793",

View File

@@ -11,7 +11,7 @@ import (
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
_ "github.com/ncruces/go-sqlite3/vfs/memdb"
"github.com/ncruces/go-sqlite3/vfs/memdb"
)
func TestParallel(t *testing.T) {
@@ -96,7 +96,16 @@ func TestChildProcess(t *testing.T) {
testParallel(t, name, 1000)
}
func testParallel(t *testing.T, name string, n int) {
func BenchmarkMemory(b *testing.B) {
memdb.Delete("test.db")
name := "file:/test.db?vfs=memdb" +
"&_pragma=busy_timeout(10000)" +
"&_pragma=journal_mode(memory)" +
"&_pragma=synchronous(off)"
testParallel(b, name, b.N)
}
func testParallel(t testing.TB, name string, n int) {
writer := func() error {
db, err := sqlite3.Open(name)
if err != nil {
@@ -174,7 +183,7 @@ func testParallel(t *testing.T, name string, n int) {
}
}
func testIntegrity(t *testing.T, name string) {
func testIntegrity(t testing.TB, name string) {
db, err := sqlite3.Open(name)
if err != nil {
t.Fatal(err)

View File

@@ -7,6 +7,7 @@ import (
"time"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func TestStmt(t *testing.T) {
@@ -29,6 +30,10 @@ func TestStmt(t *testing.T) {
}
defer stmt.Close()
if got := stmt.ReadOnly(); got != false {
t.Error("got true, want false")
}
if got := stmt.BindCount(); got != 1 {
t.Errorf("got %d, want 1", got)
}
@@ -136,6 +141,10 @@ func TestStmt(t *testing.T) {
}
defer stmt.Close()
if got := stmt.ReadOnly(); got != true {
t.Error("got false, want true")
}
if stmt.Step() {
if got := stmt.ColumnType(0); got != sqlite3.INTEGER {
t.Errorf("got %v, want INTEGER", got)
@@ -585,4 +594,61 @@ func TestStmt_ColumnTime(t *testing.T) {
t.Errorf("want error")
}
}
if got := stmt.Status(sqlite3.STMTSTATUS_RUN, true); got != 1 {
t.Errorf("got %d, want 1", got)
}
}
func TestStmt_Error(t *testing.T) {
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
var blob [1e9 + 1]byte
_, _, err = db.Prepare(string(blob[:]))
if err == nil {
t.Errorf("want error")
} else {
t.Log(err)
}
stmt, _, err := db.Prepare(`SELECT ?`)
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
err = stmt.BindText(1, string(blob[:]))
if err == nil {
t.Errorf("want error")
} else {
t.Log(err)
}
err = stmt.BindBlob(1, blob[:])
if err == nil {
t.Errorf("want error")
} else {
t.Log(err)
}
err = stmt.BindRawText(1, blob[:])
if err == nil {
t.Errorf("want error")
} else {
t.Log(err)
}
err = stmt.BindZeroBlob(1, 1e9+1)
if err == nil {
t.Errorf("want error")
} else {
t.Log(err)
}
}

BIN
tests/testdata/utf16be.db vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,7 @@
package tests
import (
"context"
"fmt"
"reflect"
"testing"
@@ -8,6 +9,7 @@ import (
"github.com/ncruces/go-sqlite3"
"github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
)
func TestTimeFormat_Encode(t *testing.T) {
@@ -129,13 +131,22 @@ func TestTimeFormat_Decode(t *testing.T) {
func TestTimeFormat_Scanner(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
db, err := driver.Open(":memory:", nil)
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Exec(
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
_, err = conn.ExecContext(ctx,
`CREATE TABLE IF NOT EXISTS test (col)`)
if err != nil {
t.Fatal(err)
@@ -143,13 +154,13 @@ func TestTimeFormat_Scanner(t *testing.T) {
reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600))
_, err = db.Exec(`INSERT INTO test VALUES (?)`, sqlite3.TimeFormat7TZ.Encode(reference))
_, err = conn.ExecContext(ctx, `INSERT INTO test VALUES (?)`, sqlite3.TimeFormat7TZ.Encode(reference))
if err != nil {
t.Fatal(err)
}
var got time.Time
err = db.QueryRow("SELECT * FROM test").Scan(sqlite3.TimeFormatAuto.Scanner(&got))
err = conn.QueryRowContext(ctx, "SELECT * FROM test").Scan(sqlite3.TimeFormatAuto.Scanner(&got))
if err != nil {
t.Fatal(err)
}

View File

@@ -6,6 +6,7 @@ import (
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func TestConn_Transaction_exec(t *testing.T) {

View File

@@ -5,7 +5,6 @@ import (
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/vfs/memdb"
"github.com/ncruces/go-sqlite3/vfs/readervfs"

10
time.go
View File

@@ -15,12 +15,12 @@ import (
// See the documentation for the [TimeFormatDefault] constant
// for formats recognized by SQLite.
//
// https://www.sqlite.org/lang_datefunc.html
// https://sqlite.org/lang_datefunc.html
type TimeFormat string
// TimeFormats recognized by SQLite to encode/decode time values.
//
// https://www.sqlite.org/lang_datefunc.html
// https://sqlite.org/lang_datefunc.html#time_values
const (
TimeFormatDefault TimeFormat = "" // time.RFC3339Nano
@@ -83,9 +83,9 @@ const (
// a float64 for [TimeFormatJulianDay] and [TimeFormatUnixFrac],
// or an int64 for the other numeric formats.
//
// https://www.sqlite.org/lang_datefunc.html
// https://sqlite.org/lang_datefunc.html
//
// [collating sequence]: https://www.sqlite.org/datatype3.html#collating_sequences
// [collating sequence]: https://sqlite.org/datatype3.html#collating_sequences
func (f TimeFormat) Encode(t time.Time) any {
switch f {
// Numeric formats
@@ -136,7 +136,7 @@ func (f TimeFormat) Encode(t time.Time) any {
// Unix timestamps before 1980 and after 9999 may be misinterpreted as julian day numbers,
// or have the wrong time unit.
//
// https://www.sqlite.org/lang_datefunc.html
// https://sqlite.org/lang_datefunc.html
func (f TimeFormat) Decode(v any) (time.Time, error) {
switch f {
// Numeric formats

28
tx.go
View File

@@ -12,14 +12,14 @@ import (
// Tx is an in-progress database transaction.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
type Tx struct {
c *Conn
}
// Begin starts a deferred transaction.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (c *Conn) Begin() Tx {
// BEGIN even if interrupted.
err := c.txExecInterrupted(`BEGIN DEFERRED`)
@@ -31,7 +31,7 @@ func (c *Conn) Begin() Tx {
// BeginImmediate starts an immediate transaction.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (c *Conn) BeginImmediate() (Tx, error) {
err := c.Exec(`BEGIN IMMEDIATE`)
if err != nil {
@@ -42,7 +42,7 @@ func (c *Conn) BeginImmediate() (Tx, error) {
// BeginExclusive starts an exclusive transaction.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (c *Conn) BeginExclusive() (Tx, error) {
err := c.Exec(`BEGIN EXCLUSIVE`)
if err != nil {
@@ -56,14 +56,14 @@ func (c *Conn) BeginExclusive() (Tx, error) {
//
// This is meant to be deferred:
//
// func doWork(conn *sqlite3.Conn) (err error) {
// tx := conn.Begin()
// func doWork(db *sqlite3.Conn) (err error) {
// tx := db.Begin()
// defer tx.End(&err)
//
// // ... do work in the transaction
// }
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (tx Tx) End(errp *error) {
recovered := recover()
if recovered != nil {
@@ -94,7 +94,7 @@ func (tx Tx) End(errp *error) {
// Commit commits the transaction.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (tx Tx) Commit() error {
return tx.c.Exec(`COMMIT`)
}
@@ -102,7 +102,7 @@ func (tx Tx) Commit() error {
// Rollback rolls back the transaction,
// even if the connection has been interrupted.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (tx Tx) Rollback() error {
return tx.c.txExecInterrupted(`ROLLBACK`)
}
@@ -110,7 +110,7 @@ func (tx Tx) Rollback() error {
// Savepoint is a marker within a transaction
// that allows for partial rollback.
//
// https://www.sqlite.org/lang_savepoint.html
// https://sqlite.org/lang_savepoint.html
type Savepoint struct {
c *Conn
name string
@@ -118,7 +118,7 @@ type Savepoint struct {
// Savepoint establishes a new transaction savepoint.
//
// https://www.sqlite.org/lang_savepoint.html
// https://sqlite.org/lang_savepoint.html
func (c *Conn) Savepoint() Savepoint {
// Names can be reused; this makes catching bugs more likely.
name := saveptName() + "_" + strconv.Itoa(int(rand.Int31()))
@@ -156,8 +156,8 @@ func saveptName() (name string) {
//
// This is meant to be deferred:
//
// func doWork(conn *sqlite3.Conn) (err error) {
// savept := conn.Savepoint()
// func doWork(db *sqlite3.Conn) (err error) {
// savept := db.Savepoint()
// defer savept.Release(&err)
//
// // ... do work in the transaction
@@ -198,7 +198,7 @@ func (s Savepoint) Release(errp *error) {
// even if the connection has been interrupted.
// Rollback does not release the savepoint.
//
// https://www.sqlite.org/lang_transaction.html
// https://sqlite.org/lang_transaction.html
func (s Savepoint) Rollback() error {
// ROLLBACK even if interrupted.
return s.c.txExecInterrupted(fmt.Sprintf("ROLLBACK TO %q;", s.name))

View File

@@ -11,17 +11,50 @@ import (
// Value is any value that can be stored in a database table.
//
// https://www.sqlite.org/c3ref/value.html
// https://sqlite.org/c3ref/value.html
type Value struct {
*sqlite
handle uint32
unprot bool
copied bool
}
func (v Value) protected() uint64 {
if v.unprot {
panic(util.ValueErr)
}
return uint64(v.handle)
}
// Dup makes a copy of the SQL value and returns a pointer to that copy.
//
// https://sqlite.org/c3ref/value_dup.html
func (v Value) Dup() *Value {
r := v.call("sqlite3_value_dup", uint64(v.handle))
return &Value{
copied: true,
sqlite: v.sqlite,
handle: uint32(r),
}
}
// Close frees an SQL value previously obtained by [Value.Dup].
//
// https://sqlite.org/c3ref/value_dup.html
func (dup *Value) Close() error {
if !dup.copied {
panic(util.ValueErr)
}
dup.call("sqlite3_value_free", uint64(dup.handle))
dup.handle = 0
return nil
}
// Type returns the initial [Datatype] of the value.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Type() Datatype {
r := v.call(v.api.valueType, uint64(v.handle))
r := v.call("sqlite3_value_type", v.protected())
return Datatype(r)
}
@@ -30,7 +63,7 @@ func (v Value) Type() Datatype {
// Instead, boolean values are retrieved as integers,
// with 0 converted to false and any other value to true.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Bool() bool {
if i := v.Int64(); i != 0 {
return true
@@ -40,30 +73,30 @@ func (v Value) Bool() bool {
// Int returns the value as an int.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Int() int {
return int(v.Int64())
}
// Int64 returns the value as an int64.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Int64() int64 {
r := v.call(v.api.valueInteger, uint64(v.handle))
r := v.call("sqlite3_value_int64", v.protected())
return int64(r)
}
// Float returns the value as a float64.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Float() float64 {
r := v.call(v.api.valueFloat, uint64(v.handle))
r := v.call("sqlite3_value_double", v.protected())
return math.Float64frombits(r)
}
// Time returns the value as a [time.Time].
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Time(format TimeFormat) time.Time {
var a any
switch v.Type() {
@@ -84,7 +117,7 @@ func (v Value) Time(format TimeFormat) time.Time {
// Text returns the value as a string.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Text() string {
return string(v.RawText())
}
@@ -92,7 +125,7 @@ func (v Value) Text() string {
// Blob appends to buf and returns
// the value as a []byte.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Blob(buf []byte) []byte {
return append(buf, v.RawBlob()...)
}
@@ -101,9 +134,9 @@ func (v Value) Blob(buf []byte) []byte {
// The []byte is owned by SQLite and may be invalidated by
// subsequent calls to [Value] methods.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawText() []byte {
r := v.call(v.api.valueText, uint64(v.handle))
r := v.call("sqlite3_value_text", v.protected())
return v.rawBytes(uint32(r))
}
@@ -111,9 +144,9 @@ func (v Value) RawText() []byte {
// The []byte is owned by SQLite and may be invalidated by
// subsequent calls to [Value] methods.
//
// https://www.sqlite.org/c3ref/value_blob.html
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawBlob() []byte {
r := v.call(v.api.valueBlob, uint64(v.handle))
r := v.call("sqlite3_value_blob", v.protected())
return v.rawBytes(uint32(r))
}
@@ -122,14 +155,14 @@ func (v Value) rawBytes(ptr uint32) []byte {
return nil
}
r := v.call(v.api.valueBytes, uint64(v.handle))
r := v.call("sqlite3_value_bytes", v.protected())
return util.View(v.mod, ptr, r)
}
// Pointer gets the pointer associated with this value,
// or nil if it has no associated pointer.
func (v Value) Pointer() any {
r := v.call(v.api.valuePointer, uint64(v.handle))
r := v.call("sqlite3_value_pointer_go", v.protected())
return util.GetHandle(v.ctx, uint32(r))
}

View File

@@ -1,6 +1,6 @@
# Go SQLite VFS API
This package implements the SQLite [OS Interface](https://www.sqlite.org/vfs.html) (aka VFS).
This package implements the SQLite [OS Interface](https://sqlite.org/vfs.html) (aka VFS).
It replaces the default SQLite VFS with a pure Go implementation.

View File

@@ -7,7 +7,7 @@ import "net/url"
//
// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite.
//
// https://www.sqlite.org/c3ref/vfs.html
// https://sqlite.org/c3ref/vfs.html
type VFS interface {
Open(name string, flags OpenFlag) (File, OpenFlag, error)
Delete(name string, syncDir bool) error
@@ -18,7 +18,7 @@ type VFS interface {
// VFSParams extends VFS with the ability to handle URI parameters
// through the OpenParams method.
//
// https://www.sqlite.org/c3ref/uri_boolean.html
// https://sqlite.org/c3ref/uri_boolean.html
type VFSParams interface {
VFS
OpenParams(name string, flags OpenFlag, params url.Values) (File, OpenFlag, error)
@@ -29,7 +29,7 @@ type VFSParams interface {
// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite.
// In particular, sqlite3.BUSY is necessary to correctly implement lock methods.
//
// https://www.sqlite.org/c3ref/io_methods.html
// https://sqlite.org/c3ref/io_methods.html
type File interface {
Close() error
ReadAt(p []byte, off int64) (n int, err error)
@@ -47,7 +47,7 @@ type File interface {
// FileLockState extends File to implement the
// SQLITE_FCNTL_LOCKSTATE file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntllockstate
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntllockstate
type FileLockState interface {
File
LockState() LockLevel
@@ -56,7 +56,7 @@ type FileLockState interface {
// FileSizeHint extends File to implement the
// SQLITE_FCNTL_SIZE_HINT file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlsizehint
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlsizehint
type FileSizeHint interface {
File
SizeHint(size int64) error
@@ -65,7 +65,7 @@ type FileSizeHint interface {
// FileHasMoved extends File to implement the
// SQLITE_FCNTL_HAS_MOVED file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlhasmoved
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlhasmoved
type FileHasMoved interface {
File
HasMoved() (bool, error)
@@ -74,7 +74,7 @@ type FileHasMoved interface {
// FileOverwrite extends File to implement the
// SQLITE_FCNTL_OVERWRITE file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntloverwrite
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntloverwrite
type FileOverwrite interface {
File
Overwrite() error
@@ -83,7 +83,7 @@ type FileOverwrite interface {
// FilePowersafeOverwrite extends File to implement the
// SQLITE_FCNTL_POWERSAFE_OVERWRITE file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpowersafeoverwrite
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpowersafeoverwrite
type FilePowersafeOverwrite interface {
File
PowersafeOverwrite() bool
@@ -93,7 +93,7 @@ type FilePowersafeOverwrite interface {
// FilePowersafeOverwrite extends File to implement the
// SQLITE_FCNTL_COMMIT_PHASETWO file control opcode.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlcommitphasetwo
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlcommitphasetwo
type FileCommitPhaseTwo interface {
File
CommitPhaseTwo() error
@@ -103,7 +103,7 @@ type FileCommitPhaseTwo interface {
// SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE
// and SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE file control opcodes.
//
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbeginatomicwrite
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbeginatomicwrite
type FileBatchAtomicWrite interface {
File
BeginAtomicWrite() error

View File

@@ -3,12 +3,12 @@ package vfs
import "github.com/ncruces/go-sqlite3/internal/util"
const (
_MAX_STRING = 512 // Used for short strings: names, error messages…
_MAX_NAME = 512 // Used for short strings: names, error messages…
_MAX_PATHNAME = 512
_DEFAULT_SECTOR_SIZE = 4096
)
// https://www.sqlite.org/rescode.html
// https://sqlite.org/rescode.html
type _ErrorCode uint32
func (e _ErrorCode) Error() string {
@@ -49,7 +49,7 @@ const (
// OpenFlag is a flag for the [VFS] Open method.
//
// https://www.sqlite.org/c3ref/c_open_autoproxy.html
// https://sqlite.org/c3ref/c_open_autoproxy.html
type OpenFlag uint32
const (
@@ -78,7 +78,7 @@ const (
// AccessFlag is a flag for the [VFS] Access method.
//
// https://www.sqlite.org/c3ref/c_access_exists.html
// https://sqlite.org/c3ref/c_access_exists.html
type AccessFlag uint32
const (
@@ -89,7 +89,7 @@ const (
// SyncFlag is a flag for the [File] Sync method.
//
// https://www.sqlite.org/c3ref/c_sync_dataonly.html
// https://sqlite.org/c3ref/c_sync_dataonly.html
type SyncFlag uint32
const (
@@ -100,7 +100,7 @@ const (
// LockLevel is a value used with [File] Lock and Unlock methods.
//
// https://www.sqlite.org/c3ref/c_lock_exclusive.html
// https://sqlite.org/c3ref/c_lock_exclusive.html
type LockLevel uint32
const (
@@ -146,7 +146,7 @@ const (
// DeviceCharacteristic is a flag retuned by the [File] DeviceCharacteristics method.
//
// https://www.sqlite.org/c3ref/c_iocap_atomic.html
// https://sqlite.org/c3ref/c_iocap_atomic.html
type DeviceCharacteristic uint32
const (
@@ -167,7 +167,7 @@ const (
IOCAP_BATCH_ATOMIC DeviceCharacteristic = 0x00004000
)
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
type _FcntlOpcode uint32
const (

View File

@@ -1,6 +1,6 @@
# Go `"memdb"` SQLite VFS
This package implements the [`"memdb"`](https://www.sqlite.org/src/file/src/memdb.c)
This package implements the [`"memdb"`](https://sqlite.org/src/file/src/memdb.c)
SQLite VFS in pure Go.
It has some benefits over the C version:

View File

@@ -36,6 +36,12 @@ func Create(name string, data []byte) {
db := new(memDB)
db.size = int64(len(data))
// Convert data from WAL to rollback journal.
if len(data) >= 20 && data[18] == 2 && data[19] == 2 {
data[18] = 1
data[19] = 1
}
sectors := divRoundUp(db.size, sectorSize)
db.data = make([]*[sectorSize]byte, sectors)
for i := range db.data {

28
vfs/memdb/memdb_test.go Normal file
View File

@@ -0,0 +1,28 @@
package memdb
import (
"testing"
_ "embed"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
//go:embed testdata/wal.db
var walDB []byte
func Test_wal(t *testing.T) {
Create("test.db", walDB)
db, err := sqlite3.Open("file:/test.db?vfs=memdb")
if err != nil {
t.Fatal(err)
}
defer db.Close()
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(10))`)
if err != nil {
t.Fatal(err)
}
}

BIN
vfs/memdb/testdata/wal.db vendored Normal file

Binary file not shown.

View File

@@ -7,12 +7,6 @@ import (
"os"
)
const (
_S_IREAD = 0400
_S_IWRITE = 0200
_S_IEXEC = 0100
)
func osAccess(path string, flags AccessFlag) error {
fi, err := os.Stat(path)
if err != nil {
@@ -22,12 +16,18 @@ func osAccess(path string, flags AccessFlag) error {
return nil
}
var want fs.FileMode = _S_IREAD
const (
S_IREAD = 0400
S_IWRITE = 0200
S_IEXEC = 0100
)
var want fs.FileMode = S_IREAD
if flags == ACCESS_READWRITE {
want |= _S_IWRITE
want |= S_IWRITE
}
if fi.IsDir() {
want |= _S_IEXEC
want |= S_IEXEC
}
if fi.Mode()&want != want {
return fs.ErrPermission

View File

@@ -18,7 +18,7 @@ import (
var testDB string
func Example_http() {
readervfs.Create("demo.db", httpreadat.New("https://www.sanford.io/demo.db"))
readervfs.Create("demo.db", httpreadat.New("https://sanford.io/demo.db"))
defer readervfs.Delete("demo.db")
db, err := sql.Open("sqlite3", "file:demo.db?vfs=reader")
@@ -34,8 +34,8 @@ func Example_http() {
}
rows, err := db.Query(`
SELECT period, data_value, magntude, units FROM csv
WHERE period > '2010'
LIMIT 10`)
WHERE period > '2010'
LIMIT 10`)
if err != nil {
log.Fatal(err)
}

View File

@@ -7,7 +7,6 @@ import (
type readerVFS struct{}
// Open implements the [vfs.VFS] interface.
func (readerVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) {
if flags&vfs.OPEN_MAIN_DB == 0 {
return nil, flags, sqlite3.CANTOPEN
@@ -20,17 +19,14 @@ func (readerVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag,
return nil, flags, sqlite3.CANTOPEN
}
// Delete implements the [vfs.VFS] interface.
func (readerVFS) Delete(name string, dirSync bool) error {
return sqlite3.IOERR_DELETE
}
// Access implements the [vfs.VFS] interface.
func (readerVFS) Access(name string, flag vfs.AccessFlag) (bool, error) {
return false, nil
}
// FullPathname implements the [vfs.VFS] interface.
func (readerVFS) FullPathname(name string) (string, error) {
return name, nil
}

View File

@@ -12,7 +12,7 @@ var (
// If there is no match, nil is returned.
// If name is empty, the default VFS is returned.
//
// https://www.sqlite.org/c3ref/vfs_find.html
// https://sqlite.org/c3ref/vfs_find.html
func Find(name string) VFS {
if name == "" || name == "os" {
return vfsOS{}
@@ -24,7 +24,7 @@ func Find(name string) VFS {
// Register registers a VFS.
//
// https://www.sqlite.org/c3ref/vfs_find.html
// https://sqlite.org/c3ref/vfs_find.html
func Register(name string, vfs VFS) {
if name == "" || name == "os" {
return
@@ -39,7 +39,7 @@ func Register(name string, vfs VFS) {
// Unregister unregisters a VFS.
//
// https://www.sqlite.org/c3ref/vfs_find.html
// https://sqlite.org/c3ref/vfs_find.html
func Unregister(name string) {
vfsRegistryMtx.Lock()
defer vfsRegistryMtx.Unlock()

View File

@@ -102,7 +102,7 @@ func Test_config01(t *testing.T) {
cfg := config(ctx).WithArgs("mptest", name, "config01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}
@@ -120,7 +120,7 @@ func Test_config02(t *testing.T) {
cfg := config(ctx).WithArgs("mptest", name, "config02.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}
@@ -135,7 +135,7 @@ func Test_crash01(t *testing.T) {
cfg := config(ctx).WithArgs("mptest", name, "crash01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}
@@ -150,7 +150,7 @@ func Test_multiwrite01(t *testing.T) {
cfg := config(ctx).WithArgs("mptest", name, "multiwrite01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}
@@ -163,7 +163,7 @@ func Test_config01_memory(t *testing.T) {
"--timeout", "1000")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}
@@ -180,7 +180,7 @@ func Test_multiwrite01_memory(t *testing.T) {
"--timeout", "1000")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
t.Fatal(err)
}
mod.Close(ctx)
}

View File

@@ -23,7 +23,7 @@ WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin"
-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-D_WASI_EMULATED_GETPID -lwasi-emulated-getpid
"$BINARYEN/wasm-opt" -g --strip -c -O3 \
"$BINARYEN/wasm-opt" -g --strip --strip-producers -c -O3 \
mptest.wasm -o mptest.tmp \
--enable-simd --enable-mutable-globals --enable-multivalue \
--enable-bulk-memory --enable-reference-types \

Some files were not shown because too many files have changed in this diff Show More