homelabby/internal/store/migrations.go
Mikkel Georgsen 4bc22dc7b9 feat(06-01): add pgx/v5 store with connection pool and migrations
- Store struct wrapping pgxpool.Pool with NewStore/Close/Pool
- RunMigrations creates conversations + messages tables idempotently
- DSN never logged to avoid credential exposure (T-06-01-02)
- All queries parameterized (T-06-01-01)
2026-04-10 07:31:08 +00:00

40 lines
1.2 KiB
Go

package store
import (
"context"
"fmt"
"github.com/jackc/pgx/v5/pgxpool"
)
// RunMigrations creates the conversations and messages tables idempotently.
// It is safe to call multiple times; existing tables are left untouched.
//
// Schema:
//
// conversations(id UUID PK, started_at TIMESTAMPTZ, model TEXT)
// messages(id UUID PK, conversation_id UUID FK, role TEXT CHECK, content TEXT, created_at TIMESTAMPTZ)
func RunMigrations(ctx context.Context, pool *pgxpool.Pool) error {
statements := []string{
`CREATE TABLE IF NOT EXISTS conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
model TEXT NOT NULL DEFAULT ''
)`,
`CREATE TABLE IF NOT EXISTS messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user','assistant','system')),
content TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
)`,
}
for i, stmt := range statements {
if _, err := pool.Exec(ctx, stmt); err != nil {
return fmt.Errorf("store: migration statement %d: %w", i, err)
}
}
return nil
}