Markus Pesch
10069568f9
Changes: - Renamed storage endpoint into dsn (data source name). - Add additional dsn fallback property. This dsn will be used in futes to store informations, if the main dsn backend does not work correctly. For example, if no connection can be established over the network to a database.
122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/volker-raschek/flucky/pkg/types"
|
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
|
)
|
|
|
|
// Database is a general interface for a database backend like postgres, oracle
|
|
// or sqlite
|
|
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
|
|
}
|
|
|
|
// New returns a new database backend interface
|
|
func New(dsnURL *url.URL, flogger logger.Logger) (Database, error) {
|
|
|
|
// Check of nil pointer
|
|
for _, parameter := range []interface{}{
|
|
dsnURL,
|
|
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() {
|
|
if !strings.Contains(asset, dsnURL.Scheme) {
|
|
continue
|
|
}
|
|
|
|
body, err := Asset(asset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
queryFile := filepath.Base(asset)
|
|
|
|
queries[queryFile] = string(body)
|
|
}
|
|
|
|
var (
|
|
database Database
|
|
err error
|
|
)
|
|
|
|
switch dsnURL.Scheme {
|
|
// case "postgres":
|
|
// // postgres://[user]:[password]@[host]:[port]/[path]?[query]
|
|
// newDBO, err := sql.Open(storageEndpoint.Scheme, storageEndpoint.String())
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
|
|
// return &Postgres{
|
|
// dbo: newDBO,
|
|
// flogger: flogger,
|
|
// }, nil
|
|
|
|
case "sqlite3":
|
|
|
|
// Create directory where the db file will be created if not exists.
|
|
if _, err := os.Stat(filepath.Dir(dsnURL.Path)); os.IsNotExist(err) {
|
|
err := os.MkdirAll(filepath.Dir(dsnURL.Path), 0755)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// sqlite3:///[path]?[query] flucky dsn
|
|
// file:///[path]?[query] sql-lib dsn
|
|
newDBO, err := sql.Open(dsnURL.Scheme, fmt.Sprintf("file://%v?%v", dsnURL.Path, dsnURL.RawQuery))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
database = &SQLite{
|
|
dbo: newDBO,
|
|
flogger: flogger,
|
|
queries: queries,
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("Unsupported database scheme: %v", dsnURL.Scheme)
|
|
}
|
|
|
|
// Initialize database scheme if not exists
|
|
err = database.Scheme(context.Background())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return database, nil
|
|
|
|
}
|