package template import ( "context" "database/sql" "errors" "time" ) type SQLRepository struct { db *sql.DB } func NewSQLRepository(db *sql.DB) SQLRepository { return SQLRepository{db: db} } func (r SQLRepository) List(ctx context.Context) ([]Template, error) { rows, err := r.db.QueryContext(ctx, ` select id::text, cluster_id::text, name, description, proxmox_template_vmid, proxmox_node, created_at from public.templates order by name asc `) if err != nil { return nil, err } defer rows.Close() var templates []Template for rows.Next() { var t Template if err := rows.Scan(&t.ID, &t.ClusterID, &t.Name, &t.Description, &t.ProxmoxTemplateVMID, &t.ProxmoxNode, &t.CreatedAt); err != nil { return nil, err } templates = append(templates, t) } if err := rows.Err(); err != nil { return nil, err } return templates, nil } func (r SQLRepository) Get(ctx context.Context, id string) (Template, bool, error) { var t Template err := r.db.QueryRowContext(ctx, ` select id::text, cluster_id::text, name, description, proxmox_template_vmid, proxmox_node, created_at from public.templates where id = $1 `, id).Scan(&t.ID, &t.ClusterID, &t.Name, &t.Description, &t.ProxmoxTemplateVMID, &t.ProxmoxNode, &t.CreatedAt) if errors.Is(err, sql.ErrNoRows) { return Template{}, false, nil } if err != nil { return Template{}, false, err } return t, true, nil } func (r SQLRepository) Upsert(ctx context.Context, t Template) (Template, error) { err := r.db.QueryRowContext(ctx, ` insert into public.templates (cluster_id, name, description, proxmox_template_vmid, proxmox_node) values ($1, $2, $3, $4, $5) on conflict (cluster_id, proxmox_node, proxmox_template_vmid) do update set name = $2, description = $3, updated_at = now() returning id::text, name, description, proxmox_template_vmid, proxmox_node, created_at, coalesce(updated_at, created_at) `, t.ClusterID, t.Name, t.Description, t.ProxmoxTemplateVMID, t.ProxmoxNode).Scan( &t.ID, &t.Name, &t.Description, &t.ProxmoxTemplateVMID, &t.ProxmoxNode, &t.CreatedAt, &t.UpdatedAt, ) if err != nil { return Template{}, err } return t, nil } func (r SQLRepository) Delete(ctx context.Context, id string) (bool, error) { res, err := r.db.ExecContext(ctx, `delete from public.templates where id = $1`, id) if err != nil { return false, err } rowsAffected, err := res.RowsAffected() if err != nil { return false, err } return rowsAffected > 0, nil } type Template struct { ID string `json:"id"` ClusterID string `json:"cluster_id"` Name string `json:"name"` Description string `json:"description"` ProxmoxTemplateVMID int `json:"proxmox_template_vmid"` ProxmoxNode string `json:"proxmox_node"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` }