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 }