package main import ( "database/sql" "log" "time" ) // TagValue : holds information about a specific TagValue type TagValue struct { ID int `json:"id"` TagID int `json:"tagId"` Val string `json:"val"` TagName string `json:"tagName"` Units string `json:"units"` DataType string `json:"dataType"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } // LatestTagValue : latest tag value struct type LatestTagValue struct { ID int `json:"id"` TagID int `json:"tagId"` Val string `json:"val"` TagName string `json:"tagName"` Units string `json:"units"` DataType string `json:"dataType"` MaxExpected float32 `json:"maxExpected"` MinExpected float32 `json:"minExpected"` UpdatedAt time.Time `json:"updatedAt"` } // TagValues : a list of TagValue items type TagValues []TagValue // LatestTagValues : a list of LatestTagValue items type LatestTagValues []LatestTagValue const tagValueTableCreationQuery = `CREATE TABLE IF NOT EXISTS tagValues ( id int(10) unsigned NOT NULL AUTO_INCREMENT, tagId int(10) unsigned, val varchar(64), createdAt datetime, updatedAt datetime, PRIMARY KEY (id), CONSTRAINT fk_tag FOREIGN KEY (tagId) REFERENCES tags(id) ON DELETE CASCADE )` func ensureTagValueTableExists(db *sql.DB) { if _, err := db.Exec(tagValueTableCreationQuery); err != nil { log.Fatal(err) } } // getTagValue : used during GET command func (t *TagValue) getTagValue(db *sql.DB) error { sqlQuery := `SELECT tagValues.tagId, tagValues.val, tags.name, tags.units, dataTypes.dataType, tagValues.createdAt, tagValues.updatedAt FROM tagValues JOIN tags ON tagValues.tagId = tags.id JOIN dataTypes ON tags.dataTypeId = dataTypes.id WHERE tagValues.id=?` return db.QueryRow(sqlQuery, t.ID).Scan(&t.TagID, &t.Val, &t.TagName, &t.Units, &t.DataType, &t.CreatedAt, &t.UpdatedAt) } // updateTagValue : used during PUT command func (t *TagValue) updateTagValue(db *sql.DB) error { updStmt, updErr := db.Prepare("UPDATE tagValues SET tagId=?, val=?, updatedAt=? WHERE id=?") if updErr != nil { panic(updErr.Error()) // proper error handling instead of panic in your app } defer updStmt.Close() // Close the statement when we leave main() / the program terminates _, err := updStmt.Exec(t.TagID, t.Val, time.Now(), t.ID) return err } // deleteTagValue : used during DELETE command func (t *TagValue) deleteTagValue(db *sql.DB) error { _, err := db.Exec("DELETE FROM tagValues WHERE id=?", t.ID) return err } // createTagValue : used during PUSH command func (t *TagValue) createTagValue(db *sql.DB) error { stmtIns, insErr := db.Prepare("INSERT INTO tagValues (tagId, val, createdAt, updatedAt) VALUES (?, ?, ?, ?);") if insErr != nil { panic(insErr.Error()) // proper error handling instead of panic in your app } defer stmtIns.Close() // Close the statement when we leave main() / the program terminates _, err := stmtIns.Exec(t.TagID, t.Val, time.Now(), time.Now()) if err == nil { valStmtUpd, valStmtErr := db.Prepare("UPDATE latestValues SET val=?, updatedAt=? WHERE tagId=?") if valStmtErr != nil { panic(valStmtErr.Error()) // proper error handling instead of panic in your app } defer valStmtUpd.Close() // Close the statement when we leave main() / the program terminates _, updErr := valStmtUpd.Exec(t.Val, time.Now(), t.TagID) return updErr } return err } // getTagValues : used during GET command for all func getTagValues(db *sql.DB, start, count int) (TagValues, error) { sqlQuery := `SELECT tagValues.id, tagValues.tagId, tagValues.val, tags.name, tags.units, dataTypes.dataType, tagValues.createdAt, tagValues.updatedAt FROM tagValues JOIN tags ON tagValues.tagId = tags.id JOIN dataTypes ON tags.dataTypeId = dataTypes.id LIMIT ? OFFSET ?` rows, err := db.Query(sqlQuery, count, start) if err != nil { return nil, err } defer rows.Close() tagValues := TagValues{} for rows.Next() { var t TagValue if err := rows.Scan(&t.ID, &t.TagID, &t.Val, &t.TagName, &t.Units, &t.DataType, &t.CreatedAt, &t.UpdatedAt); err != nil { return nil, err } tagValues = append(tagValues, t) } return tagValues, nil } // getLatestTagValues : used to get all latest tag values func getLatestTagValues(db *sql.DB) (LatestTagValues, error) { tagValues := LatestTagValues{} sqlQuery := `SELECT latestValues.id, latestValues.tagId, latestValues.val, tags.name, tags.units, tags.minExpected, tags.maxExpected, dataTypes.dataType, latestValues.updatedAt FROM latestValues JOIN tags on latestValues.tagId = tags.id JOIN dataTypes ON tags.dataTypeId = dataTypes.id` rows, err := db.Query(sqlQuery) if err != nil { return nil, err } defer rows.Close() for rows.Next() { var tag LatestTagValue if err := rows.Scan(&tag.ID, &tag.TagID, &tag.Val, &tag.TagName, &tag.Units, &tag.MinExpected, &tag.MaxExpected, &tag.DataType, &tag.UpdatedAt); err != nil { return nil, err } tagValues = append(tagValues, tag) } return tagValues, nil }