I’m currently writing a custom datasource using Golang, for a query I need to return a table with entity’s informations, and one of this table column is a nullable time, but I can’t achieve to have it NULL.
Context:
An “entity” is an object returned by my MariaDB’s “events” table, it’s composed of a mere ID, Name and a OccurredAt column which is a DATETIME.
Everything works fine in my datasource, but I would like to optimize my queries by hidding the “OccurredAt” time field which can be NULL.
Currently, when the “occurred_at” of my event is NULL my query return an empty time.Time{}
which display the “1754-08-30 22:53:02.128” date (which is normal), and so an example result would be:
ID | Name | OccurredAt
1 | Event1 | 2024-10-01 13:35:30.614
2 | Event2 | 1754-08-30 22:53:02.128
3 | Event3 | 2024-09-30 15:14:30.232
4 | Event4 | 2024-09-10 13:24:31.089
(Note that here only my second event had a NULL
’s occurred_at property)
In order to obtain this result, I’m just creating a simple frame with fields like this:
package data ("github.com/grafana/grafana-plugin-sdk-go/data")
// This function's the same as `NewStringField` or `NewInt64Field` with the according types
func NewTimeField(key, label string, values []time.Time) *data.Field {
field := data.NewField(key, nil, values)
field.Config = &data.FieldConfig{DisplayNameFromDS: label}
return field
}
func GetEventsFrames(events []interface, q *query.QueryData) (data.Frames, error) {
frame := data.NewFrame("operations")
frame.RefID = q.RefID
frame.SetMeta(&data.FrameMeta{PreferredVisualization: data.VisTypeTable})
frame.Fields = append(frame.Fields,
NewInt64Field("id", "ID", nil),
NewStringField("name", "Name", nil),
NewTimeField("occurred_at", "Occurred At", nil),
)
// events is my list of events returned by my database
for _, e := range events {
frame.AppendRow(
e.ID,
e.Name,
// e.OccurredAt is a sql.NullTime, which is valid and checked beforehand
e.OccurredAt.Time,
)
}
return data.Frames{frame}, nil
}
What I tried
In order to display empty cells in my table when the events doesn’t have valid OccurredAt, I replaced my NewTimeField
function by this one:
// It's the same as the previous function but `values` is a slice of pointers
func NewNullTimeField(key, label string, values []*time.Time) *data.Field {
field := data.NewField(key, nil, values)
field.Config = &data.FieldConfig{DisplayNameFromDS: label}
return field
}
and in my function I did this:
for _, e := range events {
var occurredAt *time.Time
if e.OccurredAt.Valid {
occurredAt = &e.OccurredAt.Time
}
frame.AppendRow(
e.ID,
e.Name,
// Here `occurredAt` should be either nil or a valid `*time.Time`
occurredAt,
)
}
It should works just fine, it compile, it doesn’t panic, my table’s column are empty as excepted when OccurredAt’s nil, but all my other dates are now displayed as “1754-08-30 22:53:02.128” (because it’s equal to -6795364578872
).
example:
ID | Name | OccurredAt
1 | Event1 | 1754-08-30 22:53:02.128
2 | Event2 |
3 | Event3 | 1754-08-30 22:53:02.128
4 | Event4 | 1754-08-30 22:53:02.128
In the query inspector, we can see this:
name:"occurred_at"
type:"time"
typeInfo:Object
frame:"time.Time"
nullable:true
config:Object
displayNameFromDS:"Occurred At"
The “nullable” property is true so I don’t really know where I get it wrong, has anybody any insights ?