Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
335ef4d8e8
|
|||
61801ff20d
|
|||
361dca5c85
|
|||
9f85a243e8
|
|||
dc6cb274ee
|
@@ -20,6 +20,7 @@ Potentially needs `export GOPRIVATE="gogs.mikescher.com"`
|
||||
| zipext | Mike | Utility for zip/gzip/tar etc |
|
||||
| reflectext | Mike | Utility for golang reflection |
|
||||
| fsext | Mike | Utility for filesytem access |
|
||||
| ctxext | Mike | Utility for context.Context |
|
||||
| | | |
|
||||
| mongoext | Mike | Utility/Helper functions for mongodb (kinda abandoned) |
|
||||
| cursortoken | Mike | MongoDB cursortoken implementation |
|
||||
|
27
ctxext/getter.go
Normal file
27
ctxext/getter.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package ctxext
|
||||
|
||||
import "context"
|
||||
|
||||
func Value[T any](ctx context.Context, key any) (T, bool) {
|
||||
v := ctx.Value(key)
|
||||
if v == nil {
|
||||
return *new(T), false
|
||||
}
|
||||
if tv, ok := v.(T); !ok {
|
||||
return *new(T), false
|
||||
} else {
|
||||
return tv, true
|
||||
}
|
||||
}
|
||||
|
||||
func ValueOrDefault[T any](ctx context.Context, key any, def T) T {
|
||||
v := ctx.Value(key)
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
if tv, ok := v.(T); !ok {
|
||||
return def
|
||||
} else {
|
||||
return tv
|
||||
}
|
||||
}
|
92
dataext/ringBuffer.go
Normal file
92
dataext/ringBuffer.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package dataext
|
||||
|
||||
import "iter"
|
||||
|
||||
type RingBuffer[T any] struct {
|
||||
items []T //
|
||||
capacity int // max number of items the buffer can hold
|
||||
size int // how many items are in the buffer
|
||||
head int // ptr to next item
|
||||
}
|
||||
|
||||
func NewRingBuffer[T any](capacity int) *RingBuffer[T] {
|
||||
return &RingBuffer[T]{
|
||||
items: make([]T, capacity),
|
||||
capacity: capacity,
|
||||
size: 0,
|
||||
head: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Push(item T) {
|
||||
if rb.size < rb.capacity {
|
||||
rb.size++
|
||||
}
|
||||
rb.items[rb.head] = item
|
||||
rb.head = (rb.head + 1) % rb.capacity
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Peek() (T, bool) {
|
||||
if rb.size == 0 {
|
||||
return *new(T), false
|
||||
}
|
||||
return rb.items[(rb.head-1+rb.capacity)%rb.capacity], true
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Items() []T {
|
||||
if rb.size < rb.capacity {
|
||||
return rb.items[:rb.size]
|
||||
}
|
||||
return append(rb.items[rb.head:], rb.items[:rb.head]...)
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Size() int {
|
||||
return rb.size
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Capacity() int {
|
||||
return rb.capacity
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Clear() {
|
||||
rb.size = 0
|
||||
rb.head = 0
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) IsFull() bool {
|
||||
return rb.size == rb.capacity
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) At(i int) T {
|
||||
if i < 0 || i >= rb.size {
|
||||
panic("Index out of bounds")
|
||||
}
|
||||
return rb.items[(rb.head+i)%rb.capacity]
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Get(i int) (T, bool) {
|
||||
if i < 0 || i >= rb.size {
|
||||
return *new(T), false
|
||||
}
|
||||
return rb.items[(rb.head+i)%rb.capacity], true
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Iter() iter.Seq[T] {
|
||||
return func(yield func(T) bool) {
|
||||
for i := 0; i < rb.size; i++ {
|
||||
if !yield(rb.At(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rb *RingBuffer[T]) Iter2() iter.Seq2[int, T] {
|
||||
return func(yield func(int, T) bool) {
|
||||
for i := 0; i < rb.size; i++ {
|
||||
if !yield(i, rb.At(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
package goext
|
||||
|
||||
const GoextVersion = "0.0.518"
|
||||
const GoextVersion = "0.0.523"
|
||||
|
||||
const GoextVersionTimestamp = "2024-10-05T00:45:55+0200"
|
||||
const GoextVersionTimestamp = "2024-10-05T01:28:46+0200"
|
||||
|
@@ -61,7 +61,7 @@ func (db *database) Exec(ctx context.Context, sqlstr string, prep PP) (sql.Resul
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreExecMeta{}
|
||||
preMeta := PreExecMeta{Context: ctx, TransactionConstructorContext: nil}
|
||||
for _, v := range db.lstr {
|
||||
err := v.PreExec(ctx, nil, &sqlstr, &prep, preMeta)
|
||||
if err != nil {
|
||||
@@ -73,9 +73,9 @@ func (db *database) Exec(ctx context.Context, sqlstr string, prep PP) (sql.Resul
|
||||
|
||||
res, err := db.db.NamedExecContext(ctx, sqlstr, prep)
|
||||
|
||||
postMeta := PostExecMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostExecMeta{Context: ctx, TransactionConstructorContext: nil, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range db.lstr {
|
||||
v.PostExec(nil, origsql, sqlstr, prep, postMeta)
|
||||
v.PostExec(nil, origsql, sqlstr, prep, err, postMeta)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -90,7 +90,7 @@ func (db *database) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx.Ro
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreQueryMeta{}
|
||||
preMeta := PreQueryMeta{Context: ctx, TransactionConstructorContext: nil}
|
||||
for _, v := range db.lstr {
|
||||
err := v.PreQuery(ctx, nil, &sqlstr, &prep, preMeta)
|
||||
if err != nil {
|
||||
@@ -102,9 +102,9 @@ func (db *database) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx.Ro
|
||||
|
||||
rows, err := sqlx.NamedQueryContext(ctx, db.db, sqlstr, prep)
|
||||
|
||||
postMeta := PostQueryMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostQueryMeta{Context: ctx, TransactionConstructorContext: nil, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range db.lstr {
|
||||
v.PostQuery(nil, origsql, sqlstr, prep, postMeta)
|
||||
v.PostQuery(nil, origsql, sqlstr, prep, err, postMeta)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -118,7 +118,7 @@ func (db *database) Ping(ctx context.Context) error {
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PrePingMeta{}
|
||||
preMeta := PrePingMeta{Context: ctx}
|
||||
for _, v := range db.lstr {
|
||||
err := v.PrePing(ctx, preMeta)
|
||||
if err != nil {
|
||||
@@ -130,7 +130,7 @@ func (db *database) Ping(ctx context.Context) error {
|
||||
|
||||
err := db.db.PingContext(ctx)
|
||||
|
||||
postMeta := PostPingMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostPingMeta{Context: ctx, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range db.lstr {
|
||||
v.PostPing(err, postMeta)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ func (db *database) BeginTransaction(ctx context.Context, iso sql.IsolationLevel
|
||||
db.txctr += 1 // with overflow !
|
||||
db.lock.Unlock()
|
||||
|
||||
preMeta := PreTxBeginMeta{}
|
||||
preMeta := PreTxBeginMeta{Context: ctx}
|
||||
for _, v := range db.lstr {
|
||||
err := v.PreTxBegin(ctx, txid, preMeta)
|
||||
if err != nil {
|
||||
@@ -163,7 +163,7 @@ func (db *database) BeginTransaction(ctx context.Context, iso sql.IsolationLevel
|
||||
|
||||
xtx, err := db.db.BeginTxx(ctx, &sql.TxOptions{Isolation: iso})
|
||||
|
||||
postMeta := PostTxBeginMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostTxBeginMeta{Context: ctx, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range db.lstr {
|
||||
v.PostTxBegin(txid, err, postMeta)
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func (db *database) BeginTransaction(ctx context.Context, iso sql.IsolationLevel
|
||||
return nil, exerr.Wrap(err, "Failed to start sql transaction").Build()
|
||||
}
|
||||
|
||||
return NewTransaction(xtx, txid, db), nil
|
||||
return newTransaction(ctx, xtx, txid, db), nil
|
||||
}
|
||||
|
||||
func (db *database) Exit() error {
|
||||
|
@@ -6,61 +6,78 @@ import (
|
||||
)
|
||||
|
||||
type PrePingMeta struct {
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
type PreTxBeginMeta struct {
|
||||
Context context.Context
|
||||
ConstructorContext context.Context
|
||||
}
|
||||
|
||||
type PreTxCommitMeta struct {
|
||||
ConstructorContext context.Context
|
||||
}
|
||||
|
||||
type PreTxRollbackMeta struct {
|
||||
ConstructorContext context.Context
|
||||
}
|
||||
|
||||
type PreQueryMeta struct {
|
||||
Context context.Context
|
||||
TransactionConstructorContext context.Context
|
||||
}
|
||||
|
||||
type PreExecMeta struct {
|
||||
Context context.Context
|
||||
TransactionConstructorContext context.Context
|
||||
}
|
||||
|
||||
type PostPingMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Context context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
}
|
||||
|
||||
type PostTxBeginMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Context context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
}
|
||||
|
||||
type PostTxCommitMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
ExecCounter int
|
||||
QueryCounter int
|
||||
ConstructorContext context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
ExecCounter int
|
||||
QueryCounter int
|
||||
}
|
||||
|
||||
type PostTxRollbackMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
ExecCounter int
|
||||
QueryCounter int
|
||||
ConstructorContext context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
ExecCounter int
|
||||
QueryCounter int
|
||||
}
|
||||
|
||||
type PostQueryMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Context context.Context
|
||||
TransactionConstructorContext context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
}
|
||||
|
||||
type PostExecMeta struct {
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Context context.Context
|
||||
TransactionConstructorContext context.Context
|
||||
Init time.Time
|
||||
Start time.Time
|
||||
End time.Time
|
||||
}
|
||||
|
||||
type Listener interface {
|
||||
@@ -75,8 +92,8 @@ type Listener interface {
|
||||
PostTxBegin(txid uint16, result error, meta PostTxBeginMeta)
|
||||
PostTxCommit(txid uint16, result error, meta PostTxCommitMeta)
|
||||
PostTxRollback(txid uint16, result error, meta PostTxRollbackMeta)
|
||||
PostQuery(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostQueryMeta)
|
||||
PostExec(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostExecMeta)
|
||||
PostQuery(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostQueryMeta)
|
||||
PostExec(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostExecMeta)
|
||||
}
|
||||
|
||||
type genListener struct {
|
||||
@@ -90,8 +107,8 @@ type genListener struct {
|
||||
postTxBegin func(txid uint16, result error, meta PostTxBeginMeta)
|
||||
postTxCommit func(txid uint16, result error, meta PostTxCommitMeta)
|
||||
postTxRollback func(txid uint16, result error, meta PostTxRollbackMeta)
|
||||
postQuery func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostQueryMeta)
|
||||
postExec func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostExecMeta)
|
||||
postQuery func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostQueryMeta)
|
||||
postExec func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostExecMeta)
|
||||
}
|
||||
|
||||
func (g genListener) PrePing(ctx context.Context, meta PrePingMeta) error {
|
||||
@@ -166,15 +183,15 @@ func (g genListener) PostTxRollback(txid uint16, result error, meta PostTxRollba
|
||||
}
|
||||
}
|
||||
|
||||
func (g genListener) PostQuery(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostQueryMeta) {
|
||||
func (g genListener) PostQuery(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostQueryMeta) {
|
||||
if g.postQuery != nil {
|
||||
g.postQuery(txID, sqlOriginal, sqlReal, params, meta)
|
||||
g.postQuery(txID, sqlOriginal, sqlReal, params, result, meta)
|
||||
}
|
||||
}
|
||||
|
||||
func (g genListener) PostExec(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostExecMeta) {
|
||||
func (g genListener) PostExec(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostExecMeta) {
|
||||
if g.postExec != nil {
|
||||
g.postExec(txID, sqlOriginal, sqlReal, params, meta)
|
||||
g.postExec(txID, sqlOriginal, sqlReal, params, result, meta)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,21 +246,21 @@ func NewPostTxRollbackListener(f func(txid uint16, result error, meta PostTxRoll
|
||||
return genListener{postTxRollback: f}
|
||||
}
|
||||
|
||||
func NewPostQueryListener(f func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostQueryMeta)) Listener {
|
||||
func NewPostQueryListener(f func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostQueryMeta)) Listener {
|
||||
return genListener{postQuery: f}
|
||||
}
|
||||
|
||||
func NewPostExecListener(f func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostExecMeta)) Listener {
|
||||
func NewPostExecListener(f func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostExecMeta)) Listener {
|
||||
return genListener{postExec: f}
|
||||
}
|
||||
|
||||
func NewPostListener(f func(cmdtype string, txID *uint16, sqlOriginal string, sqlReal string, params PP)) Listener {
|
||||
func NewPostListener(f func(cmdtype string, txID *uint16, sqlOriginal string, sqlReal string, result error, params PP)) Listener {
|
||||
return genListener{
|
||||
postExec: func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostExecMeta) {
|
||||
f("EXEC", txID, sqlOriginal, sqlReal, params)
|
||||
postExec: func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostExecMeta) {
|
||||
f("EXEC", txID, sqlOriginal, sqlReal, result, params)
|
||||
},
|
||||
postQuery: func(txID *uint16, sqlOriginal string, sqlReal string, params PP, meta PostQueryMeta) {
|
||||
f("QUERY", txID, sqlOriginal, sqlReal, params)
|
||||
postQuery: func(txID *uint16, sqlOriginal string, sqlReal string, params PP, result error, meta PostQueryMeta) {
|
||||
f("QUERY", txID, sqlOriginal, sqlReal, result, params)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@@ -27,22 +27,24 @@ type Tx interface {
|
||||
}
|
||||
|
||||
type transaction struct {
|
||||
tx *sqlx.Tx
|
||||
id uint16
|
||||
status TxStatus
|
||||
execCtr int
|
||||
queryCtr int
|
||||
db *database
|
||||
constructorContext context.Context
|
||||
tx *sqlx.Tx
|
||||
id uint16
|
||||
status TxStatus
|
||||
execCtr int
|
||||
queryCtr int
|
||||
db *database
|
||||
}
|
||||
|
||||
func NewTransaction(xtx *sqlx.Tx, txid uint16, db *database) Tx {
|
||||
func newTransaction(ctx context.Context, xtx *sqlx.Tx, txid uint16, db *database) Tx {
|
||||
return &transaction{
|
||||
tx: xtx,
|
||||
id: txid,
|
||||
status: TxStatusInitial,
|
||||
execCtr: 0,
|
||||
queryCtr: 0,
|
||||
db: db,
|
||||
constructorContext: ctx,
|
||||
tx: xtx,
|
||||
id: txid,
|
||||
status: TxStatusInitial,
|
||||
execCtr: 0,
|
||||
queryCtr: 0,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +52,7 @@ func (tx *transaction) Rollback() error {
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreTxRollbackMeta{}
|
||||
preMeta := PreTxRollbackMeta{ConstructorContext: tx.constructorContext}
|
||||
for _, v := range tx.db.lstr {
|
||||
err := v.PreTxRollback(tx.id, preMeta)
|
||||
if err != nil {
|
||||
@@ -66,7 +68,7 @@ func (tx *transaction) Rollback() error {
|
||||
tx.status = TxStatusRollback
|
||||
}
|
||||
|
||||
postMeta := PostTxRollbackMeta{Init: t0, Start: t1, End: time.Now(), ExecCounter: tx.execCtr, QueryCounter: tx.queryCtr}
|
||||
postMeta := PostTxRollbackMeta{ConstructorContext: tx.constructorContext, Init: t0, Start: t1, End: time.Now(), ExecCounter: tx.execCtr, QueryCounter: tx.queryCtr}
|
||||
for _, v := range tx.db.lstr {
|
||||
v.PostTxRollback(tx.id, result, postMeta)
|
||||
}
|
||||
@@ -78,7 +80,7 @@ func (tx *transaction) Commit() error {
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreTxCommitMeta{}
|
||||
preMeta := PreTxCommitMeta{ConstructorContext: tx.constructorContext}
|
||||
for _, v := range tx.db.lstr {
|
||||
err := v.PreTxCommit(tx.id, preMeta)
|
||||
if err != nil {
|
||||
@@ -94,7 +96,7 @@ func (tx *transaction) Commit() error {
|
||||
tx.status = TxStatusComitted
|
||||
}
|
||||
|
||||
postMeta := PostTxCommitMeta{Init: t0, Start: t1, End: time.Now(), ExecCounter: tx.execCtr, QueryCounter: tx.queryCtr}
|
||||
postMeta := PostTxCommitMeta{ConstructorContext: tx.constructorContext, Init: t0, Start: t1, End: time.Now(), ExecCounter: tx.execCtr, QueryCounter: tx.queryCtr}
|
||||
for _, v := range tx.db.lstr {
|
||||
v.PostTxCommit(tx.id, result, postMeta)
|
||||
}
|
||||
@@ -107,7 +109,7 @@ func (tx *transaction) Exec(ctx context.Context, sqlstr string, prep PP) (sql.Re
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreExecMeta{}
|
||||
preMeta := PreExecMeta{Context: ctx, TransactionConstructorContext: tx.constructorContext}
|
||||
for _, v := range tx.db.lstr {
|
||||
err := v.PreExec(ctx, langext.Ptr(tx.id), &sqlstr, &prep, preMeta)
|
||||
if err != nil {
|
||||
@@ -124,9 +126,9 @@ func (tx *transaction) Exec(ctx context.Context, sqlstr string, prep PP) (sql.Re
|
||||
tx.status = TxStatusActive
|
||||
}
|
||||
|
||||
postMeta := PostExecMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostExecMeta{Context: ctx, TransactionConstructorContext: tx.constructorContext, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range tx.db.lstr {
|
||||
v.PostExec(langext.Ptr(tx.id), origsql, sqlstr, prep, postMeta)
|
||||
v.PostExec(langext.Ptr(tx.id), origsql, sqlstr, prep, err, postMeta)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -140,7 +142,7 @@ func (tx *transaction) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx
|
||||
|
||||
t0 := time.Now()
|
||||
|
||||
preMeta := PreQueryMeta{}
|
||||
preMeta := PreQueryMeta{Context: ctx, TransactionConstructorContext: tx.constructorContext}
|
||||
for _, v := range tx.db.lstr {
|
||||
err := v.PreQuery(ctx, langext.Ptr(tx.id), &sqlstr, &prep, preMeta)
|
||||
if err != nil {
|
||||
@@ -157,9 +159,9 @@ func (tx *transaction) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx
|
||||
tx.status = TxStatusActive
|
||||
}
|
||||
|
||||
postMeta := PostQueryMeta{Init: t0, Start: t1, End: time.Now()}
|
||||
postMeta := PostQueryMeta{Context: ctx, TransactionConstructorContext: tx.constructorContext, Init: t0, Start: t1, End: time.Now()}
|
||||
for _, v := range tx.db.lstr {
|
||||
v.PostQuery(langext.Ptr(tx.id), origsql, sqlstr, prep, postMeta)
|
||||
v.PostQuery(langext.Ptr(tx.id), origsql, sqlstr, prep, err, postMeta)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user