posthooks.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: Apache-2.0
  4
  5package db
  6
  7import (
  8	"crypto/sha256"
  9	"database/sql"
 10	"fmt"
 11)
 12
 13// generateAndInsertProjectIDs runs during migration 1, fetches all rows from
 14// projects_tmp, loops through the rows generating a repeatable ID for each
 15// project, and inserting it into the new table along with the data from the old
 16// table.
 17func generateAndInsertProjectIDs(tx *sql.Tx) error {
 18	// Loop through projects_tmp, generate a project_id for each, and insert
 19	// into projects
 20	rows, err := tx.Query("SELECT url, name, forge, version, created_at FROM projects_tmp")
 21	if err != nil {
 22		return fmt.Errorf("failed to list projects in projects_tmp: %w", err)
 23	}
 24	defer rows.Close()
 25
 26	for rows.Next() {
 27		var (
 28			url        string
 29			name       string
 30			forge      string
 31			version    string
 32			created_at string
 33		)
 34		if err := rows.Scan(&url, &name, &forge, &version, &created_at); err != nil {
 35			return fmt.Errorf("failed to scan row from projects_tmp: %w", err)
 36		}
 37
 38		id := fmt.Sprintf("%x", sha256.Sum256([]byte(url+name+forge+created_at)))
 39
 40		_, err = tx.Exec(
 41			"INSERT INTO projects (id, url, name, forge, version, created_at) VALUES (@id, @url, @name, @forge, @version, @created_at)",
 42			sql.Named("id", id),
 43			sql.Named("url", url),
 44			sql.Named("name", name),
 45			sql.Named("forge", forge),
 46			sql.Named("version", version),
 47			sql.Named("created_at", created_at),
 48		)
 49		if err != nil {
 50			return fmt.Errorf("failed to insert project into projects: %w", err)
 51		}
 52	}
 53
 54	if err := rows.Err(); err != nil {
 55		return fmt.Errorf("failed to iterate over rows: %w", err)
 56	}
 57
 58	if _, err := tx.Exec("DROP TABLE projects_tmp"); err != nil {
 59		return fmt.Errorf("failed to drop projects_tmp: %w", err)
 60	}
 61
 62	return nil
 63}
 64
 65// Basing the project's ID on when it was created (L37) was a bad idea.
 66func correctProjectIDs(tx *sql.Tx) error {
 67	rows, err := tx.Query("SELECT id, url, name, forge FROM projects")
 68	if err != nil {
 69		return fmt.Errorf("failed to list projects in projects_tmp: %w", err)
 70	}
 71	defer rows.Close()
 72
 73	for rows.Next() {
 74		var (
 75			old_id string
 76			url    string
 77			name   string
 78			forge  string
 79		)
 80		if err := rows.Scan(&old_id, &url, &name, &forge); err != nil {
 81			return fmt.Errorf("failed to scan row from projects_tmp: %w", err)
 82		}
 83
 84		id := fmt.Sprintf("%x", sha256.Sum256([]byte(url+name+forge)))
 85
 86		_, err = tx.Exec(
 87			"UPDATE projects SET id = @id WHERE id = @old_id",
 88			sql.Named("id", id),
 89			sql.Named("old_id", old_id),
 90		)
 91		if err != nil {
 92			return fmt.Errorf("failed to insert project into projects: %w", err)
 93		}
 94	}
 95
 96	if err := rows.Err(); err != nil {
 97		return fmt.Errorf("failed to iterate over rows: %w", err)
 98	}
 99
100	return nil
101}