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			createdAt string
 33		)
 34		if err := rows.Scan(&url, &name, &forge, &version, &createdAt); 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+createdAt)))
 39
 40		_, err = tx.Exec(
 41			"INSERT INTO projects (id, url, name, forge, version, created_at) "+
 42				"VALUES (@id, @url, @name, @forge, @version, @created_at)",
 43			sql.Named("id", id),
 44			sql.Named("url", url),
 45			sql.Named("name", name),
 46			sql.Named("forge", forge),
 47			sql.Named("version", version),
 48			sql.Named("created_at", createdAt),
 49		)
 50		if err != nil {
 51			return fmt.Errorf("failed to insert project into projects: %w", err)
 52		}
 53	}
 54
 55	if err := rows.Err(); err != nil {
 56		return fmt.Errorf("failed to iterate over rows: %w", err)
 57	}
 58
 59	if _, err := tx.Exec("DROP TABLE projects_tmp"); err != nil {
 60		return fmt.Errorf("failed to drop projects_tmp: %w", err)
 61	}
 62
 63	return nil
 64}
 65
 66// Basing the project's ID on when it was created (L37) was a bad idea.
 67func correctProjectIDs(tx *sql.Tx) error {
 68	rows, err := tx.Query("SELECT id, url, name, forge FROM projects")
 69	if err != nil {
 70		return fmt.Errorf("failed to list projects in projects_tmp: %w", err)
 71	}
 72	defer rows.Close()
 73
 74	for rows.Next() {
 75		var (
 76			oldID string
 77			url   string
 78			name  string
 79			forge string
 80		)
 81		if err := rows.Scan(&oldID, &url, &name, &forge); err != nil {
 82			return fmt.Errorf("failed to scan row from projects_tmp: %w", err)
 83		}
 84
 85		id := fmt.Sprintf("%x", sha256.Sum256([]byte(url+name+forge)))
 86
 87		_, err = tx.Exec(
 88			"UPDATE projects SET id = @id WHERE id = @old_id",
 89			sql.Named("id", id),
 90			sql.Named("old_id", oldID),
 91		)
 92		if err != nil {
 93			return fmt.Errorf("failed to insert project into projects: %w", err)
 94		}
 95	}
 96
 97	if err := rows.Err(); err != nil {
 98		return fmt.Errorf("failed to iterate over rows: %w", err)
 99	}
100
101	return nil
102}