Markus Pesch
10069568f9
Changes: - Renamed storage endpoint into dsn (data source name). - Add additional dsn fallback property. This dsn will be used in futes to store informations, if the main dsn backend does not work correctly. For example, if no connection can be established over the network to a database.
731 lines
17 KiB
Go
731 lines
17 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
"github.com/volker-raschek/flucky/pkg/types"
|
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
|
)
|
|
|
|
// SQLite implementation
|
|
type SQLite struct {
|
|
dbo *sql.DB
|
|
flogger logger.Logger
|
|
queries map[string]string
|
|
}
|
|
|
|
// DeleteDevices from the database
|
|
func (sqlite *SQLite) DeleteDevices(ctx context.Context, deviceIDs ...string) error {
|
|
queryFile := "deleteDevice.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, deviceID := range deviceIDs {
|
|
_, err = stmt.Exec(deviceID)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// DeleteSensors from the database
|
|
func (sqlite *SQLite) DeleteSensors(ctx context.Context, sensorIDs ...string) error {
|
|
queryFile := "deleteSensor.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, sensorID := range sensorIDs {
|
|
_, err = stmt.Exec(sensorID)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// InsertDevices into the database
|
|
func (sqlite *SQLite) InsertDevices(ctx context.Context, devices ...*types.Device) error {
|
|
queryFile := "insertDevice.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, device := range devices {
|
|
_, err = stmt.Exec(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// InsertMeasuredValues into the database
|
|
func (sqlite *SQLite) InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
|
splittedMeasuredValues := make(map[string][]*types.MeasuredValue, 0)
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
if _, ok := splittedMeasuredValues[measuredValue.ValueType]; !ok {
|
|
splittedMeasuredValues[measuredValue.ValueType] = make([]*types.MeasuredValue, 0)
|
|
}
|
|
splittedMeasuredValues[measuredValue.ValueType] = append(splittedMeasuredValues[measuredValue.ValueType], measuredValue)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
// General insert function
|
|
insert := func(tx *sql.Tx, queryFile string, measuredValues []*types.MeasuredValue) error {
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
_, err := stmt.Exec(
|
|
&measuredValue.ID,
|
|
&measuredValue.Value,
|
|
&measuredValue.SensorID,
|
|
&measuredValue.Date,
|
|
&measuredValue.CreationDate,
|
|
&measuredValue.UpdateDate,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
for measuredValueType, measuredValues := range splittedMeasuredValues {
|
|
var queryFile string
|
|
|
|
switch measuredValueType {
|
|
case "humidity":
|
|
queryFile = "insertHumidity.sql"
|
|
case "pressure":
|
|
queryFile = "insertPressure.sql"
|
|
case "temperature":
|
|
queryFile = "insertTemperature.sql"
|
|
default:
|
|
tx.Rollback()
|
|
return fmt.Errorf("Measured value type %v not supported", measuredValueType)
|
|
}
|
|
|
|
err := insert(tx, queryFile, measuredValues)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// InsertSensors into the database
|
|
func (sqlite *SQLite) InsertSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
|
queryFile := "insertSensor.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, sensor := range sensors {
|
|
_, err = stmt.Exec(
|
|
&sensor.ID,
|
|
&sensor.Name,
|
|
&sensor.Location,
|
|
&sensor.WireID,
|
|
&sensor.I2CBus,
|
|
&sensor.I2CAddress,
|
|
&sensor.GPIONumber,
|
|
&sensor.Model,
|
|
&sensor.Enabled,
|
|
&sensor.TickDuration,
|
|
&sensor.DeviceID,
|
|
&sensor.CreationDate,
|
|
)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// Scheme creates all required tables if not exist
|
|
func (sqlite *SQLite) Scheme(ctx context.Context) error {
|
|
for _, query := range []string{
|
|
sqlite.queries["createTableDevices.sql"],
|
|
sqlite.queries["createTableSensors.sql"],
|
|
sqlite.queries["createTableHumidites.sql"],
|
|
sqlite.queries["createTablePressures.sql"],
|
|
sqlite.queries["createTableTemperatures.sql"],
|
|
} {
|
|
_, err := sqlite.dbo.ExecContext(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SelectDevice from database
|
|
func (sqlite *SQLite) SelectDevice(ctx context.Context, id string) (*types.Device, error) {
|
|
queryFile := "selectDevice.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
devices, err := sqlite.selectDevices(tx, query, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(devices) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return devices[0], nil
|
|
}
|
|
|
|
// SelectDevices from the database
|
|
func (sqlite *SQLite) SelectDevices(ctx context.Context) ([]*types.Device, error) {
|
|
queryFile := "selectDevices.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
devices, err := sqlite.selectDevices(tx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
|
}
|
|
|
|
return devices, nil
|
|
}
|
|
|
|
func (sqlite *SQLite) selectDevices(tx *sql.Tx, query string, args ...interface{}) ([]*types.Device, error) {
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
rows, err := stmt.Query(args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
|
}
|
|
|
|
devices := make([]*types.Device, 0)
|
|
for rows.Next() {
|
|
device := new(types.Device)
|
|
err = rows.Scan(
|
|
&device.ID,
|
|
&device.Name,
|
|
&device.Location,
|
|
&device.CreationDate,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
|
}
|
|
devices = append(devices, device)
|
|
}
|
|
|
|
return devices, nil
|
|
}
|
|
|
|
// SelectHumidity returns humidity from the database
|
|
func (sqlite *SQLite) SelectHumidity(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
|
queryFile := "selectHumidity.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if measuredValues == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "humidity"
|
|
}
|
|
|
|
return measuredValues[0], nil
|
|
}
|
|
|
|
// SelectHumidities returns humidities from the database
|
|
func (sqlite *SQLite) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) {
|
|
queryFile := "selectHumidities.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "humidity"
|
|
}
|
|
|
|
return measuredValues, nil
|
|
}
|
|
|
|
func (sqlite *SQLite) selectMeasuredValue(tx *sql.Tx, query string, args ...interface{}) ([]*types.MeasuredValue, error) {
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
rows, err := stmt.Query(args...)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues := make([]*types.MeasuredValue, 0)
|
|
for rows.Next() {
|
|
measuredValue := new(types.MeasuredValue)
|
|
err := rows.Scan(
|
|
&measuredValue.ID,
|
|
&measuredValue.Value,
|
|
&measuredValue.SensorID,
|
|
&measuredValue.Date,
|
|
&measuredValue.CreationDate,
|
|
&measuredValue.UpdateDate,
|
|
)
|
|
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues = append(measuredValues, measuredValue)
|
|
}
|
|
|
|
return measuredValues, nil
|
|
}
|
|
|
|
// SelectPressure returns pressure from the database
|
|
func (sqlite *SQLite) SelectPressure(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
|
queryFile := "selectPressure.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if measuredValues == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "pressure"
|
|
}
|
|
|
|
return measuredValues[0], nil
|
|
}
|
|
|
|
// SelectPressures returns pressure from the database
|
|
func (sqlite *SQLite) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
|
queryFile := "selectPressures.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "pressure"
|
|
}
|
|
|
|
return measuredValues, nil
|
|
}
|
|
|
|
// SelectSensor from database
|
|
func (sqlite *SQLite) SelectSensor(ctx context.Context, id string) (*types.Sensor, error) {
|
|
queryFile := "selectSensor.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
sensors, err := sqlite.selectSensors(tx, query, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
|
}
|
|
|
|
if len(sensors) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return sensors[0], nil
|
|
}
|
|
|
|
// SelectSensors from the database
|
|
func (sqlite *SQLite) SelectSensors(ctx context.Context) ([]*types.Sensor, error) {
|
|
queryFile := "selectSensors.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
}
|
|
|
|
sensors, err := sqlite.selectSensors(tx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
|
}
|
|
|
|
return sensors, nil
|
|
}
|
|
|
|
func (sqlite *SQLite) selectSensors(tx *sql.Tx, query string, args ...interface{}) ([]*types.Sensor, error) {
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
|
}
|
|
defer stmt.Close()
|
|
|
|
rows, err := stmt.Query(args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
|
}
|
|
|
|
sensors := make([]*types.Sensor, 0)
|
|
for rows.Next() {
|
|
sensor := new(types.Sensor)
|
|
err = rows.Scan(
|
|
&sensor.ID,
|
|
&sensor.Name,
|
|
&sensor.Location,
|
|
&sensor.WireID,
|
|
&sensor.I2CBus,
|
|
&sensor.I2CAddress,
|
|
&sensor.GPIONumber,
|
|
&sensor.Model,
|
|
&sensor.Enabled,
|
|
&sensor.TickDuration,
|
|
&sensor.DeviceID,
|
|
&sensor.CreationDate,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
|
}
|
|
sensors = append(sensors, sensor)
|
|
}
|
|
|
|
return sensors, nil
|
|
}
|
|
|
|
// SelectTemperature returns temperatures from the database
|
|
func (sqlite *SQLite) SelectTemperature(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
|
queryFile := "selectTemperature.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if measuredValues == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "temperatures"
|
|
}
|
|
|
|
return measuredValues[0], nil
|
|
}
|
|
|
|
// SelectTemperatures returns temperatures from the database
|
|
func (sqlite *SQLite) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
|
queryFile := "selectTemperatures.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, measuredValue := range measuredValues {
|
|
measuredValue.ValueType = "temperatures"
|
|
}
|
|
|
|
return measuredValues, nil
|
|
}
|
|
|
|
// UpdateDevices updates a device in the database
|
|
func (sqlite *SQLite) UpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
|
queryFile := "updateDevice.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, device := range devices {
|
|
_, err := stmt.Exec(
|
|
&device.Name,
|
|
&device.Location,
|
|
&device.CreationDate,
|
|
&device.ID,
|
|
)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
// UpdateSensors updates a sensor in the database
|
|
func (sqlite *SQLite) UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
|
queryFile := "updateSensor.sql"
|
|
query, present := sqlite.queries[queryFile]
|
|
if !present {
|
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
|
}
|
|
|
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
stmt, err := tx.Prepare(query)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
for _, sensor := range sensors {
|
|
_, err := stmt.Exec(
|
|
&sensor.Name,
|
|
&sensor.Location,
|
|
&sensor.WireID,
|
|
&sensor.I2CBus,
|
|
&sensor.I2CAddress,
|
|
&sensor.GPIONumber,
|
|
&sensor.Model,
|
|
&sensor.Enabled,
|
|
&sensor.TickDuration,
|
|
&sensor.DeviceID,
|
|
&sensor.CreationDate,
|
|
&sensor.ID,
|
|
)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|