sqlx: optimize table prefix for query logic

r/paopao-ce-plus
Michael Li 2 years ago
parent 430df7a15f
commit a80739239f
No known key found for this signature in database

@ -0,0 +1,13 @@
package sakila_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestSakila(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Sakila Suite")
}

@ -5,10 +5,10 @@
package sakila package sakila
import ( import (
"bytes"
"context" "context"
"database/sql" "database/sql"
_ "embed" _ "embed"
"strings"
"github.com/alimy/yesql" "github.com/alimy/yesql"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -17,7 +17,8 @@ import (
) )
var ( var (
_db *sqlx.DB _db *sqlx.DB
_tablePrefix string
) )
type sqlxSrv struct { type sqlxSrv struct {
@ -110,7 +111,27 @@ func n(query string) *sqlx.NamedStmt {
// t repace table prefix for query // t repace table prefix for query
func t(query string) string { func t(query string) string {
return strings.Replace(query, "@", conf.DatabaseSetting.TablePrefix, -1) buf := bytes.NewBuffer(make([]byte, 0, len(query)))
qr := make([]rune, 0, len(query))
for _, c := range query {
qr = append(qr, c)
}
isPrevAt := false
size := len(qr)
for i := 0; i < size; i++ {
if qr[i] == '@' {
if next := i + 1; next == size || (!isPrevAt && qr[next] != '@') {
buf.WriteString(_tablePrefix)
} else {
buf.WriteRune('@')
}
isPrevAt = true
} else {
buf.WriteRune(qr[i])
isPrevAt = false
}
}
return buf.String()
} }
// yesqlScan yesql.Scan help function // yesqlScan yesql.Scan help function
@ -122,9 +143,7 @@ func yesqlScan[T any](query yesql.SQLQuery, obj T) T {
} }
func mustBuild[T any](db *sqlx.DB, fn func(yesql.PreparexBuilder, ...context.Context) (T, error)) T { func mustBuild[T any](db *sqlx.DB, fn func(yesql.PreparexBuilder, ...context.Context) (T, error)) T {
p := yesql.NewPreparexBuilder(db, func(query string) string { p := yesql.NewPreparexBuilder(db, t)
return strings.Replace(query, "@", conf.DatabaseSetting.TablePrefix, -1)
})
obj, err := fn(p) obj, err := fn(p)
if err != nil { if err != nil {
logrus.Fatalf("build object failure: %s", err) logrus.Fatalf("build object failure: %s", err)
@ -134,4 +153,10 @@ func mustBuild[T any](db *sqlx.DB, fn func(yesql.PreparexBuilder, ...context.Con
func initSqlxDB() { func initSqlxDB() {
_db = conf.MustSqlxDB() _db = conf.MustSqlxDB()
_tablePrefix = conf.DatabaseSetting.TablePrefix
}
// FnTest_t just for test t(...) function not use in out package
func FnTest_t(query string) string {
return t(query)
} }

@ -0,0 +1,51 @@
package sakila_test
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/rocboss/paopao-ce/internal/dao/sakila"
)
var _ = Describe("Sqlx", Ordered, func() {
type queries []struct {
originQuery string
fixedQuery string
}
var samples queries
BeforeAll(func() {
samples = queries{
{
originQuery: `SELECT * FROM @user WHERE username=?@_`,
fixedQuery: `SELECT * FROM user WHERE username=?_`,
},
{
originQuery: `SELECT * FROM @user WHERE username=?`,
fixedQuery: `SELECT * FROM user WHERE username=?`,
},
{
originQuery: `SELECT * FROM @@user WHERE 用户名=?`,
fixedQuery: `SELECT * FROM @@user WHERE 用户名=?`,
},
{
originQuery: `SELECT * FROM @@user, @@@@contact WHERE 用户名=?`,
fixedQuery: `SELECT * FROM @@user, @@@@contact WHERE 用户名=?`,
},
{
originQuery: `SELECT @@name, @@@@@id FROM @@user, @@@@contact WHERE 用户名=?`,
fixedQuery: `SELECT @@name, @@@@@id FROM @@user, @@@@contact WHERE 用户名=?`,
},
{
originQuery: `SELECT @name, @id FROM @user, @contact WHERE 用户名=?`,
fixedQuery: `SELECT name, id FROM user, contact WHERE 用户名=?`,
},
}
})
It("test internal t func", func() {
for _, t := range samples {
Expect(sakila.FnTest_t(t.originQuery)).To(Equal(t.fixedQuery))
}
})
})
Loading…
Cancel
Save