You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: session.go
    path of file: ./repos/db/internal/sqladapter
    
    the code of the file until where you have to start completion: package sqladapter

import (
	"bytes"
	"context"
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"math"
	"reflect"
	"strconv"
	"sync"
	"sync/atomic"
	"time"

	db "github.com/upper/db/v4"
	"github.com/upper/db/v4/internal/cache"
	"github.com/upper/db/v4/internal/sqladapter/compat"
	"github.com/upper/db/v4/internal/sqladapter/exql"
	"github.com/upper/db/v4/internal/sqlbuilder"
)

var (
	lastSessID uint64
	lastTxID   uint64
)

var (
	slowQueryThreshold          = time.Millisecond * 200
	retryTransactionWaitTime    = time.Millisecond * 10
	retryTransactionMaxWaitTime = time.Second * 1
)

// hasCleanUp is implemented by structs that have a clean up routine that needs
// to be called before Close().
type hasCleanUp interface {
	CleanUp() error
}

// statementExecer allows the adapter to have its own exec statement.
type statementExecer interface {
	StatementExec(sess Session, ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}

// statementCompiler transforms an internal statement into a format
// database/sql can understand.
type statementCompiler interface {
	CompileStatement(sess Session, stmt *exql.Statement, args []interface{}) (string, []interface{}, error)
}

// sessValueConverter converts values before being passed to the underlying driver.
type sessValueConverter interface {
	ConvertVal
    
func (sess *sessionWithContext) StatementExec(ctx context.Context, stmt *exql.Statement, args ...interface{}) (res sql.Result, err error) {
	var query string

	defer func(start time.Time) {
		status := db.QueryStatus{
			TxID:     sess.txID,
			SessID:   sess.sessID,
			RawQuery: query,
			Args:     args,
			Err:      err,
			Start:    start,
			End:      time.Now(),
			Context:  ctx,
		}

		if res != nil {
			if rowsAffected, err := res.RowsAffected(); err == nil {
				status.RowsAffected = &rowsAffected
			}

			if lastInsertID, err := res.LastInsertId(); err == nil {
				status.LastInsertID = &lastInsertID
			}
		}

		queryLog(&status)
	}(time.Now())

	if execer, ok := sess.adapter.(statementExecer); ok {
		query, args, err = sess.compileStatement(stmt, args)
		if err != nil {
			return nil, err
		}
		res, err = execer.StatementExec(sess, ctx, query, args...)
		return
	}

	tx := sess.Transaction()
	if sess.Settings.PreparedStatementCacheEnabled() && tx == nil {
		var p *Stmt
		if p, query, args, err = sess.prepareStatement(ctx, stmt, args); err != nil {
			return nil, err
		}
		defer p.Close()

		res, err = compat.PreparedExecContext(p, ctx, args)
		return
	}

	query, args, err = sess.compileStatement(stmt, args)
	if err != nil {
		return nil, err
	}

	if tx != nil {
		res, err = compat.ExecContext(tx, ctx, query, args)
		return
	}

	res, err = compat.ExecContext(sess.sqlDB, ctx, query, args)
	return
}