Merge ~andrey-fedoseev/launchpad:db-bug-task-channel into launchpad:db-devel
- Git
- lp:~andrey-fedoseev/launchpad
- db-bug-task-channel
- Merge into db-devel
Proposed by
Andrey Fedoseev
Status: | Needs review |
---|---|
Proposed branch: | ~andrey-fedoseev/launchpad:db-bug-task-channel |
Merge into: | launchpad:db-devel |
Diff against target: |
548 lines (+542/-0) 1 file modified
database/schema/patch-2211-14-0.sql (+542/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+434686@code.launchpad.net |
Commit message
Add `channel` field to `BugTask` and its derived tables/views
Description of the change
To post a comment you must log in.
Unmerged commits
- 52d9000... by Andrey Fedoseev
-
Add `channel` field to `BugTask` and its derived tables/views
-
docs:0 (build) lint:0 (build) mypy:0 (build) 1 → 3 of 3 results First • Previous • Next • Last
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/database/schema/patch-2211-14-0.sql b/database/schema/patch-2211-14-0.sql | |||
2 | 0 | new file mode 100644 | 0 | new file mode 100644 |
3 | index 0000000..719d4dd | |||
4 | --- /dev/null | |||
5 | +++ b/database/schema/patch-2211-14-0.sql | |||
6 | @@ -0,0 +1,542 @@ | |||
7 | 1 | -- Copyright 2022 Canonical Ltd. This software is licensed under the | ||
8 | 2 | -- GNU Affero General Public License version 3 (see the file LICENSE). | ||
9 | 3 | |||
10 | 4 | SET client_min_messages = ERROR; | ||
11 | 5 | |||
12 | 6 | ALTER TABLE BugTask | ||
13 | 7 | ADD COLUMN channel jsonb; | ||
14 | 8 | |||
15 | 9 | ALTER INDEX bugtask_distinct_sourcepackage_assignment | ||
16 | 10 | RENAME TO old__bugtask_distinct_sourcepackage_assignment; | ||
17 | 11 | |||
18 | 12 | ALTER TABLE BugTaskFlat | ||
19 | 13 | ADD COLUMN channel jsonb; | ||
20 | 14 | |||
21 | 15 | ALTER TABLE BugSummary | ||
22 | 16 | ADD COLUMN channel jsonb, | ||
23 | 17 | DROP CONSTRAINT bugtask_assignment_checks, | ||
24 | 18 | ADD CONSTRAINT bugtask_assignment_checks CHECK ( | ||
25 | 19 | CASE | ||
26 | 20 | WHEN product IS NOT NULL THEN | ||
27 | 21 | productseries IS NULL | ||
28 | 22 | AND distribution IS NULL | ||
29 | 23 | AND distroseries IS NULL | ||
30 | 24 | AND sourcepackagename IS NULL | ||
31 | 25 | WHEN productseries IS NOT NULL THEN | ||
32 | 26 | distribution IS NULL | ||
33 | 27 | AND distroseries IS NULL | ||
34 | 28 | AND sourcepackagename IS NULL | ||
35 | 29 | AND ociproject IS NULL | ||
36 | 30 | AND ociprojectseries IS NULL | ||
37 | 31 | WHEN distribution IS NOT NULL THEN | ||
38 | 32 | distroseries IS NULL | ||
39 | 33 | WHEN distroseries IS NOT NULL THEN | ||
40 | 34 | ociproject IS NULL | ||
41 | 35 | AND ociprojectseries IS NULL | ||
42 | 36 | WHEN ociproject IS NOT NULL THEN | ||
43 | 37 | ociprojectseries IS NULL | ||
44 | 38 | AND (distribution IS NOT NULL OR product IS NOT NULL) | ||
45 | 39 | AND sourcepackagename IS NULL | ||
46 | 40 | WHEN ociprojectseries IS NOT NULL THEN | ||
47 | 41 | ociproject IS NULL | ||
48 | 42 | AND (distribution IS NOT NULL OR product IS NOT NULL) | ||
49 | 43 | AND sourcepackagename IS NULL | ||
50 | 44 | WHEN channel IS NOT NULL THEN | ||
51 | 45 | distroseries IS NOT NULL | ||
52 | 46 | AND sourcepackagename IS NOT NULL | ||
53 | 47 | ELSE false | ||
54 | 48 | END) NOT VALID; | ||
55 | 49 | |||
56 | 50 | ALTER INDEX bugsummary__unique | ||
57 | 51 | RENAME TO old__bugsummary__unique; | ||
58 | 52 | |||
59 | 53 | |||
60 | 54 | ALTER TABLE BugSummaryJournal ADD COLUMN channel jsonb; | ||
61 | 55 | |||
62 | 56 | ALTER INDEX bugsummaryjournal__full__idx | ||
63 | 57 | RENAME TO old__bugsummaryjournal__full__idx; | ||
64 | 58 | |||
65 | 59 | |||
66 | 60 | -- Functions | ||
67 | 61 | |||
68 | 62 | CREATE OR REPLACE FUNCTION bugtask_flatten(task_id integer, check_only boolean) | ||
69 | 63 | RETURNS boolean | ||
70 | 64 | SECURITY DEFINER | ||
71 | 65 | SET search_path = public | ||
72 | 66 | LANGUAGE plpgsql | ||
73 | 67 | AS $$ | ||
74 | 68 | DECLARE | ||
75 | 69 | bug_row Bug%ROWTYPE; | ||
76 | 70 | task_row BugTask%ROWTYPE; | ||
77 | 71 | old_flat_row BugTaskFlat%ROWTYPE; | ||
78 | 72 | new_flat_row BugTaskFlat%ROWTYPE; | ||
79 | 73 | _product_active boolean; | ||
80 | 74 | _access_policies integer[]; | ||
81 | 75 | _access_grants integer[]; | ||
82 | 76 | BEGIN | ||
83 | 77 | -- This is the master function to update BugTaskFlat, but there are | ||
84 | 78 | -- maintenance triggers and jobs on the involved tables that update | ||
85 | 79 | -- it directly. Any changes here probably require a corresponding | ||
86 | 80 | -- change in other trigger functions. | ||
87 | 81 | |||
88 | 82 | SELECT * INTO task_row FROM BugTask WHERE id = task_id; | ||
89 | 83 | SELECT * INTO old_flat_row FROM BugTaskFlat WHERE bugtask = task_id; | ||
90 | 84 | |||
91 | 85 | -- If the task doesn't exist, ensure that there's no flat row. | ||
92 | 86 | IF task_row.id IS NULL THEN | ||
93 | 87 | IF old_flat_row.bugtask IS NOT NULL THEN | ||
94 | 88 | IF NOT check_only THEN | ||
95 | 89 | DELETE FROM BugTaskFlat WHERE bugtask = task_id; | ||
96 | 90 | END IF; | ||
97 | 91 | RETURN FALSE; | ||
98 | 92 | ELSE | ||
99 | 93 | RETURN TRUE; | ||
100 | 94 | END IF; | ||
101 | 95 | END IF; | ||
102 | 96 | |||
103 | 97 | SELECT * INTO bug_row FROM bug WHERE id = task_row.bug; | ||
104 | 98 | |||
105 | 99 | -- If it's a product(series) task, we must consult the active flag. | ||
106 | 100 | IF task_row.product IS NOT NULL THEN | ||
107 | 101 | SELECT product.active INTO _product_active | ||
108 | 102 | FROM product WHERE product.id = task_row.product LIMIT 1; | ||
109 | 103 | ELSIF task_row.productseries IS NOT NULL THEN | ||
110 | 104 | SELECT product.active INTO _product_active | ||
111 | 105 | FROM | ||
112 | 106 | product | ||
113 | 107 | JOIN productseries ON productseries.product = product.id | ||
114 | 108 | WHERE productseries.id = task_row.productseries LIMIT 1; | ||
115 | 109 | END IF; | ||
116 | 110 | |||
117 | 111 | SELECT policies, grants | ||
118 | 112 | INTO _access_policies, _access_grants | ||
119 | 113 | FROM bug_build_access_cache(bug_row.id, bug_row.information_type) | ||
120 | 114 | AS (policies integer[], grants integer[]); | ||
121 | 115 | |||
122 | 116 | -- Compile the new flat row. | ||
123 | 117 | SELECT task_row.id, bug_row.id, task_row.datecreated, | ||
124 | 118 | bug_row.duplicateof, bug_row.owner, bug_row.fti, | ||
125 | 119 | bug_row.information_type, bug_row.date_last_updated, | ||
126 | 120 | bug_row.heat, task_row.product, task_row.productseries, | ||
127 | 121 | task_row.distribution, task_row.distroseries, | ||
128 | 122 | task_row.sourcepackagename, task_row.status, | ||
129 | 123 | task_row.importance, task_row.assignee, | ||
130 | 124 | task_row.milestone, task_row.owner, | ||
131 | 125 | COALESCE(_product_active, TRUE), | ||
132 | 126 | _access_policies, | ||
133 | 127 | _access_grants, | ||
134 | 128 | bug_row.latest_patch_uploaded, task_row.date_closed, | ||
135 | 129 | task_row.ociproject, task_row.ociprojectseries, | ||
136 | 130 | task_row.channel | ||
137 | 131 | INTO new_flat_row; | ||
138 | 132 | |||
139 | 133 | -- Calculate the necessary updates. | ||
140 | 134 | IF old_flat_row.bugtask IS NULL THEN | ||
141 | 135 | IF NOT check_only THEN | ||
142 | 136 | INSERT INTO BugTaskFlat VALUES (new_flat_row.*); | ||
143 | 137 | END IF; | ||
144 | 138 | RETURN FALSE; | ||
145 | 139 | ELSIF new_flat_row != old_flat_row THEN | ||
146 | 140 | IF NOT check_only THEN | ||
147 | 141 | UPDATE BugTaskFlat SET | ||
148 | 142 | bug = new_flat_row.bug, | ||
149 | 143 | datecreated = new_flat_row.datecreated, | ||
150 | 144 | duplicateof = new_flat_row.duplicateof, | ||
151 | 145 | bug_owner = new_flat_row.bug_owner, | ||
152 | 146 | fti = new_flat_row.fti, | ||
153 | 147 | information_type = new_flat_row.information_type, | ||
154 | 148 | date_last_updated = new_flat_row.date_last_updated, | ||
155 | 149 | heat = new_flat_row.heat, | ||
156 | 150 | product = new_flat_row.product, | ||
157 | 151 | productseries = new_flat_row.productseries, | ||
158 | 152 | distribution = new_flat_row.distribution, | ||
159 | 153 | distroseries = new_flat_row.distroseries, | ||
160 | 154 | sourcepackagename = new_flat_row.sourcepackagename, | ||
161 | 155 | status = new_flat_row.status, | ||
162 | 156 | importance = new_flat_row.importance, | ||
163 | 157 | assignee = new_flat_row.assignee, | ||
164 | 158 | milestone = new_flat_row.milestone, | ||
165 | 159 | owner = new_flat_row.owner, | ||
166 | 160 | active = new_flat_row.active, | ||
167 | 161 | access_policies = new_flat_row.access_policies, | ||
168 | 162 | access_grants = new_flat_row.access_grants, | ||
169 | 163 | date_closed = new_flat_row.date_closed, | ||
170 | 164 | latest_patch_uploaded = new_flat_row.latest_patch_uploaded, | ||
171 | 165 | ociproject = new_flat_row.ociproject, | ||
172 | 166 | ociprojectseries = new_flat_row.ociprojectseries, | ||
173 | 167 | channel = new_flat_row.channel | ||
174 | 168 | WHERE bugtask = new_flat_row.bugtask; | ||
175 | 169 | END IF; | ||
176 | 170 | RETURN FALSE; | ||
177 | 171 | ELSE | ||
178 | 172 | RETURN TRUE; | ||
179 | 173 | END IF; | ||
180 | 174 | END; | ||
181 | 175 | $$; | ||
182 | 176 | |||
183 | 177 | CREATE OR REPLACE FUNCTION bug_summary_inc(d bugsummary) | ||
184 | 178 | RETURNS VOID | ||
185 | 179 | LANGUAGE plpgsql | ||
186 | 180 | AS $$ | ||
187 | 181 | BEGIN | ||
188 | 182 | -- Shameless adaption from postgresql manual | ||
189 | 183 | LOOP | ||
190 | 184 | -- first try to update the row | ||
191 | 185 | UPDATE BugSummary SET count = count + d.count | ||
192 | 186 | WHERE | ||
193 | 187 | product IS NOT DISTINCT FROM $1.product | ||
194 | 188 | AND productseries IS NOT DISTINCT FROM $1.productseries | ||
195 | 189 | AND distribution IS NOT DISTINCT FROM $1.distribution | ||
196 | 190 | AND distroseries IS NOT DISTINCT FROM $1.distroseries | ||
197 | 191 | AND sourcepackagename IS NOT DISTINCT FROM $1.sourcepackagename | ||
198 | 192 | AND ociproject IS NOT DISTINCT FROM $1.ociproject | ||
199 | 193 | AND ociprojectseries IS NOT DISTINCT FROM $1.ociprojectseries | ||
200 | 194 | AND channel IS NOT DISTINCT FROM $1.channel | ||
201 | 195 | AND viewed_by IS NOT DISTINCT FROM $1.viewed_by | ||
202 | 196 | AND tag IS NOT DISTINCT FROM $1.tag | ||
203 | 197 | AND status = $1.status | ||
204 | 198 | AND ((milestone IS NULL AND $1.milestone IS NULL) | ||
205 | 199 | OR milestone = $1.milestone) | ||
206 | 200 | AND importance = $1.importance | ||
207 | 201 | AND has_patch = $1.has_patch | ||
208 | 202 | AND access_policy IS NOT DISTINCT FROM $1.access_policy; | ||
209 | 203 | IF found THEN | ||
210 | 204 | RETURN; | ||
211 | 205 | END IF; | ||
212 | 206 | -- not there, so try to insert the key | ||
213 | 207 | -- if someone else inserts the same key concurrently, | ||
214 | 208 | -- we could get a unique-key failure | ||
215 | 209 | BEGIN | ||
216 | 210 | INSERT INTO BugSummary( | ||
217 | 211 | count, product, productseries, distribution, | ||
218 | 212 | distroseries, sourcepackagename, | ||
219 | 213 | ociproject, ociprojectseries, channel, | ||
220 | 214 | viewed_by, tag, | ||
221 | 215 | status, milestone, importance, has_patch, access_policy) | ||
222 | 216 | VALUES ( | ||
223 | 217 | d.count, d.product, d.productseries, d.distribution, | ||
224 | 218 | d.distroseries, d.sourcepackagename, | ||
225 | 219 | d.ociproject, d.ociprojectseries, d.channel, | ||
226 | 220 | d.viewed_by, d.tag, | ||
227 | 221 | d.status, d.milestone, d.importance, d.has_patch, | ||
228 | 222 | d.access_policy); | ||
229 | 223 | RETURN; | ||
230 | 224 | EXCEPTION WHEN unique_violation THEN | ||
231 | 225 | -- do nothing, and loop to try the UPDATE again | ||
232 | 226 | END; | ||
233 | 227 | END LOOP; | ||
234 | 228 | END; | ||
235 | 229 | $$; | ||
236 | 230 | |||
237 | 231 | CREATE OR REPLACE FUNCTION bug_summary_dec(bugsummary) | ||
238 | 232 | RETURNS VOID | ||
239 | 233 | LANGUAGE sql | ||
240 | 234 | AS $$ | ||
241 | 235 | -- We own the row reference, so in the absence of bugs this cannot | ||
242 | 236 | -- fail - just decrement the row. | ||
243 | 237 | UPDATE BugSummary SET count = count + $1.count | ||
244 | 238 | WHERE | ||
245 | 239 | ((product IS NULL AND $1.product IS NULL) | ||
246 | 240 | OR product = $1.product) | ||
247 | 241 | AND ((productseries IS NULL AND $1.productseries IS NULL) | ||
248 | 242 | OR productseries = $1.productseries) | ||
249 | 243 | AND ((distribution IS NULL AND $1.distribution IS NULL) | ||
250 | 244 | OR distribution = $1.distribution) | ||
251 | 245 | AND ((distroseries IS NULL AND $1.distroseries IS NULL) | ||
252 | 246 | OR distroseries = $1.distroseries) | ||
253 | 247 | AND ((sourcepackagename IS NULL AND $1.sourcepackagename IS NULL) | ||
254 | 248 | OR sourcepackagename = $1.sourcepackagename) | ||
255 | 249 | AND ((ociproject IS NULL AND $1.ociproject IS NULL) | ||
256 | 250 | OR ociproject = $1.ociproject) | ||
257 | 251 | AND ((ociprojectseries IS NULL AND $1.ociprojectseries IS NULL) | ||
258 | 252 | OR ociprojectseries = $1.ociprojectseries) | ||
259 | 253 | AND ((channel IS NULL AND $1.channel IS NULL) | ||
260 | 254 | OR channel = $1.channel) | ||
261 | 255 | AND ((viewed_by IS NULL AND $1.viewed_by IS NULL) | ||
262 | 256 | OR viewed_by = $1.viewed_by) | ||
263 | 257 | AND ((tag IS NULL AND $1.tag IS NULL) | ||
264 | 258 | OR tag = $1.tag) | ||
265 | 259 | AND status = $1.status | ||
266 | 260 | AND ((milestone IS NULL AND $1.milestone IS NULL) | ||
267 | 261 | OR milestone = $1.milestone) | ||
268 | 262 | AND importance = $1.importance | ||
269 | 263 | AND has_patch = $1.has_patch | ||
270 | 264 | AND access_policy IS NOT DISTINCT FROM $1.access_policy; | ||
271 | 265 | $$; | ||
272 | 266 | |||
273 | 267 | CREATE OR REPLACE FUNCTION bugsummary_rollup_journal(batchsize integer DEFAULT NULL::integer) | ||
274 | 268 | RETURNS VOID | ||
275 | 269 | SECURITY DEFINER | ||
276 | 270 | SET search_path = public | ||
277 | 271 | LANGUAGE plpgsql | ||
278 | 272 | AS $$ | ||
279 | 273 | DECLARE | ||
280 | 274 | d bugsummary%ROWTYPE; | ||
281 | 275 | max_id integer; | ||
282 | 276 | BEGIN | ||
283 | 277 | -- Lock so we don't content with other invocations of this | ||
284 | 278 | -- function. We can happily lock the BugSummary table for writes | ||
285 | 279 | -- as this function is the only thing that updates that table. | ||
286 | 280 | -- BugSummaryJournal remains unlocked so nothing should be blocked. | ||
287 | 281 | LOCK TABLE BugSummary IN ROW EXCLUSIVE MODE; | ||
288 | 282 | |||
289 | 283 | IF batchsize IS NULL THEN | ||
290 | 284 | SELECT MAX(id) INTO max_id FROM BugSummaryJournal; | ||
291 | 285 | ELSE | ||
292 | 286 | SELECT MAX(id) INTO max_id FROM ( | ||
293 | 287 | SELECT id FROM BugSummaryJournal ORDER BY id LIMIT batchsize | ||
294 | 288 | ) AS Whatever; | ||
295 | 289 | END IF; | ||
296 | 290 | |||
297 | 291 | FOR d IN | ||
298 | 292 | SELECT | ||
299 | 293 | NULL as id, | ||
300 | 294 | SUM(count), | ||
301 | 295 | product, | ||
302 | 296 | productseries, | ||
303 | 297 | distribution, | ||
304 | 298 | distroseries, | ||
305 | 299 | sourcepackagename, | ||
306 | 300 | viewed_by, | ||
307 | 301 | tag, | ||
308 | 302 | status, | ||
309 | 303 | milestone, | ||
310 | 304 | importance, | ||
311 | 305 | has_patch, | ||
312 | 306 | access_policy, | ||
313 | 307 | ociproject, | ||
314 | 308 | ociprojectseries, | ||
315 | 309 | channel | ||
316 | 310 | FROM BugSummaryJournal | ||
317 | 311 | WHERE id <= max_id | ||
318 | 312 | GROUP BY | ||
319 | 313 | product, productseries, distribution, distroseries, | ||
320 | 314 | sourcepackagename, ociproject, ociprojectseries, channel, | ||
321 | 315 | viewed_by, tag, status, milestone, | ||
322 | 316 | importance, has_patch, access_policy | ||
323 | 317 | HAVING sum(count) <> 0 | ||
324 | 318 | LOOP | ||
325 | 319 | IF d.count < 0 THEN | ||
326 | 320 | PERFORM bug_summary_dec(d); | ||
327 | 321 | ELSIF d.count > 0 THEN | ||
328 | 322 | PERFORM bug_summary_inc(d); | ||
329 | 323 | END IF; | ||
330 | 324 | END LOOP; | ||
331 | 325 | |||
332 | 326 | -- Clean out any counts we reduced to 0. | ||
333 | 327 | DELETE FROM BugSummary WHERE count=0; | ||
334 | 328 | -- Clean out the journal entries we have handled. | ||
335 | 329 | DELETE FROM BugSummaryJournal WHERE id <= max_id; | ||
336 | 330 | END; | ||
337 | 331 | $$; | ||
338 | 332 | |||
339 | 333 | CREATE OR REPLACE FUNCTION bugtask_maintain_bugtaskflat_trig() | ||
340 | 334 | RETURNS TRIGGER | ||
341 | 335 | SECURITY DEFINER | ||
342 | 336 | SET search_path = public | ||
343 | 337 | LANGUAGE plpgsql | ||
344 | 338 | AS $$ | ||
345 | 339 | BEGIN | ||
346 | 340 | IF TG_OP = 'INSERT' THEN | ||
347 | 341 | PERFORM bugtask_flatten(NEW.id, FALSE); | ||
348 | 342 | ELSIF TG_OP = 'UPDATE' THEN | ||
349 | 343 | IF NEW.bug != OLD.bug THEN | ||
350 | 344 | RAISE EXCEPTION 'cannot move bugtask to a different bug'; | ||
351 | 345 | ELSIF (NEW.product IS DISTINCT FROM OLD.product | ||
352 | 346 | OR NEW.productseries IS DISTINCT FROM OLD.productseries) THEN | ||
353 | 347 | -- product.active may differ. Do a full update. | ||
354 | 348 | PERFORM bugtask_flatten(NEW.id, FALSE); | ||
355 | 349 | ELSIF ( | ||
356 | 350 | NEW.datecreated IS DISTINCT FROM OLD.datecreated | ||
357 | 351 | OR NEW.product IS DISTINCT FROM OLD.product | ||
358 | 352 | OR NEW.productseries IS DISTINCT FROM OLD.productseries | ||
359 | 353 | OR NEW.distribution IS DISTINCT FROM OLD.distribution | ||
360 | 354 | OR NEW.distroseries IS DISTINCT FROM OLD.distroseries | ||
361 | 355 | OR NEW.sourcepackagename IS DISTINCT FROM OLD.sourcepackagename | ||
362 | 356 | OR NEW.ociproject IS DISTINCT FROM OLD.ociproject | ||
363 | 357 | OR NEW.ociprojectseries IS DISTINCT FROM OLD.ociprojectseries | ||
364 | 358 | OR NEW.channel IS DISTINCT FROM OLD.channel | ||
365 | 359 | OR NEW.status IS DISTINCT FROM OLD.status | ||
366 | 360 | OR NEW.importance IS DISTINCT FROM OLD.importance | ||
367 | 361 | OR NEW.assignee IS DISTINCT FROM OLD.assignee | ||
368 | 362 | OR NEW.milestone IS DISTINCT FROM OLD.milestone | ||
369 | 363 | OR NEW.owner IS DISTINCT FROM OLD.owner | ||
370 | 364 | OR NEW.date_closed IS DISTINCT FROM OLD.date_closed) THEN | ||
371 | 365 | -- Otherwise just update the columns from bugtask. | ||
372 | 366 | -- Access policies and grants may have changed due to target | ||
373 | 367 | -- transitions, but an earlier trigger will already have | ||
374 | 368 | -- mirrored them to all relevant flat tasks. | ||
375 | 369 | UPDATE BugTaskFlat SET | ||
376 | 370 | datecreated = NEW.datecreated, | ||
377 | 371 | product = NEW.product, | ||
378 | 372 | productseries = NEW.productseries, | ||
379 | 373 | distribution = NEW.distribution, | ||
380 | 374 | distroseries = NEW.distroseries, | ||
381 | 375 | sourcepackagename = NEW.sourcepackagename, | ||
382 | 376 | ociproject = NEW.ociproject, | ||
383 | 377 | ociprojectseries = NEW.ociprojectseries, | ||
384 | 378 | channel = NEW.channel, | ||
385 | 379 | status = NEW.status, | ||
386 | 380 | importance = NEW.importance, | ||
387 | 381 | assignee = NEW.assignee, | ||
388 | 382 | milestone = NEW.milestone, | ||
389 | 383 | owner = NEW.owner, | ||
390 | 384 | date_closed = NEW.date_closed | ||
391 | 385 | WHERE bugtask = NEW.id; | ||
392 | 386 | END IF; | ||
393 | 387 | ELSIF TG_OP = 'DELETE' THEN | ||
394 | 388 | PERFORM bugtask_flatten(OLD.id, FALSE); | ||
395 | 389 | END IF; | ||
396 | 390 | RETURN NULL; | ||
397 | 391 | END; | ||
398 | 392 | $$; | ||
399 | 393 | |||
400 | 394 | DROP FUNCTION bugsummary_targets; | ||
401 | 395 | CREATE FUNCTION bugsummary_targets(btf_row bugtaskflat) | ||
402 | 396 | RETURNS TABLE( | ||
403 | 397 | product integer, | ||
404 | 398 | productseries integer, | ||
405 | 399 | distribution integer, | ||
406 | 400 | distroseries integer, | ||
407 | 401 | sourcepackagename integer, | ||
408 | 402 | ociproject integer, | ||
409 | 403 | ociprojectseries integer, | ||
410 | 404 | channel jsonb | ||
411 | 405 | ) | ||
412 | 406 | IMMUTABLE | ||
413 | 407 | LANGUAGE sql | ||
414 | 408 | AS $$ | ||
415 | 409 | -- Include a sourcepackagename-free/ociproject(series)-free task if this | ||
416 | 410 | -- one has a sourcepackagename/ociproject(series), so package tasks are | ||
417 | 411 | -- also counted in their distro/series. | ||
418 | 412 | SELECT | ||
419 | 413 | $1.product, $1.productseries, $1.distribution, | ||
420 | 414 | $1.distroseries, $1.sourcepackagename, | ||
421 | 415 | $1.ociproject, $1.ociprojectseries, $1.channel | ||
422 | 416 | UNION -- Implicit DISTINCT | ||
423 | 417 | SELECT | ||
424 | 418 | $1.product, $1.productseries, $1.distribution, | ||
425 | 419 | $1.distroseries, NULL, NULL, NULL, NULL; | ||
426 | 420 | $$; | ||
427 | 421 | |||
428 | 422 | CREATE OR REPLACE FUNCTION bugsummary_locations(btf_row bugtaskflat, tags text[]) | ||
429 | 423 | RETURNS SETOF bugsummaryjournal | ||
430 | 424 | LANGUAGE plpgsql | ||
431 | 425 | AS $$ | ||
432 | 426 | BEGIN | ||
433 | 427 | IF btf_row.duplicateof IS NOT NULL THEN | ||
434 | 428 | RETURN; | ||
435 | 429 | END IF; | ||
436 | 430 | RETURN QUERY | ||
437 | 431 | SELECT | ||
438 | 432 | CAST(NULL AS integer) AS id, | ||
439 | 433 | CAST(1 AS integer) AS count, | ||
440 | 434 | bug_targets.product, bug_targets.productseries, | ||
441 | 435 | bug_targets.distribution, bug_targets.distroseries, | ||
442 | 436 | bug_targets.sourcepackagename, | ||
443 | 437 | bug_viewers.viewed_by, bug_tags.tag, btf_row.status, | ||
444 | 438 | btf_row.milestone, btf_row.importance, | ||
445 | 439 | btf_row.latest_patch_uploaded IS NOT NULL AS has_patch, | ||
446 | 440 | bug_viewers.access_policy, | ||
447 | 441 | bug_targets.ociproject, bug_targets.ociprojectseries, | ||
448 | 442 | bug_targets.channel | ||
449 | 443 | FROM | ||
450 | 444 | bugsummary_targets(btf_row) AS bug_targets, | ||
451 | 445 | unnest(tags) AS bug_tags (tag), | ||
452 | 446 | bugsummary_viewers(btf_row) AS bug_viewers; | ||
453 | 447 | END; | ||
454 | 448 | $$; | ||
455 | 449 | |||
456 | 450 | CREATE OR REPLACE FUNCTION bugsummary_insert_journals(journals bugsummaryjournal[]) | ||
457 | 451 | RETURNS VOID | ||
458 | 452 | LANGUAGE sql | ||
459 | 453 | AS $$ | ||
460 | 454 | -- We sum the rows here to minimise the number of inserts into the | ||
461 | 455 | -- journal, as in the case of UPDATE statement we may have -1s and +1s | ||
462 | 456 | -- cancelling each other out. | ||
463 | 457 | INSERT INTO BugSummaryJournal( | ||
464 | 458 | count, product, productseries, distribution, distroseries, | ||
465 | 459 | sourcepackagename, ociproject, ociprojectseries, channel, | ||
466 | 460 | viewed_by, tag, status, milestone, importance, has_patch, | ||
467 | 461 | access_policy) | ||
468 | 462 | SELECT | ||
469 | 463 | SUM(count), product, productseries, distribution, distroseries, | ||
470 | 464 | sourcepackagename, ociproject, ociprojectseries, channel, | ||
471 | 465 | viewed_by, tag, status, milestone, importance, has_patch, | ||
472 | 466 | access_policy | ||
473 | 467 | FROM unnest(journals) | ||
474 | 468 | GROUP BY | ||
475 | 469 | product, productseries, distribution, distroseries, | ||
476 | 470 | sourcepackagename, ociproject, ociprojectseries, channel, | ||
477 | 471 | viewed_by, tag, status, milestone, importance, has_patch, | ||
478 | 472 | access_policy | ||
479 | 473 | HAVING SUM(count) != 0; | ||
480 | 474 | $$; | ||
481 | 475 | |||
482 | 476 | -- Views | ||
483 | 477 | |||
484 | 478 | -- Combined view so we don't have to manually collate rows from both tables. | ||
485 | 479 | -- Note that we flip the sign of the id column of BugSummaryJournal to avoid | ||
486 | 480 | -- clashes. This is enough to keep Storm happy as it never needs to update | ||
487 | 481 | -- this table, and there are no other suitable primary keys. | ||
488 | 482 | -- We don't SUM() rows here to ensure PostgreSQL has the most hope of | ||
489 | 483 | -- generating good query plans when we query this view. | ||
490 | 484 | CREATE OR REPLACE VIEW CombinedBugSummary ( | ||
491 | 485 | id, | ||
492 | 486 | count, | ||
493 | 487 | product, | ||
494 | 488 | productseries, | ||
495 | 489 | distribution, | ||
496 | 490 | distroseries, | ||
497 | 491 | sourcepackagename, | ||
498 | 492 | viewed_by, | ||
499 | 493 | tag, | ||
500 | 494 | status, | ||
501 | 495 | milestone, | ||
502 | 496 | importance, | ||
503 | 497 | has_patch, | ||
504 | 498 | access_policy, | ||
505 | 499 | ociproject, | ||
506 | 500 | ociprojectseries, | ||
507 | 501 | channel | ||
508 | 502 | ) | ||
509 | 503 | AS | ||
510 | 504 | SELECT id, | ||
511 | 505 | count, | ||
512 | 506 | product, | ||
513 | 507 | productseries, | ||
514 | 508 | distribution, | ||
515 | 509 | distroseries, | ||
516 | 510 | sourcepackagename, | ||
517 | 511 | viewed_by, | ||
518 | 512 | tag, | ||
519 | 513 | status, | ||
520 | 514 | milestone, | ||
521 | 515 | importance, | ||
522 | 516 | has_patch, | ||
523 | 517 | access_policy, | ||
524 | 518 | ociproject, | ||
525 | 519 | ociprojectseries, | ||
526 | 520 | channel | ||
527 | 521 | FROM bugsummary | ||
528 | 522 | UNION ALL | ||
529 | 523 | SELECT -id AS id, | ||
530 | 524 | count, | ||
531 | 525 | product, | ||
532 | 526 | productseries, | ||
533 | 527 | distribution, | ||
534 | 528 | distroseries, | ||
535 | 529 | sourcepackagename, | ||
536 | 530 | viewed_by, | ||
537 | 531 | tag, | ||
538 | 532 | status, | ||
539 | 533 | milestone, | ||
540 | 534 | importance, | ||
541 | 535 | has_patch, | ||
542 | 536 | access_policy, | ||
543 | 537 | ociproject, | ||
544 | 538 | ociprojectseries, | ||
545 | 539 | channel | ||
546 | 540 | FROM bugsummaryjournal; | ||
547 | 541 | |||
548 | 542 | INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 14, 0); |