2023-01-13 18:02:32 +03:00
|
|
|
import db.sqlite
|
2022-11-09 20:57:06 +03:00
|
|
|
import rand
|
|
|
|
|
|
|
|
const (
|
|
|
|
max_file_name_len = 256
|
|
|
|
)
|
|
|
|
|
|
|
|
fn test_vfs_register() {
|
|
|
|
org_default_vfs := sqlite.get_default_vfs()?
|
|
|
|
|
|
|
|
assert org_default_vfs.zName != 0
|
|
|
|
|
|
|
|
vfs_name := 'sometest'
|
|
|
|
mut vfs_descr := &sqlite.Sqlite3_vfs{
|
|
|
|
zName: vfs_name.str
|
|
|
|
iVersion: 2
|
|
|
|
}
|
|
|
|
|
|
|
|
if _ := sqlite.get_vfs(vfs_name) {
|
|
|
|
panic('expected that vfs is not known')
|
|
|
|
}
|
|
|
|
|
2022-11-15 16:53:13 +03:00
|
|
|
vfs_descr.register_as_nondefault() or { panic('vfs register failed ${err}') }
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
sqlite.get_vfs(vfs_name)?
|
|
|
|
|
|
|
|
now_default_vfs := sqlite.get_default_vfs()?
|
|
|
|
|
|
|
|
assert now_default_vfs.zName == org_default_vfs.zName
|
|
|
|
|
2022-11-15 16:53:13 +03:00
|
|
|
vfs_descr.unregister() or { panic('vfs unregister failed ${err}') }
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
if _ := sqlite.get_vfs(vfs_name) {
|
|
|
|
panic('vfs supposedly unregistered yet somehow still foundable')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// minimal vfs based on example https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c
|
|
|
|
fn test_verify_vfs_is_actually_used() {
|
|
|
|
wrapped := sqlite.get_default_vfs()?
|
|
|
|
|
|
|
|
vfs_name := 'sometest'
|
|
|
|
mut vfs_state := &ExampleVfsState{
|
|
|
|
log: []string{cap: 100}
|
|
|
|
}
|
|
|
|
mut vfs_descr := &sqlite.Sqlite3_vfs{
|
|
|
|
iVersion: 2
|
|
|
|
szOsFile: int(sizeof(ExampleVfsOpenedFile))
|
|
|
|
mxPathname: max_file_name_len
|
|
|
|
zName: vfs_name.str
|
|
|
|
pAppData: vfs_state
|
|
|
|
xOpen: example_vfs_open
|
|
|
|
xDelete: example_vfs_delete
|
|
|
|
xAccess: example_vfs_access
|
|
|
|
xFullPathname: example_vfs_fullpathname
|
|
|
|
xDlOpen: wrapped.xDlOpen
|
|
|
|
xDlError: wrapped.xDlError
|
|
|
|
xDlSym: wrapped.xDlSym
|
|
|
|
xDlClose: wrapped.xDlClose
|
|
|
|
xRandomness: wrapped.xRandomness
|
|
|
|
xSleep: wrapped.xSleep
|
|
|
|
xCurrentTime: wrapped.xCurrentTime
|
|
|
|
xGetLastError: example_vfs_getlasterror
|
|
|
|
xCurrentTimeInt64: wrapped.xCurrentTimeInt64
|
|
|
|
}
|
|
|
|
|
|
|
|
vfs_descr.register_as_nondefault()?
|
|
|
|
|
|
|
|
// normally this would be written to disk
|
|
|
|
mut db := sqlite.connect_full('foo.db', [.readwrite, .create], vfs_name)!
|
|
|
|
assert ['fullpathname from=foo.db to=foo.db}', 'open temp?=false name=foo.db', 'read file=foo.db'] == vfs_state.log
|
|
|
|
vfs_state.log.clear()
|
|
|
|
|
|
|
|
db.close()!
|
|
|
|
assert ['close file=foo.db'] == vfs_state.log
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ExampleVfsState {
|
|
|
|
mut:
|
|
|
|
log []string
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ExampleVfsOpenedFile {
|
|
|
|
mut:
|
|
|
|
base sqlite.Sqlite3_file
|
|
|
|
name string
|
|
|
|
vfs_state &ExampleVfsState
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_vfsstate(t &sqlite.Sqlite3_vfs) &ExampleVfsState {
|
|
|
|
unsafe {
|
|
|
|
p := t.pAppData
|
|
|
|
if p == 0 {
|
|
|
|
assert false, 'p should not be 0'
|
|
|
|
}
|
|
|
|
return &ExampleVfsState(p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_vfsopenedfile(t &sqlite.Sqlite3_file) &ExampleVfsOpenedFile {
|
|
|
|
unsafe {
|
|
|
|
if t == 0 {
|
|
|
|
assert false, 't should not be 0'
|
|
|
|
}
|
|
|
|
return &ExampleVfsOpenedFile(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfs_fullpathname(vfs &sqlite.Sqlite3_vfs, input &char, size_of_output int, output &char) int {
|
|
|
|
println('fullpathname called')
|
|
|
|
|
|
|
|
mut vfs_state := to_vfsstate(vfs)
|
|
|
|
|
|
|
|
from := unsafe { cstring_to_vstring(input) }
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
vmemcpy(output, input, from.len)
|
|
|
|
output[from.len] = u8(0)
|
|
|
|
}
|
|
|
|
result := unsafe { cstring_to_vstring(output) }
|
|
|
|
|
2022-11-15 16:53:13 +03:00
|
|
|
vfs_state.log << 'fullpathname from=${from} to=${result}}'
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfs_access(vfs &sqlite.Sqlite3_vfs, zPath &char, flags int, pResOut &int) int {
|
|
|
|
println('access called')
|
|
|
|
mut vfs_state := &ExampleVfsState{}
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
assert 0 != vfs.pAppData
|
|
|
|
vfs_state = &ExampleVfsState(vfs.pAppData)
|
|
|
|
}
|
|
|
|
vfs_state.log << 'accessed'
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfs_open(vfs &sqlite.Sqlite3_vfs, file_name_or_null_for_tempfile &char, vfs_opened_file &sqlite.Sqlite3_file, in_flags int, out_flags &int) int {
|
|
|
|
println('open called')
|
|
|
|
|
|
|
|
mut is_temp := false
|
|
|
|
mut file_name := ''
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
if file_name_or_null_for_tempfile == nil {
|
|
|
|
is_temp = true
|
|
|
|
file_name = rand.uuid_v4()
|
|
|
|
} else {
|
|
|
|
file_name = cstring_to_vstring(file_name_or_null_for_tempfile)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mut vfs_state := to_vfsstate(vfs)
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
mut outp := to_vfsopenedfile(vfs_opened_file)
|
|
|
|
outp.base.pMethods = &sqlite.Sqlite3_io_methods{
|
|
|
|
iVersion: 1
|
|
|
|
xClose: example_vfsfile_close
|
|
|
|
xRead: example_vfsfile_read
|
|
|
|
xWrite: example_vfsfile_write
|
|
|
|
xTruncate: example_vfsfile_truncate
|
|
|
|
xSync: example_vfsfile_sync
|
|
|
|
xFileSize: example_vfsfile_size
|
|
|
|
xLock: example_vfsfile_lock
|
|
|
|
xUnlock: example_vfsfile_unlock
|
|
|
|
xCheckReservedLock: example_vfsfile_checkreservedlock
|
|
|
|
xFileControl: example_vfsfile_filecontrol
|
|
|
|
xSectorSize: example_vfsfile_sectorsize
|
|
|
|
xDeviceCharacteristics: example_vfsfile_devicecharacteristics
|
|
|
|
}
|
|
|
|
|
|
|
|
outp.name = file_name.clone()
|
|
|
|
outp.vfs_state = vfs_state
|
|
|
|
}
|
2022-11-15 16:53:13 +03:00
|
|
|
vfs_state.log << 'open temp?=${is_temp} name=${file_name}'
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_checkreservedlock(file &sqlite.Sqlite3_file, pResOut &int) int {
|
|
|
|
println('file checkreservedlock')
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
*pResOut = 0
|
|
|
|
}
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_filecontrol(file &sqlite.Sqlite3_file, op int, arg voidptr) int {
|
|
|
|
println('file filecontrol')
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_devicecharacteristics(file &sqlite.Sqlite3_file) int {
|
|
|
|
println('file devicecharacteristics')
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_size(file &sqlite.Sqlite3_file, result &i64) int {
|
|
|
|
println('file size')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_read(file &sqlite.Sqlite3_file, output voidptr, amount int, offset i64) int {
|
|
|
|
println('file read')
|
|
|
|
|
|
|
|
assert amount > 0
|
|
|
|
|
|
|
|
mut vfsfile := to_vfsopenedfile(file)
|
|
|
|
|
2022-11-15 16:53:13 +03:00
|
|
|
vfsfile.vfs_state.log << 'read file=${vfsfile.name}'
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
C.memset(output, 0, amount)
|
|
|
|
}
|
|
|
|
|
|
|
|
return sqlite.sqlite_ioerr_short_read
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_truncate(file &sqlite.Sqlite3_file, size i64) int {
|
|
|
|
println('file truncate')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_sectorsize(file &sqlite.Sqlite3_file) int {
|
|
|
|
println('file sectorsize')
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_sync(file &sqlite.Sqlite3_file, flags int) int {
|
|
|
|
println('file sync called')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_lock(file &sqlite.Sqlite3_file, elock int) int {
|
|
|
|
println('file lock called')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_unlock(file &sqlite.Sqlite3_file, elock int) int {
|
|
|
|
println('file unlock called')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_write(file &sqlite.Sqlite3_file, buf voidptr, amount int, offset i64) int {
|
|
|
|
println('file write called')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfsfile_close(file &sqlite.Sqlite3_file) int {
|
|
|
|
println('file close called')
|
|
|
|
|
|
|
|
mut vfsfile := to_vfsopenedfile(file)
|
|
|
|
|
2022-11-15 16:53:13 +03:00
|
|
|
vfsfile.vfs_state.log << 'close file=${vfsfile.name}'
|
2022-11-09 20:57:06 +03:00
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfs_delete(vfs &sqlite.Sqlite3_vfs, name &char, sync_dir int) int {
|
|
|
|
println('vfs delete called')
|
|
|
|
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|
|
|
|
|
|
|
|
fn example_vfs_getlasterror(vfs &sqlite.Sqlite3_vfs, i int, o &char) int {
|
|
|
|
println('vfs getlasterror called')
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
*o = 0
|
|
|
|
}
|
|
|
|
return sqlite.sqlite_ok
|
|
|
|
}
|