0
0
mirror of https://gitlab.com/cznic/sqlite.git synced 2025-04-27 23:07:44 +00:00
Files
2021-01-15 17:22:10 +01:00

188 lines
3.3 KiB
Go

// Copyright 2032 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"database/sql"
"fmt"
"math"
"time"
"modernc.org/sqlite/tpch/driver"
)
func cpDB(sut driver.SUT, src, dest *sql.DB) error {
for _, v := range []struct {
t, i string
int
}{
{"customer", sut.InsertCustomer(), 8},
{"lineitem", sut.InsertLineItem(), 16},
{"nation", sut.InsertNation(), 4},
{"orders", sut.InsertOrders(), 9},
{"part", sut.InsertPart(), 9},
{"partsupp", sut.InsertPartSupp(), 5},
{"region", sut.InsertRegion(), 3},
{"supplier", sut.InsertSupplier(), 7},
} {
if err := cpTable(src, dest, v.t, v.i, v.int); err != nil {
return err
}
}
return nil
}
func cpTable(src, dest *sql.DB, tn, ins string, ncols int) (err error) {
rows, err := src.Query(fmt.Sprintf("select * from %s", tn))
if err != nil {
return err
}
defer func() {
if e := rows.Close(); e != nil && err == nil {
err = e
}
}()
var tx *sql.Tx
var stmt *sql.Stmt
row := make([]interface{}, ncols)
data := make([]interface{}, ncols)
for i := range data {
data[i] = &row[i]
}
for i := 0; rows.Next(); i++ {
if i%1000 == 0 {
if i != 0 {
if err = tx.Commit(); err != nil {
return err
}
}
if tx, err = dest.Begin(); err != nil {
return err
}
if stmt, err = tx.Prepare(ins); err != nil {
return err
}
}
if err = rows.Scan(data...); err != nil {
return err
}
for i, v := range row {
switch x := v.(type) {
case time.Time:
case int64:
case []byte:
row[i] = string(x)
default:
panic("TODO")
}
}
if _, err = stmt.Exec(row...); err != nil {
return err
}
}
if err = rows.Err(); err != nil {
return err
}
return tx.Commit()
}
func run(sut driver.SUT, mem bool, n, sf int, verbose bool) (err error) {
pth := pthForSUT(sut, sf)
if err := sut.SetWD(pth); err != nil {
return err
}
db, err := sut.OpenDB()
if err != nil {
return err
}
defer func(db *sql.DB) {
if cerr := db.Close(); cerr != nil && err == nil {
err = cerr
}
}(db)
if mem {
msut, mdb, err := sut.OpenMem()
if err != nil {
return err
}
if err = msut.CreateTables(); err != nil {
return err
}
if err = cpDB(sut, db, mdb); err != nil {
return err
}
sut, db = msut, mdb
}
rng := newRng(0, math.MaxInt64)
rng.r.Seed(time.Now().UnixNano())
t0 := time.Now()
defer func() {
fmt.Println(time.Since(t0))
}()
switch n {
case 1:
return exec(db, 10, sut.Q1(), verbose, rng.randomValue(60, 120))
case 2:
return exec(db, 8, sut.Q2(), verbose, rng.randomValue(1, 50), rng.types(), rng.regions())
default:
return fmt.Errorf("No query/test #%d", n)
}
}
func exec(db *sql.DB, ncols int, q string, verbose bool, arg ...interface{}) error {
rec := make([]interface{}, ncols)
data := make([]interface{}, ncols)
for i := range data {
data[i] = &rec[i]
}
rows, err := db.Query(q, arg...)
if err != nil {
return err
}
defer func() {
if e := rows.Close(); e != nil && err == nil {
err = e
}
}()
for rows.Next() {
if !verbose {
continue
}
if err = rows.Scan(data...); err != nil {
return err
}
for i, v := range rec {
if b, ok := v.([]byte); ok {
rec[i] = string(b)
}
}
fmt.Println(rec)
}
return rows.Err()
}