1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-28 13:48:49 +08:00
Aleksandar Novaković 671c32affe
MF-473 - Add metadata field to channel (#476)
* Add metadata field to channels and update things metadata

Add metadata field to channels. Update thing metadata field to be
in JSON format. Update tests..

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add metadata to channel events

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add metadata field to channel in go SDK

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-11-28 15:58:48 +01:00

142 lines
3.2 KiB
Go

//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package postgres
import (
"database/sql"
"fmt"
"github.com/lib/pq" // required for DB access
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/things"
)
var _ things.ThingRepository = (*thingRepository)(nil)
type thingRepository struct {
db *sql.DB
log logger.Logger
}
// NewThingRepository instantiates a PostgreSQL implementation of thing
// repository.
func NewThingRepository(db *sql.DB, log logger.Logger) things.ThingRepository {
return &thingRepository{db: db, log: log}
}
func (tr thingRepository) Save(thing things.Thing) (uint64, error) {
q := `INSERT INTO things (owner, type, name, key, metadata) VALUES ($1, $2, $3, $4, $5) RETURNING id`
metadata := thing.Metadata
if metadata == "" {
metadata = "{}"
}
err := tr.db.QueryRow(q, thing.Owner, thing.Type, thing.Name, thing.Key, metadata).Scan(&thing.ID)
if err != nil {
pqErr, ok := err.(*pq.Error)
if ok && errInvalid == pqErr.Code.Name() {
return 0, things.ErrMalformedEntity
}
return 0, err
}
return thing.ID, nil
}
func (tr thingRepository) Update(thing things.Thing) error {
q := `UPDATE things SET name = $1, metadata = $2 WHERE owner = $3 AND id = $4;`
metadata := thing.Metadata
if metadata == "" {
metadata = "{}"
}
res, err := tr.db.Exec(q, thing.Name, metadata, thing.Owner, thing.ID)
if err != nil {
pqErr, ok := err.(*pq.Error)
if ok && errInvalid == pqErr.Code.Name() {
return things.ErrMalformedEntity
}
return err
}
cnt, err := res.RowsAffected()
if err != nil {
return err
}
if cnt == 0 {
return things.ErrNotFound
}
return nil
}
func (tr thingRepository) RetrieveByID(owner string, id uint64) (things.Thing, error) {
q := `SELECT name, type, key, metadata FROM things WHERE id = $1 AND owner = $2`
thing := things.Thing{ID: id, Owner: owner}
err := tr.db.
QueryRow(q, id, owner).
Scan(&thing.Name, &thing.Type, &thing.Key, &thing.Metadata)
if err != nil {
empty := things.Thing{}
if err == sql.ErrNoRows {
return empty, things.ErrNotFound
}
return empty, err
}
return thing, nil
}
func (tr thingRepository) RetrieveByKey(key string) (uint64, error) {
q := `SELECT id FROM things WHERE key = $1`
var id uint64
if err := tr.db.QueryRow(q, key).Scan(&id); err != nil {
if err == sql.ErrNoRows {
return 0, things.ErrNotFound
}
return 0, err
}
return id, nil
}
func (tr thingRepository) RetrieveAll(owner string, offset, limit uint64) []things.Thing {
q := `SELECT id, name, type, key, metadata FROM things WHERE owner = $1 ORDER BY id LIMIT $2 OFFSET $3`
items := []things.Thing{}
rows, err := tr.db.Query(q, owner, limit, offset)
if err != nil {
tr.log.Error(fmt.Sprintf("Failed to retrieve things due to %s", err))
return []things.Thing{}
}
defer rows.Close()
for rows.Next() {
c := things.Thing{Owner: owner}
if err = rows.Scan(&c.ID, &c.Name, &c.Type, &c.Key, &c.Metadata); err != nil {
tr.log.Error(fmt.Sprintf("Failed to read retrieved thing due to %s", err))
return []things.Thing{}
}
items = append(items, c)
}
return items
}
func (tr thingRepository) Remove(owner string, id uint64) error {
q := `DELETE FROM things WHERE id = $1 AND owner = $2`
tr.db.Exec(q, id, owner)
return nil
}