2020-05-21 15:40:24 +00:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
2020-06-10 19:13:05 +00:00
|
|
|
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
|
|
|
|
"git.cryptic.systems/volker.raschek/go-logger"
|
2020-05-21 15:40:24 +00:00
|
|
|
)
|
|
|
|
|
2020-06-01 10:41:48 +00:00
|
|
|
// Database is a general interface for a database backend like postgres, oracle
|
|
|
|
// or sqlite
|
2020-05-21 15:40:24 +00:00
|
|
|
type Database interface {
|
|
|
|
DeleteDevices(ctx context.Context, deviceIDs ...string) error
|
|
|
|
DeleteSensors(ctx context.Context, sensorIDs ...string) error
|
|
|
|
InsertDevices(ctx context.Context, devices ...*types.Device) error
|
|
|
|
InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
|
|
|
InsertSensors(ctx context.Context, sensors ...*types.Sensor) error
|
|
|
|
Scheme(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
|
|
|
|
}
|
|
|
|
|
2020-06-01 10:41:48 +00:00
|
|
|
// New returns a new database backend interface
|
|
|
|
func New(dsnURL *url.URL, flogger logger.Logger) (Database, error) {
|
2020-05-21 15:40:24 +00:00
|
|
|
|
|
|
|
// Check of nil pointer
|
|
|
|
for _, parameter := range []interface{}{
|
2020-06-01 10:41:48 +00:00
|
|
|
dsnURL,
|
2020-05-21 15:40:24 +00:00
|
|
|
flogger,
|
|
|
|
} {
|
|
|
|
if parameter == nil {
|
|
|
|
return nil, fmt.Errorf("Parameter does not be nil")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load Queryfiles
|
|
|
|
queries := make(map[string]string, 0)
|
|
|
|
for _, asset := range AssetNames() {
|
2020-06-01 20:36:57 +00:00
|
|
|
|
2020-06-01 10:41:48 +00:00
|
|
|
if !strings.Contains(asset, dsnURL.Scheme) {
|
2020-05-21 15:40:24 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
body, err := Asset(asset)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
queryFile := filepath.Base(asset)
|
|
|
|
|
|
|
|
queries[queryFile] = string(body)
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
database Database
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
2020-06-01 10:41:48 +00:00
|
|
|
switch dsnURL.Scheme {
|
2020-06-01 20:36:57 +00:00
|
|
|
case "postgres":
|
|
|
|
|
|
|
|
// postgres://[user]:[password]@[host]:[port]/[path]?[query]
|
|
|
|
newDBO, err := sql.Open(dsnURL.Scheme, dsnURL.String())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
database = &Postgres{
|
|
|
|
dbo: newDBO,
|
|
|
|
flogger: flogger,
|
|
|
|
queries: queries,
|
|
|
|
}
|
2020-05-21 15:40:24 +00:00
|
|
|
|
|
|
|
case "sqlite3":
|
|
|
|
|
2020-05-21 18:07:32 +00:00
|
|
|
// Create directory where the db file will be created if not exists.
|
2020-06-01 10:41:48 +00:00
|
|
|
if _, err := os.Stat(filepath.Dir(dsnURL.Path)); os.IsNotExist(err) {
|
|
|
|
err := os.MkdirAll(filepath.Dir(dsnURL.Path), 0755)
|
2020-05-21 15:40:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sqlite3:///[path]?[query] flucky dsn
|
|
|
|
// file:///[path]?[query] sql-lib dsn
|
2020-06-01 10:41:48 +00:00
|
|
|
newDBO, err := sql.Open(dsnURL.Scheme, fmt.Sprintf("file://%v?%v", dsnURL.Path, dsnURL.RawQuery))
|
2020-05-21 15:40:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
database = &SQLite{
|
|
|
|
dbo: newDBO,
|
|
|
|
flogger: flogger,
|
|
|
|
queries: queries,
|
|
|
|
}
|
|
|
|
default:
|
2020-06-01 10:41:48 +00:00
|
|
|
return nil, fmt.Errorf("Unsupported database scheme: %v", dsnURL.Scheme)
|
2020-05-21 15:40:24 +00:00
|
|
|
}
|
|
|
|
|
2020-05-21 18:07:32 +00:00
|
|
|
// Initialize database scheme if not exists
|
2020-05-21 15:40:24 +00:00
|
|
|
err = database.Scheme(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return database, nil
|
|
|
|
|
|
|
|
}
|