package main import ( // External we "git.gibonuddevalla.se/go/wrappederror" // Standard "database/sql" "time" ) type DatapointType string const ( INT DatapointType = "INT" STRING = "STRING" DATETIME = "DATETIME" ) type Datapoint struct { ID int Name string SectionID int `db:"section_id"` Datatype DatapointType LastValue time.Time `db:"last_value"` DatapointValueJSON []byte `db:"datapoint_value_json"` LastDatapointValue DatapointValue } type DatapointValue struct { ID int DatapointID int `db:"datapoint_id"` Ts time.Time ValueInt sql.NullInt64 `db:"value_int"` ValueString sql.NullString `db:"value_string"` ValueDateTime sql.NullTime `db:"value_datetime"` } func (dp DatapointValue) Value() any { if dp.ValueInt.Valid { return dp.ValueInt.Int64 } if dp.ValueString.Valid { return dp.ValueString.String } if dp.ValueDateTime.Valid { return dp.ValueDateTime.Time } return nil } func DatapointAdd[T any](name string, value T) (err error) { row := service.Db.Conn.QueryRow(`SELECT id, datatype FROM datapoint WHERE name=$1`, name) var dpID int var dpType DatapointType err = row.Scan(&dpID, &dpType) if err != nil { err = we.Wrap(err).WithData(struct { Name string Value any }{name, value}) return } switch dpType { case INT: _, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_int) VALUES($1, $2)`, dpID, value) case STRING: _, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_string) VALUES($1, $2)`, dpID, value) case DATETIME: _, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_datetime) VALUES($1, $2)`, dpID, value) } if err != nil { err = we.Wrap(err).WithData(struct { ID int value any }{dpID, value}) return } return } func DatapointRetrieve(name string) (dp Datapoint, err error) { row := service.Db.Conn.QueryRowx( `SELECT * FROM datapoint dp WHERE dp.name = $1`, name, ) err = row.StructScan(&dp) if err != nil { err = we.Wrap(err).WithData(name) return } row = service.Db.Conn.QueryRowx(` SELECT * FROM datapoint_value WHERE datapoint_id = $1 ORDER BY ts DESC LIMIT 1 `, dp.ID, ) err = row.StructScan(&dp.LastDatapointValue) if err != nil { err = we.Wrap(err).WithData(dp.ID) return } return }