package db import ( "database/sql" "lostcavewireplanner/internal/models" ) func scanDevice(scanner interface{ Scan(dest ...any) error }, d *models.Device) error { return scanner.Scan(&d.ID, &d.DeviceModelID, &d.Name, &d.UsageDescription, &d.Comment, &d.Location, &d.RackID, &d.RackUnitStart, &d.RackSide, &d.CreatedAt, &d.UpdatedAt) } const deviceColumns = `d.id, d.device_model_id, d.name, d.usage_description, d.comment, d.location, d.rack_id, d.rack_unit_start, d.rack_side, d.created_at, d.updated_at` func (s *Store) DeviceGetByID(id int64) (*models.Device, error) { d := &models.Device{} err := s.DB.QueryRow(`SELECT `+deviceColumns+` FROM devices d WHERE d.id = ?`, id).Scan( &d.ID, &d.DeviceModelID, &d.Name, &d.UsageDescription, &d.Comment, &d.Location, &d.RackID, &d.RackUnitStart, &d.RackSide, &d.CreatedAt, &d.UpdatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } d.Model, _ = s.ModelGetByID(d.DeviceModelID) d.Ports, _ = s.PortGetByDeviceID(d.ID) if d.RackID != nil { d.Rack, _ = s.RackGetByID(*d.RackID) } return d, nil } func (s *Store) DeviceGetAllUnracked() ([]models.Device, error) { rows, err := s.DB.Query(`SELECT ` + deviceColumns + ` FROM devices d WHERE d.rack_id IS NULL ORDER BY d.name`) if err != nil { return nil, err } defer rows.Close() var devices []models.Device for rows.Next() { var d models.Device if err := scanDevice(rows, &d); err != nil { return nil, err } d.Model, _ = s.ModelGetByID(d.DeviceModelID) d.Ports, _ = s.PortGetByDeviceID(d.ID) devices = append(devices, d) } return devices, rows.Err() } func (s *Store) DeviceGetByRackID(rackID int64) ([]models.Device, error) { rows, err := s.DB.Query(`SELECT `+deviceColumns+` FROM devices d WHERE d.rack_id = ? AND d.rack_unit_start IS NOT NULL ORDER BY d.rack_unit_start`, rackID) if err != nil { return nil, err } defer rows.Close() var devices []models.Device for rows.Next() { var d models.Device if err := scanDevice(rows, &d); err != nil { return nil, err } d.Model, _ = s.ModelGetByID(d.DeviceModelID) d.Ports, _ = s.PortGetByDeviceID(d.ID) devices = append(devices, d) } return devices, rows.Err() } func (s *Store) DeviceGetUnrackedByRackID(rackID int64) ([]models.Device, error) { rows, err := s.DB.Query(`SELECT `+deviceColumns+` FROM devices d WHERE d.rack_id = ? AND d.rack_unit_start IS NULL ORDER BY d.name`, rackID) if err != nil { return nil, err } defer rows.Close() var devices []models.Device for rows.Next() { var d models.Device if err := scanDevice(rows, &d); err != nil { return nil, err } d.Model, _ = s.ModelGetByID(d.DeviceModelID) d.Ports, _ = s.PortGetByDeviceID(d.ID) devices = append(devices, d) } return devices, rows.Err() } func (s *Store) DeviceCreate(d *models.Device) (int64, error) { tx, err := s.DB.Begin() if err != nil { return 0, err } defer tx.Rollback() res, err := tx.Exec(`INSERT INTO devices (device_model_id, name, usage_description, comment, location, rack_id, rack_unit_start, rack_side) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, d.DeviceModelID, d.Name, d.UsageDescription, d.Comment, d.Location, d.RackID, d.RackUnitStart, d.RackSide) if err != nil { return 0, err } deviceID, err := res.LastInsertId() if err != nil { return 0, err } model, err := s.modelGetByIDTx(tx, d.DeviceModelID) if err != nil { return 0, err } if err := s.portCreateFromModelTx(tx, deviceID, model); err != nil { return 0, err } if err := tx.Commit(); err != nil { return 0, err } return deviceID, nil } func (s *Store) DeviceUpdate(d *models.Device) error { _, err := s.DB.Exec(`UPDATE devices SET name=?, usage_description=?, comment=?, location=?, rack_id=?, rack_unit_start=?, rack_side=?, updated_at=datetime('now') WHERE id=?`, d.Name, d.UsageDescription, d.Comment, d.Location, d.RackID, d.RackUnitStart, d.RackSide, d.ID) return err } func (s *Store) DeviceDelete(id int64) error { _, err := s.DB.Exec(`DELETE FROM devices WHERE id=?`, id) return err } func (s *Store) DeviceGetByName(name string) (*models.Device, error) { d := &models.Device{} err := s.DB.QueryRow(`SELECT `+deviceColumns+` FROM devices d WHERE d.name = ?`, name).Scan( &d.ID, &d.DeviceModelID, &d.Name, &d.UsageDescription, &d.Comment, &d.Location, &d.RackID, &d.RackUnitStart, &d.RackSide, &d.CreatedAt, &d.UpdatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } return d, nil } func (s *Store) DeviceGetAllWallSockets() ([]models.Device, error) { rows, err := s.DB.Query(`SELECT ` + deviceColumns + ` FROM devices d JOIN device_models dm ON dm.id = d.device_model_id WHERE dm.is_wall_socket = TRUE ORDER BY d.location, d.name`) if err != nil { return nil, err } defer rows.Close() var devices []models.Device for rows.Next() { var d models.Device if err := scanDevice(rows, &d); err != nil { return nil, err } d.Model, _ = s.ModelGetByID(d.DeviceModelID) d.Ports, _ = s.PortGetByDeviceID(d.ID) devices = append(devices, d) } return devices, rows.Err() }