package main

import (
	"bytes"
	"database/sql"
	"fmt"
	"math/rand"

	"github.com/pingcap/errors"
	. "github.com/pingcap/tidb-test/large_txn"
)

type PrepareTask struct {
	BasePrepareTask
}

func (_ PrepareTask) CreateTable(db *sql.DB) error {
	sql1 := `create table if not exists sbtest1 (
id int(11) not null primary key,
k int(11) not null,
c char(120) not null default '',
pad char(255) not null default '')`
	_, err := db.Exec(sql1)
	if err != nil {
		return errors.WithStack(err)
	}

	sql2 := `create table if not exists sbtest2 (
id int(11) not null,
k int(11) not null,
c char(120) not null default '',
pad char(255) not null default '',
index i_k(k))`
	_, err = db.Exec(sql2)
	if err != nil {
		return errors.WithStack(err)
	}
	return nil
}

const ascii = "abcdefghijklmnopqrstuvwxyz1234567890"

func randString(n int) string {
	var buf bytes.Buffer
	for i := 0; i < n; i++ {
		pos := rand.Intn(len(ascii))
		buf.WriteByte(ascii[pos])
	}
	return buf.String()
}

func (task PrepareTask) InsertData(worker *Worker, db *sql.DB) error {
	var buf bytes.Buffer
	pkID := worker.ID
	for i := 0; i < task.InsertCount; i++ {
		buf.Reset()
		buf.WriteString("insert into sbtest1 (id, k, c, pad) values ")
		for i := 0; i < task.RowsEachInsert; i++ {
			pkID = worker.Count + pkID
			dot := ""
			if i > 0 {
				dot = ", "
			}
			fmt.Fprintf(&buf, "%s(%d, %d, '%s', '%s')", dot, pkID, rand.Intn(512), randString(32), randString(32))
		}

		_, err := db.Exec(buf.String())
		if err != nil {
			return errors.WithStack(err)
		}
	}
	return nil
}

func main() {
	// You can fill all the config content as you wish.
	conf := &Config{
		Conn: DefaultConnConfig(),
		Prepare: PrepareConfig{
			WorkerCount: 4,
			Task: PrepareTask{
				BasePrepareTask{
					InsertCount:    1 << 30 / 512 / 4 / 50,
					RowsEachInsert: 50,
				},
			},
		},
		Run: RunConfig{
			Large: LargeTxnConfig{
				TxnMode: Pessimistic,
				Task:    InsertIntoSelect{},
			},
			Small: SmallTxnConfig{
				WorkerCount: 32,
				TxnMode:     Pessimistic,
				Task:        SinglePointDoubleReadF("sbtest2", 512),
			},
		},
		Clean: DummyCleanTask{},
	}

	Run(conf)
}
