refac: use embed instead of go-bindata, secure closing of transactions
This commit is contained in:
parent
59db7cfc85
commit
7a88aaac0c
40
Makefile
40
Makefile
@ -30,7 +30,7 @@ EXECUTABLE_TARGETS:= \
|
||||
|
||||
${EXECUTABLE}: bin/tmp/${EXECUTABLE}
|
||||
|
||||
bin/linux/amd64/${EXECUTABLE}: bindata
|
||||
bin/linux/amd64/${EXECUTABLE}:
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64 \
|
||||
@ -38,7 +38,7 @@ bin/linux/amd64/${EXECUTABLE}: bindata
|
||||
GOPRIVATE=${GOPRIVATE} \
|
||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||
|
||||
bin/linux/arm/5/${EXECUTABLE}: bindata
|
||||
bin/linux/arm/5/${EXECUTABLE}:
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=linux \
|
||||
GOARCH=arm \
|
||||
@ -47,7 +47,7 @@ bin/linux/arm/5/${EXECUTABLE}: bindata
|
||||
GOPRIVATE=${GOPRIVATE} \
|
||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||
|
||||
bin/linux/arm/7/${EXECUTABLE}: bindata
|
||||
bin/linux/arm/7/${EXECUTABLE}:
|
||||
CC=arm-linux-gnueabihf-gcc \
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=linux \
|
||||
@ -57,46 +57,22 @@ bin/linux/arm/7/${EXECUTABLE}: bindata
|
||||
GOPRIVATE=${GOPRIVATE} \
|
||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||
|
||||
bin/tmp/${EXECUTABLE}: bindata
|
||||
bin/tmp/${EXECUTABLE}:
|
||||
CGO_ENABLED=1 \
|
||||
GOPROXY=${GOPROXY} \
|
||||
GOPRIVATE=${GOPRIVATE} \
|
||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||
|
||||
# GO-BINDATA
|
||||
# ==============================================================================
|
||||
BINDATA_TARGETS := \
|
||||
pkg/repository/db/postgres/ddl/bindata.go \
|
||||
pkg/repository/db/postgres/dml/bindata.go \
|
||||
pkg/repository/db/sqlite3/ddl/bindata.go \
|
||||
pkg/repository/db/sqlite3/dml/bindata.go
|
||||
|
||||
PHONY+=bindata
|
||||
bindata: clean ${BINDATA_TARGETS}
|
||||
|
||||
pkg/repository/db/postgres/ddl/bindata.go:
|
||||
go-bindata -pkg postgresddl -prefix ${@:%/bindata.go=%} -o ${@} ${@:%/bindata.go=%}/*
|
||||
|
||||
pkg/repository/db/postgres/dml/bindata.go:
|
||||
go-bindata -pkg postgresdml -prefix ${@:%/bindata.go=%} -o ${@} ${@:%/bindata.go=%}/*
|
||||
|
||||
pkg/repository/db/sqlite3/ddl/bindata.go:
|
||||
go-bindata -pkg sqlite3ddl -prefix ${@:%/bindata.go=%} -o ${@} ${@:%/bindata.go=%}/*
|
||||
|
||||
pkg/repository/db/sqlite3/dml/bindata.go:
|
||||
go-bindata -pkg sqlite3dml -prefix ${@:%/bindata.go=%} -o ${@} ${@:%/bindata.go=%}/*
|
||||
|
||||
# CLEAN
|
||||
# ==============================================================================
|
||||
PHONY+=clean
|
||||
clean:
|
||||
rm --force ${BINDATA_TARGETS} || true
|
||||
rm --force --recursive bin/ || true
|
||||
|
||||
# TEST
|
||||
# ==============================================================================
|
||||
PHONY+=test/unit
|
||||
test/unit: bindata
|
||||
test/unit:
|
||||
go test -v -race -coverprofile=coverage.txt -covermode=atomic -timeout 600s -count=1 ./pkg/...
|
||||
|
||||
PHONY+=test/integration
|
||||
@ -147,12 +123,6 @@ PHONY+=${EXECUTABLE_TARGETS:%=container-run/%}
|
||||
${EXECUTABLE_TARGETS:%=container-run/%}:
|
||||
$(MAKE) container-run COMMAND=${@:container-run/%=%}
|
||||
|
||||
# CONTAINER STEPS - GO-BINDATA
|
||||
# ==============================================================================
|
||||
PHONY+=container-run/bindata
|
||||
container-run/bindata:
|
||||
$(MAKE) container-run COMMAND=${@:container-run/%=%}
|
||||
|
||||
# CONTAINER STEPS - CLEAN
|
||||
# ==============================================================================
|
||||
PHONY+=container-run/clean
|
||||
|
@ -1,12 +1,6 @@
|
||||
package imp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/config"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/repository"
|
||||
"git.cryptic.systems/volker.raschek/go-logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -35,47 +29,47 @@ func InitCmd(cmd *cobra.Command) error {
|
||||
}
|
||||
|
||||
func importSources(cmd *cobra.Command, args []string) error {
|
||||
configFile, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return fmt.Errorf("No config file defined")
|
||||
}
|
||||
// configFile, err := cmd.Flags().GetString("config")
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("No config file defined")
|
||||
// }
|
||||
|
||||
cnf, err := config.Read(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// cnf, err := config.Read(configFile)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
destURL, err := url.Parse(cnf.DSN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// destURL, err := url.Parse(cnf.DSN)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
logLevelString, err := cmd.Flags().GetString("loglevel")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// logLevelString, err := cmd.Flags().GetString("loglevel")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
logLevel, err := logger.ParseLogLevel(logLevelString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// logLevel, err := logger.ParseLogLevel(logLevelString)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
flogger := logger.NewLogger(logLevel)
|
||||
// flogger := logger.NewLogger(logLevel)
|
||||
|
||||
sourceURL, err := url.Parse(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse source url: %w", err)
|
||||
}
|
||||
// sourceURL, err := url.Parse(args[0])
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to parse source url: %w", err)
|
||||
// }
|
||||
|
||||
err = repository.Import(sourceURL, destURL, flogger, repository.OptImport{
|
||||
Sensors: importSensors,
|
||||
Humidities: importHumidities,
|
||||
Pressures: importPressures,
|
||||
Temperatures: importTemperatures,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to import: %w", err)
|
||||
}
|
||||
// err = repository.Import(sourceURL, destURL, flogger, repository.OptImport{
|
||||
// Sensors: importSensors,
|
||||
// Humidities: importHumidities,
|
||||
// Pressures: importPressures,
|
||||
// Temperatures: importTemperatures,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to import: %w", err)
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -184,7 +185,7 @@ func addSensor(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// add sensor entry to list
|
||||
err = repo.AddSensors(sensor)
|
||||
err = repo.AddSensors(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -227,7 +228,21 @@ func disableSensor(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return repo.DisableSensorsByNames(args...)
|
||||
s, err := repo.GetSensorsByNames(context.Background(), args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range s {
|
||||
s[i].Enabled = false
|
||||
}
|
||||
|
||||
err = repo.UpdateSensors(context.Background(), s...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func enableSensor(cmd *cobra.Command, args []string) error {
|
||||
@ -259,7 +274,21 @@ func enableSensor(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return repo.EnableSensorsByNames(args...)
|
||||
s, err := repo.GetSensorsByNames(context.Background(), args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range s {
|
||||
s[i].Enabled = true
|
||||
}
|
||||
|
||||
err = repo.UpdateSensors(context.Background(), s...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listSensors(cmd *cobra.Command, args []string) error {
|
||||
@ -292,7 +321,7 @@ func listSensors(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// add sensor entry to list
|
||||
sensors, err := repo.GetSensorsByDeviceID(cnf.DeviceID)
|
||||
sensors, err := repo.GetSensorsByDeviceIDs(context.Background(), cnf.DeviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -334,7 +363,7 @@ func removeSensor(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return repo.RemoveSensorsByNames(args...)
|
||||
return repo.RemoveSensorsByNames(context.Background(), args...)
|
||||
}
|
||||
|
||||
func renameSensor(cmd *cobra.Command, args []string) error {
|
||||
@ -366,5 +395,20 @@ func renameSensor(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return repo.RenameSensors(args[0], args[1])
|
||||
s, err := repo.GetSensorsByNames(context.Background(), args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range s {
|
||||
s[i].Name = args[1]
|
||||
}
|
||||
|
||||
err = repo.UpdateSensors(context.Background(), s...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
@ -72,7 +72,9 @@ func readTemperature(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sensorTypes, err := repo.GetSensors()
|
||||
ctx := context.Background()
|
||||
|
||||
sensorTypes, err := repo.GetSensors(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -123,7 +125,7 @@ LOOP:
|
||||
}
|
||||
|
||||
if persist {
|
||||
err = repo.AddMeasuredValues(measuredValues...)
|
||||
err = repo.AddMeasuredValues(ctx, measuredValues...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
8
go.mod
8
go.mod
@ -1,22 +1,20 @@
|
||||
module git.cryptic.systems/volker.raschek/flucky
|
||||
|
||||
go 1.14
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
git.cryptic.systems/volker.raschek/dockerutils v0.2.0
|
||||
git.cryptic.systems/volker.raschek/go-dht v0.1.2
|
||||
git.cryptic.systems/volker.raschek/go-logger v0.1.0
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect
|
||||
github.com/d2r2/go-bsbmp v0.0.0-20190515110334-3b4b3aea8375
|
||||
github.com/d2r2/go-i2c v0.0.0-20191123181816-73a8a799d6bc
|
||||
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1
|
||||
github.com/golang-migrate/migrate/v4 v4.14.2-0.20201125065321-a53e6fc42574
|
||||
github.com/johejo/golang-migrate-extra v0.0.0-20210217013041-51a992e50d16
|
||||
github.com/lib/pq v1.9.0
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/ugorji/go v1.1.4 // indirect
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 // indirect
|
||||
)
|
||||
|
56
go.sum
56
go.sum
@ -34,8 +34,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.cryptic.systems/volker.raschek/dockerutils v0.1.0 h1:NjE5BVS0k9XoRj8qZOHNvpjb1+C8Zr4sK/g4Yjw5Of4=
|
||||
git.cryptic.systems/volker.raschek/dockerutils v0.1.0/go.mod h1:PikYsmSANKHEKJSD2pIY9gPqMpiQh1ufCrU/s/v2I5Q=
|
||||
git.cryptic.systems/volker.raschek/dockerutils v0.2.0 h1:HJhAfHoyKHOt76T5PxeLvpoA0FCiGu50u4GRwGLGVJs=
|
||||
git.cryptic.systems/volker.raschek/dockerutils v0.2.0/go.mod h1:c4ZZpD2unnzwr7qHDpVdCmxLGOSnJagli7xNGgTBhk0=
|
||||
git.cryptic.systems/volker.raschek/go-dht v0.1.2 h1:kGmfpaVUETQhSELCIrKXMjKwuUhQkRUz/7VbLYiTRJA=
|
||||
@ -49,9 +47,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
@ -60,7 +55,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
@ -84,14 +78,11 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
|
||||
github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.3 h1:ijQT13JedHSHrQGWFcGEwzcNKrAGIiZ+jSD5QQG07SY=
|
||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
@ -106,19 +97,16 @@ github.com/d2r2/go-i2c v0.0.0-20191123181816-73a8a799d6bc h1:HLRSIWzUGMLCq4ldt0W
|
||||
github.com/d2r2/go-i2c v0.0.0-20191123181816-73a8a799d6bc/go.mod h1:AwxDPnsgIpy47jbGXZHA9Rv7pDkOJvQbezPuK1Y+nNk=
|
||||
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e h1:ZG3JBA6rPRl0xxQ+nNSfO7tor8w+CNCTs05DNJQYbLM=
|
||||
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e/go.mod h1:oA+9PUt8F1aKJ6o4YU1T120i7sgo1T6/1LWEEBy0BSs=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dhui/dktest v0.3.3 h1:DBuH/9GFaWbDRa42qsut/hbQu+srAQ0rPWnUoiGX7CA=
|
||||
github.com/dhui/dktest v0.3.3/go.mod h1:EML9sP4sqJELHn4jV7B0TY8oF6077nk83/tz7M56jcQ=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.2+incompatible h1:vFgEHPqWBTp4pTjdLwjAA4bSo3gvIGOYwuJTlEjVBCw=
|
||||
github.com/docker/docker v20.10.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
@ -149,14 +137,11 @@ github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PL
|
||||
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-migrate/migrate v1.3.2 h1:QAlFV1QF9zdkzy/jujlBVkVu+L/+k18cg8tuY1/4JDY=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1 h1:qmRd/rNGjM1r3Ve5gHd5ZplytrD02UcItYNxJ3iUHHE=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.2-0.20201125065321-a53e6fc42574 h1:YEVMe8861NCZxTMzTI5BCobpwGpt1Md6D8v00jDc68w=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.2-0.20201125065321-a53e6fc42574/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -197,8 +182,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@ -221,10 +206,9 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
@ -283,6 +267,8 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/johejo/golang-migrate-extra v0.0.0-20210217013041-51a992e50d16 h1:sDjlyV4OzJYR2ZdLAAKZwV6N/CcX60xbGnPZzKJOZ50=
|
||||
github.com/johejo/golang-migrate-extra v0.0.0-20210217013041-51a992e50d16/go.mod h1:lzH77MbyyahK7YO90wGRb65i9xLSoy2fD0dUSm23yMs=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@ -310,11 +296,9 @@ github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@ -337,6 +321,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@ -359,9 +344,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -405,41 +388,31 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -516,8 +489,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -540,8 +511,6 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -575,7 +544,6 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -602,9 +570,7 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM=
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -618,8 +584,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -739,7 +705,6 @@ google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 h1:sg8vLDNIxFPHTch
|
||||
google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
@ -751,7 +716,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
@ -779,7 +743,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@ -789,6 +752,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -27,8 +27,10 @@ func Start(cnf *config.Config, cachedEntries uint, flogger logger.Logger) error
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Add
|
||||
repoDevice, err := repo.GetDevice(cnf.DeviceID)
|
||||
repoDevice, err := repo.GetDeviceByID(ctx, cnf.DeviceID)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
@ -39,7 +41,7 @@ func Start(cnf *config.Config, cachedEntries uint, flogger logger.Logger) error
|
||||
return err
|
||||
}
|
||||
|
||||
err = repo.AddDevices(&types.Device{
|
||||
err = repo.AddDevices(ctx, &types.Device{
|
||||
ID: cnf.DeviceID,
|
||||
Name: hostname,
|
||||
})
|
||||
@ -47,13 +49,13 @@ func Start(cnf *config.Config, cachedEntries uint, flogger logger.Logger) error
|
||||
return err
|
||||
}
|
||||
|
||||
repoDevice, err = repo.GetDevice(cnf.DeviceID)
|
||||
repoDevice, err = repo.GetDeviceByID(ctx, cnf.DeviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
repoSensors, err := repo.GetSensorsByDeviceID(repoDevice.ID)
|
||||
repoSensors, err := repo.GetSensorsByDeviceIDs(ctx, repoDevice.ID)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
@ -110,7 +112,7 @@ func Start(cnf *config.Config, cachedEntries uint, flogger logger.Logger) error
|
||||
|
||||
if cap(measuredValues) == len(measuredValues) {
|
||||
flogger.Debug("Flush cache with %v values", len(measuredValues))
|
||||
err := repo.AddMeasuredValues(measuredValues...)
|
||||
err := repo.AddMeasuredValues(ctx, measuredValues...)
|
||||
if err != nil {
|
||||
flogger.Error("%v", err)
|
||||
}
|
||||
@ -124,7 +126,7 @@ func Start(cnf *config.Config, cachedEntries uint, flogger logger.Logger) error
|
||||
|
||||
flogger.Debug("Flush cache with %v remaining values", len(measuredValues))
|
||||
|
||||
err := repo.AddMeasuredValues(measuredValues...)
|
||||
err := repo.AddMeasuredValues(ctx, measuredValues...)
|
||||
if err != nil {
|
||||
flogger.Error("%v", err)
|
||||
}
|
||||
|
@ -1,134 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
postgresdml "git.cryptic.systems/volker.raschek/flucky/pkg/repository/db/postgres/dml"
|
||||
sqlite3dml "git.cryptic.systems/volker.raschek/flucky/pkg/repository/db/sqlite3/dml"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
|
||||
"git.cryptic.systems/volker.raschek/go-logger"
|
||||
)
|
||||
|
||||
// Database is a general interface for a database backend like postgres, oracle
|
||||
// or sqlite
|
||||
type Database interface {
|
||||
Close() error
|
||||
DeleteDevices(ctx context.Context, deviceIDs ...string) error
|
||||
DeleteSensors(ctx context.Context, sensorIDs ...string) error
|
||||
InsertDevices(ctx context.Context, devices ...*types.Device) error
|
||||
InsertOrUpdateDevices(ctx context.Context, devices ...*types.Device) error
|
||||
InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
||||
InsertOrUpdateMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
||||
InsertSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
InsertOrUpdateSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
Migrate(ctx context.Context) error
|
||||
SelectDevice(ctx context.Context, deviceID string) (*types.Device, error)
|
||||
SelectDevices(ctx context.Context) ([]*types.Device, error)
|
||||
SelectHumidity(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
SelectPressure(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
SelectSensor(ctx context.Context, sensorID string) (*types.Sensor, error)
|
||||
SelectSensors(ctx context.Context) ([]*types.Sensor, error)
|
||||
SelectTemperature(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
UpdateDevices(ctx context.Context, devices ...*types.Device) error
|
||||
UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
}
|
||||
|
||||
// New returns a new database backend interface
|
||||
func New(databaseURL *url.URL, flogger logger.Logger) (Database, error) {
|
||||
|
||||
// Check of nil pointer
|
||||
for _, parameter := range []interface{}{
|
||||
databaseURL,
|
||||
flogger,
|
||||
} {
|
||||
if parameter == nil {
|
||||
return nil, fmt.Errorf("Parameter does not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
database Database
|
||||
err error
|
||||
)
|
||||
|
||||
switch databaseURL.Scheme {
|
||||
case "postgres":
|
||||
|
||||
// postgres://[user]:[password]@[host]:[port]/[path]?[query]
|
||||
newDBO, err := sql.Open(databaseURL.Scheme, databaseURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queries := make(map[string]string, 0)
|
||||
for _, assetName := range postgresdml.AssetNames() {
|
||||
body, err := postgresdml.Asset(assetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to load asset %v, %w", assetName, err)
|
||||
}
|
||||
queries[assetName] = string(body)
|
||||
}
|
||||
|
||||
database = &Postgres{
|
||||
databaseURL: databaseURL,
|
||||
dbo: newDBO,
|
||||
flogger: flogger,
|
||||
queries: queries,
|
||||
}
|
||||
|
||||
case "sqlite3":
|
||||
|
||||
// Create directory if not exist
|
||||
if _, err := os.Stat(filepath.Dir(databaseURL.Path)); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(filepath.Dir(databaseURL.Path), 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// enable foreign keys
|
||||
values := databaseURL.Query()
|
||||
values.Set("_foreign_keys", "on")
|
||||
|
||||
customRawURL := fmt.Sprintf("file://%v?%v", databaseURL.Path, values.Encode())
|
||||
|
||||
sqlDB, err := sql.Open("sqlite3", customRawURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queries := make(map[string]string, 0)
|
||||
for _, assetName := range sqlite3dml.AssetNames() {
|
||||
body, err := sqlite3dml.Asset(assetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to load asset %v, %w", assetName, err)
|
||||
}
|
||||
queries[assetName] = string(body)
|
||||
}
|
||||
|
||||
database = &SQLite{
|
||||
databaseURL: databaseURL,
|
||||
dbo: sqlDB,
|
||||
flogger: flogger,
|
||||
queries: queries,
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported database scheme: %v", databaseURL.Scheme)
|
||||
}
|
||||
|
||||
// Initialize database scheme if not exists
|
||||
err = database.Migrate(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return database, nil
|
||||
}
|
@ -1,951 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
postgresddl "git.cryptic.systems/volker.raschek/flucky/pkg/repository/db/postgres/ddl"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
|
||||
"git.cryptic.systems/volker.raschek/go-logger"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
bindata "github.com/golang-migrate/migrate/v4/source/go_bindata"
|
||||
)
|
||||
|
||||
// Postgres implementation
|
||||
type Postgres struct {
|
||||
databaseURL *url.URL
|
||||
dbo *sql.DB
|
||||
flogger logger.Logger
|
||||
queries map[string]string
|
||||
}
|
||||
|
||||
// Close closes the database and prevents new queries from starting. Close then
|
||||
// waits for all queries that have started processing on the server to finish.
|
||||
func (postgres *Postgres) Close() error {
|
||||
return postgres.dbo.Close()
|
||||
}
|
||||
|
||||
// DeleteDevices from the database
|
||||
func (postgres *Postgres) DeleteDevices(ctx context.Context, deviceIDs ...string) error {
|
||||
queryFile := "deleteDevice.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 (postgres *Postgres) DeleteSensors(ctx context.Context, sensorIDs ...string) error {
|
||||
queryFile := "deleteSensor.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 (postgres *Postgres) InsertDevices(ctx context.Context, devices ...*types.Device) error {
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
err = postgres.insertDevices(tx, devices...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (postgres *Postgres) insertDevices(tx *sql.Tx, devices ...*types.Device) error {
|
||||
queryFile := "insertDevice.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-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 _, device := range devices {
|
||||
|
||||
if device.CreationDate.Equal(time.Time{}) {
|
||||
device.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(
|
||||
&device.ID,
|
||||
&device.Name,
|
||||
&device.Location,
|
||||
&device.CreationDate,
|
||||
&device.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertMeasuredValues into the database
|
||||
func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
||||
splittedMeasuredValues := make(map[types.MeasuredValueType][]*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 := postgres.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 := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-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 {
|
||||
|
||||
if measuredValue.CreationDate.Equal(time.Time{}) {
|
||||
measuredValue.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, err := stmt.Exec(
|
||||
&measuredValue.ID,
|
||||
&measuredValue.Value,
|
||||
&measuredValue.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 types.Humidity:
|
||||
queryFile = "insertHumidity.sql"
|
||||
case types.Pressure:
|
||||
queryFile = "insertPressure.sql"
|
||||
case types.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()
|
||||
}
|
||||
|
||||
func (postgres *Postgres) InsertOrUpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
||||
queryFile := "insertOrUpdateDevice.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
|
||||
if device.CreationDate.Equal(time.Time{}) {
|
||||
device.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, err = tx.Exec(
|
||||
query,
|
||||
&device.ID,
|
||||
&device.Name,
|
||||
&device.Location,
|
||||
&device.CreationDate,
|
||||
&device.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// InsertOrUpdateMeasuredValues into the database
|
||||
func (postgres *Postgres) InsertOrUpdateMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
||||
splittedMeasuredValues := make(map[types.MeasuredValueType][]*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 := postgres.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 := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-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 {
|
||||
|
||||
if measuredValue.CreationDate.Equal(time.Time{}) {
|
||||
measuredValue.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, err := stmt.Exec(
|
||||
&measuredValue.ID,
|
||||
&measuredValue.Value,
|
||||
&measuredValue.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 types.Humidity:
|
||||
queryFile = "insertOrUpdateHumidity.sql"
|
||||
case types.Pressure:
|
||||
queryFile = "insertOrUpdatePressure.sql"
|
||||
case types.Temperature:
|
||||
queryFile = "insertOrUpdateTemperature.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()
|
||||
}
|
||||
|
||||
// InsertOrUpdateSensors into the database
|
||||
func (postgres *Postgres) InsertOrUpdateSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||
queryFile := "insertOrUpdateSensor.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 {
|
||||
|
||||
if sensor.CreationDate.Equal(time.Time{}) {
|
||||
sensor.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, 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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// InsertSensors into the database
|
||||
func (postgres *Postgres) InsertSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||
queryFile := "insertSensor.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 {
|
||||
|
||||
if sensor.CreationDate.Equal(time.Time{}) {
|
||||
sensor.CreationDate = time.Now()
|
||||
}
|
||||
|
||||
_, 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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// Migrate creates all required tables if not exist
|
||||
func (postgres *Postgres) Migrate(ctx context.Context) error {
|
||||
assetSource := bindata.Resource(postgresddl.AssetNames(), func(query string) ([]byte, error) {
|
||||
return postgresddl.Asset(query)
|
||||
})
|
||||
|
||||
sourceDriver, err := bindata.WithInstance(assetSource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithSourceInstance("bindata", sourceDriver, postgres.databaseURL.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.Up()
|
||||
switch {
|
||||
case errors.Is(err, migrate.ErrNoChange):
|
||||
return nil
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// SelectDevice from database
|
||||
func (postgres *Postgres) SelectDevice(ctx context.Context, id string) (*types.Device, error) {
|
||||
queryFile := "selectDevice.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
devices, err := postgres.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 (postgres *Postgres) SelectDevices(ctx context.Context) ([]*types.Device, error) {
|
||||
queryFile := "selectDevices.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
devices, err := postgres.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 (postgres *Postgres) 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,
|
||||
&device.UpdateDate,
|
||||
)
|
||||
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 (postgres *Postgres) SelectHumidity(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||
queryFile := "selectHumidity.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.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 = types.Humidity
|
||||
}
|
||||
|
||||
return measuredValues[0], nil
|
||||
}
|
||||
|
||||
// SelectHumidities returns humidities from the database
|
||||
func (postgres *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||
queryFile := "selectHumidities.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.selectMeasuredValue(tx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.Humidity
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
func (postgres *Postgres) 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.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 (postgres *Postgres) SelectPressure(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||
queryFile := "selectPressure.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.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 = types.Pressure
|
||||
}
|
||||
|
||||
return measuredValues[0], nil
|
||||
}
|
||||
|
||||
// SelectPressures returns pressure from the database
|
||||
func (postgres *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||
queryFile := "selectPressures.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.selectMeasuredValue(tx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.Pressure
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
// SelectSensor from database
|
||||
func (postgres *Postgres) SelectSensor(ctx context.Context, id string) (*types.Sensor, error) {
|
||||
queryFile := "selectSensor.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
sensors, err := postgres.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 (postgres *Postgres) SelectSensors(ctx context.Context) ([]*types.Sensor, error) {
|
||||
queryFile := "selectSensors.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
sensors, err := postgres.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 (postgres *Postgres) 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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
|
||||
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 (postgres *Postgres) SelectTemperature(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||
queryFile := "selectTemperature.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.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 = types.Temperature
|
||||
}
|
||||
|
||||
return measuredValues[0], nil
|
||||
}
|
||||
|
||||
// SelectTemperatures returns temperatures from the database
|
||||
func (postgres *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||
queryFile := "selectTemperatures.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return nil, fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
measuredValues, err := postgres.selectMeasuredValue(tx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.Temperature
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
// UpdateDevices updates a device in the database
|
||||
func (postgres *Postgres) UpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
||||
queryFile := "updateDevice.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 {
|
||||
now := time.Now()
|
||||
device.UpdateDate = &now
|
||||
|
||||
_, err := stmt.Exec(
|
||||
&device.Name,
|
||||
&device.Location,
|
||||
&device.CreationDate,
|
||||
&device.UpdateDate,
|
||||
&device.ID,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// UpdateSensors updates a sensor in the database
|
||||
func (postgres *Postgres) UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||
queryFile := "updateSensor.sql"
|
||||
query, present := postgres.queries[queryFile]
|
||||
if !present {
|
||||
return fmt.Errorf("Postgres-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := postgres.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 {
|
||||
now := time.Now()
|
||||
sensor.UpdateDate = &now
|
||||
_, 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.UpdateDate,
|
||||
&sensor.ID,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
@ -1,939 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
sqlite3ddl "git.cryptic.systems/volker.raschek/flucky/pkg/repository/db/sqlite3/ddl"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
|
||||
"git.cryptic.systems/volker.raschek/go-logger"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
bindata "github.com/golang-migrate/migrate/v4/source/go_bindata"
|
||||
)
|
||||
|
||||
// SQLite implementation
|
||||
type SQLite struct {
|
||||
databaseURL *url.URL
|
||||
dbo *sql.DB
|
||||
flogger logger.Logger
|
||||
queries map[string]string
|
||||
}
|
||||
|
||||
// Close closes the database and prevents new queries from starting. Close then
|
||||
// waits for all queries that have started processing on the server to finish.
|
||||
func (sqlite *SQLite) Close() error {
|
||||
return sqlite.dbo.Close()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
func (sqlite *SQLite) ExistDevice(ctx context.Context, deviceID string) (bool, error) {
|
||||
queryFile := "existDevice.sql"
|
||||
query, present := sqlite.queries[queryFile]
|
||||
if !present {
|
||||
return false, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||
}
|
||||
|
||||
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(query)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to prepare statement: %v", err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
rows, err := stmt.Query()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to query statement: %v", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var t bool
|
||||
for rows.Next() {
|
||||
rows.Scan(&t)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (sqlite *SQLite) ExistDevices(ctx context.Context, deviceIDs ...string) (map[string]bool, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 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, &device.UpdateDate)
|
||||
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[types.MeasuredValueType][]*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.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 types.Humidity:
|
||||
queryFile = "insertHumidity.sql"
|
||||
case types.Pressure:
|
||||
queryFile = "insertPressure.sql"
|
||||
case types.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()
|
||||
}
|
||||
|
||||
// InsertOrUpdateMeasuredValues into the database
|
||||
func (sqlite *SQLite) InsertOrUpdateMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
||||
splittedMeasuredValues := make(map[types.MeasuredValueType][]*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.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 types.Humidity:
|
||||
queryFile = "insertOrUpdateHumidity.sql"
|
||||
case types.Pressure:
|
||||
queryFile = "insertOrUpdatePressure.sql"
|
||||
case types.Temperature:
|
||||
queryFile = "insertOrUpdateTemperature.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()
|
||||
}
|
||||
|
||||
// InsertOrUpdateDevices into the database
|
||||
func (sqlite *SQLite) InsertOrUpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
||||
queryFile := "insertOrUpdateDevice.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, &device.UpdateDate)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// InsertOrUpdateSensors into the database
|
||||
func (sqlite *SQLite) InsertOrUpdateSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||
queryFile := "insertOrUpdateSensor.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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", 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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// Migrate creates all required tables if not exist
|
||||
func (sqlite *SQLite) Migrate(ctx context.Context) error {
|
||||
assetSource := bindata.Resource(sqlite3ddl.AssetNames(), func(query string) ([]byte, error) {
|
||||
return sqlite3ddl.Asset(query)
|
||||
})
|
||||
|
||||
sourceDriver, err := bindata.WithInstance(assetSource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithSourceInstance("bindata", sourceDriver, sqlite.databaseURL.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.Up()
|
||||
switch {
|
||||
case errors.Is(err, migrate.ErrNoChange):
|
||||
return nil
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
devices := make([]*types.Device, 0)
|
||||
for rows.Next() {
|
||||
device := new(types.Device)
|
||||
err = rows.Scan(
|
||||
&device.ID,
|
||||
&device.Name,
|
||||
&device.Location,
|
||||
&device.CreationDate,
|
||||
&device.UpdateDate,
|
||||
)
|
||||
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 = types.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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.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
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
measuredValues := make([]*types.MeasuredValue, 0)
|
||||
for rows.Next() {
|
||||
measuredValue := new(types.MeasuredValue)
|
||||
err := rows.Scan(
|
||||
&measuredValue.ID,
|
||||
&measuredValue.Value,
|
||||
&measuredValue.Date,
|
||||
&measuredValue.SensorID,
|
||||
&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 = types.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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.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)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
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,
|
||||
&sensor.UpdateDate,
|
||||
)
|
||||
|
||||
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 = types.Temperature
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValue.ValueType = types.Temperature
|
||||
}
|
||||
|
||||
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.UpdateDate,
|
||||
&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.UpdateDate,
|
||||
&sensor.ID,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
2
pkg/repository/postgres/dml/deleteDeviceByName.sql
Normal file
2
pkg/repository/postgres/dml/deleteDeviceByName.sql
Normal file
@ -0,0 +1,2 @@
|
||||
DELETE FROM devices
|
||||
WHERE device_name = $1;
|
2
pkg/repository/postgres/dml/deleteSensorByName.sql
Normal file
2
pkg/repository/postgres/dml/deleteSensorByName.sql
Normal file
@ -0,0 +1,2 @@
|
||||
DELETE FROM sensors
|
||||
WHERE sensor_name = $1;
|
9
pkg/repository/postgres/dml/selectDeviceByName.sql
Normal file
9
pkg/repository/postgres/dml/selectDeviceByName.sql
Normal file
@ -0,0 +1,9 @@
|
||||
SELECT
|
||||
device_id,
|
||||
device_name,
|
||||
device_location,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
devices
|
||||
WHERE device_name = $1;
|
18
pkg/repository/postgres/dml/selectSensorsByDeviceID.sql
Normal file
18
pkg/repository/postgres/dml/selectSensorsByDeviceID.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
device_id = $1;
|
18
pkg/repository/postgres/dml/selectSensorsByModel.sql
Normal file
18
pkg/repository/postgres/dml/selectSensorsByModel.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
sensor_model = $1;
|
18
pkg/repository/postgres/dml/selectSensorsByName.sql
Normal file
18
pkg/repository/postgres/dml/selectSensorsByName.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
sensor_name = $1;
|
1206
pkg/repository/postgres/postgres.go
Normal file
1206
pkg/repository/postgres/postgres.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,339 +4,412 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/repository/db"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/repository/postgres"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/repository/sqlite3"
|
||||
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
|
||||
"git.cryptic.systems/volker.raschek/go-logger"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
AddDevices(ctx context.Context, devices ...*types.Device) error
|
||||
AddMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
||||
AddOrUpdateDevices(ctx context.Context, devices ...*types.Device) error
|
||||
AddOrUpdateMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
||||
AddOrUpdateSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
AddSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
Close() error
|
||||
GetDeviceByID(ctx context.Context, deviceID string) (*types.Device, error)
|
||||
GetDeviceByName(ctx context.Context, name string) (*types.Device, error)
|
||||
GetDevices(ctx context.Context) ([]*types.Device, error)
|
||||
GetHumidities(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
GetHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
GetPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
GetPressures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
GetSensorByID(ctx context.Context, sensorID string) (*types.Sensor, error)
|
||||
GetSensorsByDeviceIDs(ctx context.Context, deviceIDs ...string) ([]*types.Sensor, error)
|
||||
GetSensorsByModels(ctx context.Context, sensorModels ...string) ([]*types.Sensor, error)
|
||||
GetSensorsByNames(ctx context.Context, sensorModels ...string) ([]*types.Sensor, error)
|
||||
GetSensors(ctx context.Context) ([]*types.Sensor, error)
|
||||
GetTemperatureByID(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||
GetTemperatures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||
Migrate(ctx context.Context) error
|
||||
RemoveDevicesByIDs(ctx context.Context, deviceIDs ...string) error
|
||||
RemoveDevicesByNames(ctx context.Context, names ...string) error
|
||||
RemoveSensorsByIDs(ctx context.Context, sensorIDs ...string) error
|
||||
RemoveSensorsByNames(ctx context.Context, names ...string) error
|
||||
UpdateDevices(ctx context.Context, devices ...*types.Device) error
|
||||
UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||
}
|
||||
|
||||
// New returns a new database backend interface
|
||||
func New(databaseURL *url.URL, flogger logger.Logger) (Repository, error) {
|
||||
switch databaseURL.Scheme {
|
||||
case "postgres":
|
||||
repo, err := postgres.New(postgres.Opts{
|
||||
DatabaseURL: databaseURL,
|
||||
Logger: flogger,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Initialize database scheme if not exists
|
||||
err = repo.Migrate(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
|
||||
case "sqlite3":
|
||||
repo, err := sqlite3.New(sqlite3.Opts{
|
||||
DatabaseURL: databaseURL,
|
||||
Logger: flogger,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Initialize database scheme if not exists
|
||||
err = repo.Migrate(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported repository scheme: %v", databaseURL.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// Repository represent a repository where all devices, sensors and measured
|
||||
// values are stored.
|
||||
type Repository struct {
|
||||
database db.Database
|
||||
}
|
||||
// type Repository struct {
|
||||
// database db.Database
|
||||
// }
|
||||
|
||||
// AddDevices to the repository
|
||||
func (repo *Repository) AddDevices(devices ...*types.Device) error {
|
||||
return repo.database.InsertDevices(context.Background(), devices...)
|
||||
}
|
||||
// // AddDevices to the repository
|
||||
// func (repo *Repository) AddDevices(devices ...*types.Device) error {
|
||||
// return repo.database.InsertDevices(context.Background(), devices...)
|
||||
// }
|
||||
|
||||
// AddMeasuredValues to the repository
|
||||
func (repo *Repository) AddMeasuredValues(measuredValues ...*types.MeasuredValue) error {
|
||||
return repo.database.InsertMeasuredValues(context.Background(), measuredValues...)
|
||||
}
|
||||
// // AddMeasuredValues to the repository
|
||||
// func (repo *Repository) AddMeasuredValues(measuredValues ...*types.MeasuredValue) error {
|
||||
// return repo.database.InsertMeasuredValues(context.Background(), measuredValues...)
|
||||
// }
|
||||
|
||||
// AddOrUpdateDevices to the repository
|
||||
func (repo *Repository) AddOrUpdateDevices(devices ...*types.Device) error {
|
||||
return repo.database.InsertOrUpdateDevices(context.Background(), devices...)
|
||||
}
|
||||
// // AddOrUpdateDevices to the repository
|
||||
// func (repo *Repository) AddOrUpdateDevices(devices ...*types.Device) error {
|
||||
// return repo.database.InsertOrUpdateDevices(context.Background(), devices...)
|
||||
// }
|
||||
|
||||
// AddOrUpdateMeasuredValues to the repository
|
||||
func (repo *Repository) AddOrUpdateMeasuredValues(measuredValues ...*types.MeasuredValue) error {
|
||||
return repo.database.InsertOrUpdateMeasuredValues(context.Background(), measuredValues...)
|
||||
}
|
||||
// // AddOrUpdateMeasuredValues to the repository
|
||||
// func (repo *Repository) AddOrUpdateMeasuredValues(measuredValues ...*types.MeasuredValue) error {
|
||||
// return repo.database.InsertOrUpdateMeasuredValues(context.Background(), measuredValues...)
|
||||
// }
|
||||
|
||||
// AddOrUpdateSensors to the repository
|
||||
func (repo *Repository) AddOrUpdateSensors(sensors ...*types.Sensor) error {
|
||||
return repo.database.InsertOrUpdateSensors(context.Background(), sensors...)
|
||||
}
|
||||
// // AddOrUpdateSensors to the repository
|
||||
// func (repo *Repository) AddOrUpdateSensors(sensors ...*types.Sensor) error {
|
||||
// return repo.database.InsertOrUpdateSensors(context.Background(), sensors...)
|
||||
// }
|
||||
|
||||
// AddSensors to the repository
|
||||
func (repo *Repository) AddSensors(sensors ...*types.Sensor) error {
|
||||
return repo.database.InsertSensors(context.Background(), sensors...)
|
||||
}
|
||||
// // AddSensors to the repository
|
||||
// func (repo *Repository) AddSensors(sensors ...*types.Sensor) error {
|
||||
// return repo.database.InsertSensors(context.Background(), sensors...)
|
||||
// }
|
||||
|
||||
// Close closes the repository and prevents new queries from starting. Close
|
||||
// then waits for all queries that have started processing on the server to
|
||||
// finish.
|
||||
func (repo *Repository) Close() error {
|
||||
return repo.database.Close()
|
||||
}
|
||||
// // Close closes the repository and prevents new queries from starting. Close
|
||||
// // then waits for all queries that have started processing on the server to
|
||||
// // finish.
|
||||
// func (repo *Repository) Close() error {
|
||||
// return repo.database.Close()
|
||||
// }
|
||||
|
||||
// DisableSensorsByNames disable all sensors which match bei their name
|
||||
func (repo *Repository) DisableSensorsByNames(sensorNames ...string) error {
|
||||
sensors, err := repo.GetSensors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // DisableSensorsByNames disable all sensors which match bei their name
|
||||
// func (repo *Repository) DisableSensorsByNames(sensorNames ...string) error {
|
||||
// sensors, err := repo.GetSensors()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
matchedSensors := make([]*types.Sensor, 0)
|
||||
for _, sensor := range sensors {
|
||||
for _, sensorName := range sensorNames {
|
||||
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
sensor.Enabled = false
|
||||
matchedSensors = append(matchedSensors, sensor)
|
||||
}
|
||||
}
|
||||
}
|
||||
// matchedSensors := make([]*types.Sensor, 0)
|
||||
// for _, sensor := range sensors {
|
||||
// for _, sensorName := range sensorNames {
|
||||
// if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
// sensor.Enabled = false
|
||||
// matchedSensors = append(matchedSensors, sensor)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return repo.UpdateSensors(matchedSensors...)
|
||||
}
|
||||
// return repo.UpdateSensors(matchedSensors...)
|
||||
// }
|
||||
|
||||
// EnableSensorsByNames enable all sensors which match bei their name
|
||||
func (repo *Repository) EnableSensorsByNames(sensorNames ...string) error {
|
||||
sensors, err := repo.GetSensors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // EnableSensorsByNames enable all sensors which match bei their name
|
||||
// func (repo *Repository) EnableSensorsByNames(sensorNames ...string) error {
|
||||
// sensors, err := repo.GetSensors()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
matchedSensors := make([]*types.Sensor, 0)
|
||||
for _, sensor := range sensors {
|
||||
for _, sensorName := range sensorNames {
|
||||
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
sensor.Enabled = true
|
||||
matchedSensors = append(matchedSensors, sensor)
|
||||
}
|
||||
}
|
||||
}
|
||||
// matchedSensors := make([]*types.Sensor, 0)
|
||||
// for _, sensor := range sensors {
|
||||
// for _, sensorName := range sensorNames {
|
||||
// if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
// sensor.Enabled = true
|
||||
// matchedSensors = append(matchedSensors, sensor)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return repo.UpdateSensors(matchedSensors...)
|
||||
}
|
||||
// return repo.UpdateSensors(matchedSensors...)
|
||||
// }
|
||||
|
||||
// GetDevice returns a device by his id. If no device has been found, the
|
||||
// function returns nil.
|
||||
func (repo *Repository) GetDevice(deviceID string) (*types.Device, error) {
|
||||
return repo.database.SelectDevice(context.Background(), deviceID)
|
||||
}
|
||||
// // GetDevice returns a device by his id. If no device has been found, the
|
||||
// // function returns nil.
|
||||
// func (repo *Repository) GetDevice(deviceID string) (*types.Device, error) {
|
||||
// return repo.database.SelectDevice(context.Background(), deviceID)
|
||||
// }
|
||||
|
||||
// GetDevices returns all devices. If no devices has been found, the function
|
||||
// returns nil.
|
||||
func (repo *Repository) GetDevices() ([]*types.Device, error) {
|
||||
return repo.database.SelectDevices(context.Background())
|
||||
}
|
||||
// // GetDevices returns all devices. If no devices has been found, the function
|
||||
// // returns nil.
|
||||
// func (repo *Repository) GetDevices() ([]*types.Device, error) {
|
||||
// return repo.database.SelectDevices(context.Background())
|
||||
// }
|
||||
|
||||
// GetHumidity returns a humidity value by id
|
||||
func (repo *Repository) GetHumidity(humidityID string) (*types.MeasuredValue, error) {
|
||||
return repo.database.SelectHumidity(context.Background(), humidityID)
|
||||
}
|
||||
// // GetHumidity returns a humidity value by id
|
||||
// func (repo *Repository) GetHumidity(humidityID string) (*types.MeasuredValue, error) {
|
||||
// return repo.database.SelectHumidity(context.Background(), humidityID)
|
||||
// }
|
||||
|
||||
// GetPressure returns a pressure value by id
|
||||
func (repo *Repository) GetPressure(pressureID string) (*types.MeasuredValue, error) {
|
||||
return repo.database.SelectPressure(context.Background(), pressureID)
|
||||
}
|
||||
// // GetPressure returns a pressure value by id
|
||||
// func (repo *Repository) GetPressure(pressureID string) (*types.MeasuredValue, error) {
|
||||
// return repo.database.SelectPressure(context.Background(), pressureID)
|
||||
// }
|
||||
|
||||
// GetSensor returns a sensor by his id. If no sensor has been found, the
|
||||
// function returns nil.
|
||||
func (repo *Repository) GetSensor(sensorID string) (*types.Sensor, error) {
|
||||
return repo.database.SelectSensor(context.Background(), sensorID)
|
||||
}
|
||||
// // GetSensor returns a sensor by his id. If no sensor has been found, the
|
||||
// // function returns nil.
|
||||
// func (repo *Repository) GetSensor(sensorID string) (*types.Sensor, error) {
|
||||
// return repo.database.SelectSensor(context.Background(), sensorID)
|
||||
// }
|
||||
|
||||
// GetSensors returns all sensors. If no sensors has been found, the function
|
||||
// returns nil.
|
||||
func (repo *Repository) GetSensors(models ...string) ([]*types.Sensor, error) {
|
||||
sensors, err := repo.database.SelectSensors(context.Background())
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case len(models) > 0:
|
||||
cachedSensors := make([]*types.Sensor, 0)
|
||||
LOOP:
|
||||
for i := range sensors {
|
||||
for j := range models {
|
||||
if strings.ToLower(sensors[i].Model) == strings.ToLower(models[j]) {
|
||||
cachedSensors = append(cachedSensors, sensors[i])
|
||||
continue LOOP
|
||||
}
|
||||
}
|
||||
}
|
||||
return cachedSensors, nil
|
||||
case len(models) <= 0:
|
||||
fallthrough
|
||||
default:
|
||||
return sensors, err
|
||||
}
|
||||
}
|
||||
// // GetSensors returns all sensors. If no sensors has been found, the function
|
||||
// // returns nil.
|
||||
// func (repo *Repository) GetSensors(models ...string) ([]*types.Sensor, error) {
|
||||
// sensors, err := repo.database.SelectSensors(context.Background())
|
||||
// switch {
|
||||
// case err != nil:
|
||||
// return nil, err
|
||||
// case len(models) > 0:
|
||||
// cachedSensors := make([]*types.Sensor, 0)
|
||||
// LOOP:
|
||||
// for i := range sensors {
|
||||
// for j := range models {
|
||||
// if strings.ToLower(sensors[i].Model) == strings.ToLower(models[j]) {
|
||||
// cachedSensors = append(cachedSensors, sensors[i])
|
||||
// continue LOOP
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return cachedSensors, nil
|
||||
// case len(models) <= 0:
|
||||
// fallthrough
|
||||
// default:
|
||||
// return sensors, err
|
||||
// }
|
||||
// }
|
||||
|
||||
// GetSensorsByDeviceID returns all sensors by a device id. If no sensor has
|
||||
// been found by the id, the function returns nil.
|
||||
func (repo *Repository) GetSensorsByDeviceID(deviceID string) ([]*types.Sensor, error) {
|
||||
cachedSensors := make([]*types.Sensor, 0)
|
||||
sensors, err := repo.GetSensors()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// // GetSensorsByDeviceID returns all sensors by a device id. If no sensor has
|
||||
// // been found by the id, the function returns nil.
|
||||
// func (repo *Repository) GetSensorsByDeviceID(deviceID string) ([]*types.Sensor, error) {
|
||||
// cachedSensors := make([]*types.Sensor, 0)
|
||||
// sensors, err := repo.GetSensors()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
for _, sensor := range sensors {
|
||||
if strings.Compare(sensor.DeviceID, deviceID) == 0 {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
// for _, sensor := range sensors {
|
||||
// if strings.Compare(sensor.DeviceID, deviceID) == 0 {
|
||||
// cachedSensors = append(cachedSensors, sensor)
|
||||
// }
|
||||
// }
|
||||
|
||||
return cachedSensors, nil
|
||||
}
|
||||
// return cachedSensors, nil
|
||||
// }
|
||||
|
||||
// GetTemperature returns a temperature value by id
|
||||
func (repo *Repository) GetTemperature(pressureID string) (*types.MeasuredValue, error) {
|
||||
return repo.database.SelectTemperature(context.Background(), pressureID)
|
||||
}
|
||||
// // GetTemperature returns a temperature value by id
|
||||
// func (repo *Repository) GetTemperature(pressureID string) (*types.MeasuredValue, error) {
|
||||
// return repo.database.SelectTemperature(context.Background(), pressureID)
|
||||
// }
|
||||
|
||||
// RemoveDevices removes devices by their ids from the repository. Additional
|
||||
// all sensors and measured values, which are in relation with the device
|
||||
// respectively the sensors will also be deleted.
|
||||
func (repo *Repository) RemoveDevices(deviceIDs ...string) error {
|
||||
return repo.database.DeleteDevices(context.Background(), deviceIDs...)
|
||||
}
|
||||
// // RemoveDevices removes devices by their ids from the repository. Additional
|
||||
// // all sensors and measured values, which are in relation with the device
|
||||
// // respectively the sensors will also be deleted.
|
||||
// func (repo *Repository) RemoveDevices(deviceIDs ...string) error {
|
||||
// return repo.database.DeleteDevices(context.Background(), deviceIDs...)
|
||||
// }
|
||||
|
||||
// RenameSensors all sensors which match by their current name to the new name
|
||||
func (repo *Repository) RenameSensors(oldName string, newName string) error {
|
||||
sensors, err := repo.GetSensors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // RenameSensors all sensors which match by their current name to the new name
|
||||
// func (repo *Repository) RenameSensors(oldName string, newName string) error {
|
||||
// sensors, err := repo.GetSensors()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
matchedSensors := make([]*types.Sensor, 0)
|
||||
for _, sensor := range sensors {
|
||||
if strings.Compare(sensor.Name, oldName) == 0 {
|
||||
sensor.Name = newName
|
||||
matchedSensors = append(matchedSensors, sensor)
|
||||
}
|
||||
}
|
||||
// matchedSensors := make([]*types.Sensor, 0)
|
||||
// for _, sensor := range sensors {
|
||||
// if strings.Compare(sensor.Name, oldName) == 0 {
|
||||
// sensor.Name = newName
|
||||
// matchedSensors = append(matchedSensors, sensor)
|
||||
// }
|
||||
// }
|
||||
|
||||
return repo.UpdateSensors(matchedSensors...)
|
||||
}
|
||||
// return repo.UpdateSensors(matchedSensors...)
|
||||
// }
|
||||
|
||||
// RemoveSensors removes sensors by their ids from the repository. Additional
|
||||
// all measured values, which are in relation with the sensor will also be
|
||||
// deleted.
|
||||
func (repo *Repository) RemoveSensors(sensorIDs ...string) error {
|
||||
return repo.database.DeleteSensors(context.Background(), sensorIDs...)
|
||||
}
|
||||
// // RemoveSensors removes sensors by their ids from the repository. Additional
|
||||
// // all measured values, which are in relation with the sensor will also be
|
||||
// // deleted.
|
||||
// func (repo *Repository) RemoveSensors(sensorIDs ...string) error {
|
||||
// return repo.database.DeleteSensors(context.Background(), sensorIDs...)
|
||||
// }
|
||||
|
||||
// RemoveSensorsByNames removes all sensors which match bei their name
|
||||
func (repo *Repository) RemoveSensorsByNames(sensorNames ...string) error {
|
||||
sensors, err := repo.GetSensors()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // RemoveSensorsByNames removes all sensors which match bei their name
|
||||
// func (repo *Repository) RemoveSensorsByNames(sensorNames ...string) error {
|
||||
// sensors, err := repo.GetSensors()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
matchedSensorIDs := make([]string, 0)
|
||||
for _, sensor := range sensors {
|
||||
for _, sensorName := range sensorNames {
|
||||
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
matchedSensorIDs = append(matchedSensorIDs, sensor.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
// matchedSensorIDs := make([]string, 0)
|
||||
// for _, sensor := range sensors {
|
||||
// for _, sensorName := range sensorNames {
|
||||
// if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||
// matchedSensorIDs = append(matchedSensorIDs, sensor.ID)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return repo.RemoveSensors(matchedSensorIDs...)
|
||||
}
|
||||
// return repo.RemoveSensors(matchedSensorIDs...)
|
||||
// }
|
||||
|
||||
// UpdateDevices update devices which are stored into the repository by their
|
||||
// id. The id of the device can not be updated.
|
||||
func (repo *Repository) UpdateDevices(devices ...*types.Device) error {
|
||||
return repo.database.UpdateDevices(context.Background(), devices...)
|
||||
}
|
||||
// // UpdateDevices update devices which are stored into the repository by their
|
||||
// // id. The id of the device can not be updated.
|
||||
// func (repo *Repository) UpdateDevices(devices ...*types.Device) error {
|
||||
// return repo.database.UpdateDevices(context.Background(), devices...)
|
||||
// }
|
||||
|
||||
// UpdateSensors update sensors which are stored into the repository by their
|
||||
// id. The id of the sensor can not be updated.
|
||||
func (repo *Repository) UpdateSensors(sensors ...*types.Sensor) error {
|
||||
return repo.database.UpdateSensors(context.Background(), sensors...)
|
||||
}
|
||||
// // UpdateSensors update sensors which are stored into the repository by their
|
||||
// // id. The id of the sensor can not be updated.
|
||||
// func (repo *Repository) UpdateSensors(sensors ...*types.Sensor) error {
|
||||
// return repo.database.UpdateSensors(context.Background(), sensors...)
|
||||
// }
|
||||
|
||||
// New returns a new repository based on the data source name (dsn)
|
||||
func New(dsnURL *url.URL, flogger logger.Logger) (*Repository, error) {
|
||||
database, err := db.New(dsnURL, flogger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// // New returns a new repository based on the data source name (dsn)
|
||||
// func New(dsnURL *url.URL, flogger logger.Logger) (*Repository, error) {
|
||||
// database, err := db.New(dsnURL, flogger)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
return &Repository{
|
||||
database: database,
|
||||
}, nil
|
||||
}
|
||||
// return &Repository{
|
||||
// database: database,
|
||||
// }, nil
|
||||
// }
|
||||
|
||||
type OptImport struct {
|
||||
Sensors bool
|
||||
Humidities bool
|
||||
Pressures bool
|
||||
Temperatures bool
|
||||
}
|
||||
// type OptImport struct {
|
||||
// Sensors bool
|
||||
// Humidities bool
|
||||
// Pressures bool
|
||||
// Temperatures bool
|
||||
// }
|
||||
|
||||
func Import(sourceDSNURL *url.URL, destDNSURL *url.URL, flogger logger.Logger, optImport OptImport) error {
|
||||
// func Import(sourceDSNURL *url.URL, destDNSURL *url.URL, flogger logger.Logger, optImport OptImport) error {
|
||||
|
||||
importMap := map[string]bool{
|
||||
"humidities": optImport.Humidities,
|
||||
"pressures": optImport.Pressures,
|
||||
"temperatures": optImport.Temperatures,
|
||||
}
|
||||
// importMap := map[string]bool{
|
||||
// "humidities": optImport.Humidities,
|
||||
// "pressures": optImport.Pressures,
|
||||
// "temperatures": optImport.Temperatures,
|
||||
// }
|
||||
|
||||
// enable sensors if one measured value is enabled
|
||||
if !optImport.Sensors {
|
||||
for key, value := range importMap {
|
||||
if value {
|
||||
flogger.Info("Enable import option sensors. It's required as foreign key for %v", key)
|
||||
optImport.Sensors = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// // enable sensors if one measured value is enabled
|
||||
// if !optImport.Sensors {
|
||||
// for key, value := range importMap {
|
||||
// if value {
|
||||
// flogger.Info("Enable import option sensors. It's required as foreign key for %v", key)
|
||||
// optImport.Sensors = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Initialize source repository
|
||||
sourceRepo, err := New(sourceDSNURL, flogger)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to open the source repo: %w", err)
|
||||
}
|
||||
defer sourceRepo.Close()
|
||||
// // Initialize source repository
|
||||
// sourceRepo, err := New(sourceDSNURL, flogger)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to open the source repo: %w", err)
|
||||
// }
|
||||
// defer sourceRepo.Close()
|
||||
|
||||
// Initialize destination repository
|
||||
destRepo, err := New(destDNSURL, flogger)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to open the destination repo: %w", err)
|
||||
}
|
||||
defer destRepo.Close()
|
||||
// // Initialize destination repository
|
||||
// destRepo, err := New(destDNSURL, flogger)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to open the destination repo: %w", err)
|
||||
// }
|
||||
// defer destRepo.Close()
|
||||
|
||||
// AddOrUpdate: Devices
|
||||
ctx := context.Background()
|
||||
devices, err := sourceRepo.database.SelectDevices(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch devices from source repo: %w", err)
|
||||
}
|
||||
// // AddOrUpdate: Devices
|
||||
// ctx := context.Background()
|
||||
// devices, err := sourceRepo.database.SelectDevices(ctx)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to fetch devices from source repo: %w", err)
|
||||
// }
|
||||
|
||||
flogger.Debug("Found %v devices", len(devices))
|
||||
// flogger.Debug("Found %v devices", len(devices))
|
||||
|
||||
for i := range devices {
|
||||
err := destRepo.AddOrUpdateDevices(devices[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to add or update device %v into dest repo: %w", devices[i].Name, err)
|
||||
}
|
||||
}
|
||||
// for i := range devices {
|
||||
// err := destRepo.AddOrUpdateDevices(devices[i])
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to add or update device %v into dest repo: %w", devices[i].Name, err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// AddOrUpdate: Sensors
|
||||
if optImport.Sensors {
|
||||
sensors, err := sourceRepo.database.SelectSensors(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch sensors from source repo: %w", err)
|
||||
}
|
||||
// // AddOrUpdate: Sensors
|
||||
// if optImport.Sensors {
|
||||
// sensors, err := sourceRepo.database.SelectSensors(ctx)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to fetch sensors from source repo: %w", err)
|
||||
// }
|
||||
|
||||
flogger.Debug("Found %v sensors", len(sensors))
|
||||
// flogger.Debug("Found %v sensors", len(sensors))
|
||||
|
||||
for i := range sensors {
|
||||
err := destRepo.AddOrUpdateSensors(sensors[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to add or update sensor %v into dest repo: %w", sensors[i].Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// for i := range sensors {
|
||||
// err := destRepo.AddOrUpdateSensors(sensors[i])
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to add or update sensor %v into dest repo: %w", sensors[i].Name, err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
for key, f := range map[string]func(context.Context) ([]*types.MeasuredValue, error){
|
||||
"humidities": sourceRepo.database.SelectHumidities,
|
||||
"pressures": sourceRepo.database.SelectPressures,
|
||||
"temperatures": sourceRepo.database.SelectTemperatures,
|
||||
} {
|
||||
if importMap[key] {
|
||||
measuredValues, err := f(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to select %v from source repo: %w", key, err)
|
||||
}
|
||||
// for key, f := range map[string]func(context.Context) ([]*types.MeasuredValue, error){
|
||||
// "humidities": sourceRepo.database.SelectHumidities,
|
||||
// "pressures": sourceRepo.database.SelectPressures,
|
||||
// "temperatures": sourceRepo.database.SelectTemperatures,
|
||||
// } {
|
||||
// if importMap[key] {
|
||||
// measuredValues, err := f(ctx)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to select %v from source repo: %w", key, err)
|
||||
// }
|
||||
|
||||
flogger.Debug("Found %v %v values", len(measuredValues), key)
|
||||
// flogger.Debug("Found %v %v values", len(measuredValues), key)
|
||||
|
||||
err = destRepo.AddOrUpdateMeasuredValues(measuredValues...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to add or update %v into dest repo: %w", key, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// err = destRepo.AddOrUpdateMeasuredValues(measuredValues...)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Failed to add or update %v into dest repo: %w", key, err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
// return nil
|
||||
// }
|
||||
|
@ -31,15 +31,13 @@ func TestPostgresBackend(t *testing.T) {
|
||||
require.NoError(err)
|
||||
|
||||
rand.Seed(time.Now().Unix())
|
||||
postgresHostPort := rand.Intn(10024-1024) + 1024
|
||||
postgresDBPasswort := "postgres"
|
||||
postgresContainerID, err := dockerClient.NewBuilder("postgres:13-alpine").
|
||||
Port(fmt.Sprintf("%v:5432/tcp", postgresHostPort)).
|
||||
Pull().
|
||||
AddEnv("PGTZ", "Europe/Berlin").
|
||||
AddEnv("POSTGRES_PASSWORD", postgresDBPasswort).
|
||||
AddEnv("TZ", "Europe/Berlin").
|
||||
Mount("/etc/localtime", "/etc/localtime").
|
||||
Pull().
|
||||
Start(context.Background())
|
||||
cleanup := func() {
|
||||
dockerClient.ContainerRemoveByIDs(context.Background(), postgresContainerID)
|
||||
@ -49,8 +47,12 @@ func TestPostgresBackend(t *testing.T) {
|
||||
|
||||
time.Sleep(time.Second * 10)
|
||||
|
||||
// inspect container to get his container ip
|
||||
cjson, err := dockerClient.ContainerInspect(context.Background(), postgresContainerID)
|
||||
require.NoError(err)
|
||||
|
||||
// postgres://[user]:[password]@[host]:[port]/[path]?[query]
|
||||
dsnURL, err := url.Parse(fmt.Sprintf("postgres://postgres:%v@127.0.0.1:%v?sslmode=disable", postgresDBPasswort, postgresHostPort))
|
||||
dsnURL, err := url.Parse(fmt.Sprintf("postgres://postgres:%v@%v:5432?sslmode=disable", postgresDBPasswort, cjson.NetworkSettings.IPAddress))
|
||||
require.NoError(err)
|
||||
|
||||
repo, err := repository.New(dsnURL, logger.NewLogger(logger.LogLevelDebug))
|
||||
@ -75,7 +77,8 @@ func TestSQLiteBackend(t *testing.T) {
|
||||
testBackend(t, repo)
|
||||
}
|
||||
|
||||
func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
func testBackend(t *testing.T, repo repository.Repository) {
|
||||
ctx := context.Background()
|
||||
require := require.New(t)
|
||||
location := uuid.NewV4().String()
|
||||
expectedDevices := []*types.Device{
|
||||
@ -94,33 +97,50 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
}
|
||||
|
||||
// Test: AddDevice
|
||||
err := repo.AddDevices(expectedDevices...)
|
||||
err := repo.AddDevices(ctx, expectedDevices...)
|
||||
require.NoError(err)
|
||||
|
||||
// Test: GetDevices
|
||||
devices, err := repo.GetDevices()
|
||||
devices, err := repo.GetDevices(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(devices, len(expectedDevices))
|
||||
require.JSONEq(jsonEncoder(expectedDevices), jsonEncoder(devices))
|
||||
|
||||
// Test: GetDevice
|
||||
device, err := repo.GetDevice(expectedDevices[0].ID)
|
||||
// Test: GetDeviceByID
|
||||
device, err := repo.GetDeviceByID(ctx, expectedDevices[0].ID)
|
||||
require.NoError(err)
|
||||
require.JSONEq(jsonEncoder(expectedDevices[0]), jsonEncoder(device))
|
||||
|
||||
// Test: RemoveDevice
|
||||
err = repo.RemoveDevices(expectedDevices[0].ID)
|
||||
// Test: GetDeviceByName
|
||||
device, err = repo.GetDeviceByName(ctx, expectedDevices[0].Name)
|
||||
require.NoError(err)
|
||||
require.JSONEq(jsonEncoder(expectedDevices[0]), jsonEncoder(device))
|
||||
|
||||
// Test: RemoveDevicesByIDs
|
||||
err = repo.RemoveDevicesByIDs(ctx, expectedDevices[0].ID)
|
||||
require.NoError(err)
|
||||
|
||||
devices, err = repo.GetDevices()
|
||||
devices, err = repo.GetDevices(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(devices, 1)
|
||||
|
||||
device, err = repo.GetDevice(expectedDevices[0].ID)
|
||||
device, err = repo.GetDeviceByID(ctx, expectedDevices[0].ID)
|
||||
require.NoError(err)
|
||||
require.Nil(device)
|
||||
|
||||
err = repo.AddDevices(expectedDevices[0])
|
||||
// Test: RemoveDevicesByNames
|
||||
err = repo.RemoveDevicesByNames(ctx, expectedDevices[0].Name)
|
||||
require.NoError(err)
|
||||
|
||||
devices, err = repo.GetDevices(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(devices, 1)
|
||||
|
||||
device, err = repo.GetDeviceByID(ctx, expectedDevices[0].ID)
|
||||
require.NoError(err)
|
||||
require.Nil(device)
|
||||
|
||||
err = repo.AddDevices(ctx, expectedDevices[0])
|
||||
require.NoError(err)
|
||||
|
||||
// Test: Update Devices
|
||||
@ -132,10 +152,10 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
|
||||
err = repo.UpdateDevices(expectedDevice)
|
||||
err = repo.UpdateDevices(ctx, expectedDevice)
|
||||
require.NoError(err)
|
||||
|
||||
device, err = repo.GetDevice(expectedDevice.ID)
|
||||
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(device)
|
||||
require.Equal(expectedDevice.ID, device.ID)
|
||||
@ -150,12 +170,12 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
Location: &location,
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
err = repo.AddOrUpdateDevices(expectedDevice)
|
||||
err = repo.AddOrUpdateDevices(ctx, expectedDevice)
|
||||
require.NoError(err)
|
||||
|
||||
// time.Sleep(time.Minute * 10)
|
||||
|
||||
device, err = repo.GetDevice(expectedDevice.ID)
|
||||
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(device)
|
||||
require.Equal(expectedDevice.ID, device.ID)
|
||||
@ -169,10 +189,10 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
Location: &location,
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
err = repo.AddOrUpdateDevices(expectedDevice)
|
||||
err = repo.AddOrUpdateDevices(ctx, expectedDevice)
|
||||
require.NoError(err)
|
||||
|
||||
device, err = repo.GetDevice(expectedDevice.ID)
|
||||
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(device)
|
||||
require.Equal(expectedDevice.ID, device.ID)
|
||||
@ -222,97 +242,80 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
)
|
||||
|
||||
// Test: AddSensors
|
||||
err = repo.AddSensors(expectedSensors...)
|
||||
err = repo.AddSensors(ctx, expectedSensors...)
|
||||
require.NoError(err)
|
||||
|
||||
// Test: GetSensors
|
||||
sensors, err := repo.GetSensors()
|
||||
sensors, err := repo.GetSensors(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(sensors, len(expectedSensors))
|
||||
|
||||
sensors, err = repo.GetSensors("BME280")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[2]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensors("DS18B20")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[1]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensors("DHT11")
|
||||
// Test: GetSensorsByNames
|
||||
sensors, err = repo.GetSensorsByNames(ctx, "01fbdbe9-cebf-42ed-8065-bf4882ccf76b")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensors("DHT11", "DS18B20")
|
||||
// Test: GetSensorsByModels
|
||||
sensors, err = repo.GetSensorsByModels(ctx, "BME280")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[2]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensorsByModels(ctx, "DS18B20")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[1]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensorsByModels(ctx, "DHT11")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensors[0]))
|
||||
|
||||
sensors, err = repo.GetSensorsByModels(ctx, "DHT11", "DS18B20")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 2)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[0:2]), jsonEncoder(sensors[0:2]))
|
||||
|
||||
// Test: GetSensor
|
||||
sensor, err := repo.GetSensor(expectedSensors[0].ID)
|
||||
// Test: GetSensorByID
|
||||
sensor, err := repo.GetSensorByID(ctx, expectedSensors[0].ID)
|
||||
require.NoError(err)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensor))
|
||||
|
||||
// Test: GetSensorsByDeviceID
|
||||
sensors, err = repo.GetSensorsByDeviceID("ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
|
||||
sensors, err = repo.GetSensorsByDeviceIDs(ctx, "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 2)
|
||||
require.JSONEq(jsonEncoder(expectedSensors[0:2]), jsonEncoder(sensors))
|
||||
|
||||
// Test: RemoveSensors
|
||||
err = repo.RemoveSensors(expectedSensors[0].ID)
|
||||
// Test: RemoveSensorsByIDs
|
||||
err = repo.RemoveSensorsByIDs(ctx, expectedSensors[0].ID)
|
||||
require.NoError(err)
|
||||
|
||||
sensors, err = repo.GetSensors()
|
||||
sensors, err = repo.GetSensors(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 2)
|
||||
|
||||
sensors, err = repo.GetSensorsByDeviceID("ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
|
||||
sensors, err = repo.GetSensorsByDeviceIDs(ctx, "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensors[0].ID)
|
||||
sensor, err = repo.GetSensorByID(ctx, expectedSensors[0].ID)
|
||||
require.NoError(err)
|
||||
require.Nil(sensor)
|
||||
|
||||
// Test: RemoveSensorsByNames
|
||||
err = repo.RemoveSensorsByNames(expectedSensors[1].Name)
|
||||
err = repo.RemoveSensorsByNames(ctx, expectedSensors[1].Name)
|
||||
require.NoError(err)
|
||||
|
||||
sensors, err = repo.GetSensors()
|
||||
sensors, err = repo.GetSensors(ctx)
|
||||
require.NoError(err)
|
||||
require.Len(sensors, 1)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensors[1].ID)
|
||||
sensor, err = repo.GetSensorByID(ctx, expectedSensors[1].ID)
|
||||
require.NoError(err)
|
||||
require.Nil(sensor)
|
||||
|
||||
// Test: RenameSensor
|
||||
err = repo.RenameSensors(expectedSensors[2].Name, "Hello")
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensors[2].ID)
|
||||
require.Equal("Hello", sensor.Name)
|
||||
require.NotNil(sensor)
|
||||
|
||||
// Test: DisableSensorsByNames
|
||||
err = repo.DisableSensorsByNames("Hello")
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensors[2].ID)
|
||||
require.False(sensor.Enabled)
|
||||
require.NotNil(sensor)
|
||||
|
||||
// Test: EnableSensorsByName
|
||||
err = repo.EnableSensorsByNames("Hello")
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensors[2].ID)
|
||||
require.True(sensor.Enabled)
|
||||
require.NotNil(sensor)
|
||||
|
||||
// Test: UpdateSensors
|
||||
expectedSensor := &types.Sensor{
|
||||
ID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
|
||||
@ -327,10 +330,10 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
|
||||
err = repo.UpdateSensors(expectedSensor)
|
||||
err = repo.UpdateSensors(ctx, expectedSensor)
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensor.ID)
|
||||
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(sensor)
|
||||
// require.JSONEq(jsonEncoder(expectedSensor), jsonEncoder(sensor))
|
||||
@ -349,10 +352,10 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
|
||||
err = repo.AddOrUpdateSensors(expectedSensor)
|
||||
err = repo.AddOrUpdateSensors(ctx, expectedSensor)
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensor.ID)
|
||||
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(sensor)
|
||||
require.Equal(expectedSensor.ID, sensor.ID)
|
||||
@ -378,10 +381,10 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
CreationDate: *timeNow(require),
|
||||
}
|
||||
|
||||
err = repo.AddOrUpdateSensors(expectedSensor)
|
||||
err = repo.AddOrUpdateSensors(ctx, expectedSensor)
|
||||
require.NoError(err)
|
||||
|
||||
sensor, err = repo.GetSensor(expectedSensor.ID)
|
||||
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(sensor)
|
||||
require.Equal(expectedSensor.ID, sensor.ID)
|
||||
@ -427,7 +430,7 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
)
|
||||
|
||||
// Test: AddMeasuredValues
|
||||
err = repo.AddMeasuredValues(expectedMeasuredValues...)
|
||||
err = repo.AddMeasuredValues(ctx, expectedMeasuredValues...)
|
||||
require.NoError(err)
|
||||
|
||||
for i := range expectedMeasuredValues {
|
||||
@ -439,15 +442,15 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
|
||||
switch expectedMeasuredValues[i].ValueType {
|
||||
case types.Humidity:
|
||||
measuredValue, err = repo.GetHumidity(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetHumidityByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
case types.Pressure:
|
||||
measuredValue, err = repo.GetPressure(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetPressureByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
case types.Temperature:
|
||||
measuredValue, err = repo.GetTemperature(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetTemperatureByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
}
|
||||
@ -489,7 +492,7 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
},
|
||||
}
|
||||
|
||||
err = repo.AddOrUpdateMeasuredValues(expectedMeasuredValues...)
|
||||
err = repo.AddOrUpdateMeasuredValues(ctx, expectedMeasuredValues...)
|
||||
require.NoError(err)
|
||||
|
||||
for i := range expectedMeasuredValues {
|
||||
@ -501,15 +504,15 @@ func testBackend(t *testing.T, repo *repository.Repository) {
|
||||
|
||||
switch expectedMeasuredValues[i].ValueType {
|
||||
case types.Humidity:
|
||||
measuredValue, err = repo.GetHumidity(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetHumidityByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
case types.Pressure:
|
||||
measuredValue, err = repo.GetPressure(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetPressureByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
case types.Temperature:
|
||||
measuredValue, err = repo.GetTemperature(expectedMeasuredValues[i].ID)
|
||||
measuredValue, err = repo.GetTemperatureByID(ctx, expectedMeasuredValues[i].ID)
|
||||
require.NoError(err)
|
||||
require.NotNil(measuredValue)
|
||||
}
|
||||
|
2
pkg/repository/sqlite3/dml/deleteDeviceByName.sql
Normal file
2
pkg/repository/sqlite3/dml/deleteDeviceByName.sql
Normal file
@ -0,0 +1,2 @@
|
||||
DELETE FROM devices
|
||||
WHERE device_name = $1;
|
2
pkg/repository/sqlite3/dml/deleteSensorByName.sql
Normal file
2
pkg/repository/sqlite3/dml/deleteSensorByName.sql
Normal file
@ -0,0 +1,2 @@
|
||||
DELETE FROM sensors
|
||||
WHERE sensor_name = $1;
|
9
pkg/repository/sqlite3/dml/selectDeviceByName.sql
Normal file
9
pkg/repository/sqlite3/dml/selectDeviceByName.sql
Normal file
@ -0,0 +1,9 @@
|
||||
SELECT
|
||||
device_id,
|
||||
device_name,
|
||||
device_location,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
devices
|
||||
WHERE device_name = $1;
|
18
pkg/repository/sqlite3/dml/selectSensorsByDeviceID.sql
Normal file
18
pkg/repository/sqlite3/dml/selectSensorsByDeviceID.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
device_id = $1;
|
18
pkg/repository/sqlite3/dml/selectSensorsByModel.sql
Normal file
18
pkg/repository/sqlite3/dml/selectSensorsByModel.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
sensor_model = $1;
|
18
pkg/repository/sqlite3/dml/selectSensorsByName.sql
Normal file
18
pkg/repository/sqlite3/dml/selectSensorsByName.sql
Normal file
@ -0,0 +1,18 @@
|
||||
SELECT
|
||||
sensor_id,
|
||||
sensor_name,
|
||||
sensor_location,
|
||||
wire_id,
|
||||
i2c_bus,
|
||||
i2c_address,
|
||||
gpio_number,
|
||||
sensor_model,
|
||||
sensor_enabled,
|
||||
tick_duration,
|
||||
device_id,
|
||||
creation_date,
|
||||
update_date
|
||||
FROM
|
||||
sensors
|
||||
WHERE
|
||||
sensor_name = $1;
|
1256
pkg/repository/sqlite3/sqlite.go
Normal file
1256
pkg/repository/sqlite3/sqlite.go
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user