github.com/seeker-insurance/kit@v0.0.13/db/psql/psqlx.go (about)

     1  package psql
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  
     8  	"github.com/seeker-insurance/kit/flect"
     9  	"github.com/seeker-insurance/kit/islice"
    10  	"github.com/seeker-insurance/kit/stringslice"
    11  	"github.com/jmoiron/sqlx"
    12  	"github.com/spf13/cobra"
    13  	"github.com/spf13/viper"
    14  
    15  	//register postgres dialect
    16  	_ "github.com/lib/pq"
    17  )
    18  
    19  var (
    20  	DBx      *IQSqlx
    21  	DBxError error
    22  )
    23  
    24  func init() {
    25  	cobra.OnInitialize(ConnectDBx)
    26  }
    27  
    28  type (
    29  	IQSqlx struct {
    30  		X *sqlx.DB
    31  	}
    32  
    33  	IQModel interface {
    34  		TableName() string
    35  	}
    36  
    37  	Mappable interface {
    38  		IdColumn() string
    39  	}
    40  )
    41  
    42  func ConnectDBx() {
    43  	viper.SetDefault("database_scheme", "postgres")
    44  	scheme := viper.GetString("database_scheme")
    45  	url := viper.GetString("database_url")
    46  
    47  	if len(url) == 0 {
    48  		DBxError = errors.New("Missing database_url")
    49  		return
    50  	}
    51  	var dbx *sqlx.DB
    52  	dbx, DBxError = sqlx.Connect(scheme, url)
    53  	DBx = &IQSqlx{dbx}
    54  }
    55  
    56  
    57  //Takes a map[string]struct, populates the stuct, and sets the map keys to the column specified by the mappable interface
    58  func (db IQSqlx) MapById(mappable Mappable, query string, params ...interface{}) error {
    59  	if flect.NotA(mappable, reflect.Map) {
    60  		return fmt.Errorf("MapById: mappable must be a map, %T is a %s", mappable, reflect.TypeOf(mappable).Kind())
    61  	}
    62  
    63  	rows, err := db.X.Queryx(query, params...)
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	cols, err := rows.Columns()
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	idColIndex, ok := stringslice.IndexOf(cols, mappable.IdColumn())
    74  
    75  	if !ok {
    76  		return fmt.Errorf("MapById: IdColumn() %s not in returned cols: %v", mappable.IdColumn(), cols)
    77  	}
    78  
    79  	valuePtrs := islice.StringPtrs(len(cols))
    80  
    81  	for rows.Next() {
    82  		if err := rows.Scan(valuePtrs...); err != nil {
    83  			return err
    84  		}
    85  
    86  		structElem := reflect.TypeOf(mappable).Elem()
    87  		structInterface := reflect.New(structElem).Interface()
    88  
    89  		if err := rows.StructScan(structInterface); err != nil {
    90  			return err
    91  		}
    92  
    93  		idColValue := valuePtrs[idColIndex]
    94  
    95  		key := reflect.ValueOf(idColValue).Elem()
    96  		value := reflect.ValueOf(structInterface).Elem()
    97  
    98  		reflect.ValueOf(mappable).SetMapIndex(key, value)
    99  	}
   100  	return nil
   101  }