mirror of
				https://github.com/glebarez/go-sqlite.git
				synced 2025-10-31 19:13:06 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			188 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			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()
 | |
| }
 | 
