// NewFromSQLRows returns a new dataframe populated with the data from rows. The Field Vector types
// NewFromSQLRows returns a new Frame populated with the data from rows. The Field Vector types
// will be Vectors of pointer types, []*T, if the SQL column is nullable or if the nullable property is unknown.
// Otherwise, they will be []T types.
//
// Fields will be named to match name of the SQL columns and the SQL column names must be unique (https://github.com/grafana/grafana-plugin-sdk-go/issues/59).
//
// All the types must be supported by the dataframe or a SQLStringConverter will be created and
// All the types must be supported by the Frame or a SQLStringConverter will be created and
// the resulting Field Vector type will be of type []*string.
//
// The SQLStringConverter's ConversionFunc will be applied to matching rows if it is not nil.
// LongToWide converts a Long formated time series Frame to a Wide format (see TimeSeriesType for descriptions).
// The first Field of type time.Time or *time.Time will be the time index for the series,
// and will be the first field of the outputted longFrame.
//
// During conversion: String Fields in the longFrame become Labels on the Fields of wideFrame. The name of each string Field becomes a label key, and the values of that Field become label values.
// Each unique combination of value Fields and set of Label key/values become a Field of longFrame.
//
// Additionally, if the time index is a *time.Time field, it will become time.Time Field. If a *string Field has nil values, they are equivalent to "" when converted into labels.
//
// An error is returned if any of the following are true:
// The input frame is not a long formated time series frame.
// The input frame's Fields are of length 0.
// The time index is not sorted ascending by time.
// The time index has null values.
//
// With a conversion of Long to Wide, and then back to Long via WideToLong(), the outputted Long Frame
// may not match the original inputted Long frame.
funcLongToWide(longFrame*Frame)(*Frame,error){
tsSchema:=longFrame.TimeSeriesSchema()
iftsSchema.Type!=TimeSeriesTypeLong{
returnnil,fmt.Errorf("can not convert to wide series, expected long format series input but got %s series",tsSchema.Type)
}
longLen,err:=longFrame.RowLen()
iferr!=nil{
returnnil,err
}elseiflongLen==0{
returnnil,fmt.Errorf("can not convert to wide series, input fields have no rows")
// WideToLong converts a Wide formated time series Frame to a Long formated time series Frame (see TimeSeriesType for descriptions). The first Field of type time.Time or *time.Time in wideFrame will be the time index for the series, and will be the first field of the outputted wideFrame.
//
// During conversion: All the unique keys in all of the Labels across the Fields of wideFrame become string
// Fields with the corresponding name in longFrame. The corresponding Labels values become values in those Fields of longFrame.
// For each unique non-timeIndex Field across the Fields of wideFrame (value fields), a Field of the same type is created in longFrame.
// For each unique set of Labels across the Fields of wideFrame, a row is added to longFrame, and then
// for each unique value Field, the corresponding value Field of longFrame is set.
//
// An error is returned if any of the following are true:
// The input frame is not a wide formated time series frame.
// The input row has no rows.
// The time index not sorted ascending by time.
// The time index has null values.
// Two numeric Fields have the same name but different types.
//
// With a conversion of Wide to Long, and then back to Wide via LongToWide(), the outputted Wide Frame
// may not match the original inputted Wide frame.
funcWideToLong(wideFrame*Frame)(*Frame,error){
tsSchema:=wideFrame.TimeSeriesSchema()
iftsSchema.Type!=TimeSeriesTypeWide{
returnnil,fmt.Errorf("can not convert to long series, expected wide format series input but got %s series",tsSchema.Type)
}
wideLen,err:=wideFrame.RowLen()
iferr!=nil{
returnnil,err
}elseifwideLen==0{
returnnil,fmt.Errorf("can not convert to long series, input fields have no rows")
}
uniqueValueNames:=[]string{}// unique names of Fields that are value types
uniqueValueNamesToType:=make(map[string]FieldType)// unique value Field names to Field type
uniqueLabelKeys:=make(map[string]struct{})// unique Label keys, used to build schema
labelKeyToWideIndices:=make(map[string][]int)// unique label sets to corresponding Field indices of wideFrame
// Gather schema information from wideFrame required to build longFrame
returnnil,fmt.Errorf("two fields in input frame may not have the same name but different types, field name %s has type %s but also type %s and field idx %v",wideField.Name,pType,wideField.Type(),vIdx)