Remove misc/sqlite directory. Old experiment.

Change-Id: I207c96dc77221fddeebb8ecdf1bc61c15269ef16
This commit is contained in:
Brad Fitzpatrick 2013-07-05 09:55:11 -07:00
parent d065aac5b7
commit f7707d75c1
10 changed files with 0 additions and 136009 deletions

View File

@ -1 +0,0 @@
foo.db*

View File

@ -1,13 +0,0 @@
include $(GOROOT)/src/Make.inc
TARG=camdev/sqlite
CGOFILES=\
vfs.go\
sqlite.go\
CGO_OFILES=\
sqlite3_obj.o\
vfs.o\
include $(GOROOT)/src/Make.pkg

View File

@ -1,13 +0,0 @@
#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
# define __USE_MINGW_ANSI_STDIO 0
# include <stdio.h>
#elif defined(__unix__)
# define SQLITE_OS_OTHER 1
#else
# error Unsupported OS
#endif
#ifndef INCLUDE_SQLITE_VERSION_SYMBOL
#define SKIP_SQLITE_VERSION
#endif
#include "sqlite3.h"

View File

@ -1,297 +0,0 @@
package sqlite
/*
#cgo linux CFLAGS: -D_GNU_SOURCE -D_XOPEN_SOURCE=500
#cgo linux LDFLAGS: -lpthread
#cgo windows CFLAGS: -D_GNU_SOURCE
#cgo windows LDFLAGS: -lpthread -lgcc_s -lmingwex -lmsvcrt
#include "go-sqlite.h"
#include <stdlib.h>
static int my_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
}
static int my_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
}
extern int go_init_vfs();
*/
import "C"
import (
"fmt"
"os"
"reflect"
"strconv"
"unsafe"
)
func init() {
C.go_init_vfs()
}
type Errno int
func (e Errno) String() string {
s := errText[e]
if s == "" {
return fmt.Sprintf("errno %d", e)
}
return s
}
var (
ErrError os.Error = Errno(1) // /* SQL error or missing database */
ErrInternal os.Error = Errno(2) // /* Internal logic error in SQLite */
ErrPerm os.Error = Errno(3) // /* Access permission denied */
ErrAbort os.Error = Errno(4) // /* Callback routine requested an abort */
ErrBusy os.Error = Errno(5) // /* The database file is locked */
ErrLocked os.Error = Errno(6) // /* A table in the database is locked */
ErrNoMem os.Error = Errno(7) // /* A malloc() failed */
ErrReadOnly os.Error = Errno(8) // /* Attempt to write a readonly database */
ErrInterrupt os.Error = Errno(9) // /* Operation terminated by sqlite3_interrupt()*/
ErrIOErr os.Error = Errno(10) // /* Some kind of disk I/O error occurred */
ErrCorrupt os.Error = Errno(11) // /* The database disk image is malformed */
ErrFull os.Error = Errno(13) // /* Insertion failed because database is full */
ErrCantOpen os.Error = Errno(14) // /* Unable to open the database file */
ErrEmpty os.Error = Errno(16) // /* Database is empty */
ErrSchema os.Error = Errno(17) // /* The database schema changed */
ErrTooBig os.Error = Errno(18) // /* String or BLOB exceeds size limit */
ErrConstraint os.Error = Errno(19) // /* Abort due to constraint violation */
ErrMismatch os.Error = Errno(20) // /* Data type mismatch */
ErrMisuse os.Error = Errno(21) // /* Library used incorrectly */
ErrNolfs os.Error = Errno(22) // /* Uses OS features not supported on host */
ErrAuth os.Error = Errno(23) // /* Authorization denied */
ErrFormat os.Error = Errno(24) // /* Auxiliary database format error */
ErrRange os.Error = Errno(25) // /* 2nd parameter to sqlite3_bind out of range */
ErrNotDB os.Error = Errno(26) // /* File opened that is not a database file */
Row = Errno(100) // /* sqlite3_step() has another row ready */
Done = Errno(101) // /* sqlite3_step() has finished executing */
)
var errText = map[Errno]string{
1: "SQL error or missing database",
2: "Internal logic error in SQLite",
3: "Access permission denied",
4: "Callback routine requested an abort",
5: "The database file is locked",
6: "A table in the database is locked",
7: "A malloc() failed",
8: "Attempt to write a readonly database",
9: "Operation terminated by sqlite3_interrupt()*/",
10: "Some kind of disk I/O error occurred",
11: "The database disk image is malformed",
12: "NOT USED. Table or record not found",
13: "Insertion failed because database is full",
14: "Unable to open the database file",
15: "NOT USED. Database lock protocol error",
16: "Database is empty",
17: "The database schema changed",
18: "String or BLOB exceeds size limit",
19: "Abort due to constraint violation",
20: "Data type mismatch",
21: "Library used incorrectly",
22: "Uses OS features not supported on host",
23: "Authorization denied",
24: "Auxiliary database format error",
25: "2nd parameter to sqlite3_bind out of range",
26: "File opened that is not a database file",
100: "sqlite3_step() has another row ready",
101: "sqlite3_step() has finished executing",
}
func (c *Conn) error(rv C.int) os.Error {
if rv == 21 { // misuse
return Errno(rv)
}
return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
}
type Conn struct {
db *C.sqlite3
}
func Version() string {
p := C.sqlite3_libversion()
return C.GoString(p)
}
func Open(filename string) (*Conn, os.Error) {
var db *C.sqlite3
name := C.CString(filename)
defer C.free(unsafe.Pointer(name))
rv := C.sqlite3_open(name, &db)
if rv != 0 {
return nil, Errno(rv)
}
if db == nil {
return nil, os.NewError("sqlite succeeded without returning a database")
}
return &Conn{db}, nil
}
func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
s, err := c.Prepare(cmd)
if err != nil {
return err
}
defer s.Finalize()
err = s.Exec(args...)
if err != nil {
return err
}
rv := C.sqlite3_step(s.stmt)
errno := Errno(rv)
if errno != Done {
return errno
}
return nil
}
type Stmt struct {
c *Conn
stmt *C.sqlite3_stmt
err os.Error
}
func (c *Conn) Prepare(cmd string) (*Stmt, os.Error) {
cmdstr := C.CString(cmd)
defer C.free(unsafe.Pointer(cmdstr))
var stmt *C.sqlite3_stmt
var tail *C.char
rv := C.sqlite3_prepare_v2(c.db, cmdstr, C.int(len(cmd)+1), &stmt, &tail)
if rv != 0 {
return nil, c.error(rv)
}
return &Stmt{c: c, stmt: stmt}, nil
}
func (s *Stmt) Exec(args ...interface{}) os.Error {
rv := C.sqlite3_reset(s.stmt)
if rv != 0 {
return s.c.error(rv)
}
n := int(C.sqlite3_bind_parameter_count(s.stmt))
if n != len(args) {
return os.NewError(fmt.Sprintf("incorrect argument count: have %d want %d", len(args), n))
}
for i, v := range args {
var str string
switch v := v.(type) {
case []byte:
var p *byte
if len(v) > 0 {
p = &v[0]
}
if rv := C.my_bind_blob(s.stmt, C.int(i+1), unsafe.Pointer(p), C.int(len(v))); rv != 0 {
return s.c.error(rv)
}
continue
case bool:
if v {
str = "1"
} else {
str = "0"
}
default:
str = fmt.Sprint(v)
}
cstr := C.CString(str)
rv := C.my_bind_text(s.stmt, C.int(i+1), cstr, C.int(len(str)))
C.free(unsafe.Pointer(cstr))
if rv != 0 {
return s.c.error(rv)
}
}
return nil
}
func (s *Stmt) Error() os.Error {
return s.err
}
func (s *Stmt) Next() bool {
rv := C.sqlite3_step(s.stmt)
err := Errno(rv)
if err == Row {
return true
}
if err != Done {
s.err = s.c.error(rv)
}
return false
}
func (s *Stmt) Scan(args ...interface{}) os.Error {
n := int(C.sqlite3_column_count(s.stmt))
if n != len(args) {
return os.NewError("incorrect argument count")
}
for i, v := range args {
n := C.sqlite3_column_bytes(s.stmt, C.int(i))
p := C.sqlite3_column_blob(s.stmt, C.int(i))
if p == nil && n > 0 {
return os.NewError("got nil blob")
}
var data []byte
if n > 0 {
data = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
}
switch v := v.(type) {
case *[]byte:
*v = data
case *string:
*v = string(data)
case *bool:
*v = string(data) == "1"
case *int:
x, err := strconv.Atoi(string(data))
if err != nil {
return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String())
}
*v = x
case *int64:
x, err := strconv.Atoi64(string(data))
if err != nil {
return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String())
}
*v = x
case *float64:
x, err := strconv.Atof64(string(data))
if err != nil {
return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String())
}
*v = x
default:
return os.NewError("unsupported type in Scan: " + reflect.TypeOf(v).String())
}
}
return nil
}
func (s *Stmt) Finalize() os.Error {
rv := C.sqlite3_finalize(s.stmt)
if rv != 0 {
return s.c.error(rv)
}
return nil
}
func (c *Conn) Close() os.Error {
rv := C.sqlite3_close(c.db)
if rv != 0 {
return c.error(rv)
}
return nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
#define INCLUDE_SQLITE_VERSION_SYMBOL
#include "go-sqlite.h"
#include "sqlite3.c"

View File

@ -1,48 +0,0 @@
package sqlite
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestFoo(t *testing.T) {
td, err := ioutil.TempDir("", "go-sqlite-test")
if err != nil {
t.Fatalf("TempDir: %v", err)
}
dbName := filepath.Join(td, "foo.db")
defer os.RemoveAll(td)
db, err := Open(dbName)
if err != nil {
t.Fatalf("open: %v", err)
}
err = db.Exec("CREATE TABLE IF NOT EXISTS foo (a INT, b VARCHAR(200))")
if err != nil {
t.Fatalf("create table: %v", err)
}
err = db.Exec("INSERT INTO foo VALUES (1, ?)", "foo")
if err != nil {
t.Fatalf("insert: %v", err)
}
err = db.Exec("INSERT INTO foo VALUES (2, DATETIME('now'))")
if err != nil {
t.Fatalf("insert: %v", err)
}
err = db.Close()
if err != nil {
t.Fatalf("close: %v", err)
}
fi, err := os.Stat(dbName)
if err != nil {
t.Fatalf("Stat: %v", err)
}
if fi.Size == 0 {
t.Fatalf("FileInfo.Size after writes was 0")
}
t.Logf("fi.Size = %d", fi.Size)
}

View File

@ -1,258 +0,0 @@
#include "go-sqlite.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "_cgo_export.h"
static sqlite3_io_methods g_file_methods;
typedef struct GoFile GoFile;
struct GoFile {
sqlite3_io_methods const *pMethod; /* Always the first entry */
int fd;
};
/* File methods */
static int go_file_close(sqlite3_file* file) {
GoFileClose(((GoFile*) file)->fd);
// Matching sqlite3's os_unix.c here.
memset(file, 0, sizeof(GoFile));
return SQLITE_OK;
}
static int go_file_read(sqlite3_file* file, void* dest, int iAmt, sqlite3_int64 iOfst) {
return GoFileRead(((GoFile*) file)->fd, dest, iAmt, iOfst);
}
static int go_file_write(sqlite3_file* file, const void* src, int iAmt, sqlite3_int64 iOfst) {
return GoFileWrite(((GoFile*) file)->fd, src, iAmt, iOfst);
}
static int go_file_truncate(sqlite3_file* file, sqlite3_int64 size) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_truncate(%d)\n", fd);
// TODO: implement
return SQLITE_OK;
}
static int go_file_sync(sqlite3_file* file, int flags) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_sync(%d)\n", fd);
// TODO: implement
return SQLITE_OK;
}
static int go_file_file_size(sqlite3_file* file, sqlite3_int64* pSize) {
const int fd = ((GoFile*) file)->fd;
struct GoFileFileSize_return result = GoFileFileSize(fd);
fprintf(stderr, "go_file_file_size(%d) = %d, %lld\n", fd, result.r0, result.r1);
if (result.r0 != 0) {
return SQLITE_ERROR;
}
*pSize = result.r1;
return SQLITE_OK;
}
static int go_file_lock(sqlite3_file* file, int flags) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_lock(%d)\n", fd);
// TODO: implement
return SQLITE_OK;
}
static int go_file_unlock(sqlite3_file* file, int flags) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_unlock(%d)\n", fd);
// TODO: implement
return SQLITE_OK;
}
static int go_file_check_reserved_lock(sqlite3_file* file, int* pResOut) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_check_reserved_lock(%d)\n", fd);
// TODO: implement
return SQLITE_OK;
}
static int go_file_file_control(sqlite3_file* file, int op, void* pArg) {
const int fd = ((GoFile*) file)->fd;
fprintf(stderr, "TODO go_file_file_control(%d, %d)\n", fd, op);
// TODO: implement
return SQLITE_OK;
}
static int go_file_sector_size(sqlite3_file* file) {
// Matching sqlite3's os_unix.c here; this is SQLITE_DEFAULT_SECTOR_SIZE.
return 512;
}
static int go_file_device_characteristics(sqlite3_file* file) {
// Matching sqlite3's os_unix.c here.
return 0;
}
/* VFS methods */
static int go_vfs_open(sqlite3_vfs* vfs,
const char* zName,
sqlite3_file* file,
int flags,
int* pOutFlags) {
fprintf(stderr, "go_vfs_open: %s\n", zName);
GoFile* go_file = (GoFile*) file;
memset(go_file, 0, sizeof(go_file));
const int fd = GoVFSOpen((char*) zName, flags);
if (fd == -1) {
return SQLITE_ERROR;
}
go_file->pMethod = &g_file_methods;
go_file->fd = fd;
return SQLITE_OK;
}
static int go_vfs_delete(sqlite3_vfs* vfs, const char* zName, int syncDir) {
return GoVFSDelete(zName, syncDir);
}
static int go_vfs_access(sqlite3_vfs* vfs,
const char* zName,
int flags,
int* pResOut) {
*pResOut = GoVFSAccess(zName, flags);
return SQLITE_OK;
}
static int go_vfs_full_pathname(sqlite3_vfs* vfs,
const char* zName,
int nOut,
char* zOut) {
fprintf(stderr, "TODO go_vfs_full_pathname: %s\n", zName);
// TODO: Actually implement this.
strncpy(zOut, zName, nOut);
zOut[nOut - 1] = '\0';
return SQLITE_OK;
}
static void* go_vfs_dl_open(sqlite3_vfs* vfs, const char* zFilename) {
fprintf(stderr, "TODO go_vfs_dl_open\n");
return NULL;
}
static void go_vfs_dl_error(sqlite3_vfs* vfs, int nByte, char *zErrMsg) {
fprintf(stderr, "TODO go_vfs_dl_error\n");
}
static void* go_vfs_dl_sym(sqlite3_vfs* vfs,
void* handle,
const char* zSymbol) {
fprintf(stderr, "TODO go_vfs_dl_sym\n");
return NULL;
}
static void go_vfs_dl_close(sqlite3_vfs* vfs, void* handle) {
fprintf(stderr, "TODO go_vfs_dl_close\n");
}
static int go_vfs_randomness(sqlite3_vfs* vfs, int nByte, char *zOut) {
fprintf(stderr, "TODO go_vfs_randomness\n");
return SQLITE_OK;
}
static int go_vfs_sleep(sqlite3_vfs* vfs, int microseconds) {
fprintf(stderr, "TODO go_vfs_sleep\n");
return SQLITE_OK;
}
static int go_vfs_current_time(sqlite3_vfs* vfs, double* now) {
*now = GoVFSCurrentTimeInt64() / 86400000.0;
return SQLITE_OK;
}
static int go_vfs_get_last_error(sqlite3_vfs* vfs, int foo, char* bar) {
// Unused, per sqlite3's os_unix.c.
return SQLITE_OK;
}
static int go_vfs_current_time_int64(sqlite3_vfs* vfs, sqlite3_int64* now) {
*now = GoVFSCurrentTimeInt64();
return SQLITE_OK;
}
int go_init_vfs(void) {
static sqlite3_vfs vfs;
memset(&vfs, 0, sizeof(vfs));
vfs.iVersion = 2;
vfs.szOsFile = sizeof(GoFile);
vfs.mxPathname = 512;
vfs.pNext = NULL;
vfs.zName = "go";
vfs.pAppData = NULL;
/* Version 1 methods */
vfs.xOpen = go_vfs_open;
vfs.xDelete = go_vfs_delete;
vfs.xAccess = go_vfs_access;
vfs.xFullPathname = go_vfs_full_pathname;
vfs.xDlOpen = go_vfs_dl_open;
vfs.xDlError = go_vfs_dl_error;
vfs.xDlSym = go_vfs_dl_sym;
vfs.xDlClose = go_vfs_dl_close;
vfs.xRandomness = go_vfs_randomness;
vfs.xSleep = go_vfs_sleep;
vfs.xCurrentTime = go_vfs_current_time;
vfs.xGetLastError = go_vfs_get_last_error;
/* Version 2 method */
vfs.xCurrentTimeInt64 = go_vfs_current_time_int64;
#if 0
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
** Those below are for version 3 and greater.
*/
int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
/*
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
** New fields may be appended in figure versions. The iVersion
** value will increment whenever this happens.
*/
};
#endif
sqlite3_vfs_register(&vfs, 1);
memset(&g_file_methods, 0, sizeof(g_file_methods));
g_file_methods.iVersion = 1;
g_file_methods.xClose = go_file_close;
g_file_methods.xRead = go_file_read;
g_file_methods.xWrite = go_file_write;
g_file_methods.xTruncate = go_file_truncate;
g_file_methods.xSync = go_file_sync;
g_file_methods.xFileSize = go_file_file_size;
g_file_methods.xLock = go_file_lock;
g_file_methods.xUnlock = go_file_unlock;
g_file_methods.xCheckReservedLock = go_file_check_reserved_lock;
g_file_methods.xFileControl = go_file_file_control;
g_file_methods.xSectorSize = go_file_sector_size;
g_file_methods.xDeviceCharacteristics = go_file_device_characteristics;
#if 0
/* Methods above are valid for version 1 */
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
void (*xShmBarrier)(sqlite3_file*);
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
/* Methods above are valid for version 2 */
/* Additional methods may be added in future releases */
#endif
return SQLITE_OK;
}
#if SQLITE_OS_OTHER==1
int sqlite3_os_init(void) { return SQLITE_OK; }
int sqlite3_os_end(void) { return SQLITE_OK; }
#endif

