Should complete DL-1, adds functions for getting latest values of all tags
This commit is contained in:
1
app.go
1
app.go
@@ -98,6 +98,7 @@ func (a *App) initializeRoutes() {
|
||||
a.Router.HandleFunc("/api/v1/tag/{id:[0-9]+}", a.deleteTag).Methods("DELETE")
|
||||
|
||||
a.Router.HandleFunc("/api/v1/tagValues", a.getTagValues).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagValues/latest", a.getLatestTagValues).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagValue", a.createTagValue).Methods("POST")
|
||||
a.Router.HandleFunc("/api/v1/tagValue/{id:[0-9]+}", a.getTagValue).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagValue/{id:[0-9]+}", a.updateTagValue).Methods("PUT")
|
||||
|
||||
@@ -109,3 +109,14 @@ func (a *App) deleteTagValue(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
respondWithJSON(w, http.StatusOK, map[string]string{"result": "success"})
|
||||
}
|
||||
|
||||
func (a *App) getLatestTagValues(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
latesTagValues, err := getLatestTagValues(a.DB)
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, latesTagValues)
|
||||
}
|
||||
|
||||
2
main.go
2
main.go
@@ -26,6 +26,8 @@ func main() {
|
||||
ensureFileTableExists(a.DB)
|
||||
ensureTagClassTableExists(a.DB)
|
||||
ensureTagTableExists(a.DB)
|
||||
ensureTagValueTableExists(a.DB)
|
||||
ensureLatestTagValueTableExists(a.DB)
|
||||
|
||||
seedDeviceTypeData(a.DB)
|
||||
seedDataTypeData(a.DB)
|
||||
|
||||
114
model_tag.go
114
model_tag.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
@@ -53,15 +54,31 @@ const tagTableCreationQuery = `CREATE TABLE IF NOT EXISTS tags (
|
||||
CONSTRAINT fk_datatype FOREIGN KEY (dataTypeId) REFERENCES dataTypes(id)
|
||||
);`
|
||||
|
||||
const latestTagValueCreationQuery = `CREATE TABLE IF NOT EXISTS latestValues (
|
||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
tagId int(10) unsigned,
|
||||
val varchar(64),
|
||||
createdAt datetime,
|
||||
updatedAt datetime,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT fk_tagId FOREIGN KEY (tagId) REFERENCES tags(id) ON DELETE CASCADE
|
||||
);`
|
||||
|
||||
func ensureTagTableExists(db *sql.DB) {
|
||||
if _, err := db.Exec(tagTableCreationQuery); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func ensureLatestTagValueTableExists(db *sql.DB) {
|
||||
if _, err := db.Exec(latestTagValueCreationQuery); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// getTag : used during GET command
|
||||
func (t *Tag) getTag(db *sql.DB) error {
|
||||
sqlQuery := `SELECT
|
||||
sqlQuery := `SELECT
|
||||
tags.name,
|
||||
tags.tagName,
|
||||
tags.tagClassId,
|
||||
@@ -79,7 +96,7 @@ func (t *Tag) getTag(db *sql.DB) error {
|
||||
deviceTypes.createdAt,
|
||||
deviceTypes.updatedAt,
|
||||
devices.address,
|
||||
devices.createdAt,
|
||||
devices.createdAt,
|
||||
devices.updatedAt,
|
||||
tags.description,
|
||||
tags.dataTypeId,
|
||||
@@ -94,13 +111,13 @@ func (t *Tag) getTag(db *sql.DB) error {
|
||||
tags.units,
|
||||
tags.maxExpected,
|
||||
tags.minExpected,
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
JOIN tagClasses ON tags.tagClassId = tagClasses.id
|
||||
JOIN devices ON tags.deviceId = devices.id
|
||||
JOIN deviceTypes ON devices.deviceTypeId = deviceTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
WHERE tags.id=?`
|
||||
return db.QueryRow(sqlQuery, t.ID).Scan(
|
||||
&t.Name,
|
||||
@@ -142,19 +159,19 @@ func (t *Tag) getTag(db *sql.DB) error {
|
||||
// updateTag : used during PUT command
|
||||
func (t *Tag) updateTag(db *sql.DB) error {
|
||||
sqlQuery := `UPDATE tags SET
|
||||
name=?,
|
||||
tagName=?,
|
||||
tagClassId=?,
|
||||
deviceId=?,
|
||||
description=?,
|
||||
dataTypeId=?,
|
||||
changeThreshold=?,
|
||||
guaranteeSec=?,
|
||||
mapFunction=?,
|
||||
units=?,
|
||||
minExpected=?,
|
||||
maxExpected=?,
|
||||
updatedAt=?
|
||||
name=?,
|
||||
tagName=?,
|
||||
tagClassId=?,
|
||||
deviceId=?,
|
||||
description=?,
|
||||
dataTypeId=?,
|
||||
changeThreshold=?,
|
||||
guaranteeSec=?,
|
||||
mapFunction=?,
|
||||
units=?,
|
||||
minExpected=?,
|
||||
maxExpected=?,
|
||||
updatedAt=?
|
||||
WHERE id=?`
|
||||
updStmt, updErr := db.Prepare(sqlQuery)
|
||||
if updErr != nil {
|
||||
@@ -176,36 +193,53 @@ func (t *Tag) deleteTag(db *sql.DB) error {
|
||||
|
||||
// createTag : used during PUSH command
|
||||
func (t *Tag) createTag(db *sql.DB) error {
|
||||
sqlQuery := `INSERT INTO tags (
|
||||
name,
|
||||
tagName,
|
||||
tagClassId,
|
||||
deviceId,
|
||||
description,
|
||||
dataTypeId,
|
||||
changeThreshold,
|
||||
guaranteeSec,
|
||||
mapFunction,
|
||||
units,
|
||||
minExpected,
|
||||
maxExpected,
|
||||
tagSQLQuery := `INSERT INTO tags (
|
||||
name,
|
||||
tagName,
|
||||
tagClassId,
|
||||
deviceId,
|
||||
description,
|
||||
dataTypeId,
|
||||
changeThreshold,
|
||||
guaranteeSec,
|
||||
mapFunction,
|
||||
units,
|
||||
minExpected,
|
||||
maxExpected,
|
||||
createdAt,
|
||||
updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
stmtIns, insErr := db.Prepare(sqlQuery)
|
||||
|
||||
valSQLQuery := `INSERT INTO latestValues (tagId, val, createdAt, updatedAt) VALUES (?, ?, ?, ?)`
|
||||
|
||||
stmtIns, insErr := db.Prepare(tagSQLQuery)
|
||||
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.Name, t.TagName, t.TagClassID, t.DeviceID,
|
||||
stmtInsVal, insValErr := db.Prepare(valSQLQuery)
|
||||
if insValErr != nil {
|
||||
panic(insValErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer stmtInsVal.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
res, err := stmtIns.Exec(t.Name, t.TagName, t.TagClassID, t.DeviceID,
|
||||
t.Description, t.DataTypeID, t.ChangeThreshold, t.GuaranteeSec,
|
||||
t.MapFunction, t.Units, t.MinExpected, t.MaxExpected, time.Now(), time.Now())
|
||||
|
||||
lastID, idErr := res.LastInsertId()
|
||||
if idErr == nil {
|
||||
_, valErr := stmtInsVal.Exec(lastID, "0.0", time.Now(), time.Now())
|
||||
return valErr
|
||||
}
|
||||
fmt.Printf("\n%s -- %d\n", "Invalid last inserted id", lastID)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// getTags : used during GET command for all
|
||||
func getTags(db *sql.DB, start, count int) (Tags, error) {
|
||||
sqlQuery := `SELECT
|
||||
sqlQuery := `SELECT
|
||||
tags.ID,
|
||||
tags.name,
|
||||
tags.tagName,
|
||||
@@ -224,7 +258,7 @@ func getTags(db *sql.DB, start, count int) (Tags, error) {
|
||||
deviceTypes.createdAt,
|
||||
deviceTypes.updatedAt,
|
||||
devices.address,
|
||||
devices.createdAt,
|
||||
devices.createdAt,
|
||||
devices.updatedAt,
|
||||
tags.description,
|
||||
tags.dataTypeId,
|
||||
@@ -239,13 +273,13 @@ func getTags(db *sql.DB, start, count int) (Tags, error) {
|
||||
tags.units,
|
||||
tags.maxExpected,
|
||||
tags.minExpected,
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
JOIN tagClasses ON tags.tagClassId = tagClasses.id
|
||||
JOIN devices ON tags.deviceId = devices.id
|
||||
JOIN deviceTypes ON devices.deviceTypeId = deviceTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
LIMIT ? OFFSET ?;`
|
||||
|
||||
getStmt, prepErr := db.Prepare(sqlQuery)
|
||||
|
||||
@@ -18,9 +18,25 @@ type TagValue struct {
|
||||
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,
|
||||
@@ -28,7 +44,7 @@ const tagValueTableCreationQuery = `CREATE TABLE IF NOT EXISTS tagValues (
|
||||
createdAt datetime,
|
||||
updatedAt datetime,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT fk_tag FOREIGN KEY (tagId) REFERENCES tags(id)
|
||||
CONSTRAINT fk_tag FOREIGN KEY (tagId) REFERENCES tags(id) ON DELETE CASCADE
|
||||
)`
|
||||
|
||||
func ensureTagValueTableExists(db *sql.DB) {
|
||||
@@ -80,6 +96,18 @@ func (t *TagValue) createTagValue(db *sql.DB) error {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -118,3 +146,37 @@ func getTagValues(db *sql.DB, start, count int) (TagValues, error) {
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ func TestMain(m *testing.M) {
|
||||
ensureTagClassTableExists(a.DB)
|
||||
ensureTagTableExists(a.DB)
|
||||
ensureTagValueTableExists(a.DB)
|
||||
ensureLatestTagValueTableExists(a.DB)
|
||||
|
||||
code := m.Run()
|
||||
|
||||
@@ -42,6 +43,7 @@ func TestMain(m *testing.M) {
|
||||
clearTagClassTable()
|
||||
clearTagTable()
|
||||
clearTagValueTable()
|
||||
clearLatestTagValueTable()
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ func clearTagValueTable() {
|
||||
a.DB.Exec("DELETE FROM tagValues")
|
||||
a.DB.Exec("ALTER TABLE tagValues AUTO_INCREMENT = 1")
|
||||
}
|
||||
func clearLatestTagValueTable() {
|
||||
a.DB.Exec("DELETE FROM latestValues")
|
||||
a.DB.Exec("ALTER TABLE latestValues AUTO_INCREMENT = 1")
|
||||
}
|
||||
|
||||
func TestEmptyTagValueTable(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
|
||||
Reference in New Issue
Block a user