Add support for prepared statement caching.

This commit is contained in:
go-jet 2024-03-07 18:01:31 +01:00
parent 1b63280b74
commit 0918e5503e
30 changed files with 603 additions and 289 deletions

View file

@ -2,9 +2,9 @@ package mysql
import (
"context"
"database/sql"
"github.com/go-jet/jet/v2/internal/testutils"
. "github.com/go-jet/jet/v2/mysql"
"github.com/go-jet/jet/v2/qrm"
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/table"
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/test_sample/model"
. "github.com/go-jet/jet/v2/tests/.gentestdata/mysql/test_sample/table"
@ -113,7 +113,7 @@ DELETE /*+ QB_NAME(deleteIns) MRR(link) */ FROM test_sample.link
WHERE link.name IN ('Gmail', 'Outlook');
`)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
})

View file

@ -2,9 +2,9 @@ package mysql
import (
"context"
"database/sql"
"github.com/go-jet/jet/v2/internal/testutils"
. "github.com/go-jet/jet/v2/mysql"
"github.com/go-jet/jet/v2/qrm"
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/test_sample/model"
. "github.com/go-jet/jet/v2/tests/.gentestdata/mysql/test_sample/table"
"github.com/stretchr/testify/require"
@ -29,7 +29,7 @@ VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT
101, "http://www.google.com", "Google",
102, "http://www.yahoo.com", "Yahoo", nil)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := insertQuery.Exec(tx)
require.NoError(t, err)
requireLogged(t, insertQuery)
@ -74,7 +74,7 @@ VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT
`,
100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
requireLogged(t, stmt)
@ -108,7 +108,7 @@ VALUES ('http://www.duckduckgo.com', 'Duck Duck go');
`,
"http://www.duckduckgo.com", "Duck Duck go")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := query.Exec(tx)
require.NoError(t, err)
})
@ -130,7 +130,7 @@ INSERT INTO test_sample.link
VALUES (1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
`, int32(1000), "http://www.duckduckgo.com", "Duck Duck go", nil)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := query.Exec(tx)
require.NoError(t, err)
})
@ -166,7 +166,7 @@ VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
"http://www.google.com", "Google",
"http://www.yahoo.com", "Yahoo")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := query.Exec(tx)
require.NoError(t, err)
})
@ -201,7 +201,7 @@ VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
"http://www.google.com", "Google", nil,
"http://www.yahoo.com", "Yahoo", nil)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
})
@ -225,7 +225,7 @@ INSERT INTO test_sample.link (url, name) (
);
`, int64(1))
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := query.Exec(tx)
require.NoError(t, err)
@ -261,7 +261,7 @@ ON DUPLICATE KEY UPDATE id = (link.id + ?),
randId, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
int64(11), "PostgreSQL Tutorial 2")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
@ -320,7 +320,7 @@ ON DUPLICATE KEY UPDATE id = (link.id + ?),
description = new.description;
`)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
@ -352,9 +352,12 @@ func TestInsertWithQueryContext(t *testing.T) {
time.Sleep(10 * time.Millisecond)
var dest []model.Link
err := stmt.QueryContext(ctx, db, &dest)
require.Error(t, err, "context deadline exceeded")
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
err := stmt.QueryContext(ctx, tx, &dest)
require.Error(t, err, "context deadline exceeded")
})
}
func TestInsertWithExecContext(t *testing.T) {
@ -366,9 +369,10 @@ func TestInsertWithExecContext(t *testing.T) {
time.Sleep(10 * time.Millisecond)
_, err := stmt.ExecContext(ctx, db)
require.Error(t, err, "context deadline exceeded")
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.ExecContext(ctx, tx)
require.Error(t, err, "context deadline exceeded")
})
}
func TestInsertOptimizerHints(t *testing.T) {
@ -385,7 +389,7 @@ INSERT /*+ QB_NAME(qbIns) NO_ICP(link) */ INTO test_sample.link (url, name, desc
VALUES ('http://www.google.com', 'Google', NULL);
`)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
})

View file

@ -14,10 +14,14 @@ func TestLockRead(t *testing.T) {
testutils.AssertStatementSql(t, query, `
LOCK TABLES dvds.customer READ;
`)
_, err := query.Exec(db)
tx, err := db.DB.Begin() // can't prepare LOCK statement
require.NoError(t, err)
requireLogged(t, query)
defer func() {
err := tx.Rollback()
require.NoError(t, err)
}()
testutils.AssertExec(t, query, tx)
}
func TestLockWrite(t *testing.T) {
@ -27,9 +31,14 @@ func TestLockWrite(t *testing.T) {
LOCK TABLES dvds.customer WRITE;
`)
_, err := query.Exec(db)
tx, err := db.DB.Begin() // can't prepare LOCK statement
require.NoError(t, err)
requireLogged(t, query)
defer func() {
err := tx.Rollback()
require.NoError(t, err)
}()
testutils.AssertExec(t, query, tx)
}
func TestUnlockTables(t *testing.T) {
@ -39,7 +48,12 @@ func TestUnlockTables(t *testing.T) {
UNLOCK TABLES;
`)
_, err := query.Exec(db)
tx, err := db.DB.Begin() // can't prepare LOCK statement
require.NoError(t, err)
requireLogged(t, query)
defer func() {
err := tx.Rollback()
require.NoError(t, err)
}()
testutils.AssertExec(t, query, tx)
}

View file

@ -18,7 +18,7 @@ import (
"testing"
)
var db *sql.DB
var db *jetmysql.DB
var source string
@ -37,15 +37,20 @@ func TestMain(m *testing.M) {
defer profile.Start().Stop()
var err error
db, err = sql.Open("mysql", dbconfig.MySQLConnectionString(sourceIsMariaDB(), ""))
sqlDB, err := sql.Open("mysql", dbconfig.MySQLConnectionString(sourceIsMariaDB(), ""))
if err != nil {
panic("Failed to connect to test db" + err.Error())
}
db = jetmysql.NewDB(sqlDB).WithStatementsCaching(true)
defer db.Close()
ret := m.Run()
os.Exit(ret)
for i := 0; i < 2; i++ {
ret := m.Run()
if ret != 0 {
os.Exit(ret)
}
}
}
var loggedSQL string

View file

@ -2,8 +2,8 @@ package mysql
import (
"context"
"database/sql"
"github.com/go-jet/jet/v2/postgres"
"github.com/go-jet/jet/v2/qrm"
"strings"
"testing"
"time"
@ -868,11 +868,13 @@ func TestRowLock(t *testing.T) {
expectedSQL := `
SELECT *
FROM dvds.address
ORDER BY address.address_id
LIMIT 3
OFFSET 1
FOR`
query := Address.
SELECT(STAR).
query := SELECT(STAR).
FROM(Address).
ORDER_BY(Address.AddressID).
LIMIT(3).
OFFSET(1)
@ -881,28 +883,14 @@ FOR`
expectedQuery := expectedSQL + " " + lockTypeStr + ";\n"
testutils.AssertDebugStatementSql(t, query, expectedQuery, int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
require.NoError(t, err)
err = tx.Rollback()
require.NoError(t, err)
testutils.AssertExecAndRollback(t, query, db)
}
for lockType, lockTypeStr := range getRowLockTestData() {
query.FOR(lockType.NOWAIT())
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+lockTypeStr+" NOWAIT;\n", int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
require.NoError(t, err)
err = tx.Rollback()
require.NoError(t, err)
testutils.AssertExecAndRollback(t, query, db)
}
if sourceIsMariaDB() {
@ -913,14 +901,7 @@ FOR`
query.FOR(lockType.SKIP_LOCKED())
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+lockTypeStr+" SKIP LOCKED;\n", int64(3), int64(1))
tx, _ := db.Begin()
_, err := query.Exec(tx)
require.NoError(t, err)
err = tx.Rollback()
require.NoError(t, err)
testutils.AssertExecAndRollback(t, query, db)
}
}
@ -956,7 +937,7 @@ LIMIT 1
FOR UPDATE OF film, actor NOWAIT;
`)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
var dest []struct {
model.Film
CategoryID int
@ -993,7 +974,7 @@ LIMIT 1
FOR UPDATE OF ''myFilm'';
`, "''", "`"))
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
var dest []struct {
model.Film `alias:"myFilm.*"`
}

View file

@ -2,7 +2,7 @@ package mysql
import (
"context"
"database/sql"
"github.com/go-jet/jet/v2/qrm"
"testing"
"time"
@ -28,7 +28,7 @@ WHERE link.name = 'Bing';
WHERE(Link.Name.EQ(String("Bing")))
testutils.AssertDebugStatementSql(t, query, expectedSQL, "Bong", "http://bong.com", "Bing")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
testutils.AssertExec(t, query, tx)
requireLogged(t, query)
@ -59,7 +59,7 @@ WHERE link.name = 'Bing';
WHERE(Link.Name.EQ(String("Bing")))
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "Bong", "http://bong.com", "Bing")
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
testutils.AssertExec(t, stmt, tx)
requireLogged(t, stmt)
@ -280,7 +280,7 @@ SET id = 501,
WHERE link.name = 'Bing';
`)
testutils.ExecuteInTxAndRollback(t, db, func(tx *sql.Tx) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
_, err := stmt.Exec(tx)
require.NoError(t, err)
})