-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore_schema.sql.docu
More file actions
277 lines (236 loc) · 11.1 KB
/
Copy pathcore_schema.sql.docu
File metadata and controls
277 lines (236 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
CREATE SCHEMA IF NOT EXISTS core;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE IF NOT EXISTS core.users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS core.repositories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
path VARCHAR(1024) NOT NULL UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
description TEXT NOT NULL DEFAULT '',
website VARCHAR(255) NOT NULL DEFAULT '',
topics JSONB NOT NULL DEFAULT '[]'::jsonb,
visibility VARCHAR(16) NOT NULL DEFAULT 'PUBLIC'
CHECK (visibility IN ('PUBLIC', 'PRIVATE')),
primary_language VARCHAR(64) NOT NULL DEFAULT '',
parent_id UUID REFERENCES core.repositories(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_core_repositories_created_at
ON core.repositories (created_at);
CREATE INDEX IF NOT EXISTS idx_core_repositories_name
ON core.repositories (name);
CREATE INDEX IF NOT EXISTS idx_core_repositories_primary_language
ON core.repositories (primary_language);
CREATE TABLE IF NOT EXISTS core.repository_collaborators (
repository_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL
CHECK (role IN ('OWNER', 'MAINTAINER', 'WRITE')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (repository_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_core_repository_collaborators_user
ON core.repository_collaborators (user_id);
CREATE TABLE IF NOT EXISTS core.issues (
id UUID PRIMARY KEY,
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
creator_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
status VARCHAR(16) NOT NULL DEFAULT 'OPEN'
CHECK (status IN ('OPEN', 'CLOSED')),
close_reason VARCHAR(24)
CHECK (close_reason IN ('COMPLETED', 'NOT_PLANNED', 'DUPLICATE')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_issues_repo_created_at
ON core.issues (repo_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_core_issues_repo_status
ON core.issues (repo_id, status);
CREATE TABLE IF NOT EXISTS core.pull_requests (
id UUID PRIMARY KEY,
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
creator_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL DEFAULT '',
source_branch VARCHAR(255) NOT NULL,
target_branch VARCHAR(255) NOT NULL,
source_commit_hash VARCHAR(64) NOT NULL DEFAULT '',
target_commit_hash VARCHAR(64) NOT NULL DEFAULT '',
status VARCHAR(16) NOT NULL DEFAULT 'OPEN'
CHECK (status IN ('OPEN', 'MERGED', 'CLOSED')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_pull_requests_repo_created_at
ON core.pull_requests (repo_id, created_at DESC);
CREATE TABLE IF NOT EXISTS core.labels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
name VARCHAR(50) NOT NULL,
color VARCHAR(7) NOT NULL DEFAULT '#cccccc',
description TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (repo_id, name)
);
CREATE INDEX IF NOT EXISTS idx_core_labels_repo
ON core.labels (repo_id);
CREATE TABLE IF NOT EXISTS core.issue_assignees (
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (issue_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_core_issue_assignees_issue_assigned_at
ON core.issue_assignees (issue_id, assigned_at);
CREATE TABLE IF NOT EXISTS core.issue_labels (
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
label_id UUID NOT NULL REFERENCES core.labels(id) ON DELETE CASCADE,
PRIMARY KEY (issue_id, label_id)
);
CREATE INDEX IF NOT EXISTS idx_core_issue_labels_issue
ON core.issue_labels (issue_id);
CREATE TABLE IF NOT EXISTS core.issue_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
actor_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
event_type VARCHAR(32) NOT NULL,
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_issue_events_issue
ON core.issue_events (issue_id, created_at);
CREATE TABLE IF NOT EXISTS core.issue_comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
author_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
body TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_issue_comments_issue
ON core.issue_comments (issue_id, created_at);
CREATE TABLE IF NOT EXISTS core.issue_linked_branches (
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
branch_name VARCHAR(255) NOT NULL,
linked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (issue_id, branch_name)
);
CREATE TABLE IF NOT EXISTS core.issue_relationships (
blocking_issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
blocked_issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
linked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (blocking_issue_id, blocked_issue_id),
CHECK (blocking_issue_id <> blocked_issue_id)
);
CREATE INDEX IF NOT EXISTS idx_core_issue_relationships_blocked
ON core.issue_relationships (blocked_issue_id, linked_at);
CREATE INDEX IF NOT EXISTS idx_core_issue_relationships_blocking
ON core.issue_relationships (blocking_issue_id, linked_at);
CREATE TABLE IF NOT EXISTS core.pull_request_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
pull_request_id UUID NOT NULL REFERENCES core.pull_requests(id) ON DELETE CASCADE,
actor_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
event_type VARCHAR(32) NOT NULL,
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_pull_request_events_pull_request
ON core.pull_request_events (pull_request_id, created_at);
CREATE TABLE IF NOT EXISTS core.pull_request_labels (
pull_request_id UUID NOT NULL REFERENCES core.pull_requests(id) ON DELETE CASCADE,
label_id UUID NOT NULL REFERENCES core.labels(id) ON DELETE CASCADE,
PRIMARY KEY (pull_request_id, label_id)
);
CREATE INDEX IF NOT EXISTS idx_core_pr_labels_pr
ON core.pull_request_labels (pull_request_id);
CREATE TABLE IF NOT EXISTS core.pull_request_assignees (
pull_request_id UUID NOT NULL REFERENCES core.pull_requests(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (pull_request_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_core_pr_assignees_pr
ON core.pull_request_assignees (pull_request_id, assigned_at);
CREATE TABLE IF NOT EXISTS core.pull_request_linked_issues (
pull_request_id UUID NOT NULL REFERENCES core.pull_requests(id) ON DELETE CASCADE,
issue_id UUID NOT NULL REFERENCES core.issues(id) ON DELETE CASCADE,
linked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (pull_request_id, issue_id)
);
CREATE TABLE IF NOT EXISTS core.repo_stars (
user_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (user_id, repo_id)
);
CREATE INDEX IF NOT EXISTS idx_core_repo_stars_repo
ON core.repo_stars (repo_id);
CREATE INDEX IF NOT EXISTS idx_core_repo_stars_user
ON core.repo_stars (user_id, created_at DESC);
CREATE TABLE IF NOT EXISTS core.repo_watchers (
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (repo_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_core_repo_watchers_repo
ON core.repo_watchers (repo_id);
CREATE INDEX IF NOT EXISTS idx_core_repo_watchers_user
ON core.repo_watchers (user_id, created_at DESC);
CREATE TABLE IF NOT EXISTS core.repo_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repo_id UUID NOT NULL REFERENCES core.repositories(id) ON DELETE CASCADE,
actor_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
event_type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_repo_events_repo_id
ON core.repo_events (repo_id, created_at DESC);
CREATE TABLE IF NOT EXISTS core.projects (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
owner_id UUID NOT NULL REFERENCES core.users(id) ON DELETE CASCADE,
number INTEGER NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (owner_id, number)
);
CREATE INDEX IF NOT EXISTS idx_core_projects_owner_created_at
ON core.projects (owner_id, created_at DESC);
CREATE TABLE IF NOT EXISTS core.project_views (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES core.projects(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
layout VARCHAR(32) NOT NULL
CHECK (layout IN ('TABLE', 'BOARD', 'ROADMAP')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_core_project_views_project_created_at
ON core.project_views (project_id, created_at);
CREATE TABLE IF NOT EXISTS core.project_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES core.projects(id) ON DELETE CASCADE,
content_type VARCHAR(32) NOT NULL
CHECK (content_type IN ('ISSUE', 'PULL_REQUEST')),
content_id UUID NOT NULL,
status VARCHAR(255) NOT NULL DEFAULT '',
start_date TIMESTAMPTZ,
target_date TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (project_id, content_type, content_id)
);
CREATE INDEX IF NOT EXISTS idx_core_project_items_project_created_at
ON core.project_items (project_id, created_at);
CREATE INDEX IF NOT EXISTS idx_core_project_items_content
ON core.project_items (content_type, content_id);