View File

@ -1,224 +0,0 @@
package sqlite
/*
#include <string.h>
#define SKIP_SQLITE_VERSION
#include "sqlite3.h"
*/
import "C"
import (
"io"
"os"
"sync"
"time"
"unsafe"
)
// Our map of fake fds to our internal *os.File. These aren't
// actual fd numbers, since those don't exist on Windows.
// Instead we just make some identifiers up.
var fmu sync.Mutex
var fileMap = make(map[int]*os.File) // fake_fd -> *os.File
var lastFakeFd = 99000 // start high to catch bugs of people using these like real fds
func GetFile(fd int) (file *os.File) {
fmu.Lock()
defer fmu.Unlock()
return fileMap[fd]
}
//export GoFileClose
// Returns 0 on success and -1 on error.
func GoFileClose(fd C.int) int {
file := GetFile(int(fd))
fmu.Lock()
fileMap[int(fd)] = nil, false
fmu.Unlock()
if file.Close() != nil {
return -1
}
return 0
}
//export GoFileRead
// Returns SQLite error code to be returned by xRead:
// SQLITE_OK: read n bytes
// SQLITE_IOERR_READ: got error while reading
// SQLITE_IOERR_SHORT_READ: read fewer than n bytes; rest will be zeroed
func GoFileRead(fd C.int, dst *C.char, n C.int, offset C.long) (rv int) {
println("reading", n, "bytes at offset", offset, "from fd", fd)
defer func() {
println("read returning", rv)
}()
file := GetFile(int(fd))
if file == nil {
return C.SQLITE_IOERR_READ
}
buf := make([]byte, n)
curbuf := buf
for n > 0 {
read, err := file.ReadAt(curbuf, int64(offset))
curbuf = curbuf[read:]
n -= C.int(read)
if err == io.EOF {
break
}
if err != nil {
return C.SQLITE_IOERR_READ
}
}
C.memcpy(unsafe.Pointer(dst), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n != 0 {
return C.SQLITE_IOERR_SHORT_READ
}
return C.SQLITE_OK
}
//export GoFileWrite
// Returns SQLite error code to be returned by xWrite:
// SQLITE_OK: wrote n bytes
// SQLITE_IOERR_WRITE: got error while writing
// SQLITE_FULL: partial write
func GoFileWrite(fd C.int, src *C.char, n C.int, offset C.long) (rv int) {
println("writing", n, "bytes at offset", offset, "to fd", fd)
defer func() {
println("write returning", rv)
}()
file := GetFile(int(fd))
if file == nil {
return C.SQLITE_IOERR_WRITE
}
// TODO: avoid this copy
buf := make([]byte, n)
C.memcpy(unsafe.Pointer(&buf[0]), unsafe.Pointer(src), C.size_t(len(buf)))
nwritten, err := file.WriteAt(buf, int64(offset))
if err != nil {
if err == os.ENOSPC {
return C.SQLITE_FULL
}
return C.SQLITE_IOERR_WRITE
}
if nwritten != int(n) {
return C.SQLITE_IOERR_WRITE
}
return C.SQLITE_OK
}
//export GoFileFileSize
// return[0]: 0 on success and -1 on error.
// return[1]: size
func GoFileFileSize(fd C.int) (rv int, size C.long) {
println("getting file size for fd", fd)
defer func() {
println("returning", rv, "with size", size)
}()
file := GetFile(int(fd))
if file == nil {
return -1, 0
}
info, err := file.Stat()
if err != nil {
return -1, 0
}
return 0, C.long(info.Size)
}
//export GoVFSOpen
// fd is -1 on error.
func GoVFSOpen(filename *C.char, flags C.int) (fd int) {
println("opening", C.GoString(filename), "with flags", int(flags))
goflags := 0
if flags&C.SQLITE_OPEN_READONLY != 0 {
goflags |= os.O_RDONLY
}
if flags&C.SQLITE_OPEN_READWRITE != 0 {
goflags |= os.O_RDWR
}
if flags&C.SQLITE_OPEN_CREATE != 0 {
goflags |= os.O_RDWR | os.O_CREATE
}
if flags&C.SQLITE_OPEN_DELETEONCLOSE != 0 {
// TODO: Do something.
}
if flags&C.SQLITE_OPEN_EXCLUSIVE != 0 {
goflags |= os.O_EXCL
}
file, err := os.OpenFile(C.GoString(filename), goflags, 0666)
defer func() {
if err != nil {
println("got error:", err.String())
}
println("returning fd", fd)
}()
if err != nil {
return -1
}
fmu.Lock()
defer fmu.Unlock()
fakeFd := lastFakeFd
lastFakeFd++
fileMap[fakeFd] = file
return fakeFd
}
//export GoVFSDelete
// Returns SQLite error code to be returned by xWrite:
// SQLITE_OK: deleted the file
// SQLITE_IOERR_DELETE: failed to delete
// SQLITE_IOERR_DIR_FSYNC: failed to fsync dir after deleting
func GoVFSDelete(filename *C.char, syncDir C.int) (rv int) {
println("deleting", C.GoString(filename), "with syncdir", syncDir)
if err := os.Remove(C.GoString(filename)); err != nil {
if os.IsNotExist(err) {
return C.SQLITE_OK
}
println("delete of", C.GoString(filename), "failed:", err.String())
return C.SQLITE_IOERR_DELETE
}
// TODO: Support syncDir.
return C.SQLITE_OK
}
//export GoVFSAccess
func GoVFSAccess(filename *C.char, flags C.int) (rv int) {
fi, err := os.Stat(C.GoString(filename))
if err != nil {
return 0
}
switch flags {
case C.SQLITE_ACCESS_EXISTS:
if fi.Size != 0 {
return 1
} else {
return 0
}
case C.SQLITE_ACCESS_READWRITE:
// TODO: compute read/writeability in a manner similar to access()
return 1
case C.SQLITE_ACCESS_READ:
return 1
}
return 0
}
//export GoVFSCurrentTimeInt64
func GoVFSCurrentTimeInt64() (now int64) {
// Unix epoch as a Julian Day number times 86_400_000.
const unixEpoch = 24405875 * 8640000
return unixEpoch + (time.Nanoseconds() / 1000000)
}