tenseleyflow/shithub / bedb6d0

Browse files

Add migrations + migrationsfs embed package (0001_meta + tg_set_updated_at)

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
bedb6d0500bf6c1d01d03d0b4e7932082b1a073f
Parents
de04d8e
Tree
ddf0b64

2 changed files

StatusFile+-
A internal/migrationsfs/migrations/0001_meta.sql 39 0
A internal/migrationsfs/migrationsfs.go 30 0
internal/migrationsfs/migrations/0001_meta.sqladded
@@ -0,0 +1,39 @@
1
+-- SPDX-License-Identifier: AGPL-3.0-or-later
2
+--
3
+-- Initial migration: a generic key/value `meta` table used for
4
+-- schema-version-friendly metadata, plus the canonical `tg_set_updated_at`
5
+-- trigger function reused by every later table that has an `updated_at`
6
+-- column.
7
+--
8
+-- This is the only migration where we bootstrap the trigger; subsequent
9
+-- migrations attach the trigger to their tables via:
10
+--
11
+--     CREATE TRIGGER set_updated_at BEFORE UPDATE ON <table>
12
+--         FOR EACH ROW EXECUTE FUNCTION tg_set_updated_at();
13
+
14
+-- +goose Up
15
+-- +goose StatementBegin
16
+CREATE OR REPLACE FUNCTION tg_set_updated_at() RETURNS trigger AS $$
17
+BEGIN
18
+    NEW.updated_at := now();
19
+    RETURN NEW;
20
+END;
21
+$$ LANGUAGE plpgsql;
22
+-- +goose StatementEnd
23
+
24
+CREATE TABLE meta (
25
+    key        text        PRIMARY KEY,
26
+    value      jsonb       NOT NULL,
27
+    updated_at timestamptz NOT NULL DEFAULT now()
28
+);
29
+
30
+CREATE TRIGGER set_updated_at BEFORE UPDATE ON meta
31
+    FOR EACH ROW EXECUTE FUNCTION tg_set_updated_at();
32
+
33
+INSERT INTO meta (key, value) VALUES
34
+    ('schema_version', '"0001"'::jsonb),
35
+    ('app',            '"shithub"'::jsonb);
36
+
37
+-- +goose Down
38
+DROP TABLE IF EXISTS meta;
39
+DROP FUNCTION IF EXISTS tg_set_updated_at();
internal/migrationsfs/migrationsfs.goadded
@@ -0,0 +1,30 @@
1
+// SPDX-License-Identifier: AGPL-3.0-or-later
2
+
3
+// Package migrationsfs embeds the SQL migrations from the repo root and
4
+// registers them with the db package. It exists as its own package because
5
+// //go:embed paths can't traverse upward; the migrationsfs/ directory is at
6
+// the right level relative to migrations/ to embed it.
7
+package migrationsfs
8
+
9
+import (
10
+	"embed"
11
+	"io/fs"
12
+
13
+	"github.com/tenseleyFlow/shithub/internal/infra/db"
14
+)
15
+
16
+//go:embed all:migrations
17
+var migrationsFS embed.FS
18
+
19
+// FS returns the embedded migrations filesystem rooted at "migrations/".
20
+func FS() fs.FS {
21
+	sub, err := fs.Sub(migrationsFS, "migrations")
22
+	if err != nil {
23
+		panic(err)
24
+	}
25
+	return sub
26
+}
27
+
28
+func init() {
29
+	db.SetMigrationsFS(FS())
30
+}