forked from mystiq/dex
Godeps: add sqlite3
This commit is contained in:
parent
cd72a1f69f
commit
8f16279f49
22 changed files with 157966 additions and 1 deletions
7
Godeps/Godeps.json
generated
7
Godeps/Godeps.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/dex",
|
"ImportPath": "github.com/coreos/dex",
|
||||||
"GoVersion": "go1.4.2",
|
"GoVersion": "go1.5",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
|
@ -91,6 +91,11 @@
|
||||||
"ImportPath": "github.com/mailgun/mailgun-go",
|
"ImportPath": "github.com/mailgun/mailgun-go",
|
||||||
"Rev": "9578dc67692294bb7e2a6f4b15dd18c97af19440"
|
"Rev": "9578dc67692294bb7e2a6f4b15dd18c97af19440"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/mattn/go-sqlite3",
|
||||||
|
"Comment": "v1.1.0-25-g2513631",
|
||||||
|
"Rev": "2513631704612107a1c8b1803fb8e6b3dda2230e"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mbanzon/simplehttp",
|
"ImportPath": "github.com/mbanzon/simplehttp",
|
||||||
"Rev": "04c542e7ac706a25820090f274ea6a4f39a63326"
|
"Rev": "04c542e7ac706a25820090f274ea6a4f39a63326"
|
||||||
|
|
3
Godeps/_workspace/src/github.com/mattn/go-sqlite3/.gitignore
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/mattn/go-sqlite3/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
*.db
|
||||||
|
*.exe
|
||||||
|
*.dll
|
9
Godeps/_workspace/src/github.com/mattn/go-sqlite3/.travis.yml
generated
vendored
Normal file
9
Godeps/_workspace/src/github.com/mattn/go-sqlite3/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- tip
|
||||||
|
before_install:
|
||||||
|
- go get github.com/axw/gocov/gocov
|
||||||
|
- go get github.com/mattn/goveralls
|
||||||
|
- go get golang.org/x/tools/cmd/cover
|
||||||
|
script:
|
||||||
|
- $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx
|
21
Godeps/_workspace/src/github.com/mattn/go-sqlite3/LICENSE
generated
vendored
Normal file
21
Godeps/_workspace/src/github.com/mattn/go-sqlite3/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Yasuhiro Matsumoto
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
74
Godeps/_workspace/src/github.com/mattn/go-sqlite3/README.md
generated
vendored
Normal file
74
Godeps/_workspace/src/github.com/mattn/go-sqlite3/README.md
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
go-sqlite3
|
||||||
|
==========
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/mattn/go-sqlite3.png?branch=master)](https://travis-ci.org/mattn/go-sqlite3)
|
||||||
|
[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.png?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
sqlite3 driver conforming to the built-in database/sql interface
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
This package can be installed with the go get command:
|
||||||
|
|
||||||
|
go get github.com/mattn/go-sqlite3
|
||||||
|
|
||||||
|
_go-sqlite3_ is *cgo* package.
|
||||||
|
If you want to build your app using go-sqlite3, you need gcc.
|
||||||
|
However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite`, you don't need gcc to build your app anymore.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3
|
||||||
|
|
||||||
|
Examples can be found under the `./_example` directory
|
||||||
|
|
||||||
|
FAQ
|
||||||
|
---
|
||||||
|
|
||||||
|
* Want to build go-sqlite3 with libsqlite3 on my linux.
|
||||||
|
|
||||||
|
Use `go build --tags "libsqlite3 linux"`
|
||||||
|
|
||||||
|
* Want to build go-sqlite3 with icu extension.
|
||||||
|
|
||||||
|
Use `go build --tags "icu"`
|
||||||
|
|
||||||
|
* Can't build go-sqlite3 on windows 64bit.
|
||||||
|
|
||||||
|
> Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
|
||||||
|
> See: https://github.com/mattn/go-sqlite3/issues/27
|
||||||
|
|
||||||
|
* Getting insert error while query is opened.
|
||||||
|
|
||||||
|
> You can pass some arguments into the connection string, for example, a URI.
|
||||||
|
> See: https://github.com/mattn/go-sqlite3/issues/39
|
||||||
|
|
||||||
|
* Do you want cross compiling? mingw on Linux or Mac?
|
||||||
|
|
||||||
|
> See: https://github.com/mattn/go-sqlite3/issues/106
|
||||||
|
> See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
|
||||||
|
|
||||||
|
* Want to get time.Time with current locale
|
||||||
|
|
||||||
|
Use `loc=auto` in SQLite3 filename schema like `file:foo.db?loc=auto`.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
MIT: http://mattn.mit-license.org/2012
|
||||||
|
|
||||||
|
sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h
|
||||||
|
|
||||||
|
The -binding suffix was added to avoid build failures under gccgo.
|
||||||
|
|
||||||
|
In this repository, those files are amalgamation code that copied from SQLite3. The license of those codes are depend on the license of SQLite3.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
|
||||||
|
Yasuhiro Matsumoto (a.k.a mattn)
|
70
Godeps/_workspace/src/github.com/mattn/go-sqlite3/backup.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/mattn/go-sqlite3/backup.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SQLiteBackup struct {
|
||||||
|
b *C.sqlite3_backup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) {
|
||||||
|
destptr := C.CString(dest)
|
||||||
|
defer C.free(unsafe.Pointer(destptr))
|
||||||
|
srcptr := C.CString(src)
|
||||||
|
defer C.free(unsafe.Pointer(srcptr))
|
||||||
|
|
||||||
|
if b := C.sqlite3_backup_init(c.db, destptr, conn.db, srcptr); b != nil {
|
||||||
|
bb := &SQLiteBackup{b: b}
|
||||||
|
runtime.SetFinalizer(bb, (*SQLiteBackup).Finish)
|
||||||
|
return bb, nil
|
||||||
|
}
|
||||||
|
return nil, c.lastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backs up for one step. Calls the underlying `sqlite3_backup_step` function.
|
||||||
|
// This function returns a boolean indicating if the backup is done and
|
||||||
|
// an error signalling any other error. Done is returned if the underlying C
|
||||||
|
// function returns SQLITE_DONE (Code 101)
|
||||||
|
func (b *SQLiteBackup) Step(p int) (bool, error) {
|
||||||
|
ret := C.sqlite3_backup_step(b.b, C.int(p))
|
||||||
|
if ret == C.SQLITE_DONE {
|
||||||
|
return true, nil
|
||||||
|
} else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY {
|
||||||
|
return false, Error{Code: ErrNo(ret)}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *SQLiteBackup) Remaining() int {
|
||||||
|
return int(C.sqlite3_backup_remaining(b.b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *SQLiteBackup) PageCount() int {
|
||||||
|
return int(C.sqlite3_backup_pagecount(b.b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *SQLiteBackup) Finish() error {
|
||||||
|
return b.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *SQLiteBackup) Close() error {
|
||||||
|
ret := C.sqlite3_backup_finish(b.b)
|
||||||
|
if ret != 0 {
|
||||||
|
return Error{Code: ErrNo(ret)}
|
||||||
|
}
|
||||||
|
b.b = nil
|
||||||
|
runtime.SetFinalizer(b, nil)
|
||||||
|
return nil
|
||||||
|
}
|
290
Godeps/_workspace/src/github.com/mattn/go-sqlite3/callback.go
generated
vendored
Normal file
290
Godeps/_workspace/src/github.com/mattn/go-sqlite3/callback.go
generated
vendored
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
// You can't export a Go function to C and have definitions in the C
|
||||||
|
// preamble in the same file, so we have to have callbackTrampoline in
|
||||||
|
// its own file. Because we need a separate file anyway, the support
|
||||||
|
// code for SQLite custom functions is in here.
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
|
||||||
|
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//export callbackTrampoline
|
||||||
|
func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
|
||||||
|
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
||||||
|
fi := (*functionInfo)(unsafe.Pointer(C.sqlite3_user_data(ctx)))
|
||||||
|
fi.Call(ctx, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export stepTrampoline
|
||||||
|
func stepTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
|
||||||
|
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
||||||
|
ai := (*aggInfo)(unsafe.Pointer(C.sqlite3_user_data(ctx)))
|
||||||
|
ai.Step(ctx, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export doneTrampoline
|
||||||
|
func doneTrampoline(ctx *C.sqlite3_context) {
|
||||||
|
ai := (*aggInfo)(unsafe.Pointer(C.sqlite3_user_data(ctx)))
|
||||||
|
ai.Done(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is only here so that tests can refer to it.
|
||||||
|
type callbackArgRaw C.sqlite3_value
|
||||||
|
|
||||||
|
type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
|
||||||
|
|
||||||
|
type callbackArgCast struct {
|
||||||
|
f callbackArgConverter
|
||||||
|
typ reflect.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
val, err := c.f(v)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, err
|
||||||
|
}
|
||||||
|
if !val.Type().ConvertibleTo(c.typ) {
|
||||||
|
return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
|
||||||
|
}
|
||||||
|
return val.Convert(c.typ), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
|
||||||
|
return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
|
||||||
|
return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
|
||||||
|
}
|
||||||
|
i := int64(C.sqlite3_value_int64(v))
|
||||||
|
val := false
|
||||||
|
if i != 0 {
|
||||||
|
val = true
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(val), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
|
||||||
|
return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
switch C.sqlite3_value_type(v) {
|
||||||
|
case C.SQLITE_BLOB:
|
||||||
|
l := C.sqlite3_value_bytes(v)
|
||||||
|
p := C.sqlite3_value_blob(v)
|
||||||
|
return reflect.ValueOf(C.GoBytes(p, l)), nil
|
||||||
|
case C.SQLITE_TEXT:
|
||||||
|
l := C.sqlite3_value_bytes(v)
|
||||||
|
c := unsafe.Pointer(C.sqlite3_value_text(v))
|
||||||
|
return reflect.ValueOf(C.GoBytes(c, l)), nil
|
||||||
|
default:
|
||||||
|
return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
switch C.sqlite3_value_type(v) {
|
||||||
|
case C.SQLITE_BLOB:
|
||||||
|
l := C.sqlite3_value_bytes(v)
|
||||||
|
p := (*C.char)(C.sqlite3_value_blob(v))
|
||||||
|
return reflect.ValueOf(C.GoStringN(p, l)), nil
|
||||||
|
case C.SQLITE_TEXT:
|
||||||
|
c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
|
||||||
|
return reflect.ValueOf(C.GoString(c)), nil
|
||||||
|
default:
|
||||||
|
return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
switch C.sqlite3_value_type(v) {
|
||||||
|
case C.SQLITE_INTEGER:
|
||||||
|
return callbackArgInt64(v)
|
||||||
|
case C.SQLITE_FLOAT:
|
||||||
|
return callbackArgFloat64(v)
|
||||||
|
case C.SQLITE_TEXT:
|
||||||
|
return callbackArgString(v)
|
||||||
|
case C.SQLITE_BLOB:
|
||||||
|
return callbackArgBytes(v)
|
||||||
|
case C.SQLITE_NULL:
|
||||||
|
// Interpret NULL as a nil byte slice.
|
||||||
|
var ret []byte
|
||||||
|
return reflect.ValueOf(ret), nil
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
|
if typ.NumMethod() != 0 {
|
||||||
|
return nil, errors.New("the only supported interface type is interface{}")
|
||||||
|
}
|
||||||
|
return callbackArgGeneric, nil
|
||||||
|
case reflect.Slice:
|
||||||
|
if typ.Elem().Kind() != reflect.Uint8 {
|
||||||
|
return nil, errors.New("the only supported slice type is []byte")
|
||||||
|
}
|
||||||
|
return callbackArgBytes, nil
|
||||||
|
case reflect.String:
|
||||||
|
return callbackArgString, nil
|
||||||
|
case reflect.Bool:
|
||||||
|
return callbackArgBool, nil
|
||||||
|
case reflect.Int64:
|
||||||
|
return callbackArgInt64, nil
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
||||||
|
c := callbackArgCast{callbackArgInt64, typ}
|
||||||
|
return c.Run, nil
|
||||||
|
case reflect.Float64:
|
||||||
|
return callbackArgFloat64, nil
|
||||||
|
case reflect.Float32:
|
||||||
|
c := callbackArgCast{callbackArgFloat64, typ}
|
||||||
|
return c.Run, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("don't know how to convert to %s", typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) {
|
||||||
|
var args []reflect.Value
|
||||||
|
|
||||||
|
if len(argv) < len(converters) {
|
||||||
|
return nil, fmt.Errorf("function requires at least %d arguments", len(converters))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, arg := range argv[:len(converters)] {
|
||||||
|
v, err := converters[i](arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args = append(args, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if variadic != nil {
|
||||||
|
for _, arg := range argv[len(converters):] {
|
||||||
|
v, err := variadic(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args = append(args, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
|
||||||
|
|
||||||
|
func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int64:
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
||||||
|
v = v.Convert(reflect.TypeOf(int64(0)))
|
||||||
|
case reflect.Bool:
|
||||||
|
b := v.Interface().(bool)
|
||||||
|
if b {
|
||||||
|
v = reflect.ValueOf(int64(1))
|
||||||
|
} else {
|
||||||
|
v = reflect.ValueOf(int64(0))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Float64:
|
||||||
|
case reflect.Float32:
|
||||||
|
v = v.Convert(reflect.TypeOf(float64(0)))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||||
|
if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
|
||||||
|
return fmt.Errorf("cannot convert %s to BLOB", v.Type())
|
||||||
|
}
|
||||||
|
i := v.Interface()
|
||||||
|
if i == nil || len(i.([]byte)) == 0 {
|
||||||
|
C.sqlite3_result_null(ctx)
|
||||||
|
} else {
|
||||||
|
bs := i.([]byte)
|
||||||
|
C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
|
||||||
|
if v.Type().Kind() != reflect.String {
|
||||||
|
return fmt.Errorf("cannot convert %s to TEXT", v.Type())
|
||||||
|
}
|
||||||
|
C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
if typ.Elem().Kind() != reflect.Uint8 {
|
||||||
|
return nil, errors.New("the only supported slice type is []byte")
|
||||||
|
}
|
||||||
|
return callbackRetBlob, nil
|
||||||
|
case reflect.String:
|
||||||
|
return callbackRetText, nil
|
||||||
|
case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
||||||
|
return callbackRetInteger, nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return callbackRetFloat, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("don't know how to convert to %s", typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func callbackError(ctx *C.sqlite3_context, err error) {
|
||||||
|
cstr := C.CString(err.Error())
|
||||||
|
defer C.free(unsafe.Pointer(cstr))
|
||||||
|
C.sqlite3_result_error(ctx, cstr, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test support code. Tests are not allowed to import "C", so we can't
|
||||||
|
// declare any functions that use C.sqlite3_value.
|
||||||
|
func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
|
||||||
|
return func(*C.sqlite3_value) (reflect.Value, error) {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
}
|
147782
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3-binding.c
generated
vendored
Normal file
147782
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3-binding.c
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
7478
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3-binding.h
generated
vendored
Normal file
7478
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3-binding.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
487
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3ext.h
generated
vendored
Normal file
487
Godeps/_workspace/src/github.com/mattn/go-sqlite3/code/sqlite3ext.h
generated
vendored
Normal file
|
@ -0,0 +1,487 @@
|
||||||
|
/*
|
||||||
|
** 2006 June 7
|
||||||
|
**
|
||||||
|
** The author disclaims copyright to this source code. In place of
|
||||||
|
** a legal notice, here is a blessing:
|
||||||
|
**
|
||||||
|
** May you do good and not evil.
|
||||||
|
** May you find forgiveness for yourself and forgive others.
|
||||||
|
** May you share freely, never taking more than you give.
|
||||||
|
**
|
||||||
|
*************************************************************************
|
||||||
|
** This header file defines the SQLite interface for use by
|
||||||
|
** shared libraries that want to be imported as extensions into
|
||||||
|
** an SQLite instance. Shared libraries that intend to be loaded
|
||||||
|
** as extensions by SQLite should #include this file instead of
|
||||||
|
** sqlite3.h.
|
||||||
|
*/
|
||||||
|
#ifndef _SQLITE3EXT_H_
|
||||||
|
#define _SQLITE3EXT_H_
|
||||||
|
#include "sqlite3-binding.h"
|
||||||
|
|
||||||
|
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The following structure holds pointers to all of the SQLite API
|
||||||
|
** routines.
|
||||||
|
**
|
||||||
|
** WARNING: In order to maintain backwards compatibility, add new
|
||||||
|
** interfaces to the end of this structure only. If you insert new
|
||||||
|
** interfaces in the middle of this structure, then older different
|
||||||
|
** versions of SQLite will not be able to load each others' shared
|
||||||
|
** libraries!
|
||||||
|
*/
|
||||||
|
struct sqlite3_api_routines {
|
||||||
|
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
||||||
|
int (*aggregate_count)(sqlite3_context*);
|
||||||
|
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
||||||
|
int (*bind_double)(sqlite3_stmt*,int,double);
|
||||||
|
int (*bind_int)(sqlite3_stmt*,int,int);
|
||||||
|
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
||||||
|
int (*bind_null)(sqlite3_stmt*,int);
|
||||||
|
int (*bind_parameter_count)(sqlite3_stmt*);
|
||||||
|
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
||||||
|
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
||||||
|
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
||||||
|
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
||||||
|
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
||||||
|
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
||||||
|
int (*busy_timeout)(sqlite3*,int ms);
|
||||||
|
int (*changes)(sqlite3*);
|
||||||
|
int (*close)(sqlite3*);
|
||||||
|
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||||
|
int eTextRep,const char*));
|
||||||
|
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||||
|
int eTextRep,const void*));
|
||||||
|
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
||||||
|
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
||||||
|
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
||||||
|
int (*column_count)(sqlite3_stmt*pStmt);
|
||||||
|
const char * (*column_database_name)(sqlite3_stmt*,int);
|
||||||
|
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
||||||
|
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
||||||
|
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
||||||
|
double (*column_double)(sqlite3_stmt*,int iCol);
|
||||||
|
int (*column_int)(sqlite3_stmt*,int iCol);
|
||||||
|
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
||||||
|
const char * (*column_name)(sqlite3_stmt*,int);
|
||||||
|
const void * (*column_name16)(sqlite3_stmt*,int);
|
||||||
|
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
||||||
|
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
||||||
|
const char * (*column_table_name)(sqlite3_stmt*,int);
|
||||||
|
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
||||||
|
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
||||||
|
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
||||||
|
int (*column_type)(sqlite3_stmt*,int iCol);
|
||||||
|
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
||||||
|
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
||||||
|
int (*complete)(const char*sql);
|
||||||
|
int (*complete16)(const void*sql);
|
||||||
|
int (*create_collation)(sqlite3*,const char*,int,void*,
|
||||||
|
int(*)(void*,int,const void*,int,const void*));
|
||||||
|
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
||||||
|
int(*)(void*,int,const void*,int,const void*));
|
||||||
|
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
||||||
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*));
|
||||||
|
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
||||||
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*));
|
||||||
|
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
||||||
|
int (*data_count)(sqlite3_stmt*pStmt);
|
||||||
|
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
||||||
|
int (*declare_vtab)(sqlite3*,const char*);
|
||||||
|
int (*enable_shared_cache)(int);
|
||||||
|
int (*errcode)(sqlite3*db);
|
||||||
|
const char * (*errmsg)(sqlite3*);
|
||||||
|
const void * (*errmsg16)(sqlite3*);
|
||||||
|
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
||||||
|
int (*expired)(sqlite3_stmt*);
|
||||||
|
int (*finalize)(sqlite3_stmt*pStmt);
|
||||||
|
void (*free)(void*);
|
||||||
|
void (*free_table)(char**result);
|
||||||
|
int (*get_autocommit)(sqlite3*);
|
||||||
|
void * (*get_auxdata)(sqlite3_context*,int);
|
||||||
|
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
||||||
|
int (*global_recover)(void);
|
||||||
|
void (*interruptx)(sqlite3*);
|
||||||
|
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
||||||
|
const char * (*libversion)(void);
|
||||||
|
int (*libversion_number)(void);
|
||||||
|
void *(*malloc)(int);
|
||||||
|
char * (*mprintf)(const char*,...);
|
||||||
|
int (*open)(const char*,sqlite3**);
|
||||||
|
int (*open16)(const void*,sqlite3**);
|
||||||
|
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||||
|
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||||
|
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
||||||
|
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
||||||
|
void *(*realloc)(void*,int);
|
||||||
|
int (*reset)(sqlite3_stmt*pStmt);
|
||||||
|
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||||
|
void (*result_double)(sqlite3_context*,double);
|
||||||
|
void (*result_error)(sqlite3_context*,const char*,int);
|
||||||
|
void (*result_error16)(sqlite3_context*,const void*,int);
|
||||||
|
void (*result_int)(sqlite3_context*,int);
|
||||||
|
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
||||||
|
void (*result_null)(sqlite3_context*);
|
||||||
|
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
||||||
|
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||||
|
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||||
|
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||||
|
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
||||||
|
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
||||||
|
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||||
|
const char*,const char*),void*);
|
||||||
|
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||||
|
char * (*snprintf)(int,char*,const char*,...);
|
||||||
|
int (*step)(sqlite3_stmt*);
|
||||||
|
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||||
|
char const**,char const**,int*,int*,int*);
|
||||||
|
void (*thread_cleanup)(void);
|
||||||
|
int (*total_changes)(sqlite3*);
|
||||||
|
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
||||||
|
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
||||||
|
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
||||||
|
sqlite_int64),void*);
|
||||||
|
void * (*user_data)(sqlite3_context*);
|
||||||
|
const void * (*value_blob)(sqlite3_value*);
|
||||||
|
int (*value_bytes)(sqlite3_value*);
|
||||||
|
int (*value_bytes16)(sqlite3_value*);
|
||||||
|
double (*value_double)(sqlite3_value*);
|
||||||
|
int (*value_int)(sqlite3_value*);
|
||||||
|
sqlite_int64 (*value_int64)(sqlite3_value*);
|
||||||
|
int (*value_numeric_type)(sqlite3_value*);
|
||||||
|
const unsigned char * (*value_text)(sqlite3_value*);
|
||||||
|
const void * (*value_text16)(sqlite3_value*);
|
||||||
|
const void * (*value_text16be)(sqlite3_value*);
|
||||||
|
const void * (*value_text16le)(sqlite3_value*);
|
||||||
|
int (*value_type)(sqlite3_value*);
|
||||||
|
char *(*vmprintf)(const char*,va_list);
|
||||||
|
/* Added ??? */
|
||||||
|
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
||||||
|
/* Added by 3.3.13 */
|
||||||
|
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||||
|
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||||
|
int (*clear_bindings)(sqlite3_stmt*);
|
||||||
|
/* Added by 3.4.1 */
|
||||||
|
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
||||||
|
void (*xDestroy)(void *));
|
||||||
|
/* Added by 3.5.0 */
|
||||||
|
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
||||||
|
int (*blob_bytes)(sqlite3_blob*);
|
||||||
|
int (*blob_close)(sqlite3_blob*);
|
||||||
|
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
||||||
|
int,sqlite3_blob**);
|
||||||
|
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
||||||
|
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
||||||
|
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
||||||
|
int(*)(void*,int,const void*,int,const void*),
|
||||||
|
void(*)(void*));
|
||||||
|
int (*file_control)(sqlite3*,const char*,int,void*);
|
||||||
|
sqlite3_int64 (*memory_highwater)(int);
|
||||||
|
sqlite3_int64 (*memory_used)(void);
|
||||||
|
sqlite3_mutex *(*mutex_alloc)(int);
|
||||||
|
void (*mutex_enter)(sqlite3_mutex*);
|
||||||
|
void (*mutex_free)(sqlite3_mutex*);
|
||||||
|
void (*mutex_leave)(sqlite3_mutex*);
|
||||||
|
int (*mutex_try)(sqlite3_mutex*);
|
||||||
|
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
||||||
|
int (*release_memory)(int);
|
||||||
|
void (*result_error_nomem)(sqlite3_context*);
|
||||||
|
void (*result_error_toobig)(sqlite3_context*);
|
||||||
|
int (*sleep)(int);
|
||||||
|
void (*soft_heap_limit)(int);
|
||||||
|
sqlite3_vfs *(*vfs_find)(const char*);
|
||||||
|
int (*vfs_register)(sqlite3_vfs*,int);
|
||||||
|
int (*vfs_unregister)(sqlite3_vfs*);
|
||||||
|
int (*xthreadsafe)(void);
|
||||||
|
void (*result_zeroblob)(sqlite3_context*,int);
|
||||||
|
void (*result_error_code)(sqlite3_context*,int);
|
||||||
|
int (*test_control)(int, ...);
|
||||||
|
void (*randomness)(int,void*);
|
||||||
|
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
||||||
|
int (*extended_result_codes)(sqlite3*,int);
|
||||||
|
int (*limit)(sqlite3*,int,int);
|
||||||
|
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
||||||
|
const char *(*sql)(sqlite3_stmt*);
|
||||||
|
int (*status)(int,int*,int*,int);
|
||||||
|
int (*backup_finish)(sqlite3_backup*);
|
||||||
|
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
||||||
|
int (*backup_pagecount)(sqlite3_backup*);
|
||||||
|
int (*backup_remaining)(sqlite3_backup*);
|
||||||
|
int (*backup_step)(sqlite3_backup*,int);
|
||||||
|
const char *(*compileoption_get)(int);
|
||||||
|
int (*compileoption_used)(const char*);
|
||||||
|
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
||||||
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*),
|
||||||
|
void(*xDestroy)(void*));
|
||||||
|
int (*db_config)(sqlite3*,int,...);
|
||||||
|
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
||||||
|
int (*db_status)(sqlite3*,int,int*,int*,int);
|
||||||
|
int (*extended_errcode)(sqlite3*);
|
||||||
|
void (*log)(int,const char*,...);
|
||||||
|
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
||||||
|
const char *(*sourceid)(void);
|
||||||
|
int (*stmt_status)(sqlite3_stmt*,int,int);
|
||||||
|
int (*strnicmp)(const char*,const char*,int);
|
||||||
|
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
||||||
|
int (*wal_autocheckpoint)(sqlite3*,int);
|
||||||
|
int (*wal_checkpoint)(sqlite3*,const char*);
|
||||||
|
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
||||||
|
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||||
|
int (*vtab_config)(sqlite3*,int op,...);
|
||||||
|
int (*vtab_on_conflict)(sqlite3*);
|
||||||
|
/* Version 3.7.16 and later */
|
||||||
|
int (*close_v2)(sqlite3*);
|
||||||
|
const char *(*db_filename)(sqlite3*,const char*);
|
||||||
|
int (*db_readonly)(sqlite3*,const char*);
|
||||||
|
int (*db_release_memory)(sqlite3*);
|
||||||
|
const char *(*errstr)(int);
|
||||||
|
int (*stmt_busy)(sqlite3_stmt*);
|
||||||
|
int (*stmt_readonly)(sqlite3_stmt*);
|
||||||
|
int (*stricmp)(const char*,const char*);
|
||||||
|
int (*uri_boolean)(const char*,const char*,int);
|
||||||
|
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||||
|
const char *(*uri_parameter)(const char*,const char*);
|
||||||
|
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||||
|
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The following macros redefine the API routines so that they are
|
||||||
|
** redirected throught the global sqlite3_api structure.
|
||||||
|
**
|
||||||
|
** This header file is also used by the loadext.c source file
|
||||||
|
** (part of the main SQLite library - not an extension) so that
|
||||||
|
** it can get access to the sqlite3_api_routines structure
|
||||||
|
** definition. But the main library does not want to redefine
|
||||||
|
** the API. So the redefinition macros are only valid if the
|
||||||
|
** SQLITE_CORE macros is undefined.
|
||||||
|
*/
|
||||||
|
#ifndef SQLITE_CORE
|
||||||
|
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||||
|
#ifndef SQLITE_OMIT_DEPRECATED
|
||||||
|
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||||
|
#endif
|
||||||
|
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
||||||
|
#define sqlite3_bind_double sqlite3_api->bind_double
|
||||||
|
#define sqlite3_bind_int sqlite3_api->bind_int
|
||||||
|
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
||||||
|
#define sqlite3_bind_null sqlite3_api->bind_null
|
||||||
|
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
||||||
|
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
||||||
|
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
||||||
|
#define sqlite3_bind_text sqlite3_api->bind_text
|
||||||
|
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
||||||
|
#define sqlite3_bind_value sqlite3_api->bind_value
|
||||||
|
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
||||||
|
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
||||||
|
#define sqlite3_changes sqlite3_api->changes
|
||||||
|
#define sqlite3_close sqlite3_api->close
|
||||||
|
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
||||||
|
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
||||||
|
#define sqlite3_column_blob sqlite3_api->column_blob
|
||||||
|
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
||||||
|
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
||||||
|
#define sqlite3_column_count sqlite3_api->column_count
|
||||||
|
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
||||||
|
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
||||||
|
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
||||||
|
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
||||||
|
#define sqlite3_column_double sqlite3_api->column_double
|
||||||
|
#define sqlite3_column_int sqlite3_api->column_int
|
||||||
|
#define sqlite3_column_int64 sqlite3_api->column_int64
|
||||||
|
#define sqlite3_column_name sqlite3_api->column_name
|
||||||
|
#define sqlite3_column_name16 sqlite3_api->column_name16
|
||||||
|
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
||||||
|
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
||||||
|
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
||||||
|
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
||||||
|
#define sqlite3_column_text sqlite3_api->column_text
|
||||||
|
#define sqlite3_column_text16 sqlite3_api->column_text16
|
||||||
|
#define sqlite3_column_type sqlite3_api->column_type
|
||||||
|
#define sqlite3_column_value sqlite3_api->column_value
|
||||||
|
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
||||||
|
#define sqlite3_complete sqlite3_api->complete
|
||||||
|
#define sqlite3_complete16 sqlite3_api->complete16
|
||||||
|
#define sqlite3_create_collation sqlite3_api->create_collation
|
||||||
|
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
||||||
|
#define sqlite3_create_function sqlite3_api->create_function
|
||||||
|
#define sqlite3_create_function16 sqlite3_api->create_function16
|
||||||
|
#define sqlite3_create_module sqlite3_api->create_module
|
||||||
|
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
||||||
|
#define sqlite3_data_count sqlite3_api->data_count
|
||||||
|
#define sqlite3_db_handle sqlite3_api->db_handle
|
||||||
|
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
||||||
|
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
||||||
|
#define sqlite3_errcode sqlite3_api->errcode
|
||||||
|
#define sqlite3_errmsg sqlite3_api->errmsg
|
||||||
|
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
||||||
|
#define sqlite3_exec sqlite3_api->exec
|
||||||
|
#ifndef SQLITE_OMIT_DEPRECATED
|
||||||
|
#define sqlite3_expired sqlite3_api->expired
|
||||||
|
#endif
|
||||||
|
#define sqlite3_finalize sqlite3_api->finalize
|
||||||
|
#define sqlite3_free sqlite3_api->free
|
||||||
|
#define sqlite3_free_table sqlite3_api->free_table
|
||||||
|
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
||||||
|
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
||||||
|
#define sqlite3_get_table sqlite3_api->get_table
|
||||||
|
#ifndef SQLITE_OMIT_DEPRECATED
|
||||||
|
#define sqlite3_global_recover sqlite3_api->global_recover
|
||||||
|
#endif
|
||||||
|
#define sqlite3_interrupt sqlite3_api->interruptx
|
||||||
|
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
||||||
|
#define sqlite3_libversion sqlite3_api->libversion
|
||||||
|
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
||||||
|
#define sqlite3_malloc sqlite3_api->malloc
|
||||||
|
#define sqlite3_mprintf sqlite3_api->mprintf
|
||||||
|
#define sqlite3_open sqlite3_api->open
|
||||||
|
#define sqlite3_open16 sqlite3_api->open16
|
||||||
|
#define sqlite3_prepare sqlite3_api->prepare
|
||||||
|
#define sqlite3_prepare16 sqlite3_api->prepare16
|
||||||
|
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||||
|
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||||
|
#define sqlite3_profile sqlite3_api->profile
|
||||||
|
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
||||||
|
#define sqlite3_realloc sqlite3_api->realloc
|
||||||
|
#define sqlite3_reset sqlite3_api->reset
|
||||||
|
#define sqlite3_result_blob sqlite3_api->result_blob
|
||||||
|
#define sqlite3_result_double sqlite3_api->result_double
|
||||||
|
#define sqlite3_result_error sqlite3_api->result_error
|
||||||
|
#define sqlite3_result_error16 sqlite3_api->result_error16
|
||||||
|
#define sqlite3_result_int sqlite3_api->result_int
|
||||||
|
#define sqlite3_result_int64 sqlite3_api->result_int64
|
||||||
|
#define sqlite3_result_null sqlite3_api->result_null
|
||||||
|
#define sqlite3_result_text sqlite3_api->result_text
|
||||||
|
#define sqlite3_result_text16 sqlite3_api->result_text16
|
||||||
|
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
||||||
|
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
||||||
|
#define sqlite3_result_value sqlite3_api->result_value
|
||||||
|
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||||
|
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||||
|
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||||
|
#define sqlite3_snprintf sqlite3_api->snprintf
|
||||||
|
#define sqlite3_step sqlite3_api->step
|
||||||
|
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||||
|
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||||
|
#define sqlite3_total_changes sqlite3_api->total_changes
|
||||||
|
#define sqlite3_trace sqlite3_api->trace
|
||||||
|
#ifndef SQLITE_OMIT_DEPRECATED
|
||||||
|
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
||||||
|
#endif
|
||||||
|
#define sqlite3_update_hook sqlite3_api->update_hook
|
||||||
|
#define sqlite3_user_data sqlite3_api->user_data
|
||||||
|
#define sqlite3_value_blob sqlite3_api->value_blob
|
||||||
|
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
||||||
|
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
||||||
|
#define sqlite3_value_double sqlite3_api->value_double
|
||||||
|
#define sqlite3_value_int sqlite3_api->value_int
|
||||||
|
#define sqlite3_value_int64 sqlite3_api->value_int64
|
||||||
|
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
||||||
|
#define sqlite3_value_text sqlite3_api->value_text
|
||||||
|
#define sqlite3_value_text16 sqlite3_api->value_text16
|
||||||
|
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
||||||
|
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||||
|
#define sqlite3_value_type sqlite3_api->value_type
|
||||||
|
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||||
|
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||||
|
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||||
|
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||||
|
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
||||||
|
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
||||||
|
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
||||||
|
#define sqlite3_blob_close sqlite3_api->blob_close
|
||||||
|
#define sqlite3_blob_open sqlite3_api->blob_open
|
||||||
|
#define sqlite3_blob_read sqlite3_api->blob_read
|
||||||
|
#define sqlite3_blob_write sqlite3_api->blob_write
|
||||||
|
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
||||||
|
#define sqlite3_file_control sqlite3_api->file_control
|
||||||
|
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
||||||
|
#define sqlite3_memory_used sqlite3_api->memory_used
|
||||||
|
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
||||||
|
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
||||||
|
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
||||||
|
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
||||||
|
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
||||||
|
#define sqlite3_open_v2 sqlite3_api->open_v2
|
||||||
|
#define sqlite3_release_memory sqlite3_api->release_memory
|
||||||
|
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
||||||
|
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
||||||
|
#define sqlite3_sleep sqlite3_api->sleep
|
||||||
|
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
||||||
|
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
||||||
|
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
||||||
|
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
||||||
|
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
||||||
|
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
||||||
|
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
||||||
|
#define sqlite3_test_control sqlite3_api->test_control
|
||||||
|
#define sqlite3_randomness sqlite3_api->randomness
|
||||||
|
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
||||||
|
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
||||||
|
#define sqlite3_limit sqlite3_api->limit
|
||||||
|
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
||||||
|
#define sqlite3_sql sqlite3_api->sql
|
||||||
|
#define sqlite3_status sqlite3_api->status
|
||||||
|
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
||||||
|
#define sqlite3_backup_init sqlite3_api->backup_init
|
||||||
|
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
||||||
|
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
||||||
|
#define sqlite3_backup_step sqlite3_api->backup_step
|
||||||
|
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
||||||
|
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
||||||
|
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
||||||
|
#define sqlite3_db_config sqlite3_api->db_config
|
||||||
|
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
||||||
|
#define sqlite3_db_status sqlite3_api->db_status
|
||||||
|
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
||||||
|
#define sqlite3_log sqlite3_api->log
|
||||||
|
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
||||||
|
#define sqlite3_sourceid sqlite3_api->sourceid
|
||||||
|
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
||||||
|
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
||||||
|
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
||||||
|
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
||||||
|
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
||||||
|
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
||||||
|
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||||
|
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||||
|
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||||
|
/* Version 3.7.16 and later */
|
||||||
|
#define sqlite3_close_v2 sqlite3_api->close_v2
|
||||||
|
#define sqlite3_db_filename sqlite3_api->db_filename
|
||||||
|
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
||||||
|
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
||||||
|
#define sqlite3_errstr sqlite3_api->errstr
|
||||||
|
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
||||||
|
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
||||||
|
#define sqlite3_stricmp sqlite3_api->stricmp
|
||||||
|
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||||
|
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||||
|
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||||
|
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||||
|
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||||
|
#endif /* SQLITE_CORE */
|
||||||
|
|
||||||
|
#ifndef SQLITE_CORE
|
||||||
|
/* This case when the file really is being compiled as a loadable
|
||||||
|
** extension */
|
||||||
|
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||||
|
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
||||||
|
# define SQLITE_EXTENSION_INIT3 \
|
||||||
|
extern const sqlite3_api_routines *sqlite3_api;
|
||||||
|
#else
|
||||||
|
/* This case when the file is being statically linked into the
|
||||||
|
** application */
|
||||||
|
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
||||||
|
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
||||||
|
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SQLITE3EXT_H_ */
|
112
Godeps/_workspace/src/github.com/mattn/go-sqlite3/doc.go
generated
vendored
Normal file
112
Godeps/_workspace/src/github.com/mattn/go-sqlite3/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
Package sqlite3 provides interface to SQLite3 databases.
|
||||||
|
|
||||||
|
This works as driver for database/sql.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
|
||||||
|
go get github.com/mattn/go-sqlite3
|
||||||
|
|
||||||
|
Supported Types
|
||||||
|
|
||||||
|
Currently, go-sqlite3 support following data types.
|
||||||
|
|
||||||
|
+------------------------------+
|
||||||
|
|go | sqlite3 |
|
||||||
|
|----------|-------------------|
|
||||||
|
|nil | null |
|
||||||
|
|int | integer |
|
||||||
|
|int64 | integer |
|
||||||
|
|float64 | float |
|
||||||
|
|bool | integer |
|
||||||
|
|[]byte | blob |
|
||||||
|
|string | text |
|
||||||
|
|time.Time | timestamp/datetime|
|
||||||
|
+------------------------------+
|
||||||
|
|
||||||
|
SQLite3 Extension
|
||||||
|
|
||||||
|
You can write your own extension module for sqlite3. For example, below is a
|
||||||
|
extension for Regexp matcher operation.
|
||||||
|
|
||||||
|
#include <pcre.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sqlite3ext.h>
|
||||||
|
|
||||||
|
SQLITE_EXTENSION_INIT1
|
||||||
|
static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) {
|
||||||
|
if (argc >= 2) {
|
||||||
|
const char *target = (const char *)sqlite3_value_text(argv[1]);
|
||||||
|
const char *pattern = (const char *)sqlite3_value_text(argv[0]);
|
||||||
|
const char* errstr = NULL;
|
||||||
|
int erroff = 0;
|
||||||
|
int vec[500];
|
||||||
|
int n, rc;
|
||||||
|
pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL);
|
||||||
|
rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500);
|
||||||
|
if (rc <= 0) {
|
||||||
|
sqlite3_result_error(context, errstr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sqlite3_result_int(context, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
__declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
int sqlite3_extension_init(sqlite3 *db, char **errmsg,
|
||||||
|
const sqlite3_api_routines *api) {
|
||||||
|
SQLITE_EXTENSION_INIT2(api);
|
||||||
|
return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8,
|
||||||
|
(void*)db, regexp_func, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
It need to build as so/dll shared library. And you need to register
|
||||||
|
extension module like below.
|
||||||
|
|
||||||
|
sql.Register("sqlite3_with_extensions",
|
||||||
|
&sqlite3.SQLiteDriver{
|
||||||
|
Extensions: []string{
|
||||||
|
"sqlite3_mod_regexp",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Then, you can use this extension.
|
||||||
|
|
||||||
|
rows, err := db.Query("select text from mytable where name regexp '^golang'")
|
||||||
|
|
||||||
|
Connection Hook
|
||||||
|
|
||||||
|
You can hook and inject your codes when connection established. database/sql
|
||||||
|
doesn't provide the way to get native go-sqlite3 interfaces. So if you want,
|
||||||
|
you need to hook ConnectHook and get the SQLiteConn.
|
||||||
|
|
||||||
|
sql.Register("sqlite3_with_hook_example",
|
||||||
|
&sqlite3.SQLiteDriver{
|
||||||
|
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
|
||||||
|
sqlite3conn = append(sqlite3conn, conn)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Go SQlite3 Extensions
|
||||||
|
|
||||||
|
If you want to register Go functions as SQLite extension functions,
|
||||||
|
call RegisterFunction from ConnectHook.
|
||||||
|
|
||||||
|
regex = func(re, s string) (bool, error) {
|
||||||
|
return regexp.MatchString(re, s)
|
||||||
|
}
|
||||||
|
sql.Register("sqlite3_with_go_func",
|
||||||
|
&sqlite3.SQLiteDriver{
|
||||||
|
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
|
||||||
|
return conn.RegisterFunc("regex", regex, true)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
See the documentation of RegisterFunc for more details.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package sqlite3
|
128
Godeps/_workspace/src/github.com/mattn/go-sqlite3/error.go
generated
vendored
Normal file
128
Godeps/_workspace/src/github.com/mattn/go-sqlite3/error.go
generated
vendored
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type ErrNo int
|
||||||
|
|
||||||
|
const ErrNoMask C.int = 0xff
|
||||||
|
|
||||||
|
type ErrNoExtended int
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Code ErrNo /* The error code returned by SQLite */
|
||||||
|
ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */
|
||||||
|
err string /* The error string returned by sqlite3_errmsg(),
|
||||||
|
this usually contains more specific details. */
|
||||||
|
}
|
||||||
|
|
||||||
|
// result codes from http://www.sqlite.org/c3ref/c_abort.html
|
||||||
|
var (
|
||||||
|
ErrError = ErrNo(1) /* SQL error or missing database */
|
||||||
|
ErrInternal = ErrNo(2) /* Internal logic error in SQLite */
|
||||||
|
ErrPerm = ErrNo(3) /* Access permission denied */
|
||||||
|
ErrAbort = ErrNo(4) /* Callback routine requested an abort */
|
||||||
|
ErrBusy = ErrNo(5) /* The database file is locked */
|
||||||
|
ErrLocked = ErrNo(6) /* A table in the database is locked */
|
||||||
|
ErrNomem = ErrNo(7) /* A malloc() failed */
|
||||||
|
ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */
|
||||||
|
ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */
|
||||||
|
ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */
|
||||||
|
ErrCorrupt = ErrNo(11) /* The database disk image is malformed */
|
||||||
|
ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */
|
||||||
|
ErrFull = ErrNo(13) /* Insertion failed because database is full */
|
||||||
|
ErrCantOpen = ErrNo(14) /* Unable to open the database file */
|
||||||
|
ErrProtocol = ErrNo(15) /* Database lock protocol error */
|
||||||
|
ErrEmpty = ErrNo(16) /* Database is empty */
|
||||||
|
ErrSchema = ErrNo(17) /* The database schema changed */
|
||||||
|
ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */
|
||||||
|
ErrConstraint = ErrNo(19) /* Abort due to constraint violation */
|
||||||
|
ErrMismatch = ErrNo(20) /* Data type mismatch */
|
||||||
|
ErrMisuse = ErrNo(21) /* Library used incorrectly */
|
||||||
|
ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */
|
||||||
|
ErrAuth = ErrNo(23) /* Authorization denied */
|
||||||
|
ErrFormat = ErrNo(24) /* Auxiliary database format error */
|
||||||
|
ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */
|
||||||
|
ErrNotADB = ErrNo(26) /* File opened that is not a database file */
|
||||||
|
ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */
|
||||||
|
ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */
|
||||||
|
)
|
||||||
|
|
||||||
|
func (err ErrNo) Error() string {
|
||||||
|
return Error{Code: err}.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrNo) Extend(by int) ErrNoExtended {
|
||||||
|
return ErrNoExtended(int(err) | (by << 8))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrNoExtended) Error() string {
|
||||||
|
return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err Error) Error() string {
|
||||||
|
if err.err != "" {
|
||||||
|
return err.err
|
||||||
|
}
|
||||||
|
return errorString(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html
|
||||||
|
var (
|
||||||
|
ErrIoErrRead = ErrIoErr.Extend(1)
|
||||||
|
ErrIoErrShortRead = ErrIoErr.Extend(2)
|
||||||
|
ErrIoErrWrite = ErrIoErr.Extend(3)
|
||||||
|
ErrIoErrFsync = ErrIoErr.Extend(4)
|
||||||
|
ErrIoErrDirFsync = ErrIoErr.Extend(5)
|
||||||
|
ErrIoErrTruncate = ErrIoErr.Extend(6)
|
||||||
|
ErrIoErrFstat = ErrIoErr.Extend(7)
|
||||||
|
ErrIoErrUnlock = ErrIoErr.Extend(8)
|
||||||
|
ErrIoErrRDlock = ErrIoErr.Extend(9)
|
||||||
|
ErrIoErrDelete = ErrIoErr.Extend(10)
|
||||||
|
ErrIoErrBlocked = ErrIoErr.Extend(11)
|
||||||
|
ErrIoErrNoMem = ErrIoErr.Extend(12)
|
||||||
|
ErrIoErrAccess = ErrIoErr.Extend(13)
|
||||||
|
ErrIoErrCheckReservedLock = ErrIoErr.Extend(14)
|
||||||
|
ErrIoErrLock = ErrIoErr.Extend(15)
|
||||||
|
ErrIoErrClose = ErrIoErr.Extend(16)
|
||||||
|
ErrIoErrDirClose = ErrIoErr.Extend(17)
|
||||||
|
ErrIoErrSHMOpen = ErrIoErr.Extend(18)
|
||||||
|
ErrIoErrSHMSize = ErrIoErr.Extend(19)
|
||||||
|
ErrIoErrSHMLock = ErrIoErr.Extend(20)
|
||||||
|
ErrIoErrSHMMap = ErrIoErr.Extend(21)
|
||||||
|
ErrIoErrSeek = ErrIoErr.Extend(22)
|
||||||
|
ErrIoErrDeleteNoent = ErrIoErr.Extend(23)
|
||||||
|
ErrIoErrMMap = ErrIoErr.Extend(24)
|
||||||
|
ErrIoErrGetTempPath = ErrIoErr.Extend(25)
|
||||||
|
ErrIoErrConvPath = ErrIoErr.Extend(26)
|
||||||
|
ErrLockedSharedCache = ErrLocked.Extend(1)
|
||||||
|
ErrBusyRecovery = ErrBusy.Extend(1)
|
||||||
|
ErrBusySnapshot = ErrBusy.Extend(2)
|
||||||
|
ErrCantOpenNoTempDir = ErrCantOpen.Extend(1)
|
||||||
|
ErrCantOpenIsDir = ErrCantOpen.Extend(2)
|
||||||
|
ErrCantOpenFullPath = ErrCantOpen.Extend(3)
|
||||||
|
ErrCantOpenConvPath = ErrCantOpen.Extend(4)
|
||||||
|
ErrCorruptVTab = ErrCorrupt.Extend(1)
|
||||||
|
ErrReadonlyRecovery = ErrReadonly.Extend(1)
|
||||||
|
ErrReadonlyCantLock = ErrReadonly.Extend(2)
|
||||||
|
ErrReadonlyRollback = ErrReadonly.Extend(3)
|
||||||
|
ErrReadonlyDbMoved = ErrReadonly.Extend(4)
|
||||||
|
ErrAbortRollback = ErrAbort.Extend(2)
|
||||||
|
ErrConstraintCheck = ErrConstraint.Extend(1)
|
||||||
|
ErrConstraintCommitHook = ErrConstraint.Extend(2)
|
||||||
|
ErrConstraintForeignKey = ErrConstraint.Extend(3)
|
||||||
|
ErrConstraintFunction = ErrConstraint.Extend(4)
|
||||||
|
ErrConstraintNotNull = ErrConstraint.Extend(5)
|
||||||
|
ErrConstraintPrimaryKey = ErrConstraint.Extend(6)
|
||||||
|
ErrConstraintTrigger = ErrConstraint.Extend(7)
|
||||||
|
ErrConstraintUnique = ErrConstraint.Extend(8)
|
||||||
|
ErrConstraintVTab = ErrConstraint.Extend(9)
|
||||||
|
ErrConstraintRowId = ErrConstraint.Extend(10)
|
||||||
|
ErrNoticeRecoverWAL = ErrNotice.Extend(1)
|
||||||
|
ErrNoticeRecoverRollback = ErrNotice.Extend(2)
|
||||||
|
ErrWarningAutoIndex = ErrWarning.Extend(1)
|
||||||
|
)
|
4
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
Normal file
4
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef USE_LIBSQLITE3
|
||||||
|
# include "code/sqlite3-binding.c"
|
||||||
|
#endif
|
||||||
|
|
5
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
Normal file
5
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef USE_LIBSQLITE3
|
||||||
|
#include "code/sqlite3-binding.h"
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
977
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
Normal file
977
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
Normal file
|
@ -0,0 +1,977 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -std=gnu99
|
||||||
|
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
|
||||||
|
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SQLITE_OPEN_READWRITE
|
||||||
|
# define SQLITE_OPEN_READWRITE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SQLITE_OPEN_FULLMUTEX
|
||||||
|
# define SQLITE_OPEN_FULLMUTEX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) {
|
||||||
|
#ifdef SQLITE_OPEN_URI
|
||||||
|
return sqlite3_open_v2(filename, ppDb, flags | SQLITE_OPEN_URI, zVfs);
|
||||||
|
#else
|
||||||
|
return sqlite3_open_v2(filename, ppDb, flags, zVfs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
|
||||||
|
return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
|
||||||
|
return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_exec(sqlite3* db, const char* pcmd, long long* rowid, long long* changes)
|
||||||
|
{
|
||||||
|
int rv = sqlite3_exec(db, pcmd, 0, 0, 0);
|
||||||
|
*rowid = (long long) sqlite3_last_insert_rowid(db);
|
||||||
|
*changes = (long long) sqlite3_changes(db);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_step(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
||||||
|
{
|
||||||
|
int rv = sqlite3_step(stmt);
|
||||||
|
sqlite3* db = sqlite3_db_handle(stmt);
|
||||||
|
*rowid = (long long) sqlite3_last_insert_rowid(db);
|
||||||
|
*changes = (long long) sqlite3_changes(db);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sqlite3_result_text(sqlite3_context* ctx, const char* s) {
|
||||||
|
sqlite3_result_text(ctx, s, -1, &free);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l) {
|
||||||
|
sqlite3_result_blob(ctx, b, l, SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callbackTrampoline(sqlite3_context*, int, sqlite3_value**);
|
||||||
|
void stepTrampoline(sqlite3_context*, int, sqlite3_value**);
|
||||||
|
void doneTrampoline(sqlite3_context*);
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timestamp formats understood by both this module and SQLite.
|
||||||
|
// The first format in the slice will be used when saving time values
|
||||||
|
// into the database. When parsing a string from a timestamp or
|
||||||
|
// datetime column, the formats are tried in order.
|
||||||
|
var SQLiteTimestampFormats = []string{
|
||||||
|
// By default, store timestamps with whatever timezone they come with.
|
||||||
|
// When parsed, they will be returned with the same timezone.
|
||||||
|
"2006-01-02 15:04:05.999999999-07:00",
|
||||||
|
"2006-01-02T15:04:05.999999999-07:00",
|
||||||
|
"2006-01-02 15:04:05.999999999",
|
||||||
|
"2006-01-02T15:04:05.999999999",
|
||||||
|
"2006-01-02 15:04:05",
|
||||||
|
"2006-01-02T15:04:05",
|
||||||
|
"2006-01-02 15:04",
|
||||||
|
"2006-01-02T15:04",
|
||||||
|
"2006-01-02",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
sql.Register("sqlite3", &SQLiteDriver{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return SQLite library Version information.
|
||||||
|
func Version() (libVersion string, libVersionNumber int, sourceId string) {
|
||||||
|
libVersion = C.GoString(C.sqlite3_libversion())
|
||||||
|
libVersionNumber = int(C.sqlite3_libversion_number())
|
||||||
|
sourceId = C.GoString(C.sqlite3_sourceid())
|
||||||
|
return libVersion, libVersionNumber, sourceId
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver struct.
|
||||||
|
type SQLiteDriver struct {
|
||||||
|
Extensions []string
|
||||||
|
ConnectHook func(*SQLiteConn) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conn struct.
|
||||||
|
type SQLiteConn struct {
|
||||||
|
db *C.sqlite3
|
||||||
|
loc *time.Location
|
||||||
|
txlock string
|
||||||
|
funcs []*functionInfo
|
||||||
|
aggregators []*aggInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tx struct.
|
||||||
|
type SQLiteTx struct {
|
||||||
|
c *SQLiteConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stmt struct.
|
||||||
|
type SQLiteStmt struct {
|
||||||
|
c *SQLiteConn
|
||||||
|
s *C.sqlite3_stmt
|
||||||
|
nv int
|
||||||
|
nn []string
|
||||||
|
t string
|
||||||
|
closed bool
|
||||||
|
cls bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result struct.
|
||||||
|
type SQLiteResult struct {
|
||||||
|
id int64
|
||||||
|
changes int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows struct.
|
||||||
|
type SQLiteRows struct {
|
||||||
|
s *SQLiteStmt
|
||||||
|
nc int
|
||||||
|
cols []string
|
||||||
|
decltype []string
|
||||||
|
cls bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type functionInfo struct {
|
||||||
|
f reflect.Value
|
||||||
|
argConverters []callbackArgConverter
|
||||||
|
variadicConverter callbackArgConverter
|
||||||
|
retConverter callbackRetConverter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi *functionInfo) Call(ctx *C.sqlite3_context, argv []*C.sqlite3_value) {
|
||||||
|
args, err := callbackConvertArgs(argv, fi.argConverters, fi.variadicConverter)
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := fi.f.Call(args)
|
||||||
|
|
||||||
|
if len(ret) == 2 && ret[1].Interface() != nil {
|
||||||
|
callbackError(ctx, ret[1].Interface().(error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fi.retConverter(ctx, ret[0])
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type aggInfo struct {
|
||||||
|
constructor reflect.Value
|
||||||
|
|
||||||
|
// Active aggregator objects for aggregations in flight. The
|
||||||
|
// aggregators are indexed by a counter stored in the aggregation
|
||||||
|
// user data space provided by sqlite.
|
||||||
|
active map[int64]reflect.Value
|
||||||
|
next int64
|
||||||
|
|
||||||
|
stepArgConverters []callbackArgConverter
|
||||||
|
stepVariadicConverter callbackArgConverter
|
||||||
|
|
||||||
|
doneRetConverter callbackRetConverter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ai *aggInfo) agg(ctx *C.sqlite3_context) (int64, reflect.Value, error) {
|
||||||
|
aggIdx := (*int64)(C.sqlite3_aggregate_context(ctx, C.int(8)))
|
||||||
|
if *aggIdx == 0 {
|
||||||
|
*aggIdx = ai.next
|
||||||
|
ret := ai.constructor.Call(nil)
|
||||||
|
if len(ret) == 2 && ret[1].Interface() != nil {
|
||||||
|
return 0, reflect.Value{}, ret[1].Interface().(error)
|
||||||
|
}
|
||||||
|
if ret[0].IsNil() {
|
||||||
|
return 0, reflect.Value{}, errors.New("aggregator constructor returned nil state")
|
||||||
|
}
|
||||||
|
ai.next++
|
||||||
|
ai.active[*aggIdx] = ret[0]
|
||||||
|
}
|
||||||
|
return *aggIdx, ai.active[*aggIdx], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ai *aggInfo) Step(ctx *C.sqlite3_context, argv []*C.sqlite3_value) {
|
||||||
|
_, agg, err := ai.agg(ctx)
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := callbackConvertArgs(argv, ai.stepArgConverters, ai.stepVariadicConverter)
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := agg.MethodByName("Step").Call(args)
|
||||||
|
if len(ret) == 1 && ret[0].Interface() != nil {
|
||||||
|
callbackError(ctx, ret[0].Interface().(error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ai *aggInfo) Done(ctx *C.sqlite3_context) {
|
||||||
|
idx, agg, err := ai.agg(ctx)
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { delete(ai.active, idx) }()
|
||||||
|
|
||||||
|
ret := agg.MethodByName("Done").Call(nil)
|
||||||
|
if len(ret) == 2 && ret[1].Interface() != nil {
|
||||||
|
callbackError(ctx, ret[1].Interface().(error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ai.doneRetConverter(ctx, ret[0])
|
||||||
|
if err != nil {
|
||||||
|
callbackError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaction.
|
||||||
|
func (tx *SQLiteTx) Commit() error {
|
||||||
|
_, err := tx.c.exec("COMMIT")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback transaction.
|
||||||
|
func (tx *SQLiteTx) Rollback() error {
|
||||||
|
_, err := tx.c.exec("ROLLBACK")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFunc makes a Go function available as a SQLite function.
|
||||||
|
//
|
||||||
|
// The Go function can have arguments of the following types: any
|
||||||
|
// numeric type except complex, bool, []byte, string and
|
||||||
|
// interface{}. interface{} arguments are given the direct translation
|
||||||
|
// of the SQLite data type: int64 for INTEGER, float64 for FLOAT,
|
||||||
|
// []byte for BLOB, string for TEXT.
|
||||||
|
//
|
||||||
|
// The function can additionally be variadic, as long as the type of
|
||||||
|
// the variadic argument is one of the above.
|
||||||
|
//
|
||||||
|
// If pure is true. SQLite will assume that the function's return
|
||||||
|
// value depends only on its inputs, and make more aggressive
|
||||||
|
// optimizations in its queries.
|
||||||
|
//
|
||||||
|
// See _example/go_custom_funcs for a detailed example.
|
||||||
|
func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) error {
|
||||||
|
var fi functionInfo
|
||||||
|
fi.f = reflect.ValueOf(impl)
|
||||||
|
t := fi.f.Type()
|
||||||
|
if t.Kind() != reflect.Func {
|
||||||
|
return errors.New("Non-function passed to RegisterFunc")
|
||||||
|
}
|
||||||
|
if t.NumOut() != 1 && t.NumOut() != 2 {
|
||||||
|
return errors.New("SQLite functions must return 1 or 2 values")
|
||||||
|
}
|
||||||
|
if t.NumOut() == 2 && !t.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||||
|
return errors.New("Second return value of SQLite function must be error")
|
||||||
|
}
|
||||||
|
|
||||||
|
numArgs := t.NumIn()
|
||||||
|
if t.IsVariadic() {
|
||||||
|
numArgs--
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < numArgs; i++ {
|
||||||
|
conv, err := callbackArg(t.In(i))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fi.argConverters = append(fi.argConverters, conv)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.IsVariadic() {
|
||||||
|
conv, err := callbackArg(t.In(numArgs).Elem())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fi.variadicConverter = conv
|
||||||
|
// Pass -1 to sqlite so that it allows any number of
|
||||||
|
// arguments. The call helper verifies that the minimum number
|
||||||
|
// of arguments is present for variadic functions.
|
||||||
|
numArgs = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
conv, err := callbackRet(t.Out(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fi.retConverter = conv
|
||||||
|
|
||||||
|
// fi must outlast the database connection, or we'll have dangling pointers.
|
||||||
|
c.funcs = append(c.funcs, &fi)
|
||||||
|
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
opts := C.SQLITE_UTF8
|
||||||
|
if pure {
|
||||||
|
opts |= C.SQLITE_DETERMINISTIC
|
||||||
|
}
|
||||||
|
rv := C.sqlite3_create_function(c.db, cname, C.int(numArgs), C.int(opts), unsafe.Pointer(&fi), (*[0]byte)(unsafe.Pointer(C.callbackTrampoline)), nil, nil)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return c.lastError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterAggregator makes a Go type available as a SQLite aggregation function.
|
||||||
|
//
|
||||||
|
// Because aggregation is incremental, it's implemented in Go with a
|
||||||
|
// type that has 2 methods: func Step(values) accumulates one row of
|
||||||
|
// data into the accumulator, and func Done() ret finalizes and
|
||||||
|
// returns the aggregate value. "values" and "ret" may be any type
|
||||||
|
// supported by RegisterFunc.
|
||||||
|
//
|
||||||
|
// RegisterAggregator takes as implementation a constructor function
|
||||||
|
// that constructs an instance of the aggregator type each time an
|
||||||
|
// aggregation begins. The constructor must return a pointer to a
|
||||||
|
// type, or an interface that implements Step() and Done().
|
||||||
|
//
|
||||||
|
// The constructor function and the Step/Done methods may optionally
|
||||||
|
// return an error in addition to their other return values.
|
||||||
|
//
|
||||||
|
// See _example/go_custom_funcs for a detailed example.
|
||||||
|
func (c *SQLiteConn) RegisterAggregator(name string, impl interface{}, pure bool) error {
|
||||||
|
var ai aggInfo
|
||||||
|
ai.constructor = reflect.ValueOf(impl)
|
||||||
|
t := ai.constructor.Type()
|
||||||
|
if t.Kind() != reflect.Func {
|
||||||
|
return errors.New("non-function passed to RegisterAggregator")
|
||||||
|
}
|
||||||
|
if t.NumOut() != 1 && t.NumOut() != 2 {
|
||||||
|
return errors.New("SQLite aggregator constructors must return 1 or 2 values")
|
||||||
|
}
|
||||||
|
if t.NumOut() == 2 && !t.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||||
|
return errors.New("Second return value of SQLite function must be error")
|
||||||
|
}
|
||||||
|
if t.NumIn() != 0 {
|
||||||
|
return errors.New("SQLite aggregator constructors must not have arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
agg := t.Out(0)
|
||||||
|
switch agg.Kind() {
|
||||||
|
case reflect.Ptr, reflect.Interface:
|
||||||
|
default:
|
||||||
|
return errors.New("SQlite aggregator constructor must return a pointer object")
|
||||||
|
}
|
||||||
|
stepFn, found := agg.MethodByName("Step")
|
||||||
|
if !found {
|
||||||
|
return errors.New("SQlite aggregator doesn't have a Step() function")
|
||||||
|
}
|
||||||
|
step := stepFn.Type
|
||||||
|
if step.NumOut() != 0 && step.NumOut() != 1 {
|
||||||
|
return errors.New("SQlite aggregator Step() function must return 0 or 1 values")
|
||||||
|
}
|
||||||
|
if step.NumOut() == 1 && !step.Out(0).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||||
|
return errors.New("type of SQlite aggregator Step() return value must be error")
|
||||||
|
}
|
||||||
|
|
||||||
|
stepNArgs := step.NumIn()
|
||||||
|
start := 0
|
||||||
|
if agg.Kind() == reflect.Ptr {
|
||||||
|
// Skip over the method receiver
|
||||||
|
stepNArgs--
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
if step.IsVariadic() {
|
||||||
|
stepNArgs--
|
||||||
|
}
|
||||||
|
for i := start; i < start+stepNArgs; i++ {
|
||||||
|
conv, err := callbackArg(step.In(i))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ai.stepArgConverters = append(ai.stepArgConverters, conv)
|
||||||
|
}
|
||||||
|
if step.IsVariadic() {
|
||||||
|
conv, err := callbackArg(t.In(start + stepNArgs).Elem())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ai.stepVariadicConverter = conv
|
||||||
|
// Pass -1 to sqlite so that it allows any number of
|
||||||
|
// arguments. The call helper verifies that the minimum number
|
||||||
|
// of arguments is present for variadic functions.
|
||||||
|
stepNArgs = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
doneFn, found := agg.MethodByName("Done")
|
||||||
|
if !found {
|
||||||
|
return errors.New("SQlite aggregator doesn't have a Done() function")
|
||||||
|
}
|
||||||
|
done := doneFn.Type
|
||||||
|
doneNArgs := done.NumIn()
|
||||||
|
if agg.Kind() == reflect.Ptr {
|
||||||
|
// Skip over the method receiver
|
||||||
|
doneNArgs--
|
||||||
|
}
|
||||||
|
if doneNArgs != 0 {
|
||||||
|
return errors.New("SQlite aggregator Done() function must have no arguments")
|
||||||
|
}
|
||||||
|
if done.NumOut() != 1 && done.NumOut() != 2 {
|
||||||
|
return errors.New("SQLite aggregator Done() function must return 1 or 2 values")
|
||||||
|
}
|
||||||
|
if done.NumOut() == 2 && !done.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||||
|
return errors.New("second return value of SQLite aggregator Done() function must be error")
|
||||||
|
}
|
||||||
|
|
||||||
|
conv, err := callbackRet(done.Out(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ai.doneRetConverter = conv
|
||||||
|
ai.active = make(map[int64]reflect.Value)
|
||||||
|
ai.next = 1
|
||||||
|
|
||||||
|
// ai must outlast the database connection, or we'll have dangling pointers.
|
||||||
|
c.aggregators = append(c.aggregators, &ai)
|
||||||
|
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
opts := C.SQLITE_UTF8
|
||||||
|
if pure {
|
||||||
|
opts |= C.SQLITE_DETERMINISTIC
|
||||||
|
}
|
||||||
|
rv := C.sqlite3_create_function(c.db, cname, C.int(stepNArgs), C.int(opts), unsafe.Pointer(&ai), nil, (*[0]byte)(unsafe.Pointer(C.stepTrampoline)), (*[0]byte)(unsafe.Pointer(C.doneTrampoline)))
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return c.lastError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoCommit return which currently auto commit or not.
|
||||||
|
func (c *SQLiteConn) AutoCommit() bool {
|
||||||
|
return int(C.sqlite3_get_autocommit(c.db)) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SQLiteConn) lastError() Error {
|
||||||
|
return Error{
|
||||||
|
Code: ErrNo(C.sqlite3_errcode(c.db)),
|
||||||
|
ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)),
|
||||||
|
err: C.GoString(C.sqlite3_errmsg(c.db)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Execer
|
||||||
|
func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, error) {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return c.exec(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
s, err := c.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res driver.Result
|
||||||
|
if s.(*SQLiteStmt).s != nil {
|
||||||
|
na := s.NumInput()
|
||||||
|
if len(args) < na {
|
||||||
|
return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
|
||||||
|
}
|
||||||
|
res, err = s.Exec(args[:na])
|
||||||
|
if err != nil && err != driver.ErrSkip {
|
||||||
|
s.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args = args[na:]
|
||||||
|
}
|
||||||
|
tail := s.(*SQLiteStmt).t
|
||||||
|
s.Close()
|
||||||
|
if tail == "" {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
query = tail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Queryer
|
||||||
|
func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, error) {
|
||||||
|
for {
|
||||||
|
s, err := c.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.(*SQLiteStmt).cls = true
|
||||||
|
na := s.NumInput()
|
||||||
|
if len(args) < na {
|
||||||
|
return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
|
||||||
|
}
|
||||||
|
rows, err := s.Query(args[:na])
|
||||||
|
if err != nil && err != driver.ErrSkip {
|
||||||
|
s.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args = args[na:]
|
||||||
|
tail := s.(*SQLiteStmt).t
|
||||||
|
if tail == "" {
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
rows.Close()
|
||||||
|
s.Close()
|
||||||
|
query = tail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SQLiteConn) exec(cmd string) (driver.Result, error) {
|
||||||
|
pcmd := C.CString(cmd)
|
||||||
|
defer C.free(unsafe.Pointer(pcmd))
|
||||||
|
|
||||||
|
var rowid, changes C.longlong
|
||||||
|
rv := C._sqlite3_exec(c.db, pcmd, &rowid, &changes)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return nil, c.lastError()
|
||||||
|
}
|
||||||
|
return &SQLiteResult{int64(rowid), int64(changes)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin transaction.
|
||||||
|
func (c *SQLiteConn) Begin() (driver.Tx, error) {
|
||||||
|
if _, err := c.exec(c.txlock); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SQLiteTx{c}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorString(err Error) string {
|
||||||
|
return C.GoString(C.sqlite3_errstr(C.int(err.Code)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open database and return a new connection.
|
||||||
|
// You can specify DSN string with URI filename.
|
||||||
|
// test.db
|
||||||
|
// file:test.db?cache=shared&mode=memory
|
||||||
|
// :memory:
|
||||||
|
// file::memory:
|
||||||
|
// go-sqlite3 adds the following query parameters to those used by SQLite:
|
||||||
|
// _loc=XXX
|
||||||
|
// Specify location of time format. It's possible to specify "auto".
|
||||||
|
// _busy_timeout=XXX
|
||||||
|
// Specify value for sqlite3_busy_timeout.
|
||||||
|
// _txlock=XXX
|
||||||
|
// Specify locking behavior for transactions. XXX can be "immediate",
|
||||||
|
// "deferred", "exclusive".
|
||||||
|
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
|
||||||
|
if C.sqlite3_threadsafe() == 0 {
|
||||||
|
return nil, errors.New("sqlite library was not compiled for thread-safe operation")
|
||||||
|
}
|
||||||
|
|
||||||
|
var loc *time.Location
|
||||||
|
txlock := "BEGIN"
|
||||||
|
busy_timeout := 5000
|
||||||
|
pos := strings.IndexRune(dsn, '?')
|
||||||
|
if pos >= 1 {
|
||||||
|
params, err := url.ParseQuery(dsn[pos+1:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// _loc
|
||||||
|
if val := params.Get("_loc"); val != "" {
|
||||||
|
if val == "auto" {
|
||||||
|
loc = time.Local
|
||||||
|
} else {
|
||||||
|
loc, err = time.LoadLocation(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _busy_timeout
|
||||||
|
if val := params.Get("_busy_timeout"); val != "" {
|
||||||
|
iv, err := strconv.ParseInt(val, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)
|
||||||
|
}
|
||||||
|
busy_timeout = int(iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
// _txlock
|
||||||
|
if val := params.Get("_txlock"); val != "" {
|
||||||
|
switch val {
|
||||||
|
case "immediate":
|
||||||
|
txlock = "BEGIN IMMEDIATE"
|
||||||
|
case "exclusive":
|
||||||
|
txlock = "BEGIN EXCLUSIVE"
|
||||||
|
case "deferred":
|
||||||
|
txlock = "BEGIN"
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Invalid _txlock: %v", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(dsn, "file:") {
|
||||||
|
dsn = dsn[:pos]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var db *C.sqlite3
|
||||||
|
name := C.CString(dsn)
|
||||||
|
defer C.free(unsafe.Pointer(name))
|
||||||
|
rv := C._sqlite3_open_v2(name, &db,
|
||||||
|
C.SQLITE_OPEN_FULLMUTEX|
|
||||||
|
C.SQLITE_OPEN_READWRITE|
|
||||||
|
C.SQLITE_OPEN_CREATE,
|
||||||
|
nil)
|
||||||
|
if rv != 0 {
|
||||||
|
return nil, Error{Code: ErrNo(rv)}
|
||||||
|
}
|
||||||
|
if db == nil {
|
||||||
|
return nil, errors.New("sqlite succeeded without returning a database")
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = C.sqlite3_busy_timeout(db, C.int(busy_timeout))
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return nil, Error{Code: ErrNo(rv)}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
|
||||||
|
|
||||||
|
if len(d.Extensions) > 0 {
|
||||||
|
if err := conn.loadExtensions(d.Extensions); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.ConnectHook != nil {
|
||||||
|
if err := d.ConnectHook(conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(conn, (*SQLiteConn).Close)
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the connection.
|
||||||
|
func (c *SQLiteConn) Close() error {
|
||||||
|
rv := C.sqlite3_close_v2(c.db)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return c.lastError()
|
||||||
|
}
|
||||||
|
c.db = nil
|
||||||
|
runtime.SetFinalizer(c, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare query string. Return a new statement.
|
||||||
|
func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
|
||||||
|
pquery := C.CString(query)
|
||||||
|
defer C.free(unsafe.Pointer(pquery))
|
||||||
|
var s *C.sqlite3_stmt
|
||||||
|
var tail *C.char
|
||||||
|
rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &tail)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return nil, c.lastError()
|
||||||
|
}
|
||||||
|
var t string
|
||||||
|
if tail != nil && *tail != '\000' {
|
||||||
|
t = strings.TrimSpace(C.GoString(tail))
|
||||||
|
}
|
||||||
|
nv := int(C.sqlite3_bind_parameter_count(s))
|
||||||
|
var nn []string
|
||||||
|
for i := 0; i < nv; i++ {
|
||||||
|
pn := C.GoString(C.sqlite3_bind_parameter_name(s, C.int(i+1)))
|
||||||
|
if len(pn) > 1 && pn[0] == '$' && 48 <= pn[1] && pn[1] <= 57 {
|
||||||
|
nn = append(nn, C.GoString(C.sqlite3_bind_parameter_name(s, C.int(i+1))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss := &SQLiteStmt{c: c, s: s, nv: nv, nn: nn, t: t}
|
||||||
|
runtime.SetFinalizer(ss, (*SQLiteStmt).Close)
|
||||||
|
return ss, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the statement.
|
||||||
|
func (s *SQLiteStmt) Close() error {
|
||||||
|
if s.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s.closed = true
|
||||||
|
if s.c == nil || s.c.db == nil {
|
||||||
|
return errors.New("sqlite statement with already closed database connection")
|
||||||
|
}
|
||||||
|
rv := C.sqlite3_finalize(s.s)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return s.c.lastError()
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(s, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a number of parameters.
|
||||||
|
func (s *SQLiteStmt) NumInput() int {
|
||||||
|
return s.nv
|
||||||
|
}
|
||||||
|
|
||||||
|
type bindArg struct {
|
||||||
|
n int
|
||||||
|
v driver.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SQLiteStmt) bind(args []driver.Value) error {
|
||||||
|
rv := C.sqlite3_reset(s.s)
|
||||||
|
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
||||||
|
return s.c.lastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
var vargs []bindArg
|
||||||
|
narg := len(args)
|
||||||
|
vargs = make([]bindArg, narg)
|
||||||
|
if len(s.nn) > 0 {
|
||||||
|
for i, v := range s.nn {
|
||||||
|
if pi, err := strconv.Atoi(v[1:]); err == nil {
|
||||||
|
vargs[i] = bindArg{pi, args[i]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i, v := range args {
|
||||||
|
vargs[i] = bindArg{i + 1, v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, varg := range vargs {
|
||||||
|
n := C.int(varg.n)
|
||||||
|
v := varg.v
|
||||||
|
switch v := v.(type) {
|
||||||
|
case nil:
|
||||||
|
rv = C.sqlite3_bind_null(s.s, n)
|
||||||
|
case string:
|
||||||
|
if len(v) == 0 {
|
||||||
|
b := []byte{0}
|
||||||
|
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0))
|
||||||
|
} else {
|
||||||
|
b := []byte(v)
|
||||||
|
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v))
|
||||||
|
case bool:
|
||||||
|
if bool(v) {
|
||||||
|
rv = C.sqlite3_bind_int(s.s, n, 1)
|
||||||
|
} else {
|
||||||
|
rv = C.sqlite3_bind_int(s.s, n, 0)
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
rv = C.sqlite3_bind_double(s.s, n, C.double(v))
|
||||||
|
case []byte:
|
||||||
|
var p *byte
|
||||||
|
if len(v) > 0 {
|
||||||
|
p = &v[0]
|
||||||
|
}
|
||||||
|
rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v)))
|
||||||
|
case time.Time:
|
||||||
|
b := []byte(v.Format(SQLiteTimestampFormats[0]))
|
||||||
|
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
|
||||||
|
}
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return s.c.lastError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query the statement with arguments. Return records.
|
||||||
|
func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) {
|
||||||
|
if err := s.bind(args); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil, s.cls}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return last inserted ID.
|
||||||
|
func (r *SQLiteResult) LastInsertId() (int64, error) {
|
||||||
|
return r.id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return how many rows affected.
|
||||||
|
func (r *SQLiteResult) RowsAffected() (int64, error) {
|
||||||
|
return r.changes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the statement with arguments. Return result object.
|
||||||
|
func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
|
||||||
|
if err := s.bind(args); err != nil {
|
||||||
|
C.sqlite3_reset(s.s)
|
||||||
|
C.sqlite3_clear_bindings(s.s)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var rowid, changes C.longlong
|
||||||
|
rv := C._sqlite3_step(s.s, &rowid, &changes)
|
||||||
|
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
||||||
|
err := s.c.lastError()
|
||||||
|
C.sqlite3_reset(s.s)
|
||||||
|
C.sqlite3_clear_bindings(s.s)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SQLiteResult{int64(rowid), int64(changes)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the rows.
|
||||||
|
func (rc *SQLiteRows) Close() error {
|
||||||
|
if rc.s.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if rc.cls {
|
||||||
|
return rc.s.Close()
|
||||||
|
}
|
||||||
|
rv := C.sqlite3_reset(rc.s.s)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return rc.s.c.lastError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return column names.
|
||||||
|
func (rc *SQLiteRows) Columns() []string {
|
||||||
|
if rc.nc != len(rc.cols) {
|
||||||
|
rc.cols = make([]string, rc.nc)
|
||||||
|
for i := 0; i < rc.nc; i++ {
|
||||||
|
rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc.cols
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move cursor to next.
|
||||||
|
func (rc *SQLiteRows) Next(dest []driver.Value) error {
|
||||||
|
rv := C.sqlite3_step(rc.s.s)
|
||||||
|
if rv == C.SQLITE_DONE {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
if rv != C.SQLITE_ROW {
|
||||||
|
rv = C.sqlite3_reset(rc.s.s)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return rc.s.c.lastError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if rc.decltype == nil {
|
||||||
|
rc.decltype = make([]string, rc.nc)
|
||||||
|
for i := 0; i < rc.nc; i++ {
|
||||||
|
rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range dest {
|
||||||
|
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
|
||||||
|
case C.SQLITE_INTEGER:
|
||||||
|
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
|
||||||
|
switch rc.decltype[i] {
|
||||||
|
case "timestamp", "datetime", "date":
|
||||||
|
var t time.Time
|
||||||
|
// Assume a millisecond unix timestamp if it's 13 digits -- too
|
||||||
|
// large to be a reasonable timestamp in seconds.
|
||||||
|
if val > 1e12 || val < -1e12 {
|
||||||
|
val *= int64(time.Millisecond) // convert ms to nsec
|
||||||
|
} else {
|
||||||
|
val *= int64(time.Second) // convert sec to nsec
|
||||||
|
}
|
||||||
|
t = time.Unix(0, val).UTC()
|
||||||
|
if rc.s.c.loc != nil {
|
||||||
|
t = t.In(rc.s.c.loc)
|
||||||
|
}
|
||||||
|
dest[i] = t
|
||||||
|
case "boolean":
|
||||||
|
dest[i] = val > 0
|
||||||
|
default:
|
||||||
|
dest[i] = val
|
||||||
|
}
|
||||||
|
case C.SQLITE_FLOAT:
|
||||||
|
dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))
|
||||||
|
case C.SQLITE_BLOB:
|
||||||
|
p := C.sqlite3_column_blob(rc.s.s, C.int(i))
|
||||||
|
if p == nil {
|
||||||
|
dest[i] = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
|
||||||
|
switch dest[i].(type) {
|
||||||
|
case sql.RawBytes:
|
||||||
|
dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
|
||||||
|
default:
|
||||||
|
slice := make([]byte, n)
|
||||||
|
copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n])
|
||||||
|
dest[i] = slice
|
||||||
|
}
|
||||||
|
case C.SQLITE_NULL:
|
||||||
|
dest[i] = nil
|
||||||
|
case C.SQLITE_TEXT:
|
||||||
|
var err error
|
||||||
|
var timeVal time.Time
|
||||||
|
|
||||||
|
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
|
||||||
|
s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))
|
||||||
|
|
||||||
|
switch rc.decltype[i] {
|
||||||
|
case "timestamp", "datetime", "date":
|
||||||
|
var t time.Time
|
||||||
|
s = strings.TrimSuffix(s, "Z")
|
||||||
|
for _, format := range SQLiteTimestampFormats {
|
||||||
|
if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil {
|
||||||
|
t = timeVal
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// The column is a time value, so return the zero time on parse failure.
|
||||||
|
t = time.Time{}
|
||||||
|
}
|
||||||
|
if rc.s.c.loc != nil {
|
||||||
|
t = t.In(rc.s.c.loc)
|
||||||
|
}
|
||||||
|
dest[i] = t
|
||||||
|
default:
|
||||||
|
dest[i] = []byte(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_icu.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_icu.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build icu
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -licuuc -licui18n
|
||||||
|
#cgo CFLAGS: -DSQLITE_ENABLE_ICU
|
||||||
|
*/
|
||||||
|
import "C"
|
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build libsqlite3
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -DUSE_LIBSQLITE3
|
||||||
|
#cgo LDFLAGS: -lsqlite3
|
||||||
|
*/
|
||||||
|
import "C"
|
39
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
generated
vendored
Normal file
39
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build !sqlite_omit_load_extension
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *SQLiteConn) loadExtensions(extensions []string) error {
|
||||||
|
rv := C.sqlite3_enable_load_extension(c.db, 1)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, extension := range extensions {
|
||||||
|
cext := C.CString(extension)
|
||||||
|
defer C.free(unsafe.Pointer(cext))
|
||||||
|
rv = C.sqlite3_load_extension(c.db, cext, nil, nil)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = C.sqlite3_enable_load_extension(c.db, 0)
|
||||||
|
if rv != C.SQLITE_OK {
|
||||||
|
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
19
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build sqlite_omit_load_extension
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *SQLiteConn) loadExtensions(extensions []string) error {
|
||||||
|
return errors.New("Extensions have been disabled for static builds")
|
||||||
|
}
|
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_other.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_other.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -I.
|
||||||
|
#cgo linux LDFLAGS: -ldl
|
||||||
|
*/
|
||||||
|
import "C"
|
409
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_test/sqltest.go
generated
vendored
Normal file
409
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_test/sqltest.go
generated
vendored
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
package sqlite3_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dialect int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SQLITE Dialect = iota
|
||||||
|
POSTGRESQL
|
||||||
|
MYSQL
|
||||||
|
)
|
||||||
|
|
||||||
|
type DB struct {
|
||||||
|
*testing.T
|
||||||
|
*sql.DB
|
||||||
|
dialect Dialect
|
||||||
|
once sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
var db *DB
|
||||||
|
|
||||||
|
// the following tables will be created and dropped during the test
|
||||||
|
var testTables = []string{"foo", "bar", "t", "bench"}
|
||||||
|
|
||||||
|
var tests = []testing.InternalTest{
|
||||||
|
{"TestBlobs", TestBlobs},
|
||||||
|
{"TestManyQueryRow", TestManyQueryRow},
|
||||||
|
{"TestTxQuery", TestTxQuery},
|
||||||
|
{"TestPreparedStmt", TestPreparedStmt},
|
||||||
|
}
|
||||||
|
|
||||||
|
var benchmarks = []testing.InternalBenchmark{
|
||||||
|
{"BenchmarkExec", BenchmarkExec},
|
||||||
|
{"BenchmarkQuery", BenchmarkQuery},
|
||||||
|
{"BenchmarkParams", BenchmarkParams},
|
||||||
|
{"BenchmarkStmt", BenchmarkStmt},
|
||||||
|
{"BenchmarkRows", BenchmarkRows},
|
||||||
|
{"BenchmarkStmtRows", BenchmarkStmtRows},
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunTests runs the SQL test suite
|
||||||
|
func RunTests(t *testing.T, d *sql.DB, dialect Dialect) {
|
||||||
|
db = &DB{t, d, dialect, sync.Once{}}
|
||||||
|
testing.RunTests(func(string, string) (bool, error) { return true, nil }, tests)
|
||||||
|
|
||||||
|
if !testing.Short() {
|
||||||
|
for _, b := range benchmarks {
|
||||||
|
fmt.Printf("%-20s", b.Name)
|
||||||
|
r := testing.Benchmark(b.F)
|
||||||
|
fmt.Printf("%10d %10.0f req/s\n", r.N, float64(r.N)/r.T.Seconds())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) mustExec(sql string, args ...interface{}) sql.Result {
|
||||||
|
res, err := db.Exec(sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
db.Fatalf("Error running %q: %v", sql, err)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) tearDown() {
|
||||||
|
for _, tbl := range testTables {
|
||||||
|
switch db.dialect {
|
||||||
|
case SQLITE:
|
||||||
|
db.mustExec("drop table if exists " + tbl)
|
||||||
|
case MYSQL, POSTGRESQL:
|
||||||
|
db.mustExec("drop table if exists " + tbl)
|
||||||
|
default:
|
||||||
|
db.Fatal("unkown dialect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// q replaces ? parameters if needed
|
||||||
|
func (db *DB) q(sql string) string {
|
||||||
|
switch db.dialect {
|
||||||
|
case POSTGRESQL: // repace with $1, $2, ..
|
||||||
|
qrx := regexp.MustCompile(`\?`)
|
||||||
|
n := 0
|
||||||
|
return qrx.ReplaceAllStringFunc(sql, func(string) string {
|
||||||
|
n++
|
||||||
|
return "$" + strconv.Itoa(n)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return sql
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) blobType(size int) string {
|
||||||
|
switch db.dialect {
|
||||||
|
case SQLITE:
|
||||||
|
return fmt.Sprintf("blob[%d]", size)
|
||||||
|
case POSTGRESQL:
|
||||||
|
return "bytea"
|
||||||
|
case MYSQL:
|
||||||
|
return fmt.Sprintf("VARBINARY(%d)", size)
|
||||||
|
}
|
||||||
|
panic("unkown dialect")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) serialPK() string {
|
||||||
|
switch db.dialect {
|
||||||
|
case SQLITE:
|
||||||
|
return "integer primary key autoincrement"
|
||||||
|
case POSTGRESQL:
|
||||||
|
return "serial primary key"
|
||||||
|
case MYSQL:
|
||||||
|
return "integer primary key auto_increment"
|
||||||
|
}
|
||||||
|
panic("unkown dialect")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) now() string {
|
||||||
|
switch db.dialect {
|
||||||
|
case SQLITE:
|
||||||
|
return "datetime('now')"
|
||||||
|
case POSTGRESQL:
|
||||||
|
return "now()"
|
||||||
|
case MYSQL:
|
||||||
|
return "now()"
|
||||||
|
}
|
||||||
|
panic("unkown dialect")
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeBench() {
|
||||||
|
if _, err := db.Exec("create table bench (n varchar(32), i integer, d double, s varchar(32), t datetime)"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
st, err := db.Prepare("insert into bench values (?, ?, ?, ?, ?)")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer st.Close()
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if _, err = st.Exec(nil, i, float64(i), fmt.Sprintf("%d", i), time.Now()); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResult(t *testing.T) {
|
||||||
|
db.tearDown()
|
||||||
|
db.mustExec("create temporary table test (id " + db.serialPK() + ", name varchar(10))")
|
||||||
|
|
||||||
|
for i := 1; i < 3; i++ {
|
||||||
|
r := db.mustExec(db.q("insert into test (name) values (?)"), fmt.Sprintf("row %d", i))
|
||||||
|
n, err := r.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n != 1 {
|
||||||
|
t.Errorf("got %v, want %v", n, 1)
|
||||||
|
}
|
||||||
|
n, err = r.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n != int64(i) {
|
||||||
|
t.Errorf("got %v, want %v", n, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := db.Exec("error!"); err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBlobs(t *testing.T) {
|
||||||
|
db.tearDown()
|
||||||
|
var blob = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
|
||||||
|
db.mustExec("create table foo (id integer primary key, bar " + db.blobType(16) + ")")
|
||||||
|
db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 0, blob)
|
||||||
|
|
||||||
|
want := fmt.Sprintf("%x", blob)
|
||||||
|
|
||||||
|
b := make([]byte, 16)
|
||||||
|
err := db.QueryRow(db.q("select bar from foo where id = ?"), 0).Scan(&b)
|
||||||
|
got := fmt.Sprintf("%x", b)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[]byte scan: %v", err)
|
||||||
|
} else if got != want {
|
||||||
|
t.Errorf("for []byte, got %q; want %q", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.QueryRow(db.q("select bar from foo where id = ?"), 0).Scan(&got)
|
||||||
|
want = string(blob)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("string scan: %v", err)
|
||||||
|
} else if got != want {
|
||||||
|
t.Errorf("for string, got %q; want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManyQueryRow(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Log("skipping in short mode")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
db.tearDown()
|
||||||
|
db.mustExec("create table foo (id integer primary key, name varchar(50))")
|
||||||
|
db.mustExec(db.q("insert into foo (id, name) values(?,?)"), 1, "bob")
|
||||||
|
var name string
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
err := db.QueryRow(db.q("select name from foo where id = ?"), 1).Scan(&name)
|
||||||
|
if err != nil || name != "bob" {
|
||||||
|
t.Fatalf("on query %d: err=%v, name=%q", i, err, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTxQuery(t *testing.T) {
|
||||||
|
db.tearDown()
|
||||||
|
tx, err := db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
_, err = tx.Exec("create table foo (id integer primary key, name varchar(50))")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(db.q("insert into foo (id, name) values(?,?)"), 1, "bob")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := tx.Query(db.q("select name from foo where id = ?"), 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
if !r.Next() {
|
||||||
|
if r.Err() != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Fatal("expected one rows")
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
err = r.Scan(&name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreparedStmt(t *testing.T) {
|
||||||
|
db.tearDown()
|
||||||
|
db.mustExec("CREATE TABLE t (count INT)")
|
||||||
|
sel, err := db.Prepare("SELECT count FROM t ORDER BY count DESC")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("prepare 1: %v", err)
|
||||||
|
}
|
||||||
|
ins, err := db.Prepare(db.q("INSERT INTO t (count) VALUES (?)"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("prepare 2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for n := 1; n <= 3; n++ {
|
||||||
|
if _, err := ins.Exec(n); err != nil {
|
||||||
|
t.Fatalf("insert(%d) = %v", n, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nRuns = 10
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < nRuns; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
count := 0
|
||||||
|
if err := sel.QueryRow().Scan(&count); err != nil && err != sql.ErrNoRows {
|
||||||
|
t.Errorf("Query: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := ins.Exec(rand.Intn(100)); err != nil {
|
||||||
|
t.Errorf("Insert: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmarks need to use panic() since b.Error errors are lost when
|
||||||
|
// running via testing.Benchmark() I would like to run these via go
|
||||||
|
// test -bench but calling Benchmark() from a benchmark test
|
||||||
|
// currently hangs go.
|
||||||
|
|
||||||
|
func BenchmarkExec(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, err := db.Exec("select 1"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkQuery(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
var n sql.NullString
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
var s string
|
||||||
|
// var t time.Time
|
||||||
|
if err := db.QueryRow("select null, 1, 1.1, 'foo'").Scan(&n, &i, &f, &s); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParams(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
var n sql.NullString
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
var s string
|
||||||
|
// var t time.Time
|
||||||
|
if err := db.QueryRow("select ?, ?, ?, ?", nil, 1, 1.1, "foo").Scan(&n, &i, &f, &s); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStmt(b *testing.B) {
|
||||||
|
st, err := db.Prepare("select ?, ?, ?, ?")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var n sql.NullString
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
var s string
|
||||||
|
// var t time.Time
|
||||||
|
if err := st.QueryRow(nil, 1, 1.1, "foo").Scan(&n, &i, &f, &s); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRows(b *testing.B) {
|
||||||
|
db.once.Do(makeBench)
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var n sql.NullString
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
var s string
|
||||||
|
var t time.Time
|
||||||
|
r, err := db.Query("select * from bench")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for r.Next() {
|
||||||
|
if err = r.Scan(&n, &i, &f, &s, &t); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = r.Err(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStmtRows(b *testing.B) {
|
||||||
|
db.once.Do(makeBench)
|
||||||
|
|
||||||
|
st, err := db.Prepare("select * from bench")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var n sql.NullString
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
var s string
|
||||||
|
var t time.Time
|
||||||
|
r, err := st.Query()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for r.Next() {
|
||||||
|
if err = r.Scan(&n, &i, &f, &s, &t); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = r.Err(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_windows.go
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
|
||||||
|
#cgo windows,386 CFLAGS: -D_localtime32=localtime
|
||||||
|
#cgo LDFLAGS: -lmingwex -lmingw32
|
||||||
|
*/
|
||||||
|
import "C"
|
Loading…
Reference in a new issue