github.com/tobgu/qframe@v0.4.0/internal/io/sql/reader.go (about)

     1  package sql
     2  
     3  import (
     4  	"database/sql"
     5  
     6  	"github.com/tobgu/qframe/qerrors"
     7  	"github.com/tobgu/qframe/types"
     8  )
     9  
    10  // ReadSQL returns a named map of types.DataSlice for consumption
    11  // by the qframe.New constructor.
    12  func ReadSQL(rows *sql.Rows, conf SQLConfig) (map[string]types.DataSlice, []string, error) {
    13  	var (
    14  		columns  []interface{}
    15  		colNames []string
    16  	)
    17  	for rows.Next() {
    18  		// Allocate columns for the returning query
    19  		if columns == nil {
    20  			names, err := rows.Columns()
    21  			if err != nil {
    22  				return nil, colNames, qerrors.New("ReadSQL Columns", err.Error())
    23  			}
    24  			for _, name := range names {
    25  				col := &Column{precision: conf.Precision}
    26  				if conf.CoerceMap != nil {
    27  					fn, ok := conf.CoerceMap[name]
    28  					if ok {
    29  						col.coerce = fn(col)
    30  					}
    31  				}
    32  				columns = append(columns, col)
    33  			}
    34  			// ensure any column in the coercion map
    35  			// exists in the resulting columns or return
    36  			// an error explicitly.
    37  			if conf.CoerceMap != nil {
    38  			checkMap:
    39  				for name := range conf.CoerceMap {
    40  					for _, colName := range colNames {
    41  						if name == colName {
    42  							continue checkMap
    43  						}
    44  						return nil, colNames, qerrors.New("ReadSQL Columns", "column %s does not exist to coerce", name)
    45  					}
    46  				}
    47  			}
    48  			colNames = names
    49  		}
    50  		// Scan the result into our columns
    51  		err := rows.Scan(columns...)
    52  		if err != nil {
    53  			return nil, colNames, qerrors.New("ReadSQL Scan", err.Error())
    54  		}
    55  	}
    56  	result := map[string]types.DataSlice{}
    57  	for i, column := range columns {
    58  		result[colNames[i]] = column.(*Column).Data()
    59  	}
    60  	return result, colNames, nil
    61  }