wireplanner/internal/db/connections.go

193 lines
5.8 KiB
Go

package db
import (
"database/sql"
"fmt"
"lostcavewireplanner/internal/models"
)
func (s *Store) ConnectionTypeGetAll() ([]models.ConnectionType, error) {
rows, err := s.DB.Query(`SELECT id, name FROM connection_types ORDER BY id`)
if err != nil {
return nil, err
}
defer rows.Close()
var types []models.ConnectionType
for rows.Next() {
var ct models.ConnectionType
if err := rows.Scan(&ct.ID, &ct.Name); err != nil {
return nil, err
}
types = append(types, ct)
}
return types, rows.Err()
}
func (s *Store) ConnectionGetByPortID(portID int64) (*models.Connection, error) {
c := &models.Connection{}
err := s.DB.QueryRow(`SELECT id, connection_type_id, label_1, label_2, color, port_id_1, port_id_2, created_at, updated_at FROM connections WHERE port_id_1 = ? OR port_id_2 = ?`, portID, portID).
Scan(&c.ID, &c.ConnectionTypeID, &c.Label1, &c.Label2, &c.Color, &c.PortID1, &c.PortID2, &c.CreatedAt, &c.UpdatedAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
s.populateConnection(c)
return c, nil
}
func (s *Store) ConnectionGetByPortIDExcluding(portID int64, excludeConnID int64) (*models.Connection, error) {
c := &models.Connection{}
err := s.DB.QueryRow(`SELECT id, connection_type_id, label_1, label_2, color, port_id_1, port_id_2, created_at, updated_at FROM connections WHERE (port_id_1 = ? OR port_id_2 = ?) AND id != ?`, portID, portID, excludeConnID).
Scan(&c.ID, &c.ConnectionTypeID, &c.Label1, &c.Label2, &c.Color, &c.PortID1, &c.PortID2, &c.CreatedAt, &c.UpdatedAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
s.populateConnection(c)
return c, nil
}
func (s *Store) ConnectionGetByID(id int64) (*models.Connection, error) {
c := &models.Connection{}
err := s.DB.QueryRow(`SELECT id, connection_type_id, label_1, label_2, color, port_id_1, port_id_2, created_at, updated_at FROM connections WHERE id = ?`, id).
Scan(&c.ID, &c.ConnectionTypeID, &c.Label1, &c.Label2, &c.Color, &c.PortID1, &c.PortID2, &c.CreatedAt, &c.UpdatedAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
s.populateConnection(c)
return c, nil
}
func (s *Store) ConnectionGetAllForRack(rackID int64) ([]models.Connection, error) {
rows, err := s.DB.Query(`
SELECT c.id, c.connection_type_id, c.label_1, c.label_2, c.color, c.port_id_1, c.port_id_2, c.created_at, c.updated_at
FROM connections c
WHERE (port_id_1 IN (SELECT dp.id FROM device_ports dp JOIN devices d ON d.id = dp.device_id WHERE d.rack_id = ?))
OR (port_id_2 IN (SELECT dp.id FROM device_ports dp JOIN devices d ON d.id = dp.device_id WHERE d.rack_id = ?))`, rackID, rackID)
if err != nil {
return nil, err
}
defer rows.Close()
var conns []models.Connection
for rows.Next() {
var c models.Connection
if err := rows.Scan(&c.ID, &c.ConnectionTypeID, &c.Label1, &c.Label2, &c.Color, &c.PortID1, &c.PortID2, &c.CreatedAt, &c.UpdatedAt); err != nil {
return nil, err
}
s.populateConnection(&c)
conns = append(conns, c)
}
return conns, rows.Err()
}
func (s *Store) ConnectionGetAll() ([]models.Connection, error) {
rows, err := s.DB.Query(`SELECT id, connection_type_id, label_1, label_2, color, port_id_1, port_id_2, created_at, updated_at FROM connections`)
if err != nil {
return nil, err
}
defer rows.Close()
var conns []models.Connection
for rows.Next() {
var c models.Connection
if err := rows.Scan(&c.ID, &c.ConnectionTypeID, &c.Label1, &c.Label2, &c.Color, &c.PortID1, &c.PortID2, &c.CreatedAt, &c.UpdatedAt); err != nil {
return nil, err
}
conns = append(conns, c)
}
return conns, rows.Err()
}
func (s *Store) ConnectionCreate(c *models.Connection) error {
tx, err := s.DB.Begin()
if err != nil {
return err
}
defer tx.Rollback()
if c.PortID1 != nil {
exists, err := s.portConnectedTx(tx, *c.PortID1)
if err != nil {
return err
}
if exists {
return fmt.Errorf("port %d is already connected", *c.PortID1)
}
}
if c.PortID2 != nil {
exists, err := s.portConnectedTx(tx, *c.PortID2)
if err != nil {
return err
}
if exists {
return fmt.Errorf("port %d is already connected", *c.PortID2)
}
}
res, err := tx.Exec(`INSERT INTO connections (connection_type_id, label_1, label_2, color, port_id_1, port_id_2) VALUES (?, ?, ?, ?, ?, ?)`,
c.ConnectionTypeID, c.Label1, c.Label2, c.Color, c.PortID1, c.PortID2)
if err != nil {
return err
}
c.ID, err = res.LastInsertId()
if err != nil {
return err
}
return tx.Commit()
}
func (s *Store) ConnectionUpdate(c *models.Connection) error {
_, err := s.DB.Exec(`UPDATE connections SET connection_type_id=?, label_1=?, label_2=?, color=?, port_id_1=?, port_id_2=?, updated_at=datetime('now') WHERE id=?`,
c.ConnectionTypeID, c.Label1, c.Label2, c.Color, c.PortID1, c.PortID2, c.ID)
return err
}
func (s *Store) ConnectionDelete(id int64) error {
_, err := s.DB.Exec(`DELETE FROM connections WHERE id=?`, id)
return err
}
func (s *Store) portConnectedTx(tx *sql.Tx, portID int64) (bool, error) {
var count int
err := tx.QueryRow(`SELECT COUNT(*) FROM connections WHERE port_id_1 = ? OR port_id_2 = ?`, portID, portID).Scan(&count)
return count > 0, err
}
func (s *Store) populateConnection(c *models.Connection) {
if c.PortID1 != nil {
c.Port1, _ = s.PortGetByID(*c.PortID1)
if c.Port1 != nil {
c.Device1, _ = s.DeviceGetByID(c.Port1.DeviceID)
}
}
if c.PortID2 != nil {
c.Port2, _ = s.PortGetByID(*c.PortID2)
if c.Port2 != nil {
c.Device2, _ = s.DeviceGetByID(c.Port2.DeviceID)
}
}
ct, _ := s.ConnectionTypeGetByID(c.ConnectionTypeID)
c.ConnectionType = ct
}
func (s *Store) ConnectionTypeGetByID(id int64) (*models.ConnectionType, error) {
ct := &models.ConnectionType{}
err := s.DB.QueryRow(`SELECT id, name FROM connection_types WHERE id = ?`, id).Scan(&ct.ID, &ct.Name)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
return ct, nil
}