github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/display/column.go (about)

     1  package display
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	typeHelpers "github.com/turbot/go-kit/types"
     9  	"github.com/turbot/steampipe/pkg/constants"
    10  	"github.com/turbot/steampipe/pkg/query/queryresult"
    11  )
    12  
    13  // ColumnNames :: extract names from columns
    14  func ColumnNames(columns []*queryresult.ColumnDef) []string {
    15  	var colNames = make([]string, len(columns))
    16  	for i, c := range columns {
    17  		colNames[i] = c.Name
    18  	}
    19  
    20  	return colNames
    21  }
    22  
    23  type columnValueSettings struct{ nullString string }
    24  
    25  type ColumnValueOption func(opt *columnValueSettings)
    26  
    27  func WithNullString(nullString string) ColumnValueOption {
    28  	return func(opt *columnValueSettings) {
    29  		opt.nullString = nullString
    30  	}
    31  }
    32  
    33  // ColumnValuesAsString converts a slice of columns into strings
    34  func ColumnValuesAsString(values []interface{}, columns []*queryresult.ColumnDef, opts ...ColumnValueOption) ([]string, error) {
    35  	rowAsString := make([]string, len(columns))
    36  	for idx, val := range values {
    37  		val, err := ColumnValueAsString(val, columns[idx], opts...)
    38  		if err != nil {
    39  			return nil, err
    40  		}
    41  		rowAsString[idx] = val
    42  	}
    43  	return rowAsString, nil
    44  }
    45  
    46  // ColumnValueAsString converts column value to string
    47  func ColumnValueAsString(val interface{}, col *queryresult.ColumnDef, opts ...ColumnValueOption) (result string, err error) {
    48  	opt := &columnValueSettings{nullString: constants.NullString}
    49  	for _, o := range opts {
    50  		o(opt)
    51  	}
    52  
    53  	defer func() {
    54  		if r := recover(); r != nil {
    55  			result = fmt.Sprintf("%v", val)
    56  		}
    57  	}()
    58  
    59  	if val == nil {
    60  		return opt.nullString, nil
    61  	}
    62  
    63  	//log.Printf("[TRACE] ColumnValueAsString type %s", colType.DatabaseTypeName())
    64  	// possible types for colType are defined in pq/oid/types.go
    65  	switch col.DataType {
    66  	case "JSON", "JSONB":
    67  		bytes, err := json.Marshal(val)
    68  		if err != nil {
    69  			return "", err
    70  		}
    71  		return string(bytes), nil
    72  	case "TIMESTAMP", "DATE", "TIME", "INTERVAL":
    73  		t, ok := val.(time.Time)
    74  		if ok {
    75  			return t.Format("2006-01-02 15:04:05"), nil
    76  		}
    77  		fallthrough
    78  	case "NAME":
    79  		result := string(val.([]uint8))
    80  		return result, nil
    81  
    82  	default:
    83  		return typeHelpers.ToString(val), nil
    84  	}
    85  }
    86  
    87  // ParseJSONOutputColumnValue segregate data types, ignore string conversion for certain data types :
    88  // JSON, JSONB, BOOL and so on..
    89  func ParseJSONOutputColumnValue(val interface{}, col *queryresult.ColumnDef) (interface{}, error) {
    90  	if val == nil {
    91  		return nil, nil
    92  	}
    93  
    94  	switch col.DataType {
    95  	// we can revise/increment the list of DT's in future
    96  	case "JSON", "JSONB", "BOOL", "INT2", "INT4", "INT8", "FLOAT8", "FLOAT4":
    97  		return val, nil
    98  	default:
    99  		return ColumnValueAsString(val, col)
   100  	}
   101  }