forked from
tangled.org/core
Monorepo for Tangled
1package db
2
3import (
4 "database/sql"
5 "path/filepath"
6 "testing"
7)
8
9func TestDropLabelOpsIndexedColumn(t *testing.T) {
10 path := filepath.Join(t.TempDir(), "legacy.db")
11 conn, err := sql.Open("sqlite3", path+"?_foreign_keys=1")
12 if err != nil {
13 t.Fatalf("open: %v", err)
14 }
15 defer conn.Close()
16
17 legacy := `
18 create table label_definitions (
19 id integer primary key autoincrement,
20 did text not null,
21 rkey text not null,
22 at_uri text generated always as ('at://' || did || '/' || 'sh.tangled.label.definition' || '/' || rkey) stored,
23 name text not null,
24 unique (at_uri)
25 );
26 create table label_ops (
27 id integer primary key autoincrement,
28 did text not null,
29 rkey text not null,
30 at_uri text generated always as ('at://' || did || '/' || 'sh.tangled.label.op' || '/' || rkey) stored,
31 subject text not null,
32 operation text not null check (operation in ("add", "del")),
33 operand_key text not null,
34 operand_value text not null,
35 performed text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
36 indexed text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
37 foreign key (operand_key) references label_definitions (at_uri) on delete cascade,
38 unique (did, rkey, subject, operand_key, operand_value)
39 );
40 `
41 if _, err := conn.Exec(legacy); err != nil {
42 t.Fatalf("legacy schema: %v", err)
43 }
44
45 defUri := "at://did:plc:boltless/sh.tangled.label.definition/prio"
46 if _, err := conn.Exec(
47 `insert into label_definitions (did, rkey, name) values (?, ?, ?)`,
48 "did:plc:boltless", "prio", "priority",
49 ); err != nil {
50 t.Fatalf("seed def: %v", err)
51 }
52 if _, err := conn.Exec(
53 `insert into label_ops (did, rkey, subject, operation, operand_key, operand_value) values (?, ?, ?, ?, ?, ?)`,
54 "did:plc:boltless", "op1", "at://did:plc:boltless/sh.tangled.repo.issue/issue1", "add", defUri, "high",
55 ); err != nil {
56 t.Fatalf("seed op: %v", err)
57 }
58
59 indexedColumns := func() int {
60 var count int
61 if err := conn.QueryRow(
62 `select count(*) from pragma_table_info('label_ops') where name = 'indexed'`,
63 ).Scan(&count); err != nil {
64 t.Fatalf("pragma_table_info: %v", err)
65 }
66 return count
67 }
68
69 if indexedColumns() != 1 {
70 t.Fatalf("legacy table must carry the indexed column before the migration")
71 }
72 if _, err := conn.Exec(`alter table label_ops drop column indexed`); err != nil {
73 t.Fatalf("drop column indexed must succeed against the real table shape: %v", err)
74 }
75 if indexedColumns() != 0 {
76 t.Fatalf("indexed column must be gone after the drop")
77 }
78
79 var gotAtUri, gotVal string
80 if err := conn.QueryRow(
81 `select at_uri, operand_value from label_ops where did = ? and rkey = ?`,
82 "did:plc:boltless", "op1",
83 ).Scan(&gotAtUri, &gotVal); err != nil {
84 t.Fatalf("row must survive the drop: %v", err)
85 }
86 if want := "at://did:plc:boltless/sh.tangled.label.op/op1"; gotAtUri != want {
87 t.Fatalf("generated at_uri must survive the drop: got %q want %q", gotAtUri, want)
88 }
89 if gotVal != "high" {
90 t.Fatalf("operand value must survive the drop: got %q", gotVal)
91 }
92}