Proof of concept using DB.logger

This commit is contained in:
Ian Tan 2017-11-18 19:06:00 +08:00
parent 5520530799
commit 475ba3db3e

View File

@ -1,22 +1,84 @@
package gorm
import (
"database/sql"
"errors"
"fmt"
)
type Recorder struct {
stmt string
}
func (r *Recorder) Print(args ...interface{}) {
msgs := LogFormatter(args...)
if len(msgs) >= 4 {
if v, ok := msgs[3].(string); ok {
r.stmt = v
}
// for i, msg := range msgs {
// switch v := msg.(type) {
// case string:
// case []byte:
// r.buf.Read([]byte(v))
// default:
// return
// }
// }
}
}
// AdapterFactory is a generic interface for arbitrary adapters that satisfy
// the interface. variadic args are passed to gorm.Open.
type AdapterFactory func(dialect string, args ...interface{}) (*DB, Adapter, error)
// Expecter is the exported struct used for setting expectations
type Expecter struct {
Value interface{}
adapter Adapter
search *search
values map[string]interface{}
// globally scoped expecter
root *Expecter
adapter Adapter
noop NoopDB
gorm *DB
recorder *Recorder
}
type NoopDB interface {
GetStmts() []string
}
type DefaultNoopDB struct{}
type NoopResult struct{}
func (r NoopResult) LastInsertId() (int64, error) {
return 1, nil
}
func (r NoopResult) RowsAffected() (int64, error) {
return 1, nil
}
func NewNoopDB() NoopDB {
return &DefaultNoopDB{}
}
func (r *DefaultNoopDB) Exec(query string, args ...interface{}) (sql.Result, error) {
return NoopResult{}, nil
}
func (r *DefaultNoopDB) Prepare(query string) (*sql.Stmt, error) {
return &sql.Stmt{}, nil
}
func (r *DefaultNoopDB) Query(query string, args ...interface{}) (*sql.Rows, error) {
return nil, errors.New("noop")
}
func (r *DefaultNoopDB) QueryRow(query string, args ...interface{}) *sql.Row {
return &sql.Row{}
}
func (r *DefaultNoopDB) GetStmts() []string {
return []string{"not", "implemented"}
}
// NewDefaultExpecter returns a Expecter powered by go-sqlmock
@ -27,7 +89,21 @@ func NewDefaultExpecter() (*DB, *Expecter, error) {
return nil, nil, err
}
return gormDb, &Expecter{adapter: adapter}, nil
recorder := &Recorder{}
noop := &DefaultNoopDB{}
gorm := &DB{
db: noop,
logger: recorder,
logMode: 2,
values: map[string]interface{}{},
callbacks: DefaultCallback,
dialect: newDialect("sqlmock", noop),
}
gorm.parent = gorm
return gormDb, &Expecter{adapter: adapter, noop: noop, gorm: gorm, recorder: recorder}, nil
}
// NewExpecter returns an Expecter for arbitrary adapters
@ -44,28 +120,13 @@ func NewExpecter(fn AdapterFactory, dialect string, args ...interface{}) (*DB, *
/* PUBLIC METHODS */
// First triggers a Query
func (h *Expecter) First(model interface{}) ExpectedQuery {
fmt.Printf("Expecting query: %s", "some query\n")
return h.adapter.ExpectQuery("some sql")
func (h *Expecter) First(out interface{}, where ...interface{}) ExpectedQuery {
h.gorm.First(out, where)
return h.adapter.ExpectQuery(h.recorder.stmt)
}
// Find triggers a Query
func (h *Expecter) Find(model interface{}) ExpectedQuery {
func (h *Expecter) Find(out interface{}, where ...interface{}) ExpectedQuery {
fmt.Printf("Expecting query: %s\n", "some query involving Find")
return h.adapter.ExpectQuery("some find condition")
}
/* PRIVATE METHODS */
// clone is similar to DB.clone, and ensures that the root Expecter is not
// polluted with subsequent search constraints
func (h *Expecter) clone() *Expecter {
expecterCopy := &Expecter{
adapter: h.adapter,
root: h.root,
values: map[string]interface{}{},
Value: h.Value,
}
return expecterCopy
}