88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
|
|
"gardomatic.kleiax.de/internal/storage"
|
|
"github.com/lib/pq"
|
|
)
|
|
|
|
const queryTimeout = 3 * time.Second
|
|
|
|
type scanner interface {
|
|
Scan(dest ...any) error
|
|
}
|
|
|
|
func contextWithTimeout() (context.Context, context.CancelFunc) {
|
|
return context.WithTimeout(context.Background(), queryTimeout)
|
|
}
|
|
|
|
func jsonValue(value json.RawMessage) json.RawMessage {
|
|
if len(value) == 0 {
|
|
return json.RawMessage(`{}`)
|
|
}
|
|
return value
|
|
}
|
|
|
|
func deleteByID(db *sql.DB, query string, args ...any) error {
|
|
ctx, cancel := contextWithTimeout()
|
|
defer cancel()
|
|
|
|
result, err := db.ExecContext(ctx, query, args...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rowsAffected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
return storage.ErrRecordNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func deleteByGardenID(db *sql.DB, query string, gardenID, id int) error {
|
|
ctx, cancel := contextWithTimeout()
|
|
defer cancel()
|
|
|
|
result, err := db.ExecContext(ctx, query, gardenID, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rowsAffected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rowsAffected == 0 {
|
|
return storage.ErrRecordNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func recordError(err error) error {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return storage.ErrRecordNotFound
|
|
}
|
|
var pqError *pq.Error
|
|
if errors.As(err, &pqError) && pqError.Code == "23505" {
|
|
return storage.ErrConflict
|
|
}
|
|
if errors.As(err, &pqError) && pqError.Code == "23503" {
|
|
return storage.ErrConflict
|
|
}
|
|
return err
|
|
}
|
|
|
|
func nullableUserID(id int) any {
|
|
if id < 1 {
|
|
return nil
|
|
}
|
|
return id
|
|
}
|