repo_description: Sql mock driver for golang to test database interactions
repo_topics: database go golang mock sql sql-driver tdd testing
code: package sqlmock
  
  import (
  	"database/sql/driver"
  	"errors"
  	"fmt"
  	"strconv"
  	"time"
  )
  
  type NullTime struct {
  	Time  time.Time
  	Valid bool // Valid is true if Time is not NULL
  }
  
  type NullInt struct {
  	Integer int
  	Valid   bool
  }
  
  // Satisfy sql.Scanner interface
  func (ni *NullInt) Scan(value interface{}) error {
  	switch v := value.(type) {
  	case nil:
  		ni.Integer, ni.Valid = 0, false
  	case int64:
  		const maxUint = ^uint(0)
  		const maxInt = int(maxUint >> 1)
  		const minInt = -maxInt - 1
  
  		if v > int64(maxInt) || v < int64(minInt) {
  			return errors.New("value out of int range")
  		}
  		ni.Integer, ni.Valid = int(v), true
  	case []byte:
  		n, err := strconv.Atoi(string(v))
  		if err != nil {
  			return err
  		}
  		ni.Integer, ni.Valid = n, true
  	case string:
  		n, err := strconv.Atoi(v)
  		if err != nil {
  			return err
  		}
  		ni.Integer, ni.Valid = n, true
  	default:
  		return fmt.Errorf("can't convert %T to integer", value)
  	}
  	return nil
  }
  
  // Satisfy sql.Valuer interface.
  func (ni NullInt) Value() (driver.Value, error) {
  	if !ni.Valid {
  		return nil, nil
  	}
  	return int64(ni.Integer), nil
  }
  
  // Satisfy sql.Scanner interface
  func (nt *NullTime) Scan(value interface{}) error {
  	switch v := value.(type) {
  	case nil:
  		nt.Time, nt.Valid = time.Time{}, false
  	case time.Time:
  		nt.Time, nt.Valid = v, true
  	default:
  		return fmt.Errorf("can't convert %T to time.Time", value)
  	}
  	return nil
  }
  
  // Satisfy sql.Valuer interface.
  func (nt NullTime) Value() (driver.Value, error) {
  	if !nt.Valid {
  		return nil, nil
  	}
  	return nt.Time, nil
  }
  