diff --git a/conn.go b/conn.go index 10d8b72..ddf9aa2 100644 --- a/conn.go +++ b/conn.go @@ -8,6 +8,7 @@ import ( "sync" ) +// FakeConn implements connection type FakeConn struct { db *FakeDB currTx *FakeTx // Transaction pointer @@ -19,6 +20,7 @@ func (c *FakeConn) isBad() bool { return false } +// Begin starts and returns a new transaction. func (c *FakeConn) Begin() (driver.Tx, error) { if c.isBad() { return nil, driver.ErrBadConn @@ -35,28 +37,34 @@ func (c *FakeConn) Close() (err error) { return nil } +// Exec is deprecated func (c *FakeConn) Exec(query string, args []driver.Value) (driver.Result, error) { panic("ExecContext was not called.") } +// ExecContext is optional to implement and it returns skip func (c *FakeConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { return nil, driver.ErrSkip } +// Query is deprecated func (c *FakeConn) Query(query string, args []driver.Value) (driver.Rows, error) { panic("QueryContext was not called.") } -// We do +// QueryContext is optional func (c *FakeConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { return nil, driver.ErrSkip } -// Should not be called +// Prepare is optional func (c *FakeConn) Prepare(query string) (driver.Stmt, error) { panic("use Prepare") } +// PrepareContext returns a prepared statement, bound to this connection. +// context is for the preparation of the statement, +// it must not store the context within the statement itself. func (c *FakeConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { var firstStmt = &FakeStmt{q: query, connection: c} // Create statement firstStmt.placeholders = len(strings.Split(query, "?")) - 1 // Checking how many placeholders do we have diff --git a/driver.go b/driver.go index 675a20a..d09c7d6 100644 --- a/driver.go +++ b/driver.go @@ -8,6 +8,7 @@ import ( var _ = log.Printf +// FakeDriver implements driver interface in sql package type FakeDriver struct { mu sync.Mutex // guards 3 following fields openCount int // conn opens @@ -40,6 +41,7 @@ func (t *table) columnIndex(name string) int { return -1 } +// Open returns a new connection to the database. func (d FakeDriver) Open(database string) (driver.Conn, error) { return &FakeConn{db: d.getDB(database)}, nil } diff --git a/response.go b/response.go index 7c6f1a5..4c59305 100644 --- a/response.go +++ b/response.go @@ -8,10 +8,10 @@ import ( "strings" ) -// Global instance of Catcher used for attaching all mocks to connection +//Catcher is global instance of Catcher used for attaching all mocks to connection var Catcher *MockCatcher -// Global entity to save all mocks aka FakeResponses +//MockCatcher is Global entity to save all mocks aka FakeResponses type MockCatcher struct { Mocks []*FakeResponse // Slice of all mocks Logging bool // Do we need to log what we catching? @@ -60,13 +60,13 @@ func (mc *MockCatcher) Reset() *MockCatcher { return mc } -// Possible exceptions during query executions +//Exceptions represents possible exceptions during query executions type Exceptions struct { HookQueryBadConnection func() bool HookExecBadConnection func() bool } -// Represents mock of response with holding all required values to return mocked response +//FakeResponse represents mock of response with holding all required values to return mocked response type FakeResponse struct { Pattern string // SQL query pattern to match with Args []interface{} // List args to be matched with diff --git a/result.go b/result.go index f99fc1e..16648bd 100644 --- a/result.go +++ b/result.go @@ -4,19 +4,23 @@ import ( "database/sql/driver" ) +// FakeResult implementation of sql Result interface type FakeResult struct { insertID int64 rowsAffected int64 } +// NewFakeResult returns result interface instance func NewFakeResult(insertId int64, rowsAffected int64) driver.Result { return &FakeResult{insertId, rowsAffected} } +// LastInsertId required to give sql package ability get ID of inserted record func (fr *FakeResult) LastInsertId() (int64, error) { return fr.insertID, nil } +// RowsAffected returns the number of rows affected func (fr *FakeResult) RowsAffected() (int64, error) { return fr.rowsAffected, nil } diff --git a/rows.go b/rows.go index cbd1fe0..9582877 100644 --- a/rows.go +++ b/rows.go @@ -9,6 +9,7 @@ import ( "time" ) +// RowsCursor is implementation of Rows sql interface type RowsCursor struct { cols []string colType [][]string @@ -28,6 +29,7 @@ type row struct { cols []interface{} // must be same size as its table colname + coltype } +// Close closes the rows iterator. func (rc *RowsCursor) Close() error { if !rc.closed { for _, bs := range rc.bytesClone { @@ -38,14 +40,19 @@ func (rc *RowsCursor) Close() error { return nil } +// Columns returns the names of the columns. func (rc *RowsCursor) Columns() []string { return rc.cols } +// RowsColumnTypeScanType may be implemented by Rows. It should return +// the value type that can be used to scan types into. func (rc *RowsCursor) ColumnTypeScanType(index int) reflect.Type { return colTypeToReflectType(rc.colType[rc.posSet][index]) } +// Next is called to populate the next row of data into +// the provided slice. func (rc *RowsCursor) Next(accumulator []driver.Value) error { if rc.closed { return errors.New("fake_db_driver: cursor is closed") @@ -75,10 +82,14 @@ func (rc *RowsCursor) Next(accumulator []driver.Value) error { return nil } +// HasNextResultSet is called at the end of the current result set and +// reports whether there is another result set after the current one. func (rc *RowsCursor) HasNextResultSet() bool { return rc.posSet < len(rc.rows)-1 } +// NextResultSet advances the driver to the next result set even +// if there are remaining rows in the current result set. func (rc *RowsCursor) NextResultSet() error { if rc.HasNextResultSet() { rc.posSet++ diff --git a/stmt.go b/stmt.go index 227aa35..7b6390b 100644 --- a/stmt.go +++ b/stmt.go @@ -9,6 +9,7 @@ import ( "strings" ) +// FakeStmt is implementation of Stmt sql interfcae type FakeStmt struct { connection *FakeConn q string // just for debugging SQL query generated by sql package @@ -20,6 +21,8 @@ type FakeStmt struct { placeholders int // Amount of passed args } +// ColumnConverter returns a ValueConverter for the provided +// column index. func (s *FakeStmt) ColumnConverter(idx int) driver.ValueConverter { return driver.DefaultParameterConverter } @@ -43,10 +46,16 @@ func (s *FakeStmt) Close() error { var errClosed = errors.New("fake_db_driver: statement has been closed") +// Exec executes a query that doesn't return rows, such +// as an INSERT or UPDATE. +// +// Deprecated: Drivers should implement StmtExecContext instead (or additionally). func (smt *FakeStmt) Exec(args []driver.Value) (driver.Result, error) { panic("Using ExecContext") } +// ExecContext executes a query that doesn't return rows, such +// as an INSERT or UPDATE. func (smt *FakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { if smt.closed { return nil, errClosed @@ -79,10 +88,16 @@ func (smt *FakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) return nil, fmt.Errorf("unimplemented statement Exec command type of %q", smt.command) } +// Query executes a query that may return rows, such as a +// SELECT. +// +// Deprecated: Drivers should implement StmtQueryContext instead (or additionally). func (s *FakeStmt) Query(args []driver.Value) (driver.Rows, error) { panic("Use QueryContext") } +// QueryContext executes a query that may return rows, such as a +// SELECT. func (smt *FakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { if smt.closed { @@ -145,11 +160,12 @@ func (smt *FakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) return cursor, nil } -// Returns number of args passed to query +// NumInput returns the number of placeholder parameters. func (s *FakeStmt) NumInput() int { return s.placeholders } +// FakeTx implements Tx interface type FakeTx struct { c *FakeConn }