mirror of
https://github.com/glebarez/go-sqlite.git
synced 2025-10-24 16:21:25 +08:00
Add a couple of tests. Build only on linux, do not pass.
modified: Makefile modified: all_test.go modified: generator.go modified: internal/bin/bin_linux_386.go modified: internal/bin/bin_linux_amd64.go new file: internal/mptest/mptest_linux_386.go new file: internal/mptest/mptest_linux_amd64.go new file: internal/threadtest1/threadtest1_linux_386.go new file: internal/threadtest1/threadtest1_linux_amd64.go new file: internal/threadtest2/threadtest2_linux_386.go new file: internal/threadtest2/threadtest2_linux_amd64.go new file: internal/threadtest4/threadtest4_linux_386.go new file: internal/threadtest4/threadtest4_linux_amd64.go modified: main.c new file: sqlite.h new file: testdata/mptest/config01.test new file: testdata/mptest/config02.test new file: testdata/mptest/crash01.test new file: testdata/mptest/crash02.subtest new file: testdata/mptest/multiwrite01.test
This commit is contained in:
2
Makefile
2
Makefile
@@ -8,6 +8,7 @@ grep=--include=*.go --include=*.l --include=*.y --include=*.yy
|
|||||||
ngrep='TODOOK\|parser\.go\|scanner\.go\|.*_string\.go'
|
ngrep='TODOOK\|parser\.go\|scanner\.go\|.*_string\.go'
|
||||||
|
|
||||||
all: editor
|
all: editor
|
||||||
|
go test 2>&1 | tee log
|
||||||
go vet 2>&1 | grep -v $(ngrep) || true
|
go vet 2>&1 | grep -v $(ngrep) || true
|
||||||
golint 2>&1 | grep -v $(ngrep) || true
|
golint 2>&1 | grep -v $(ngrep) || true
|
||||||
make todo
|
make todo
|
||||||
@@ -35,7 +36,6 @@ editor:
|
|||||||
gofmt -l -s -w *.go
|
gofmt -l -s -w *.go
|
||||||
indent -linux *.c
|
indent -linux *.c
|
||||||
go test -i
|
go test -i
|
||||||
go test 2>&1 | tee log
|
|
||||||
|
|
||||||
internalError:
|
internalError:
|
||||||
egrep -ho '"internal error.*"' *.go | sort | cat -n
|
egrep -ho '"internal error.*"' *.go | sort | cat -n
|
||||||
|
|||||||
181
all_test.go
181
all_test.go
@@ -11,9 +11,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -348,3 +350,182 @@ func TestMemDB(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMP(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "sqlite-test-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.Chdir(wd); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command("go", "build", "-o", "mptest", "github.com/cznic/sqlite/internal/mptest").CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("go build mptest: %s\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pat := filepath.Join(wd, filepath.FromSlash("testdata/mptest"), "*.test")
|
||||||
|
m, err := filepath.Glob(pat)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
t.Fatalf("%s: no files", pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := filepath.FromSlash("./mptest")
|
||||||
|
for _, v := range m {
|
||||||
|
os.Remove("db")
|
||||||
|
out, err := exec.Command(cmd, "db", v).CombinedOutput()
|
||||||
|
t.Logf("%s", out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestThread1(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "sqlite-test-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.Chdir(wd); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command("go", "build", "-o", "threadtest1", "github.com/cznic/sqlite/internal/threadtest1").CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("go build mptest: %s\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= 10; i++ {
|
||||||
|
out, err := exec.Command("./threadtest1", strconv.Itoa(i), "-v").CombinedOutput()
|
||||||
|
t.Logf("%v: %s", i, out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestThread2(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "sqlite-test-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.Chdir(wd); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command("go", "build", "-o", "threadtest2", "github.com/cznic/sqlite/internal/threadtest2").CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("go build mptest: %s\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := exec.Command("./threadtest2").CombinedOutput()
|
||||||
|
t.Logf("%s", out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestThread4(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "sqlite-test-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.Chdir(wd); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(dir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command("go", "build", "-o", "threadtest4", "github.com/cznic/sqlite/internal/threadtest4").CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("go build mptest: %s\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opts := range [][]string{
|
||||||
|
{},
|
||||||
|
{"-serialized", "-wal"},
|
||||||
|
{"-serialized"},
|
||||||
|
{"-multithread"},
|
||||||
|
{"-multithread", "-wal"},
|
||||||
|
{"-wal"},
|
||||||
|
} {
|
||||||
|
for i := 2; i <= 10; i++ {
|
||||||
|
out, err := exec.Command("./threadtest4", append(opts, strconv.Itoa(i))...).CombinedOutput()
|
||||||
|
t.Logf("%v: %s", i, out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
338
generator.go
338
generator.go
@@ -12,6 +12,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/format"
|
"go/format"
|
||||||
"go/scanner"
|
"go/scanner"
|
||||||
|
"go/token"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -45,12 +46,17 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
prologue = `/*
|
sqliteRepo = "sqlite.org"
|
||||||
|
version = "3190300"
|
||||||
|
|
||||||
|
prologueSqlite = `// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
%s
|
%s
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Code generated by ccgo DO NOT EDIT.
|
%s
|
||||||
|
|
||||||
package bin
|
package bin
|
||||||
|
|
||||||
@@ -71,6 +77,43 @@ func ftrace(s string, args ...interface{}) {
|
|||||||
os.Stderr.Sync()
|
os.Stderr.Sync()
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
prologueTest = `// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
%s
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
defines = `
|
||||||
|
#define HAVE_MALLOC_H 1
|
||||||
|
#define HAVE_MALLOC_USABLE_SIZE 1
|
||||||
|
#define HAVE_USLEEP 1
|
||||||
|
#define SQLITE_DEBUG 1
|
||||||
|
#define SQLITE_ENABLE_API_ARMOR 1
|
||||||
|
#define SQLITE_USE_URI 1
|
||||||
|
#define SQLITE_WITHOUT_MSIZE 1
|
||||||
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func findRepo(s string) string {
|
func findRepo(s string) string {
|
||||||
@@ -121,32 +164,29 @@ func errStr(err error) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unconvert(pth string) {
|
func build(predef string, tus [][]string, qualifiers []string, opts ...cc.Opt) ([]*cc.TranslationUnit, []byte) {
|
||||||
wd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := os.Chdir(wd); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := os.Chdir(filepath.Dir(pth)); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if out, err := exec.Command(unconvertBin, "-apply").CombinedOutput(); err != nil {
|
|
||||||
log.Fatalf("unconvert: %s\n%s", err, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit, []byte) {
|
|
||||||
ndbg := ""
|
ndbg := ""
|
||||||
if *ndebug {
|
if *ndebug {
|
||||||
ndbg = "#define NDEBUG 1"
|
ndbg = "#define NDEBUG 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lpos token.Position
|
||||||
|
if *cpp {
|
||||||
|
opts = append(opts, cc.Cpp(func(toks []xc.Token) {
|
||||||
|
if len(toks) != 0 {
|
||||||
|
p := toks[0].Position()
|
||||||
|
if p.Filename != lpos.Filename {
|
||||||
|
fmt.Fprintf(os.Stderr, "# %d %q\n", p.Line, p.Filename)
|
||||||
|
}
|
||||||
|
lpos = p
|
||||||
|
}
|
||||||
|
for _, v := range toks {
|
||||||
|
os.Stderr.WriteString(cc.TokSrc(v))
|
||||||
|
}
|
||||||
|
os.Stderr.WriteString("\n")
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
var build []*cc.TranslationUnit
|
var build []*cc.TranslationUnit
|
||||||
tus = append(tus, []string{ccir.CRT0Path})
|
tus = append(tus, []string{ccir.CRT0Path})
|
||||||
for _, src := range tus {
|
for _, src := range tus {
|
||||||
@@ -173,6 +213,7 @@ func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit
|
|||||||
cc.EnableNonConstStaticInitExpressions(),
|
cc.EnableNonConstStaticInitExpressions(),
|
||||||
cc.EnableWideBitFieldTypes(),
|
cc.EnableWideBitFieldTypes(),
|
||||||
cc.ErrLimit(*errLimit),
|
cc.ErrLimit(*errLimit),
|
||||||
|
cc.KeepComments(),
|
||||||
cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
|
cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
|
||||||
}, opts...)...,
|
}, opts...)...,
|
||||||
)
|
)
|
||||||
@@ -184,7 +225,7 @@ func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit
|
|||||||
}
|
}
|
||||||
|
|
||||||
var out buffer.Bytes
|
var out buffer.Bytes
|
||||||
if err := ccgo.New(build, &out); err != nil {
|
if err := ccgo.New(build, &out, ccgo.Packages(qualifiers)); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,36 +296,125 @@ func macros(buf io.Writer, ast *cc.TranslationUnit) {
|
|||||||
fmt.Fprintf(buf, ")\n")
|
fmt.Fprintf(buf, ")\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func unconvert(pth string) {
|
||||||
const repo = "sqlite.org/sqlite-amalgamation-3190300/"
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
log.SetFlags(log.Lshortfile | log.Lmicroseconds)
|
log.Fatal(err)
|
||||||
var err error
|
|
||||||
if unconvertBin, err = exec.LookPath("unconvert"); err != nil {
|
|
||||||
log.Fatal("Please install the unconvert tool (go get -u github.com/mdempsky/unconvert)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Parse()
|
defer func() {
|
||||||
pth := findRepo(repo)
|
if err := os.Chdir(wd); err != nil {
|
||||||
if pth == "" {
|
log.Fatal(err)
|
||||||
log.Fatalf("repository not found: %v", repo)
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(filepath.Dir(pth)); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command(unconvertBin, "-apply").CombinedOutput(); err != nil {
|
||||||
|
log.Fatalf("unconvert: %s\n%s", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cp(dst, src, glob string) {
|
||||||
|
pat := filepath.Join(filepath.FromSlash(src), glob)
|
||||||
|
m, err := filepath.Glob(pat)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
log.Fatalf("cp(%q, %q, %q): no files for %q", dst, src, glob, pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = filepath.FromSlash(dst)
|
||||||
|
for _, v := range m {
|
||||||
|
f, err := ioutil.ReadFile(v)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, nm := filepath.Split(v)
|
||||||
|
if err := ioutil.WriteFile(filepath.Join(dst, nm), f, 0664); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func header(f string) []byte {
|
||||||
|
b, err := ioutil.ReadFile(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var s scanner.Scanner
|
||||||
|
s.Init(token.NewFileSet().AddFile(f, -1, len(b)), b, nil, scanner.ScanComments)
|
||||||
|
var buf buffer.Bytes
|
||||||
|
fmt.Fprintf(&buf, "/* %s */", filepath.Base(f))
|
||||||
|
for {
|
||||||
|
_, tok, lit := s.Scan()
|
||||||
|
switch tok {
|
||||||
|
case token.COMMENT:
|
||||||
|
buf.WriteString(lit)
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
default:
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func tidyComment(s string) string {
|
||||||
|
if strings.HasPrefix(s, "/*") {
|
||||||
|
s = s[len("/*") : len(s)-len("*/")]
|
||||||
|
}
|
||||||
|
a := strings.Split(strings.TrimSpace(s), "\n")
|
||||||
|
for i, v := range a {
|
||||||
|
if strings.HasPrefix(v, "** ") {
|
||||||
|
a[i] = a[i][len("** "):]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == "**" {
|
||||||
|
a[i] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, v := range a {
|
||||||
|
a[i] = strings.TrimSpace(v)
|
||||||
|
}
|
||||||
|
return "// " + strings.Join(a, "\n// ") + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
func tidyComments(b []byte) string {
|
||||||
|
var s scanner.Scanner
|
||||||
|
s.Init(token.NewFileSet().AddFile("", -1, len(b)), b, nil, scanner.ScanComments)
|
||||||
|
var a []string
|
||||||
|
for {
|
||||||
|
_, tok, lit := s.Scan()
|
||||||
|
if tok == token.EOF {
|
||||||
|
return strings.Join(a, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = append(a, tidyComment(lit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sqlite() {
|
||||||
|
repo := findRepo(sqliteRepo)
|
||||||
|
if repo == "" {
|
||||||
|
log.Fatalf("repository not found: %v", sqliteRepo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pth := filepath.Join(repo, "sqlite-amalgamation-"+version)
|
||||||
|
sqlite3 := filepath.Join(pth, "sqlite3.c")
|
||||||
asta, src := build(
|
asta, src := build(
|
||||||
`
|
defines,
|
||||||
#define HAVE_MALLOC_H 1
|
|
||||||
#define HAVE_MALLOC_USABLE_SIZE 1
|
|
||||||
#define HAVE_USLEEP 1
|
|
||||||
#define SQLITE_DEBUG 1
|
|
||||||
#define SQLITE_ENABLE_API_ARMOR 1
|
|
||||||
#define SQLITE_USE_URI 1
|
|
||||||
#define SQLITE_WITHOUT_MSIZE 1
|
|
||||||
`,
|
|
||||||
[][]string{
|
[][]string{
|
||||||
{"main.c"},
|
{"main.c"},
|
||||||
{filepath.Join(pth, "sqlite3.c")},
|
{sqlite3},
|
||||||
},
|
},
|
||||||
|
nil,
|
||||||
cc.EnableAnonymousStructFields(),
|
cc.EnableAnonymousStructFields(),
|
||||||
cc.IncludePaths([]string{pth}),
|
cc.IncludePaths([]string{pth}),
|
||||||
)
|
)
|
||||||
@@ -295,20 +425,130 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(&b, prologue, lic)
|
fmt.Fprintf(&b, prologueSqlite, lic, tidyComments(header(sqlite3)))
|
||||||
macros(&b, asta[0])
|
macros(&b, asta[0])
|
||||||
b.Write(src)
|
b.Write(src)
|
||||||
b2, err := format.Source(b.Bytes())
|
b2, err := format.Source(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b2 = b.Bytes()
|
b2 = b.Bytes()
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll("internal/bin", 0775); err != nil {
|
if err := os.MkdirAll(filepath.Join("internal", "bin"), 0775); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := fmt.Sprintf("internal/bin/bin_%s_%s.go", runtime.GOOS, runtime.GOARCH)
|
dst := fmt.Sprintf(filepath.Join("internal", "bin", "bin_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
|
||||||
if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
|
if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
unconvert(dst)
|
unconvert(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mpTest() {
|
||||||
|
repo := findRepo(sqliteRepo)
|
||||||
|
if repo == "" {
|
||||||
|
log.Fatalf("repository not found: %v", sqliteRepo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlitePth := filepath.Join(repo, "sqlite-amalgamation-"+version)
|
||||||
|
pth := filepath.Join(repo, "sqlite-src-"+version, "mptest")
|
||||||
|
tag := "mptest"
|
||||||
|
test := filepath.Join(pth, tag+".c")
|
||||||
|
_, src := build(
|
||||||
|
defines,
|
||||||
|
[][]string{
|
||||||
|
{filepath.Join(sqlitePth, "sqlite3.c")},
|
||||||
|
{test},
|
||||||
|
},
|
||||||
|
[]string{"bin"},
|
||||||
|
cc.EnableAnonymousStructFields(),
|
||||||
|
cc.IncludePaths([]string{sqlitePth}),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
fmt.Fprintf(&b, prologueTest, tidyComments(header(test)))
|
||||||
|
b.Write(src)
|
||||||
|
b2, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b2 = b.Bytes()
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(filepath.Join("internal", tag), 0775); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Join("testdata", tag), 0775); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := fmt.Sprintf(filepath.Join("internal", tag, tag+"_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
|
||||||
|
if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
unconvert(dst)
|
||||||
|
cp(filepath.Join("testdata", tag), pth, "*.test")
|
||||||
|
cp(filepath.Join("testdata", tag), pth, "*.subtest")
|
||||||
|
}
|
||||||
|
|
||||||
|
func threadTest(n int) {
|
||||||
|
repo := findRepo(sqliteRepo)
|
||||||
|
if repo == "" {
|
||||||
|
log.Fatalf("repository not found: %v", sqliteRepo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlitePth := filepath.Join(repo, "sqlite-amalgamation-"+version)
|
||||||
|
pth := filepath.Join(repo, "sqlite-src-"+version, "test")
|
||||||
|
tag := fmt.Sprintf("threadtest%v", n)
|
||||||
|
test := filepath.Join(pth, tag+".c")
|
||||||
|
_, src := build(
|
||||||
|
defines,
|
||||||
|
[][]string{
|
||||||
|
{filepath.Join(sqlitePth, "sqlite3.c")},
|
||||||
|
{test},
|
||||||
|
},
|
||||||
|
[]string{"bin"},
|
||||||
|
cc.EnableAnonymousStructFields(),
|
||||||
|
cc.IncludePaths([]string{".", sqlitePth, filepath.Join(repo, "sqlite-src-"+version, "src")}),
|
||||||
|
)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
fmt.Fprintf(&b, prologueTest, tidyComments(header(test)))
|
||||||
|
b.Write(src)
|
||||||
|
b2, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b2 = b.Bytes()
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(filepath.Join("internal", tag), 0775); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Join("testdata", tag), 0775); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := fmt.Sprintf(filepath.Join("internal", tag, tag+"_%s_%s.go"), runtime.GOOS, runtime.GOARCH)
|
||||||
|
if err := ioutil.WriteFile(dst, b2, 0664); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
unconvert(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.SetFlags(log.Lshortfile | log.Lmicroseconds)
|
||||||
|
var err error
|
||||||
|
if unconvertBin, err = exec.LookPath("unconvert"); err != nil {
|
||||||
|
log.Fatal("Please install the unconvert tool (go get -u github.com/mdempsky/unconvert)")
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
sqlite()
|
||||||
|
mpTest()
|
||||||
|
threadTest(1)
|
||||||
|
threadTest(2)
|
||||||
|
// threadTest(3) depends on unexported function.
|
||||||
|
threadTest(4)
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1868
internal/mptest/mptest_linux_386.go
Normal file
1868
internal/mptest/mptest_linux_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1868
internal/mptest/mptest_linux_amd64.go
Normal file
1868
internal/mptest/mptest_linux_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
421
internal/threadtest1/threadtest1_linux_386.go
Normal file
421
internal/threadtest1/threadtest1_linux_386.go
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest1.c
|
||||||
|
|
||||||
|
// 2002 January 15
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to test whether
|
||||||
|
// or not the SQLite library is threadsafe.
|
||||||
|
//
|
||||||
|
// Testing the thread safety of SQLite is difficult because there are very
|
||||||
|
// few places in the code that are even potentially unsafe, and those
|
||||||
|
// places execute for very short periods of time. So even if the library
|
||||||
|
// is compiled with its mutexes disabled, it is likely to work correctly
|
||||||
|
// in a multi-threaded program most of the time.
|
||||||
|
//
|
||||||
|
// This file is NOT part of the standard SQLite library. It is used for
|
||||||
|
// testing only.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _i, _n int32
|
||||||
|
var _id uint32
|
||||||
|
var _zFile, _4_zDb, _4_zJournal *int8
|
||||||
|
var _2_zBuf, _6_zBuf [200]int8
|
||||||
|
r0 = i32(0)
|
||||||
|
if (_argc > i32(2)) && (crt.Xstrcmp(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(i32(1)))), str(0)) == i32(0)) {
|
||||||
|
_verbose = i32(1)
|
||||||
|
bug20530(_verbose)
|
||||||
|
_argc -= 1
|
||||||
|
*(*uintptr)(unsafe.Pointer(&_argv)) += uintptr(4)
|
||||||
|
}
|
||||||
|
if (_argc < i32(2)) || (store0(&_n, crt.Xatoi(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(i32(1)))))) < i32(1)) {
|
||||||
|
_n = i32(10)
|
||||||
|
}
|
||||||
|
_i = i32(0)
|
||||||
|
_4:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _7
|
||||||
|
}
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_2_zBuf)), str(3), (_i+i32(1))/i32(2))
|
||||||
|
crt.Xunlink(tls, (*int8)(unsafe.Pointer(&_2_zBuf)))
|
||||||
|
_i += 1
|
||||||
|
goto _4
|
||||||
|
_7:
|
||||||
|
_i = i32(0)
|
||||||
|
_8:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _11
|
||||||
|
}
|
||||||
|
_zFile = bin.Xsqlite3_mprintf(tls, str(13), (_i%i32(2))+i32(1), (_i+i32(2))/i32(2))
|
||||||
|
if (_i % i32(2)) == i32(0) {
|
||||||
|
_4_zDb = (*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_zFile)) + 1*uintptr(i32(2))))
|
||||||
|
_4_zJournal = bin.Xsqlite3_mprintf(tls, str(26), unsafe.Pointer(_4_zDb))
|
||||||
|
crt.Xunlink(tls, _4_zDb)
|
||||||
|
crt.Xunlink(tls, _4_zJournal)
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_4_zJournal))
|
||||||
|
}
|
||||||
|
crt.Xpthread_create(tls, &_id, nil, _worker_bee, (unsafe.Pointer)(_zFile))
|
||||||
|
crt.Xpthread_detach(tls, _id)
|
||||||
|
_i += 1
|
||||||
|
goto _8
|
||||||
|
_11:
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
_13:
|
||||||
|
if Xthread_cnt > i32(0) {
|
||||||
|
crt.Xpthread_cond_wait(tls, &Xsig, &Xlock)
|
||||||
|
goto _13
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
_i = i32(0)
|
||||||
|
_15:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _18
|
||||||
|
}
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_6_zBuf)), str(3), (_i+i32(1))/i32(2))
|
||||||
|
crt.Xunlink(tls, (*int8)(unsafe.Pointer(&_6_zBuf)))
|
||||||
|
_i += 1
|
||||||
|
goto _15
|
||||||
|
_18:
|
||||||
|
return i32(0)
|
||||||
|
|
||||||
|
_ = _2_zBuf
|
||||||
|
_ = _6_zBuf
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _verbose int32
|
||||||
|
|
||||||
|
func _worker_bee(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _i, _cnt, _t int32
|
||||||
|
var _zFilename, _azErr *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _az **int8
|
||||||
|
var _4_z1, _4_z2 [30]int8
|
||||||
|
_zFilename = (*int8)(_pArg)
|
||||||
|
_t = crt.Xatoi(tls, _zFilename)
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
Xthread_cnt += 1
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
crt.Xprintf(tls, str(37), unsafe.Pointer(_zFilename))
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_cnt = i32(0)
|
||||||
|
_0:
|
||||||
|
if _cnt >= i32(10) {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_open(tls, (*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_zFilename))+1*uintptr(i32(2)))), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _db == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(48), unsafe.Pointer(_zFilename))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_busy_handler(tls, (*bin.Xsqlite3)(_db), _db_is_locked, (unsafe.Pointer)(_zFilename))
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(64), _t)
|
||||||
|
_i = i32(1)
|
||||||
|
_5:
|
||||||
|
if _i > i32(100) {
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(89), _t, _i, _i*i32(2), _i*_i)
|
||||||
|
_i += 1
|
||||||
|
goto _5
|
||||||
|
_8:
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(123), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(148), _az, unsafe.Pointer(str(156)), i32(0))
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(160), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(183), _az, unsafe.Pointer(str(190)), i32(0))
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(194), _t)
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(160), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(221), _az, unsafe.Pointer(str(229)), i32(0))
|
||||||
|
_i = i32(1)
|
||||||
|
_9:
|
||||||
|
if _i > i32(50) {
|
||||||
|
goto _12
|
||||||
|
}
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(232), _t, _i)
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_4_z1)), str(264), _i*i32(2))
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_4_z2)), str(264), _i*_i)
|
||||||
|
Xdb_check(tls, _zFilename, str(267), _az, unsafe.Pointer((*int8)(unsafe.Pointer(&_4_z1))), unsafe.Pointer((*int8)(unsafe.Pointer(&_4_z2))), i32(0))
|
||||||
|
_i += 1
|
||||||
|
goto _9
|
||||||
|
_12:
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(276), _t)
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
_cnt += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
crt.Xprintf(tls, str(292), unsafe.Pointer(_zFilename))
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
Xthread_cnt -= 1
|
||||||
|
if Xthread_cnt <= i32(0) {
|
||||||
|
crt.Xpthread_cond_signal(tls, &Xsig)
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
_ = _azErr
|
||||||
|
_ = _4_z1
|
||||||
|
_ = _4_z2
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xlock crt.Xpthread_mutex_t
|
||||||
|
|
||||||
|
var Xthread_cnt int32
|
||||||
|
|
||||||
|
// Come here to die.
|
||||||
|
func _Exit(tls *crt.TLS, _rc int32) {
|
||||||
|
crt.Xexit(tls, _rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a lock occurs, yield.
|
||||||
|
func _db_is_locked(tls *crt.TLS, _NotUsed unsafe.Pointer, _iCount int32) (r0 int32) {
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(301), unsafe.Pointer((*int8)(_NotUsed)), _iCount)
|
||||||
|
}
|
||||||
|
crt.Xusleep(tls, uint32(i32(100)))
|
||||||
|
return bool2int(_iCount < i32(25))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute an SQL statement.
|
||||||
|
func Xdb_execute(tls *crt.TLS, _db unsafe.Pointer, _zFile *int8, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql, _zErrMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
_zErrMsg = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(314), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
_1:
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, nil, nil, &_zErrMsg)
|
||||||
|
if _rc == i32(5) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(327), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(340), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql), unsafe.Pointer(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute a query against the database. NULL values are returned
|
||||||
|
// as an empty string. The list is terminated by a single NULL pointer.
|
||||||
|
func Xdb_query(tls *crt.TLS, _db unsafe.Pointer, _zFile *int8, _zFormat *int8, args ...interface{}) (r0 **int8) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql, _zErrMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
var _sResult TQueryResult
|
||||||
|
_zErrMsg = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(&_sResult), i32(0), u32(16))
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_sResult)) + uintptr(0 /* X0 */))) = _zFile
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(369), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, _db_query_callback, (unsafe.Pointer)(&_sResult), &_zErrMsg)
|
||||||
|
if _rc != i32(17) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, _db_query_callback, (unsafe.Pointer)(&_sResult), &_zErrMsg)
|
||||||
|
_1:
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(383), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(395), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql), unsafe.Pointer(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
if (_sResult.X3) == nil {
|
||||||
|
_db_query_callback(tls, (unsafe.Pointer)(&_sResult), i32(0), nil, nil)
|
||||||
|
}
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_sResult.X3)) + 4*uintptr(_sResult.X1))) = nil
|
||||||
|
return _sResult.X3
|
||||||
|
|
||||||
|
_ = _sResult
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The callback function for db_query
|
||||||
|
func _db_query_callback(tls *crt.TLS, _pUser unsafe.Pointer, _nArg int32, _azArg **int8, _NotUsed **int8) (r0 int32) {
|
||||||
|
var _i int32
|
||||||
|
var _pResult *TQueryResult
|
||||||
|
_pResult = (*TQueryResult)(_pUser)
|
||||||
|
if ((_pResult.X1) + _nArg) < (_pResult.X2) {
|
||||||
|
goto _0
|
||||||
|
}
|
||||||
|
if (_pResult.X2) == i32(0) {
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(8 /* X2 */))) = _nArg + i32(1)
|
||||||
|
goto _2
|
||||||
|
}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(8 /* X2 */))) = (((_pResult.X2) * i32(2)) + _nArg) + i32(1)
|
||||||
|
_2:
|
||||||
|
*(***int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(12 /* X3 */))) = (**int8)(crt.Xrealloc(tls, (unsafe.Pointer)(_pResult.X3), uint32(_pResult.X2)*u32(4)))
|
||||||
|
if (_pResult.X3) == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(422), unsafe.Pointer(_pResult.X0))
|
||||||
|
return i32(1)
|
||||||
|
}
|
||||||
|
_0:
|
||||||
|
if _azArg == nil {
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
_i = i32(0)
|
||||||
|
_5:
|
||||||
|
if _i >= _nArg {
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult.X3)) + 4*uintptr(postInc0((*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult))+uintptr(4 /* X1 */))), int32(1))))) = bin.Xsqlite3_mprintf(tls, str(441), unsafe.Pointer(func() *int8 {
|
||||||
|
if (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_azArg)) + 4*uintptr(_i)))) != nil {
|
||||||
|
return (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_azArg)) + 4*uintptr(_i))))
|
||||||
|
}
|
||||||
|
return str(444)
|
||||||
|
}()))
|
||||||
|
_i += 1
|
||||||
|
goto _5
|
||||||
|
_8:
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check results
|
||||||
|
func Xdb_check(tls *crt.TLS, _zFile *int8, _zMsg *int8, _az **int8, args ...interface{}) {
|
||||||
|
var _i int32
|
||||||
|
var _z *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
_ap = args
|
||||||
|
_i = i32(0)
|
||||||
|
_0:
|
||||||
|
if store1(&_z, (*int8)(crt.VAPointer(&_ap))) == nil {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
if ((*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 4*uintptr(_i)))) == nil) || (crt.Xstrcmp(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 4*uintptr(_i))), _z) != i32(0)) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(445), unsafe.Pointer(_zFile), unsafe.Pointer(_zMsg), _i+i32(1), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 4*uintptr(_i)))))
|
||||||
|
Xdb_query_free(tls, _az)
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
_ap = nil
|
||||||
|
Xdb_query_free(tls, _az)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the results of a db_query() call.
|
||||||
|
func Xdb_query_free(tls *crt.TLS, _az **int8) {
|
||||||
|
var _i int32
|
||||||
|
_i = i32(0)
|
||||||
|
_0:
|
||||||
|
if (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 4*uintptr(_i)))) == nil {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 4*uintptr(_i)))))
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_az))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xsig crt.Xpthread_cond_t
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
func postInc0(p *int32, d int32) int32 { v := *p; *p += d; return v }
|
||||||
|
func store1(p **int8, v *int8) *int8 { *p = v; return v }
|
||||||
|
func store0(p *int32, v int32) int32 { *p = v; return v }
|
||||||
|
|
||||||
|
type TQueryResult struct {
|
||||||
|
X0 *int8
|
||||||
|
X1 int32
|
||||||
|
X2 int32
|
||||||
|
X3 **int8
|
||||||
|
} // t2 struct{*int8,int32,int32,**int8}
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("-v\x00testdb-%d\x00%d.testdb-%d\x00%s-journal\x00%s: START\x0a\x00%s: can't open\x0a\x00CREATE TABLE t%d(a,b,c);\x00INSERT INTO t%d VALUES(%d,%d,%d);\x00SELECT count(*) FROM t%d\x00tX size\x00100\x00SELECT avg(b) FROM t%d\x00tX avg\x00101\x00DELETE FROM t%d WHERE a>50\x00tX avg2\x0051\x00SELECT b, c FROM t%d WHERE a=%d\x00%d\x00readback\x00DROP TABLE t%d;\x00%s: END\x0a\x00BUSY %s #%d\x0a\x00EXEC %s: %s\x0a\x00DONE %s: %s\x0a\x00%s: command failed: %s - %s\x0a\x00QUERY %s: %s\x0a\x00DONE %s %s\x0a\x00%s: query failed: %s - %s\x0a\x00%s: malloc failed\x0a\x00%s\x00\x00%s: %s: bad result in column %d: %s\x0a\x00")
|
||||||
421
internal/threadtest1/threadtest1_linux_amd64.go
Normal file
421
internal/threadtest1/threadtest1_linux_amd64.go
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest1.c
|
||||||
|
|
||||||
|
// 2002 January 15
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to test whether
|
||||||
|
// or not the SQLite library is threadsafe.
|
||||||
|
//
|
||||||
|
// Testing the thread safety of SQLite is difficult because there are very
|
||||||
|
// few places in the code that are even potentially unsafe, and those
|
||||||
|
// places execute for very short periods of time. So even if the library
|
||||||
|
// is compiled with its mutexes disabled, it is likely to work correctly
|
||||||
|
// in a multi-threaded program most of the time.
|
||||||
|
//
|
||||||
|
// This file is NOT part of the standard SQLite library. It is used for
|
||||||
|
// testing only.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _i, _n int32
|
||||||
|
var _id uint64
|
||||||
|
var _zFile, _4_zDb, _4_zJournal *int8
|
||||||
|
var _2_zBuf, _6_zBuf [200]int8
|
||||||
|
r0 = i32(0)
|
||||||
|
if (_argc > i32(2)) && (crt.Xstrcmp(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(i32(1)))), str(0)) == i32(0)) {
|
||||||
|
_verbose = i32(1)
|
||||||
|
bug20530(_verbose)
|
||||||
|
_argc -= 1
|
||||||
|
*(*uintptr)(unsafe.Pointer(&_argv)) += uintptr(8)
|
||||||
|
}
|
||||||
|
if (_argc < i32(2)) || (store0(&_n, crt.Xatoi(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(i32(1)))))) < i32(1)) {
|
||||||
|
_n = i32(10)
|
||||||
|
}
|
||||||
|
_i = i32(0)
|
||||||
|
_4:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _7
|
||||||
|
}
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_2_zBuf)), str(3), (_i+i32(1))/i32(2))
|
||||||
|
crt.Xunlink(tls, (*int8)(unsafe.Pointer(&_2_zBuf)))
|
||||||
|
_i += 1
|
||||||
|
goto _4
|
||||||
|
_7:
|
||||||
|
_i = i32(0)
|
||||||
|
_8:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _11
|
||||||
|
}
|
||||||
|
_zFile = bin.Xsqlite3_mprintf(tls, str(13), (_i%i32(2))+i32(1), (_i+i32(2))/i32(2))
|
||||||
|
if (_i % i32(2)) == i32(0) {
|
||||||
|
_4_zDb = (*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_zFile)) + 1*uintptr(i32(2))))
|
||||||
|
_4_zJournal = bin.Xsqlite3_mprintf(tls, str(26), unsafe.Pointer(_4_zDb))
|
||||||
|
crt.Xunlink(tls, _4_zDb)
|
||||||
|
crt.Xunlink(tls, _4_zJournal)
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_4_zJournal))
|
||||||
|
}
|
||||||
|
crt.Xpthread_create(tls, &_id, nil, _worker_bee, (unsafe.Pointer)(_zFile))
|
||||||
|
crt.Xpthread_detach(tls, _id)
|
||||||
|
_i += 1
|
||||||
|
goto _8
|
||||||
|
_11:
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
_13:
|
||||||
|
if Xthread_cnt > i32(0) {
|
||||||
|
crt.Xpthread_cond_wait(tls, &Xsig, &Xlock)
|
||||||
|
goto _13
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
_i = i32(0)
|
||||||
|
_15:
|
||||||
|
if _i >= _n {
|
||||||
|
goto _18
|
||||||
|
}
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_6_zBuf)), str(3), (_i+i32(1))/i32(2))
|
||||||
|
crt.Xunlink(tls, (*int8)(unsafe.Pointer(&_6_zBuf)))
|
||||||
|
_i += 1
|
||||||
|
goto _15
|
||||||
|
_18:
|
||||||
|
return i32(0)
|
||||||
|
|
||||||
|
_ = _2_zBuf
|
||||||
|
_ = _6_zBuf
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _verbose int32
|
||||||
|
|
||||||
|
func _worker_bee(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _i, _cnt, _t int32
|
||||||
|
var _zFilename, _azErr *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _az **int8
|
||||||
|
var _4_z1, _4_z2 [30]int8
|
||||||
|
_zFilename = (*int8)(_pArg)
|
||||||
|
_t = crt.Xatoi(tls, _zFilename)
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
Xthread_cnt += 1
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
crt.Xprintf(tls, str(37), unsafe.Pointer(_zFilename))
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_cnt = i32(0)
|
||||||
|
_0:
|
||||||
|
if _cnt >= i32(10) {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_open(tls, (*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_zFilename))+1*uintptr(i32(2)))), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _db == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(48), unsafe.Pointer(_zFilename))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_busy_handler(tls, (*bin.Xsqlite3)(_db), _db_is_locked, (unsafe.Pointer)(_zFilename))
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(64), _t)
|
||||||
|
_i = i32(1)
|
||||||
|
_5:
|
||||||
|
if _i > i32(100) {
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(89), _t, _i, _i*i32(2), _i*_i)
|
||||||
|
_i += 1
|
||||||
|
goto _5
|
||||||
|
_8:
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(123), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(148), _az, unsafe.Pointer(str(156)), i32(0))
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(160), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(183), _az, unsafe.Pointer(str(190)), i32(0))
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(194), _t)
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(160), _t)
|
||||||
|
Xdb_check(tls, _zFilename, str(221), _az, unsafe.Pointer(str(229)), i32(0))
|
||||||
|
_i = i32(1)
|
||||||
|
_9:
|
||||||
|
if _i > i32(50) {
|
||||||
|
goto _12
|
||||||
|
}
|
||||||
|
_az = Xdb_query(tls, _db, _zFilename, str(232), _t, _i)
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_4_z1)), str(264), _i*i32(2))
|
||||||
|
crt.Xsprintf(tls, (*int8)(unsafe.Pointer(&_4_z2)), str(264), _i*_i)
|
||||||
|
Xdb_check(tls, _zFilename, str(267), _az, unsafe.Pointer((*int8)(unsafe.Pointer(&_4_z1))), unsafe.Pointer((*int8)(unsafe.Pointer(&_4_z2))), i32(0))
|
||||||
|
_i += 1
|
||||||
|
goto _9
|
||||||
|
_12:
|
||||||
|
Xdb_execute(tls, _db, _zFilename, str(276), _t)
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
_cnt += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
crt.Xprintf(tls, str(292), unsafe.Pointer(_zFilename))
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
crt.Xpthread_mutex_lock(tls, &Xlock)
|
||||||
|
Xthread_cnt -= 1
|
||||||
|
if Xthread_cnt <= i32(0) {
|
||||||
|
crt.Xpthread_cond_signal(tls, &Xsig)
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_unlock(tls, &Xlock)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
_ = _azErr
|
||||||
|
_ = _4_z1
|
||||||
|
_ = _4_z2
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xlock crt.Xpthread_mutex_t
|
||||||
|
|
||||||
|
var Xthread_cnt int32
|
||||||
|
|
||||||
|
// Come here to die.
|
||||||
|
func _Exit(tls *crt.TLS, _rc int32) {
|
||||||
|
crt.Xexit(tls, _rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a lock occurs, yield.
|
||||||
|
func _db_is_locked(tls *crt.TLS, _NotUsed unsafe.Pointer, _iCount int32) (r0 int32) {
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(301), unsafe.Pointer((*int8)(_NotUsed)), _iCount)
|
||||||
|
}
|
||||||
|
crt.Xusleep(tls, uint32(i32(100)))
|
||||||
|
return bool2int(_iCount < i32(25))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute an SQL statement.
|
||||||
|
func Xdb_execute(tls *crt.TLS, _db unsafe.Pointer, _zFile *int8, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql, _zErrMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
_zErrMsg = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(314), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
_1:
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, nil, nil, &_zErrMsg)
|
||||||
|
if _rc == i32(5) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(327), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(340), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql), unsafe.Pointer(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute a query against the database. NULL values are returned
|
||||||
|
// as an empty string. The list is terminated by a single NULL pointer.
|
||||||
|
func Xdb_query(tls *crt.TLS, _db unsafe.Pointer, _zFile *int8, _zFormat *int8, args ...interface{}) (r0 **int8) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql, _zErrMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
var _sResult TQueryResult
|
||||||
|
_zErrMsg = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(&_sResult), i32(0), u64(24))
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_sResult)) + uintptr(0 /* X0 */))) = _zFile
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(369), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, _db_query_callback, (unsafe.Pointer)(&_sResult), &_zErrMsg)
|
||||||
|
if _rc != i32(17) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), _zSql, _db_query_callback, (unsafe.Pointer)(&_sResult), &_zErrMsg)
|
||||||
|
_1:
|
||||||
|
if _verbose != 0 {
|
||||||
|
crt.Xprintf(tls, str(383), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql))
|
||||||
|
}
|
||||||
|
if _zErrMsg != nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(395), unsafe.Pointer(_zFile), unsafe.Pointer(_zSql), unsafe.Pointer(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zErrMsg))
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
if (_sResult.X3) == nil {
|
||||||
|
_db_query_callback(tls, (unsafe.Pointer)(&_sResult), i32(0), nil, nil)
|
||||||
|
}
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_sResult.X3)) + 8*uintptr(_sResult.X1))) = nil
|
||||||
|
return _sResult.X3
|
||||||
|
|
||||||
|
_ = _sResult
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The callback function for db_query
|
||||||
|
func _db_query_callback(tls *crt.TLS, _pUser unsafe.Pointer, _nArg int32, _azArg **int8, _NotUsed **int8) (r0 int32) {
|
||||||
|
var _i int32
|
||||||
|
var _pResult *TQueryResult
|
||||||
|
_pResult = (*TQueryResult)(_pUser)
|
||||||
|
if ((_pResult.X1) + _nArg) < (_pResult.X2) {
|
||||||
|
goto _0
|
||||||
|
}
|
||||||
|
if (_pResult.X2) == i32(0) {
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(12 /* X2 */))) = _nArg + i32(1)
|
||||||
|
goto _2
|
||||||
|
}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(12 /* X2 */))) = (((_pResult.X2) * i32(2)) + _nArg) + i32(1)
|
||||||
|
_2:
|
||||||
|
*(***int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult)) + uintptr(16 /* X3 */))) = (**int8)(crt.Xrealloc(tls, (unsafe.Pointer)(_pResult.X3), uint64(_pResult.X2)*u64(8)))
|
||||||
|
if (_pResult.X3) == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(422), unsafe.Pointer(_pResult.X0))
|
||||||
|
return i32(1)
|
||||||
|
}
|
||||||
|
_0:
|
||||||
|
if _azArg == nil {
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
_i = i32(0)
|
||||||
|
_5:
|
||||||
|
if _i >= _nArg {
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult.X3)) + 8*uintptr(postInc0((*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_pResult))+uintptr(8 /* X1 */))), int32(1))))) = bin.Xsqlite3_mprintf(tls, str(441), unsafe.Pointer(func() *int8 {
|
||||||
|
if (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_azArg)) + 8*uintptr(_i)))) != nil {
|
||||||
|
return (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_azArg)) + 8*uintptr(_i))))
|
||||||
|
}
|
||||||
|
return str(444)
|
||||||
|
}()))
|
||||||
|
_i += 1
|
||||||
|
goto _5
|
||||||
|
_8:
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check results
|
||||||
|
func Xdb_check(tls *crt.TLS, _zFile *int8, _zMsg *int8, _az **int8, args ...interface{}) {
|
||||||
|
var _i int32
|
||||||
|
var _z *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
_ap = args
|
||||||
|
_i = i32(0)
|
||||||
|
_0:
|
||||||
|
if store1(&_z, (*int8)(crt.VAPointer(&_ap))) == nil {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
if ((*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 8*uintptr(_i)))) == nil) || (crt.Xstrcmp(tls, *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 8*uintptr(_i))), _z) != i32(0)) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstdout), str(445), unsafe.Pointer(_zFile), unsafe.Pointer(_zMsg), _i+i32(1), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 8*uintptr(_i)))))
|
||||||
|
Xdb_query_free(tls, _az)
|
||||||
|
_Exit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
_ap = nil
|
||||||
|
Xdb_query_free(tls, _az)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the results of a db_query() call.
|
||||||
|
func Xdb_query_free(tls *crt.TLS, _az **int8) {
|
||||||
|
var _i int32
|
||||||
|
_i = i32(0)
|
||||||
|
_0:
|
||||||
|
if (*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 8*uintptr(_i)))) == nil {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_az)) + 8*uintptr(_i)))))
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
crt.Xfree(tls, (unsafe.Pointer)(_az))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xsig crt.Xpthread_cond_t
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
func postInc0(p *int32, d int32) int32 { v := *p; *p += d; return v }
|
||||||
|
func store1(p **int8, v *int8) *int8 { *p = v; return v }
|
||||||
|
func store0(p *int32, v int32) int32 { *p = v; return v }
|
||||||
|
|
||||||
|
type TQueryResult struct {
|
||||||
|
X0 *int8
|
||||||
|
X1 int32
|
||||||
|
X2 int32
|
||||||
|
X3 **int8
|
||||||
|
} // t2 struct{*int8,int32,int32,**int8}
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("-v\x00testdb-%d\x00%d.testdb-%d\x00%s-journal\x00%s: START\x0a\x00%s: can't open\x0a\x00CREATE TABLE t%d(a,b,c);\x00INSERT INTO t%d VALUES(%d,%d,%d);\x00SELECT count(*) FROM t%d\x00tX size\x00100\x00SELECT avg(b) FROM t%d\x00tX avg\x00101\x00DELETE FROM t%d WHERE a>50\x00tX avg2\x0051\x00SELECT b, c FROM t%d WHERE a=%d\x00%d\x00readback\x00DROP TABLE t%d;\x00%s: END\x0a\x00BUSY %s #%d\x0a\x00EXEC %s: %s\x0a\x00DONE %s: %s\x0a\x00%s: command failed: %s - %s\x0a\x00QUERY %s: %s\x0a\x00DONE %s %s\x0a\x00%s: query failed: %s - %s\x0a\x00%s: malloc failed\x0a\x00%s\x00\x00%s: %s: bad result in column %d: %s\x0a\x00")
|
||||||
181
internal/threadtest2/threadtest2_linux_386.go
Normal file
181
internal/threadtest2/threadtest2_linux_386.go
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest2.c
|
||||||
|
|
||||||
|
// 2004 January 13
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to test whether
|
||||||
|
// or not the SQLite library is threadsafe.
|
||||||
|
//
|
||||||
|
// This file is NOT part of the standard SQLite library. It is used for
|
||||||
|
// testing only.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the database and start the threads
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _i, _rc int32
|
||||||
|
var _1_zJournal *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _aThread [5]uint32
|
||||||
|
r0 = i32(0)
|
||||||
|
if crt.Xstrcmp(tls, str(0), str(8)) != 0 {
|
||||||
|
_1_zJournal = bin.Xsqlite3_mprintf(tls, str(17), unsafe.Pointer(str(0)))
|
||||||
|
crt.Xunlink(tls, str(0))
|
||||||
|
crt.Xunlink(tls, _1_zJournal)
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_1_zJournal))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_open(tls, str(0), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _db == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(28))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(59), nil, nil, nil)
|
||||||
|
if _rc != 0 {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(79), _rc)
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
_i = i32(0)
|
||||||
|
_3:
|
||||||
|
if uint32(_i) >= u32(5) {
|
||||||
|
goto _6
|
||||||
|
}
|
||||||
|
crt.Xpthread_create(tls, (*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_aThread))+4*uintptr(_i))), nil, Xworker, (unsafe.Pointer)(uintptr(_i)))
|
||||||
|
_i += 1
|
||||||
|
goto _3
|
||||||
|
_6:
|
||||||
|
_i = i32(0)
|
||||||
|
_7:
|
||||||
|
if uint32(_i) >= u32(5) {
|
||||||
|
goto _10
|
||||||
|
}
|
||||||
|
crt.Xpthread_join(tls, *(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_aThread)) + 4*uintptr(_i))), nil)
|
||||||
|
_i += 1
|
||||||
|
goto _7
|
||||||
|
_10:
|
||||||
|
if Xall_stop == 0 {
|
||||||
|
crt.Xprintf(tls, str(107))
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
crt.Xprintf(tls, str(129))
|
||||||
|
return i32(1)
|
||||||
|
|
||||||
|
_ = _aThread
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the worker thread
|
||||||
|
func Xworker(tls *crt.TLS, _workerArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _id, _rc, _cnt int32
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
_id = int32(uintptr(_workerArg))
|
||||||
|
_cnt = i32(0)
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(147), _id)
|
||||||
|
_0:
|
||||||
|
if Xall_stop != 0 || postInc0(&_cnt, int32(1)) >= i32(10000) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if (_cnt % i32(100)) == i32(0) {
|
||||||
|
crt.Xprintf(tls, str(167), _id, _cnt)
|
||||||
|
}
|
||||||
|
_4:
|
||||||
|
if bin.Xsqlite3_open(tls, str(0), (**bin.Xsqlite3)(unsafe.Pointer(&_db))) != i32(0) {
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(175), nil, nil, nil)
|
||||||
|
if Xall_stop != 0 {
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(198), nil, nil, nil)
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
goto _0
|
||||||
|
_1:
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(234), _id)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
_ = _rc
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xall_stop int32
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
func postInc0(p *int32, d int32) int32 { v := *p; *p += d; return v }
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("test.db\x00:memory:\x00%s-journal\x00unable to initialize database\x0a\x00CREATE TABLE t1(x);\x00cannot create table t1: %d\x0a\x00Everything seems ok.\x0a\x00We hit an error.\x0a\x00Starting worker %d\x0a\x00%d: %d\x0a\x00PRAGMA synchronous=OFF\x00INSERT INTO t1 VALUES('bogus data')\x00Worker %d finished\x0a\x00")
|
||||||
181
internal/threadtest2/threadtest2_linux_amd64.go
Normal file
181
internal/threadtest2/threadtest2_linux_amd64.go
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest2.c
|
||||||
|
|
||||||
|
// 2004 January 13
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to test whether
|
||||||
|
// or not the SQLite library is threadsafe.
|
||||||
|
//
|
||||||
|
// This file is NOT part of the standard SQLite library. It is used for
|
||||||
|
// testing only.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the database and start the threads
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _i, _rc int32
|
||||||
|
var _1_zJournal *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _aThread [5]uint64
|
||||||
|
r0 = i32(0)
|
||||||
|
if crt.Xstrcmp(tls, str(0), str(8)) != 0 {
|
||||||
|
_1_zJournal = bin.Xsqlite3_mprintf(tls, str(17), unsafe.Pointer(str(0)))
|
||||||
|
crt.Xunlink(tls, str(0))
|
||||||
|
crt.Xunlink(tls, _1_zJournal)
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_1_zJournal))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_open(tls, str(0), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _db == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(28))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(59), nil, nil, nil)
|
||||||
|
if _rc != 0 {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(79), _rc)
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
_i = i32(0)
|
||||||
|
_3:
|
||||||
|
if uint64(_i) >= u64(5) {
|
||||||
|
goto _6
|
||||||
|
}
|
||||||
|
crt.Xpthread_create(tls, (*uint64)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_aThread))+8*uintptr(_i))), nil, Xworker, (unsafe.Pointer)(uintptr(_i)))
|
||||||
|
_i += 1
|
||||||
|
goto _3
|
||||||
|
_6:
|
||||||
|
_i = i32(0)
|
||||||
|
_7:
|
||||||
|
if uint64(_i) >= u64(5) {
|
||||||
|
goto _10
|
||||||
|
}
|
||||||
|
crt.Xpthread_join(tls, *(*uint64)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_aThread)) + 8*uintptr(_i))), nil)
|
||||||
|
_i += 1
|
||||||
|
goto _7
|
||||||
|
_10:
|
||||||
|
if Xall_stop == 0 {
|
||||||
|
crt.Xprintf(tls, str(107))
|
||||||
|
return i32(0)
|
||||||
|
}
|
||||||
|
crt.Xprintf(tls, str(129))
|
||||||
|
return i32(1)
|
||||||
|
|
||||||
|
_ = _aThread
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the worker thread
|
||||||
|
func Xworker(tls *crt.TLS, _workerArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _id, _rc, _cnt int32
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
_id = int32(uintptr(_workerArg))
|
||||||
|
_cnt = i32(0)
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(147), _id)
|
||||||
|
_0:
|
||||||
|
if Xall_stop != 0 || postInc0(&_cnt, int32(1)) >= i32(10000) {
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
if (_cnt % i32(100)) == i32(0) {
|
||||||
|
crt.Xprintf(tls, str(167), _id, _cnt)
|
||||||
|
}
|
||||||
|
_4:
|
||||||
|
if bin.Xsqlite3_open(tls, str(0), (**bin.Xsqlite3)(unsafe.Pointer(&_db))) != i32(0) {
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(175), nil, nil, nil)
|
||||||
|
if Xall_stop != 0 {
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_exec(tls, (*bin.Xsqlite3)(_db), str(198), nil, nil, nil)
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
goto _0
|
||||||
|
_1:
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(234), _id)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
_ = _rc
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xall_stop int32
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
func postInc0(p *int32, d int32) int32 { v := *p; *p += d; return v }
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("test.db\x00:memory:\x00%s-journal\x00unable to initialize database\x0a\x00CREATE TABLE t1(x);\x00cannot create table t1: %d\x0a\x00Everything seems ok.\x0a\x00We hit an error.\x0a\x00Starting worker %d\x0a\x00%d: %d\x0a\x00PRAGMA synchronous=OFF\x00INSERT INTO t1 VALUES('bogus data')\x00Worker %d finished\x0a\x00")
|
||||||
600
internal/threadtest4/threadtest4_linux_386.go
Normal file
600
internal/threadtest4/threadtest4_linux_386.go
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest4.c
|
||||||
|
|
||||||
|
// 2014-12-11
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to stress the
|
||||||
|
// SQLite library when accessing the same set of databases simultaneously
|
||||||
|
// from multiple threads in shared-cache mode.
|
||||||
|
//
|
||||||
|
// This test program runs on unix-like systems only. It uses pthreads.
|
||||||
|
// To compile:
|
||||||
|
//
|
||||||
|
// gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread
|
||||||
|
//
|
||||||
|
// To run:
|
||||||
|
//
|
||||||
|
// ./a.out 10
|
||||||
|
//
|
||||||
|
// The argument is the number of threads. There are also options, such
|
||||||
|
// as -wal and -multithread and -serialized.
|
||||||
|
//
|
||||||
|
// Consider also compiling with clang instead of gcc and adding the
|
||||||
|
// -fsanitize=thread option.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _nWorker, _i, _nErr, _nTest, _rc int32
|
||||||
|
var _wkrFlags uint32
|
||||||
|
var _1_z *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _wrMutex crt.Xpthread_mutex_t
|
||||||
|
var _infoTop XWorkerInfo
|
||||||
|
var _aInfo, _p *XWorkerInfo
|
||||||
|
r0 = i32(0)
|
||||||
|
_nWorker = i32(0)
|
||||||
|
_wkrFlags = u32(0)
|
||||||
|
_nErr = i32(0)
|
||||||
|
_nTest = i32(0)
|
||||||
|
_db = nil
|
||||||
|
bin.Xsqlite3_config(tls, i32(2))
|
||||||
|
_i = i32(1)
|
||||||
|
_0:
|
||||||
|
if _i >= _argc {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_1_z = *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i)))
|
||||||
|
if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) != i32(45) {
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
if (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(1))))) == i32(45)) && (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(2))))) != i32(0)) {
|
||||||
|
*(*uintptr)(unsafe.Pointer(&_1_z)) += uintptr(1)
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(0)) == i32(0) {
|
||||||
|
bin.Xsqlite3_config(tls, i32(2))
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) & uint32(i32(-2))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(13)) == i32(0) {
|
||||||
|
bin.Xsqlite3_config(tls, i32(3))
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(1))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _10
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(25)) == i32(0) {
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(2))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _12
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(30)) == i32(0) {
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(4))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _14
|
||||||
|
}
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(37), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i)))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_14:
|
||||||
|
_12:
|
||||||
|
_10:
|
||||||
|
_8:
|
||||||
|
goto _15
|
||||||
|
_4:
|
||||||
|
if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) < i32(49) || int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) > i32(57) || _nWorker != i32(0) {
|
||||||
|
goto _18
|
||||||
|
}
|
||||||
|
_nWorker = crt.Xatoi(tls, _1_z)
|
||||||
|
if _nWorker < i32(2) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(70))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
goto _20
|
||||||
|
_18:
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(92), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i)))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_20:
|
||||||
|
_15:
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
if _nWorker == i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(127), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(i32(0))))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
if bin.Xsqlite3_threadsafe(tls) == 0 {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(260))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_initialize(tls)
|
||||||
|
bin.Xsqlite3_enable_shared_cache(tls, i32(1))
|
||||||
|
crt.Xpthread_mutex_init(tls, &_wrMutex, nil)
|
||||||
|
crt.Xunlink(tls, str(299))
|
||||||
|
crt.Xunlink(tls, str(312))
|
||||||
|
crt.Xunlink(tls, str(325))
|
||||||
|
_rc = bin.Xsqlite3_open(tls, str(299), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(338))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(&_infoTop), i32(0), u32(40))
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(16 /* X4 */))) = _db
|
||||||
|
*(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(8 /* X2 */))) = _wkrFlags
|
||||||
|
_p = &_infoTop
|
||||||
|
if (_wkrFlags & uint32(i32(2))) != 0 {
|
||||||
|
_run_sql(tls, _p, str(382))
|
||||||
|
}
|
||||||
|
_run_sql(tls, _p, str(406))
|
||||||
|
_run_sql(tls, _p, str(429))
|
||||||
|
_run_sql(tls, _p, str(485))
|
||||||
|
_run_sql(tls, _p, str(515))
|
||||||
|
_run_sql(tls, _p, str(544))
|
||||||
|
_run_sql(tls, _p, str(577))
|
||||||
|
_run_sql(tls, _p, str(639))
|
||||||
|
_run_sql(tls, _p, str(675))
|
||||||
|
_run_sql(tls, _p, str(710))
|
||||||
|
_run_sql(tls, _p, str(743))
|
||||||
|
_run_sql(tls, _p, str(805))
|
||||||
|
_run_sql(tls, _p, str(841))
|
||||||
|
_aInfo = (*XWorkerInfo)(_safe_malloc(tls, int32(u32(40)*uint32(_nWorker))))
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(_aInfo), i32(0), u32(40)*uint32(_nWorker))
|
||||||
|
_i = i32(0)
|
||||||
|
_25:
|
||||||
|
if _i >= _nWorker {
|
||||||
|
goto _28
|
||||||
|
}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(0 /* X0 */))) = _i + i32(1)
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(4 /* X1 */))) = _nWorker
|
||||||
|
*(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(8 /* X2 */))) = _wkrFlags
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(12 /* X3 */))) = _db
|
||||||
|
*(**crt.Xpthread_mutex_t)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(36 /* X9 */))))) = &_wrMutex
|
||||||
|
_rc = crt.Xpthread_create(tls, (*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i)))))+uintptr(32 /* X8 */))), nil, _worker_thread, (unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i)))))
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(876), _i+i32(1))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
_i += 1
|
||||||
|
goto _25
|
||||||
|
_28:
|
||||||
|
_i = i32(0)
|
||||||
|
_30:
|
||||||
|
if _i >= _nWorker {
|
||||||
|
goto _33
|
||||||
|
}
|
||||||
|
crt.Xpthread_join(tls, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X8, nil)
|
||||||
|
crt.Xprintf(tls, str(914), (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X0, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X5, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X6)
|
||||||
|
if ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X7) != nil {
|
||||||
|
crt.Xprintf(tls, str(954), unsafe.Pointer((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X7))
|
||||||
|
goto _35
|
||||||
|
}
|
||||||
|
crt.Xprintf(tls, str(960))
|
||||||
|
_35:
|
||||||
|
{
|
||||||
|
p := &_nErr
|
||||||
|
*p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X5)
|
||||||
|
sink1 = *p
|
||||||
|
}
|
||||||
|
{
|
||||||
|
p := &_nTest
|
||||||
|
*p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X6)
|
||||||
|
sink1 = *p
|
||||||
|
}
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_i += 1
|
||||||
|
goto _30
|
||||||
|
_33:
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_aInfo))
|
||||||
|
crt.Xprintf(tls, str(962), _nErr, _nTest)
|
||||||
|
return _nErr
|
||||||
|
|
||||||
|
_ = _wrMutex
|
||||||
|
_ = _infoTop
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run a SQL statements. Panic if unable.
|
||||||
|
func _run_sql(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _rc, _nRetry int32
|
||||||
|
var _zSql *int8
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _ap []interface{}
|
||||||
|
_pStmt = nil
|
||||||
|
_nRetry = i32(0)
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_p.X4), _zSql, i32(-1), &_pStmt, nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_worker_trace(tls, _p, str(1036), unsafe.Pointer(_zSql))
|
||||||
|
_1:
|
||||||
|
if store1(&_rc, bin.Xsqlite3_step(tls, _pStmt)) == i32(101) {
|
||||||
|
goto _2
|
||||||
|
}
|
||||||
|
if (_rc&i32(255)) != i32(5) && (_rc&i32(255)) != i32(6) {
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_reset(tls, _pStmt)
|
||||||
|
_nRetry += 1
|
||||||
|
if _nRetry < i32(10) {
|
||||||
|
_worker_trace(tls, _p, str(1049), _nRetry, unsafe.Pointer(_zSql))
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1067), _p.X0, unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_4:
|
||||||
|
if _rc != i32(100) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1109), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
goto _1
|
||||||
|
_2:
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report an OOM error and die if the argument is NULL
|
||||||
|
func _check_oom(tls *crt.TLS, _x unsafe.Pointer) {
|
||||||
|
if _x == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1151))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a trace message for a worker
|
||||||
|
func _worker_trace(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _zMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
if ((_p.X2) & uint32(i32(4))) == uint32(i32(0)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ap = args
|
||||||
|
_zMsg = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zMsg))
|
||||||
|
_ap = nil
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1166), _p.X0, unsafe.Pointer(_zMsg))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zMsg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory. If the allocation fails, print an error message and
|
||||||
|
// kill the process.
|
||||||
|
func _safe_malloc(tls *crt.TLS, _sz int32) (r0 unsafe.Pointer) {
|
||||||
|
var _x unsafe.Pointer
|
||||||
|
_x = bin.Xsqlite3_malloc(tls, func() int32 {
|
||||||
|
if _sz > i32(0) {
|
||||||
|
return _sz
|
||||||
|
}
|
||||||
|
return i32(1)
|
||||||
|
}())
|
||||||
|
_check_oom(tls, _x)
|
||||||
|
return _x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each thread runs the following function.
|
||||||
|
func _worker_thread(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _iOuter, _i, _rc int32
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _p *XWorkerInfo
|
||||||
|
_p = (*XWorkerInfo)(_pArg)
|
||||||
|
crt.Xprintf(tls, str(1183), _p.X0)
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_iOuter = i32(1)
|
||||||
|
_0:
|
||||||
|
if _iOuter > (_p.X1) {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_worker_open_connection(tls, _p, _iOuter)
|
||||||
|
_i = i32(0)
|
||||||
|
_4:
|
||||||
|
if _i >= i32(4) {
|
||||||
|
goto _7
|
||||||
|
}
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), (((_p.X0)+_iOuter)%i32(3))+i32(1))
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(1))%i32(3))+i32(1))
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(2))%i32(3))+i32(1))
|
||||||
|
_i += 1
|
||||||
|
goto _4
|
||||||
|
_7:
|
||||||
|
_pStmt = _prep_sql(tls, _p.X4, str(1202), _p.X0)
|
||||||
|
_worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
_rc = bin.Xsqlite3_step(tls, _pStmt)
|
||||||
|
if _rc != i32(100) {
|
||||||
|
_worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
goto _9
|
||||||
|
}
|
||||||
|
if bin.Xsqlite3_column_int(tls, _pStmt, i32(0)) != i32(400) {
|
||||||
|
_worker_error(tls, _p, str(1269), bin.Xsqlite3_column_int(tls, _pStmt, i32(0)))
|
||||||
|
}
|
||||||
|
_9:
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
if (_p.X5) != 0 {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
if ((_iOuter + (_p.X0)) % i32(3)) == i32(0) {
|
||||||
|
bin.Xsqlite3_db_release_memory(tls, (*bin.Xsqlite3)(_p.X4))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1286))
|
||||||
|
_run_sql(tls, _p, str(1293))
|
||||||
|
_run_sql(tls, _p, str(1325))
|
||||||
|
_run_sql(tls, _p, str(1357))
|
||||||
|
_run_sql(tls, _p, str(1389))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
if _iOuter == (_p.X0) {
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1399))
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
}
|
||||||
|
_pStmt = _prep_sql(tls, _p.X4, str(1406), _p.X0, _p.X0, _p.X0)
|
||||||
|
_worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
_i = i32(0)
|
||||||
|
_14:
|
||||||
|
if _i >= (_p.X1) {
|
||||||
|
goto _17
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_step(tls, _pStmt)
|
||||||
|
if _rc != i32(100) {
|
||||||
|
_worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
goto _17
|
||||||
|
}
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
_i += 1
|
||||||
|
goto _14
|
||||||
|
_17:
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
if (_p.X5) != 0 {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_worker_delete_all_content(tls, _p, ((_p.X0)+_iOuter)%i32(2))
|
||||||
|
_worker_close_connection(tls, _p)
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(16 /* X4 */))) = nil
|
||||||
|
_iOuter += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
_worker_close_connection(tls, _p)
|
||||||
|
crt.Xprintf(tls, str(1552), _p.X0)
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the database connection for WorkerInfo. The order in which
|
||||||
|
// the files are opened is a function of the tid value.
|
||||||
|
func _worker_open_connection(tls *crt.TLS, _p *XWorkerInfo, _iCnt int32) {
|
||||||
|
var _x, _rc int32
|
||||||
|
var _zFile *int8
|
||||||
|
_x = ((_p.X0) + _iCnt) % i32(6)
|
||||||
|
_zFile = bin.Xsqlite3_mprintf(tls, str(1572), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(0))))))
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zFile))
|
||||||
|
_worker_trace(tls, _p, str(1586), unsafe.Pointer(_zFile))
|
||||||
|
_rc = bin.Xsqlite3_open_v2(tls, _zFile, (**bin.Xsqlite3)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p))+uintptr(16 /* X4 */))))), i32(131074), nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1594), unsafe.Pointer(_zFile), _p.X0)
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zFile))
|
||||||
|
_run_sql(tls, _p, str(1634))
|
||||||
|
bin.Xsqlite3_busy_timeout(tls, (*bin.Xsqlite3)(_p.X4), i32(10000))
|
||||||
|
_run_sql(tls, _p, str(1662))
|
||||||
|
_run_sql(tls, _p, str(1686), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(1))))))
|
||||||
|
_run_sql(tls, _p, str(1717), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(2))))))
|
||||||
|
}
|
||||||
|
|
||||||
|
var _worker_open_connectionØ00aOrderØ001 [6][3]uint8
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_worker_open_connectionØ00aOrderØ001 = [6][3]uint8{[3]uint8{u8(1), u8(2), u8(3)}, [3]uint8{u8(1), u8(3), u8(2)}, [3]uint8{u8(2), u8(1), u8(3)}, [3]uint8{u8(2), u8(3), u8(1)}, [3]uint8{u8(3), u8(1), u8(2)}, [3]uint8{u8(3), u8(2), u8(1)}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rows mn through mx in table iTab for the given worker
|
||||||
|
func _worker_add_content(tls *crt.TLS, _p *XWorkerInfo, _mn int32, _mx int32, _iTab int32) {
|
||||||
|
var _zTabDef *int8
|
||||||
|
switch _iTab {
|
||||||
|
case i32(1):
|
||||||
|
goto _1
|
||||||
|
case i32(2):
|
||||||
|
goto _2
|
||||||
|
case i32(3):
|
||||||
|
goto _3
|
||||||
|
default:
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
|
||||||
|
_1:
|
||||||
|
_zTabDef = str(1748)
|
||||||
|
goto _4
|
||||||
|
_2:
|
||||||
|
_zTabDef = str(1765)
|
||||||
|
goto _4
|
||||||
|
_3:
|
||||||
|
_zTabDef = str(1782)
|
||||||
|
goto _4
|
||||||
|
_4:
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1799), _mn, _mx, unsafe.Pointer(_zTabDef), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare a single SQL query
|
||||||
|
func _prep_sql(tls *crt.TLS, _db unsafe.Pointer, _zFormat *int8, args ...interface{}) (r0 unsafe.Pointer) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql *int8
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _ap []interface{}
|
||||||
|
_pStmt = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_db), _zSql, i32(-1), &_pStmt, nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_db)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_db))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
return _pStmt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an error message on a worker
|
||||||
|
func _worker_error(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _ap []interface{}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(20 /* X5 */))) += 1
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_p.X7))
|
||||||
|
_ap = args
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(28 /* X7 */))) = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all content in the three databases associated with a
|
||||||
|
// single thread. Make this happen all in a single transaction if
|
||||||
|
// inTrans is true, or separately for each database if inTrans is
|
||||||
|
// false.
|
||||||
|
func _worker_delete_all_content(tls *crt.TLS, _p *XWorkerInfo, _inTrans int32) {
|
||||||
|
if _inTrans != 0 {
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1947))
|
||||||
|
_run_sql(tls, _p, str(1953), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(1981), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(2009), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(2037))
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1953), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1981), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(2009), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1
|
||||||
|
_1:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the worker database connection
|
||||||
|
func _worker_close_connection(tls *crt.TLS, _p *XWorkerInfo) {
|
||||||
|
if (_p.X4) != nil {
|
||||||
|
_worker_trace(tls, _p, str(2044))
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_p.X4))
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(16 /* X4 */))) = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
var sink1 int32 //TODO report GC bug
|
||||||
|
var sink0 uint32 //TODO report GC bug
|
||||||
|
func store1(p *int32, v int32) int32 { *p = v; return v }
|
||||||
|
|
||||||
|
type XWorkerInfo struct {
|
||||||
|
X0 int32
|
||||||
|
X1 int32
|
||||||
|
X2 uint32
|
||||||
|
X3 unsafe.Pointer
|
||||||
|
X4 unsafe.Pointer
|
||||||
|
X5 int32
|
||||||
|
X6 int32
|
||||||
|
X7 *int8
|
||||||
|
X8 uint32
|
||||||
|
X9 unsafe.Pointer
|
||||||
|
} // t2 struct{int32,int32,uint32,*struct{},*struct{},int32,int32,*int8,uint32,*struct{}}
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("-multithread\x00-serialized\x00-wal\x00-trace\x00unknown command-line option: %s\x0a\x00minimum of 2 threads\x0a\x00extra command-line argument: \"%s\"\x0a\x00usage: %s ?OPTIONS? N\x0aN is the number of threads and must be at least 2.\x0aOptions:\x0a --serialized\x0a --multithread\x0a --wal\x0a --trace\x0a\x00requires a threadsafe build of SQLite\x0a\x00tt4-test1.db\x00tt4-test2.db\x00tt4-test3.db\x00Unable to open test database: tt4-test2.db\x0a\x00PRAGMA journal_mode=WAL\x00PRAGMA synchronous=OFF\x00CREATE TABLE IF NOT EXISTS t1(tid INTEGER, sp, a, b, c)\x00CREATE INDEX t1tid ON t1(tid)\x00CREATE INDEX t1ab ON t1(a,b)\x00ATTACH 'tt4-test2.db' AS 'test2'\x00CREATE TABLE IF NOT EXISTS test2.t2(tid INTEGER, sp, d, e, f)\x00CREATE INDEX test2.t2tid ON t2(tid)\x00CREATE INDEX test2.t2de ON t2(d,e)\x00ATTACH 'tt4-test3.db' AS 'test3'\x00CREATE TABLE IF NOT EXISTS test3.t3(tid INTEGER, sp, x, y, z)\x00CREATE INDEX test3.t3tid ON t3(tid)\x00CREATE INDEX test3.t3xy ON t3(x,y)\x00thread creation failed for thread %d\x0a\x00Joined thread %d: %d errors in %d tests\x00: %s\x0a\x00\x0a\x00Total %d errors in %d tests\x0a\x00SQL error (%d,%d): %s\x0aWhile preparing: [%s]\x0a\x00running [%s]\x00retry %d for [%s]\x00Deadlock in thread %d while running [%s]\x0a\x00SQL error (%d,%d): %s\x0aWhile running [%s]\x0a\x00out of memory\x0a\x00TRACE(%02d): %s\x0a\x00worker %d startup\x0a\x00SELECT count(a) FROM t1 WHERE tid=%d\x00query [%s]\x00Failed to step: %s\x00Wrong result: %d\x00BEGIN;\x00UPDATE t1 SET c=NULL WHERE a=55\x00UPDATE t2 SET f=NULL WHERE d=42\x00UPDATE t3 SET z=NULL WHERE x=31\x00ROLLBACK;\x00VACUUM\x00SELECT t1.rowid, t2.rowid, t3.rowid FROM t1, t2, t3 WHERE t1.tid=%d AND t2.tid=%d AND t3.tid=%d AND t1.a<>t2.d AND t2.d<>t3.x ORDER BY 1, 2, 3\x00worker %d finished\x0a\x00tt4-test%d.db\x00open %s\x00sqlite_open_v2(%s) failed on thread %d\x0a\x00PRAGMA read_uncommitted=ON;\x00PRAGMA synchronous=OFF;\x00ATTACH 'tt4-test%d.db' AS aux1\x00ATTACH 'tt4-test%d.db' AS aux2\x00t1(tid,sp,a,b,c)\x00t2(tid,sp,d,e,f)\x00t3(tid,sp,x,y,z)\x00WITH RECURSIVE\x0a c(i) AS (VALUES(%d) UNION ALL SELECT i+1 FROM c WHERE i<%d)\x0aINSERT INTO %s SELECT %d, zeroblob(3000), i, printf('%%d',i), i FROM c;\x00BEGIN\x00DELETE FROM t1 WHERE tid=%d\x00DELETE FROM t2 WHERE tid=%d\x00DELETE FROM t3 WHERE tid=%d\x00COMMIT\x00close\x00")
|
||||||
600
internal/threadtest4/threadtest4_linux_amd64.go
Normal file
600
internal/threadtest4/threadtest4_linux_amd64.go
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
// Code generated by ccgo. DO NOT EDIT.
|
||||||
|
|
||||||
|
// threadtest4.c
|
||||||
|
|
||||||
|
// 2014-12-11
|
||||||
|
//
|
||||||
|
// 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 file implements a simple standalone program used to stress the
|
||||||
|
// SQLite library when accessing the same set of databases simultaneously
|
||||||
|
// from multiple threads in shared-cache mode.
|
||||||
|
//
|
||||||
|
// This test program runs on unix-like systems only. It uses pthreads.
|
||||||
|
// To compile:
|
||||||
|
//
|
||||||
|
// gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread
|
||||||
|
//
|
||||||
|
// To run:
|
||||||
|
//
|
||||||
|
// ./a.out 10
|
||||||
|
//
|
||||||
|
// The argument is the number of threads. There are also options, such
|
||||||
|
// as -wal and -multithread and -serialized.
|
||||||
|
//
|
||||||
|
// Consider also compiling with clang instead of gcc and adding the
|
||||||
|
// -fsanitize=thread option.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cznic/crt"
|
||||||
|
"github.com/cznic/sqlite/internal/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var argv []*int8
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range os.Args {
|
||||||
|
argv = append(argv, (*int8)(crt.CString(v)))
|
||||||
|
}
|
||||||
|
argv = append(argv, nil)
|
||||||
|
X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func X_start(tls *crt.TLS, _argc int32, _argv **int8) {
|
||||||
|
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
|
||||||
|
crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv))
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstdin unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdin = unsafe.Pointer(&X__stdfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
var X__stdfiles [3]unsafe.Pointer
|
||||||
|
|
||||||
|
var Xstdout unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Xstderr unsafe.Pointer
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) {
|
||||||
|
var _nWorker, _i, _nErr, _nTest, _rc int32
|
||||||
|
var _wkrFlags uint32
|
||||||
|
var _1_z *int8
|
||||||
|
var _db unsafe.Pointer
|
||||||
|
var _wrMutex crt.Xpthread_mutex_t
|
||||||
|
var _infoTop XWorkerInfo
|
||||||
|
var _aInfo, _p *XWorkerInfo
|
||||||
|
r0 = i32(0)
|
||||||
|
_nWorker = i32(0)
|
||||||
|
_wkrFlags = u32(0)
|
||||||
|
_nErr = i32(0)
|
||||||
|
_nTest = i32(0)
|
||||||
|
_db = nil
|
||||||
|
bin.Xsqlite3_config(tls, i32(2))
|
||||||
|
_i = i32(1)
|
||||||
|
_0:
|
||||||
|
if _i >= _argc {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_1_z = *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i)))
|
||||||
|
if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) != i32(45) {
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
if (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(1))))) == i32(45)) && (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(2))))) != i32(0)) {
|
||||||
|
*(*uintptr)(unsafe.Pointer(&_1_z)) += uintptr(1)
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(0)) == i32(0) {
|
||||||
|
bin.Xsqlite3_config(tls, i32(2))
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) & uint32(i32(-2))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _8
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(13)) == i32(0) {
|
||||||
|
bin.Xsqlite3_config(tls, i32(3))
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(1))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _10
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(25)) == i32(0) {
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(2))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _12
|
||||||
|
}
|
||||||
|
if crt.Xstrcmp(tls, _1_z, str(30)) == i32(0) {
|
||||||
|
{
|
||||||
|
p := &_wkrFlags
|
||||||
|
*p = (*p) | uint32(i32(4))
|
||||||
|
sink0 = *p
|
||||||
|
}
|
||||||
|
goto _14
|
||||||
|
}
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(37), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i)))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_14:
|
||||||
|
_12:
|
||||||
|
_10:
|
||||||
|
_8:
|
||||||
|
goto _15
|
||||||
|
_4:
|
||||||
|
if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) < i32(49) || int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) > i32(57) || _nWorker != i32(0) {
|
||||||
|
goto _18
|
||||||
|
}
|
||||||
|
_nWorker = crt.Xatoi(tls, _1_z)
|
||||||
|
if _nWorker < i32(2) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(70))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
goto _20
|
||||||
|
_18:
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(92), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i)))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_20:
|
||||||
|
_15:
|
||||||
|
_i += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
if _nWorker == i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(127), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(i32(0))))))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
if bin.Xsqlite3_threadsafe(tls) == 0 {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(260))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_initialize(tls)
|
||||||
|
bin.Xsqlite3_enable_shared_cache(tls, i32(1))
|
||||||
|
crt.Xpthread_mutex_init(tls, &_wrMutex, nil)
|
||||||
|
crt.Xunlink(tls, str(299))
|
||||||
|
crt.Xunlink(tls, str(312))
|
||||||
|
crt.Xunlink(tls, str(325))
|
||||||
|
_rc = bin.Xsqlite3_open(tls, str(299), (**bin.Xsqlite3)(unsafe.Pointer(&_db)))
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(338))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(&_infoTop), i32(0), u64(64))
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(24 /* X4 */))) = _db
|
||||||
|
*(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(8 /* X2 */))) = _wkrFlags
|
||||||
|
_p = &_infoTop
|
||||||
|
if (_wkrFlags & uint32(i32(2))) != 0 {
|
||||||
|
_run_sql(tls, _p, str(382))
|
||||||
|
}
|
||||||
|
_run_sql(tls, _p, str(406))
|
||||||
|
_run_sql(tls, _p, str(429))
|
||||||
|
_run_sql(tls, _p, str(485))
|
||||||
|
_run_sql(tls, _p, str(515))
|
||||||
|
_run_sql(tls, _p, str(544))
|
||||||
|
_run_sql(tls, _p, str(577))
|
||||||
|
_run_sql(tls, _p, str(639))
|
||||||
|
_run_sql(tls, _p, str(675))
|
||||||
|
_run_sql(tls, _p, str(710))
|
||||||
|
_run_sql(tls, _p, str(743))
|
||||||
|
_run_sql(tls, _p, str(805))
|
||||||
|
_run_sql(tls, _p, str(841))
|
||||||
|
_aInfo = (*XWorkerInfo)(_safe_malloc(tls, int32(u64(64)*uint64(_nWorker))))
|
||||||
|
crt.Xmemset(tls, (unsafe.Pointer)(_aInfo), i32(0), u64(64)*uint64(_nWorker))
|
||||||
|
_i = i32(0)
|
||||||
|
_25:
|
||||||
|
if _i >= _nWorker {
|
||||||
|
goto _28
|
||||||
|
}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(0 /* X0 */))) = _i + i32(1)
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(4 /* X1 */))) = _nWorker
|
||||||
|
*(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(8 /* X2 */))) = _wkrFlags
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(16 /* X3 */))) = _db
|
||||||
|
*(**crt.Xpthread_mutex_t)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(56 /* X9 */))))) = &_wrMutex
|
||||||
|
_rc = crt.Xpthread_create(tls, (*uint64)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i)))))+uintptr(48 /* X8 */))), nil, _worker_thread, (unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i)))))
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(876), _i+i32(1))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
_i += 1
|
||||||
|
goto _25
|
||||||
|
_28:
|
||||||
|
_i = i32(0)
|
||||||
|
_30:
|
||||||
|
if _i >= _nWorker {
|
||||||
|
goto _33
|
||||||
|
}
|
||||||
|
crt.Xpthread_join(tls, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X8, nil)
|
||||||
|
crt.Xprintf(tls, str(914), (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X0, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X5, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X6)
|
||||||
|
if ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X7) != nil {
|
||||||
|
crt.Xprintf(tls, str(954), unsafe.Pointer((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X7))
|
||||||
|
goto _35
|
||||||
|
}
|
||||||
|
crt.Xprintf(tls, str(960))
|
||||||
|
_35:
|
||||||
|
{
|
||||||
|
p := &_nErr
|
||||||
|
*p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X5)
|
||||||
|
sink1 = *p
|
||||||
|
}
|
||||||
|
{
|
||||||
|
p := &_nTest
|
||||||
|
*p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X6)
|
||||||
|
sink1 = *p
|
||||||
|
}
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_i += 1
|
||||||
|
goto _30
|
||||||
|
_33:
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_aInfo))
|
||||||
|
crt.Xprintf(tls, str(962), _nErr, _nTest)
|
||||||
|
return _nErr
|
||||||
|
|
||||||
|
_ = _wrMutex
|
||||||
|
_ = _infoTop
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run a SQL statements. Panic if unable.
|
||||||
|
func _run_sql(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _rc, _nRetry int32
|
||||||
|
var _zSql *int8
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _ap []interface{}
|
||||||
|
_pStmt = nil
|
||||||
|
_nRetry = i32(0)
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_p.X4), _zSql, i32(-1), &_pStmt, nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
_worker_trace(tls, _p, str(1036), unsafe.Pointer(_zSql))
|
||||||
|
_1:
|
||||||
|
if store1(&_rc, bin.Xsqlite3_step(tls, _pStmt)) == i32(101) {
|
||||||
|
goto _2
|
||||||
|
}
|
||||||
|
if (_rc&i32(255)) != i32(5) && (_rc&i32(255)) != i32(6) {
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_reset(tls, _pStmt)
|
||||||
|
_nRetry += 1
|
||||||
|
if _nRetry < i32(10) {
|
||||||
|
_worker_trace(tls, _p, str(1049), _nRetry, unsafe.Pointer(_zSql))
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1067), _p.X0, unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
_4:
|
||||||
|
if _rc != i32(100) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1109), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
goto _1
|
||||||
|
_2:
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report an OOM error and die if the argument is NULL
|
||||||
|
func _check_oom(tls *crt.TLS, _x unsafe.Pointer) {
|
||||||
|
if _x == nil {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1151))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a trace message for a worker
|
||||||
|
func _worker_trace(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _zMsg *int8
|
||||||
|
var _ap []interface{}
|
||||||
|
if ((_p.X2) & uint32(i32(4))) == uint32(i32(0)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ap = args
|
||||||
|
_zMsg = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zMsg))
|
||||||
|
_ap = nil
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1166), _p.X0, unsafe.Pointer(_zMsg))
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zMsg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory. If the allocation fails, print an error message and
|
||||||
|
// kill the process.
|
||||||
|
func _safe_malloc(tls *crt.TLS, _sz int32) (r0 unsafe.Pointer) {
|
||||||
|
var _x unsafe.Pointer
|
||||||
|
_x = bin.Xsqlite3_malloc(tls, func() int32 {
|
||||||
|
if _sz > i32(0) {
|
||||||
|
return _sz
|
||||||
|
}
|
||||||
|
return i32(1)
|
||||||
|
}())
|
||||||
|
_check_oom(tls, _x)
|
||||||
|
return _x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each thread runs the following function.
|
||||||
|
func _worker_thread(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) {
|
||||||
|
var _iOuter, _i, _rc int32
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _p *XWorkerInfo
|
||||||
|
_p = (*XWorkerInfo)(_pArg)
|
||||||
|
crt.Xprintf(tls, str(1183), _p.X0)
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
_iOuter = i32(1)
|
||||||
|
_0:
|
||||||
|
if _iOuter > (_p.X1) {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_worker_open_connection(tls, _p, _iOuter)
|
||||||
|
_i = i32(0)
|
||||||
|
_4:
|
||||||
|
if _i >= i32(4) {
|
||||||
|
goto _7
|
||||||
|
}
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), (((_p.X0)+_iOuter)%i32(3))+i32(1))
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(1))%i32(3))+i32(1))
|
||||||
|
_worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(2))%i32(3))+i32(1))
|
||||||
|
_i += 1
|
||||||
|
goto _4
|
||||||
|
_7:
|
||||||
|
_pStmt = _prep_sql(tls, _p.X4, str(1202), _p.X0)
|
||||||
|
_worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
_rc = bin.Xsqlite3_step(tls, _pStmt)
|
||||||
|
if _rc != i32(100) {
|
||||||
|
_worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
goto _9
|
||||||
|
}
|
||||||
|
if bin.Xsqlite3_column_int(tls, _pStmt, i32(0)) != i32(400) {
|
||||||
|
_worker_error(tls, _p, str(1269), bin.Xsqlite3_column_int(tls, _pStmt, i32(0)))
|
||||||
|
}
|
||||||
|
_9:
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
if (_p.X5) != 0 {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
if ((_iOuter + (_p.X0)) % i32(3)) == i32(0) {
|
||||||
|
bin.Xsqlite3_db_release_memory(tls, (*bin.Xsqlite3)(_p.X4))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1286))
|
||||||
|
_run_sql(tls, _p, str(1293))
|
||||||
|
_run_sql(tls, _p, str(1325))
|
||||||
|
_run_sql(tls, _p, str(1357))
|
||||||
|
_run_sql(tls, _p, str(1389))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
if _iOuter == (_p.X0) {
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1399))
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
}
|
||||||
|
_pStmt = _prep_sql(tls, _p.X4, str(1406), _p.X0, _p.X0, _p.X0)
|
||||||
|
_worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
_i = i32(0)
|
||||||
|
_14:
|
||||||
|
if _i >= (_p.X1) {
|
||||||
|
goto _17
|
||||||
|
}
|
||||||
|
_rc = bin.Xsqlite3_step(tls, _pStmt)
|
||||||
|
if _rc != i32(100) {
|
||||||
|
_worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt)))
|
||||||
|
goto _17
|
||||||
|
}
|
||||||
|
crt.Xsched_yield(tls)
|
||||||
|
_i += 1
|
||||||
|
goto _14
|
||||||
|
_17:
|
||||||
|
bin.Xsqlite3_finalize(tls, _pStmt)
|
||||||
|
if (_p.X5) != 0 {
|
||||||
|
goto _3
|
||||||
|
}
|
||||||
|
_worker_delete_all_content(tls, _p, ((_p.X0)+_iOuter)%i32(2))
|
||||||
|
_worker_close_connection(tls, _p)
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X4 */))) = nil
|
||||||
|
_iOuter += 1
|
||||||
|
goto _0
|
||||||
|
_3:
|
||||||
|
_worker_close_connection(tls, _p)
|
||||||
|
crt.Xprintf(tls, str(1552), _p.X0)
|
||||||
|
crt.Xfflush(tls, (*crt.XFILE)(Xstdout))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the database connection for WorkerInfo. The order in which
|
||||||
|
// the files are opened is a function of the tid value.
|
||||||
|
func _worker_open_connection(tls *crt.TLS, _p *XWorkerInfo, _iCnt int32) {
|
||||||
|
var _x, _rc int32
|
||||||
|
var _zFile *int8
|
||||||
|
_x = ((_p.X0) + _iCnt) % i32(6)
|
||||||
|
_zFile = bin.Xsqlite3_mprintf(tls, str(1572), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(0))))))
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zFile))
|
||||||
|
_worker_trace(tls, _p, str(1586), unsafe.Pointer(_zFile))
|
||||||
|
_rc = bin.Xsqlite3_open_v2(tls, _zFile, (**bin.Xsqlite3)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p))+uintptr(24 /* X4 */))))), i32(131074), nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1594), unsafe.Pointer(_zFile), _p.X0)
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zFile))
|
||||||
|
_run_sql(tls, _p, str(1634))
|
||||||
|
bin.Xsqlite3_busy_timeout(tls, (*bin.Xsqlite3)(_p.X4), i32(10000))
|
||||||
|
_run_sql(tls, _p, str(1662))
|
||||||
|
_run_sql(tls, _p, str(1686), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(1))))))
|
||||||
|
_run_sql(tls, _p, str(1717), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(2))))))
|
||||||
|
}
|
||||||
|
|
||||||
|
var _worker_open_connectionØ00aOrderØ001 [6][3]uint8
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_worker_open_connectionØ00aOrderØ001 = [6][3]uint8{[3]uint8{u8(1), u8(2), u8(3)}, [3]uint8{u8(1), u8(3), u8(2)}, [3]uint8{u8(2), u8(1), u8(3)}, [3]uint8{u8(2), u8(3), u8(1)}, [3]uint8{u8(3), u8(1), u8(2)}, [3]uint8{u8(3), u8(2), u8(1)}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rows mn through mx in table iTab for the given worker
|
||||||
|
func _worker_add_content(tls *crt.TLS, _p *XWorkerInfo, _mn int32, _mx int32, _iTab int32) {
|
||||||
|
var _zTabDef *int8
|
||||||
|
switch _iTab {
|
||||||
|
case i32(1):
|
||||||
|
goto _1
|
||||||
|
case i32(2):
|
||||||
|
goto _2
|
||||||
|
case i32(3):
|
||||||
|
goto _3
|
||||||
|
default:
|
||||||
|
goto _4
|
||||||
|
}
|
||||||
|
|
||||||
|
_1:
|
||||||
|
_zTabDef = str(1748)
|
||||||
|
goto _4
|
||||||
|
_2:
|
||||||
|
_zTabDef = str(1765)
|
||||||
|
goto _4
|
||||||
|
_3:
|
||||||
|
_zTabDef = str(1782)
|
||||||
|
goto _4
|
||||||
|
_4:
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1799), _mn, _mx, unsafe.Pointer(_zTabDef), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare a single SQL query
|
||||||
|
func _prep_sql(tls *crt.TLS, _db unsafe.Pointer, _zFormat *int8, args ...interface{}) (r0 unsafe.Pointer) {
|
||||||
|
var _rc int32
|
||||||
|
var _zSql *int8
|
||||||
|
var _pStmt unsafe.Pointer
|
||||||
|
var _ap []interface{}
|
||||||
|
_pStmt = nil
|
||||||
|
_ap = args
|
||||||
|
_zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
_check_oom(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
_rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_db), _zSql, i32(-1), &_pStmt, nil)
|
||||||
|
if _rc != i32(0) {
|
||||||
|
crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_db)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_db))), unsafe.Pointer(_zSql))
|
||||||
|
crt.Xexit(tls, i32(1))
|
||||||
|
}
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql))
|
||||||
|
return _pStmt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an error message on a worker
|
||||||
|
func _worker_error(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) {
|
||||||
|
var _ap []interface{}
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(32 /* X5 */))) += 1
|
||||||
|
bin.Xsqlite3_free(tls, (unsafe.Pointer)(_p.X7))
|
||||||
|
_ap = args
|
||||||
|
*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(40 /* X7 */))) = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap)
|
||||||
|
_ap = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all content in the three databases associated with a
|
||||||
|
// single thread. Make this happen all in a single transaction if
|
||||||
|
// inTrans is true, or separately for each database if inTrans is
|
||||||
|
// false.
|
||||||
|
func _worker_delete_all_content(tls *crt.TLS, _p *XWorkerInfo, _inTrans int32) {
|
||||||
|
if _inTrans != 0 {
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1947))
|
||||||
|
_run_sql(tls, _p, str(1953), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(1981), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(2009), _p.X0)
|
||||||
|
_run_sql(tls, _p, str(2037))
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
goto _1
|
||||||
|
}
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1953), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(1981), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
_run_sql(tls, _p, str(2009), _p.X0)
|
||||||
|
crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9))
|
||||||
|
*(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1
|
||||||
|
_1:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the worker database connection
|
||||||
|
func _worker_close_connection(tls *crt.TLS, _p *XWorkerInfo) {
|
||||||
|
if (_p.X4) != nil {
|
||||||
|
_worker_trace(tls, _p, str(2044))
|
||||||
|
bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_p.X4))
|
||||||
|
*(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X4 */))) = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bool2int(b bool) int32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed.
|
||||||
|
func i16(n int16) int16 { return n }
|
||||||
|
func i32(n int32) int32 { return n }
|
||||||
|
func i64(n int64) int64 { return n }
|
||||||
|
func i8(n int8) int8 { return n }
|
||||||
|
func init() { nzf32 *= -1; nzf64 *= -1 }
|
||||||
|
func u16(n uint16) uint16 { return n }
|
||||||
|
func u32(n uint32) uint32 { return n }
|
||||||
|
func u64(n uint64) uint64 { return n }
|
||||||
|
func u8(n byte) byte { return n }
|
||||||
|
|
||||||
|
var inf = math.Inf(1)
|
||||||
|
var nzf32 float32 // -0.0
|
||||||
|
var nzf64 float64 // -0.0
|
||||||
|
var sink1 int32 //TODO report GC bug
|
||||||
|
var sink0 uint32 //TODO report GC bug
|
||||||
|
func store1(p *int32, v int32) int32 { *p = v; return v }
|
||||||
|
|
||||||
|
type XWorkerInfo struct {
|
||||||
|
X0 int32
|
||||||
|
X1 int32
|
||||||
|
X2 uint32
|
||||||
|
X3 unsafe.Pointer
|
||||||
|
X4 unsafe.Pointer
|
||||||
|
X5 int32
|
||||||
|
X6 int32
|
||||||
|
X7 *int8
|
||||||
|
X8 uint64
|
||||||
|
X9 unsafe.Pointer
|
||||||
|
} // t2 struct{int32,int32,uint32,*struct{},*struct{},int32,int32,*int8,uint64,*struct{}}
|
||||||
|
func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) }
|
||||||
|
|
||||||
|
var strTab = []byte("-multithread\x00-serialized\x00-wal\x00-trace\x00unknown command-line option: %s\x0a\x00minimum of 2 threads\x0a\x00extra command-line argument: \"%s\"\x0a\x00usage: %s ?OPTIONS? N\x0aN is the number of threads and must be at least 2.\x0aOptions:\x0a --serialized\x0a --multithread\x0a --wal\x0a --trace\x0a\x00requires a threadsafe build of SQLite\x0a\x00tt4-test1.db\x00tt4-test2.db\x00tt4-test3.db\x00Unable to open test database: tt4-test2.db\x0a\x00PRAGMA journal_mode=WAL\x00PRAGMA synchronous=OFF\x00CREATE TABLE IF NOT EXISTS t1(tid INTEGER, sp, a, b, c)\x00CREATE INDEX t1tid ON t1(tid)\x00CREATE INDEX t1ab ON t1(a,b)\x00ATTACH 'tt4-test2.db' AS 'test2'\x00CREATE TABLE IF NOT EXISTS test2.t2(tid INTEGER, sp, d, e, f)\x00CREATE INDEX test2.t2tid ON t2(tid)\x00CREATE INDEX test2.t2de ON t2(d,e)\x00ATTACH 'tt4-test3.db' AS 'test3'\x00CREATE TABLE IF NOT EXISTS test3.t3(tid INTEGER, sp, x, y, z)\x00CREATE INDEX test3.t3tid ON t3(tid)\x00CREATE INDEX test3.t3xy ON t3(x,y)\x00thread creation failed for thread %d\x0a\x00Joined thread %d: %d errors in %d tests\x00: %s\x0a\x00\x0a\x00Total %d errors in %d tests\x0a\x00SQL error (%d,%d): %s\x0aWhile preparing: [%s]\x0a\x00running [%s]\x00retry %d for [%s]\x00Deadlock in thread %d while running [%s]\x0a\x00SQL error (%d,%d): %s\x0aWhile running [%s]\x0a\x00out of memory\x0a\x00TRACE(%02d): %s\x0a\x00worker %d startup\x0a\x00SELECT count(a) FROM t1 WHERE tid=%d\x00query [%s]\x00Failed to step: %s\x00Wrong result: %d\x00BEGIN;\x00UPDATE t1 SET c=NULL WHERE a=55\x00UPDATE t2 SET f=NULL WHERE d=42\x00UPDATE t3 SET z=NULL WHERE x=31\x00ROLLBACK;\x00VACUUM\x00SELECT t1.rowid, t2.rowid, t3.rowid FROM t1, t2, t3 WHERE t1.tid=%d AND t2.tid=%d AND t3.tid=%d AND t1.a<>t2.d AND t2.d<>t3.x ORDER BY 1, 2, 3\x00worker %d finished\x0a\x00tt4-test%d.db\x00open %s\x00sqlite_open_v2(%s) failed on thread %d\x0a\x00PRAGMA read_uncommitted=ON;\x00PRAGMA synchronous=OFF;\x00ATTACH 'tt4-test%d.db' AS aux1\x00ATTACH 'tt4-test%d.db' AS aux2\x00t1(tid,sp,a,b,c)\x00t2(tid,sp,d,e,f)\x00t3(tid,sp,x,y,z)\x00WITH RECURSIVE\x0a c(i) AS (VALUES(%d) UNION ALL SELECT i+1 FROM c WHERE i<%d)\x0aINSERT INTO %s SELECT %d, zeroblob(3000), i, printf('%%d',i), i FROM c;\x00BEGIN\x00DELETE FROM t1 WHERE tid=%d\x00DELETE FROM t2 WHERE tid=%d\x00DELETE FROM t3 WHERE tid=%d\x00COMMIT\x00close\x00")
|
||||||
7
main.c
7
main.c
@@ -6,8 +6,11 @@
|
|||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
static void use(int, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Prevent the linker from optimizing out everything.
|
use(0, sqlite3_exec, sqlite3_enable_load_extension);
|
||||||
int (*f) (int, ...) = sqlite3_config;
|
|
||||||
}
|
}
|
||||||
|
|||||||
8
sqlite.h
Normal file
8
sqlite.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// Help some old tests work.
|
||||||
|
|
||||||
|
#include "sqlite3.h"
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
#define sqlite sqlite3
|
||||||
46
testdata/mptest/config01.test
vendored
Normal file
46
testdata/mptest/config01.test
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
** Configure five tasks in different ways, then run tests.
|
||||||
|
*/
|
||||||
|
--if vfsname() GLOB 'unix'
|
||||||
|
PRAGMA page_size=8192;
|
||||||
|
--task 1
|
||||||
|
PRAGMA journal_mode=PERSIST;
|
||||||
|
PRAGMA mmap_size=0;
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
PRAGMA journal_mode=TRUNCATE;
|
||||||
|
PRAGMA mmap_size=28672;
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
PRAGMA journal_mode=MEMORY;
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
PRAGMA journal_mode=OFF;
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
PRAGMA mmap_size(268435456);
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--wait all
|
||||||
|
PRAGMA page_size=16384;
|
||||||
|
VACUUM;
|
||||||
|
CREATE TABLE pgsz(taskid, sz INTEGER);
|
||||||
|
--task 1
|
||||||
|
INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--wait all
|
||||||
|
SELECT sz FROM pgsz;
|
||||||
|
--match 16384 16384 16384 16384 16384
|
||||||
123
testdata/mptest/config02.test
vendored
Normal file
123
testdata/mptest/config02.test
vendored
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
** Configure five tasks in different ways, then run tests.
|
||||||
|
*/
|
||||||
|
PRAGMA page_size=512;
|
||||||
|
--task 1
|
||||||
|
PRAGMA mmap_size=0;
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
PRAGMA mmap_size=28672;
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
PRAGMA mmap_size=8192;
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
PRAGMA mmap_size=65536;
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
PRAGMA mmap_size=268435456;
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
PRAGMA page_size=1024;
|
||||||
|
VACUUM;
|
||||||
|
CREATE TABLE pgsz(taskid, sz INTEGER);
|
||||||
|
--task 1
|
||||||
|
INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
--wait all
|
||||||
|
SELECT sz FROM pgsz;
|
||||||
|
--match 1024 1024 1024 1024 1024
|
||||||
|
PRAGMA page_size=2048;
|
||||||
|
VACUUM;
|
||||||
|
DELETE FROM pgsz;
|
||||||
|
--task 1
|
||||||
|
INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
--wait all
|
||||||
|
SELECT sz FROM pgsz;
|
||||||
|
--match 2048 2048 2048 2048 2048
|
||||||
|
PRAGMA page_size=8192;
|
||||||
|
VACUUM;
|
||||||
|
DELETE FROM pgsz;
|
||||||
|
--task 1
|
||||||
|
INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
--wait all
|
||||||
|
SELECT sz FROM pgsz;
|
||||||
|
--match 8192 8192 8192 8192 8192
|
||||||
|
PRAGMA page_size=16384;
|
||||||
|
VACUUM;
|
||||||
|
DELETE FROM pgsz;
|
||||||
|
--task 1
|
||||||
|
INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
|
||||||
|
--end
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
--wait all
|
||||||
|
SELECT sz FROM pgsz;
|
||||||
|
--match 16384 16384 16384 16384 16384
|
||||||
|
PRAGMA auto_vacuum=FULL;
|
||||||
|
VACUUM;
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
|
--wait all
|
||||||
|
PRAGMA auto_vacuum=FULL;
|
||||||
|
PRAGMA page_size=512;
|
||||||
|
VACUUM;
|
||||||
|
--source multiwrite01.test
|
||||||
|
--source crash02.subtest
|
||||||
106
testdata/mptest/crash01.test
vendored
Normal file
106
testdata/mptest/crash01.test
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* Test cases involving incomplete transactions that must be rolled back.
|
||||||
|
*/
|
||||||
|
--task 1
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t1 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t1;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t1;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t1 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t1b ON t1(b);
|
||||||
|
SELECT a FROM t1 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
--wait 1
|
||||||
|
--task 2
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||||
|
INSERT INTO t2 SELECT a, b FROM t1;
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t2;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t2 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t2b ON t2(b);
|
||||||
|
SELECT a FROM t2 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
|
||||||
|
INSERT INTO t3 SELECT a, b FROM t1;
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t3;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t3 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t3b ON t3(b);
|
||||||
|
SELECT a FROM t3 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
DROP TABLE IF EXISTS t4;
|
||||||
|
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
|
||||||
|
INSERT INTO t4 SELECT a, b FROM t1;
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t4;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t4 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t4b ON t4(b);
|
||||||
|
SELECT a FROM t4 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
DROP TABLE IF EXISTS t5;
|
||||||
|
CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
|
||||||
|
INSERT INTO t5 SELECT a, b FROM t1;
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t5;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t5 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t5b ON t5(b);
|
||||||
|
SELECT a FROM t5 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
--wait all
|
||||||
|
/* After the database file has been set up, run the crash2 subscript
|
||||||
|
** multiple times. */
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
|
--source crash02.subtest
|
||||||
53
testdata/mptest/crash02.subtest
vendored
Normal file
53
testdata/mptest/crash02.subtest
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
** This script is called from crash01.test and config02.test and perhaps other
|
||||||
|
** script. After the database file has been set up, make a big rollback
|
||||||
|
** journal in client 1, then crash client 1.
|
||||||
|
** Then in the other clients, do an integrity check.
|
||||||
|
*/
|
||||||
|
--task 1 leave-hot-journal
|
||||||
|
--sleep 5
|
||||||
|
--finish
|
||||||
|
PRAGMA cache_size=10;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t1 SET b=randomblob(20000);
|
||||||
|
UPDATE t2 SET b=randomblob(20000);
|
||||||
|
UPDATE t3 SET b=randomblob(20000);
|
||||||
|
UPDATE t4 SET b=randomblob(20000);
|
||||||
|
UPDATE t5 SET b=randomblob(20000);
|
||||||
|
UPDATE t1 SET b=NULL;
|
||||||
|
UPDATE t2 SET b=NULL;
|
||||||
|
UPDATE t3 SET b=NULL;
|
||||||
|
UPDATE t4 SET b=NULL;
|
||||||
|
UPDATE t5 SET b=NULL;
|
||||||
|
--print Task one crashing an incomplete transaction
|
||||||
|
--exit 1
|
||||||
|
--end
|
||||||
|
--task 2 integrity_check-2
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
--sleep 100
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 3 integrity_check-3
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
--sleep 100
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 4 integrity_check-4
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
--sleep 100
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 5 integrity_check-5
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
--sleep 100
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
415
testdata/mptest/multiwrite01.test
vendored
Normal file
415
testdata/mptest/multiwrite01.test
vendored
Normal file
@@ -0,0 +1,415 @@
|
|||||||
|
/*
|
||||||
|
** This script sets up five different tasks all writing and updating
|
||||||
|
** the database at the same time, but each in its own table.
|
||||||
|
*/
|
||||||
|
--task 1 build-t1
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t1 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t1;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t1;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t1 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t1b ON t1(b);
|
||||||
|
SELECT a FROM t1 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
|
||||||
|
--task 2 build-t2
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t2 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t2 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t2 SELECT a+2, randomblob(1500) FROM t2;
|
||||||
|
INSERT INTO t2 SELECT a+4, randomblob(1500) FROM t2;
|
||||||
|
INSERT INTO t2 SELECT a+8, randomblob(1500) FROM t2;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t2 SELECT a+16, randomblob(1500) FROM t2;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t2 SELECT a+32, randomblob(1500) FROM t2;
|
||||||
|
SELECT count(*) FROM t2;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t2;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t2 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t2;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t2 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t2b ON t2(b);
|
||||||
|
SELECT a FROM t2 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
--task 3 build-t3
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t3 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t3 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t3 SELECT a+2, randomblob(1500) FROM t3;
|
||||||
|
INSERT INTO t3 SELECT a+4, randomblob(1500) FROM t3;
|
||||||
|
INSERT INTO t3 SELECT a+8, randomblob(1500) FROM t3;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t3 SELECT a+16, randomblob(1500) FROM t3;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t3 SELECT a+32, randomblob(1500) FROM t3;
|
||||||
|
SELECT count(*) FROM t3;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t3;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t3 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t3;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t3 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t3b ON t3(b);
|
||||||
|
SELECT a FROM t3 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
--task 4 build-t4
|
||||||
|
DROP TABLE IF EXISTS t4;
|
||||||
|
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t4 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t4 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t4 SELECT a+2, randomblob(1500) FROM t4;
|
||||||
|
INSERT INTO t4 SELECT a+4, randomblob(1500) FROM t4;
|
||||||
|
INSERT INTO t4 SELECT a+8, randomblob(1500) FROM t4;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t4 SELECT a+16, randomblob(1500) FROM t4;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t4 SELECT a+32, randomblob(1500) FROM t4;
|
||||||
|
SELECT count(*) FROM t4;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t4;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t4 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t4;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t4 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t4b ON t4(b);
|
||||||
|
SELECT a FROM t4 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
--task 5 build-t5
|
||||||
|
DROP TABLE IF EXISTS t5;
|
||||||
|
CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t5 VALUES(1, randomblob(2000));
|
||||||
|
INSERT INTO t5 VALUES(2, randomblob(1000));
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t5 SELECT a+2, randomblob(1500) FROM t5;
|
||||||
|
INSERT INTO t5 SELECT a+4, randomblob(1500) FROM t5;
|
||||||
|
INSERT INTO t5 SELECT a+8, randomblob(1500) FROM t5;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t5 SELECT a+16, randomblob(1500) FROM t5;
|
||||||
|
--sleep 1
|
||||||
|
INSERT INTO t5 SELECT a+32, randomblob(1500) FROM t5;
|
||||||
|
SELECT count(*) FROM t5;
|
||||||
|
--match 64
|
||||||
|
SELECT avg(length(b)) FROM t5;
|
||||||
|
--match 1500.0
|
||||||
|
--sleep 2
|
||||||
|
UPDATE t5 SET b='x'||a||'y';
|
||||||
|
SELECT sum(length(b)) FROM t5;
|
||||||
|
--match 247
|
||||||
|
SELECT a FROM t5 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
CREATE INDEX t5b ON t5(b);
|
||||||
|
SELECT a FROM t5 WHERE b='x17y';
|
||||||
|
--match 17
|
||||||
|
SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
|
||||||
|
--match 29 28 27 26 25
|
||||||
|
--end
|
||||||
|
|
||||||
|
--wait all
|
||||||
|
SELECT count(*), sum(length(b)) FROM t1;
|
||||||
|
--match 64 247
|
||||||
|
SELECT count(*), sum(length(b)) FROM t2;
|
||||||
|
--match 64 247
|
||||||
|
SELECT count(*), sum(length(b)) FROM t3;
|
||||||
|
--match 64 247
|
||||||
|
SELECT count(*), sum(length(b)) FROM t4;
|
||||||
|
--match 64 247
|
||||||
|
SELECT count(*), sum(length(b)) FROM t5;
|
||||||
|
--match 64 247
|
||||||
|
|
||||||
|
--task 1
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
|
|
||||||
|
--task 5
|
||||||
|
DROP INDEX t5b;
|
||||||
|
--sleep 5
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
CREATE INDEX t5b ON t5(b DESC);
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
DROP INDEX t3b;
|
||||||
|
--sleep 5
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
CREATE INDEX t3b ON t3(b DESC);
|
||||||
|
--end
|
||||||
|
--task 1
|
||||||
|
DROP INDEX t1b;
|
||||||
|
--sleep 5
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
CREATE INDEX t1b ON t1(b DESC);
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
DROP INDEX t2b;
|
||||||
|
--sleep 5
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
CREATE INDEX t2b ON t2(b DESC);
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
DROP INDEX t4b;
|
||||||
|
--sleep 5
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
CREATE INDEX t4b ON t4(b DESC);
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
|
|
||||||
|
--task 1
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
|
|
||||||
|
VACUUM;
|
||||||
|
PRAGMA integrity_check(10);
|
||||||
|
--match ok
|
||||||
|
|
||||||
|
--task 1
|
||||||
|
UPDATE t1 SET b=randomblob(20000);
|
||||||
|
--sleep 5
|
||||||
|
UPDATE t1 SET b='x'||a||'y';
|
||||||
|
SELECT a FROM t1 WHERE b='x63y';
|
||||||
|
--match 63
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
UPDATE t2 SET b=randomblob(20000);
|
||||||
|
--sleep 5
|
||||||
|
UPDATE t2 SET b='x'||a||'y';
|
||||||
|
SELECT a FROM t2 WHERE b='x63y';
|
||||||
|
--match 63
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
UPDATE t3 SET b=randomblob(20000);
|
||||||
|
--sleep 5
|
||||||
|
UPDATE t3 SET b='x'||a||'y';
|
||||||
|
SELECT a FROM t3 WHERE b='x63y';
|
||||||
|
--match 63
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
UPDATE t4 SET b=randomblob(20000);
|
||||||
|
--sleep 5
|
||||||
|
UPDATE t4 SET b='x'||a||'y';
|
||||||
|
SELECT a FROM t4 WHERE b='x63y';
|
||||||
|
--match 63
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
UPDATE t5 SET b=randomblob(20000);
|
||||||
|
--sleep 5
|
||||||
|
UPDATE t5 SET b='x'||a||'y';
|
||||||
|
SELECT a FROM t5 WHERE b='x63y';
|
||||||
|
--match 63
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
|
|
||||||
|
--task 1
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 5
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 3
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 2
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--task 4
|
||||||
|
SELECT t1.a FROM t1, t2
|
||||||
|
WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
|
||||||
|
ORDER BY t1.a LIMIT 4
|
||||||
|
--match 33 34 35 36
|
||||||
|
SELECT t3.a FROM t3, t4
|
||||||
|
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||||
|
ORDER BY t3.a LIMIT 7
|
||||||
|
--match 45 46 47 48 49 50 51
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
--match ok
|
||||||
|
--end
|
||||||
|
--wait all
|
||||||
Reference in New Issue
Block a user