~launchpad-pqm/launchpad/devel

7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
1
-- Copyright 2011 Canonical Ltd.  This software is licensed under the
2
-- GNU Affero General Public License version 3 (see the file LICENSE).
3
4
SET client_min_messages=ERROR;
5
6
-- Trash our existing data, which we will rebuild in a minute.
7
-- Slony-I doesn't like TRUNCATE noramlly, but OK in a DB patch.
8
TRUNCATE BugSummary;
9
TRUNCATE BugSummaryJournal;
10
11
-- Drop indexes we will rebuild later.
12
DROP INDEX bugsummary__dimensions__unique;
13
DROP INDEX bugsummary__full__idx;
14
15
ALTER TABLE BugSummary
16
    -- Add a missing foreign key constraint we were unable to add live.
17
    -- Person table is always being read, so locks are never acquired.
18
    ADD CONSTRAINT bugsummaryjournal_viewed_by_fkey
19
        FOREIGN KEY(viewed_by) REFERENCES Person ON DELETE CASCADE,
20
    ADD COLUMN importance integer NOT NULL,
21
    ADD COLUMN has_patch boolean NOT NULL,
22
    ADD COLUMN fixed_upstream boolean NOT NULL;
23
24
ALTER TABLE BugSummaryJournal
25
    ADD COLUMN importance integer NOT NULL,
26
    ADD COLUMN has_patch boolean NOT NULL,
27
    ADD COLUMN fixed_upstream boolean NOT NULL;
28
29
DROP VIEW CombinedBugSummary;
30
CREATE VIEW CombinedBugSummary AS (
31
    SELECT
32
        id, count, product, productseries, distribution, distroseries,
33
        sourcepackagename, viewed_by, tag, status, milestone,
34
        importance, has_patch, fixed_upstream
35
    FROM BugSummary
36
    UNION ALL
37
    SELECT
38
        -id as id, count, product, productseries, distribution, distroseries,
39
        sourcepackagename, viewed_by, tag, status, milestone,
40
        importance, has_patch, fixed_upstream
41
    FROM BugSummaryJournal);
42
43
44
-- Rebuild the BugSummary data with the new columns.
7675.1202.20 by Stuart Bishop
Replace slow data migration query
45
INSERT INTO BugSummary (
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
46
    count, product, productseries, distribution, distroseries,
7675.1202.20 by Stuart Bishop
Replace slow data migration query
47
    sourcepackagename, viewed_by, tag, status, importance, has_patch,
48
    fixed_upstream, milestone)
49
WITH
50
    -- kill dupes
51
    relevant_bug AS (SELECT * FROM bug where duplicateof is NULL),
52
53
    -- (bug.id, tag) for all bug-tag pairs plus (bug.id, NULL) for all bugs
54
    bug_tags AS (
55
        SELECT relevant_bug.id, NULL::text AS tag FROM relevant_bug
56
        UNION
57
        SELECT relevant_bug.id, tag
58
        FROM relevant_bug INNER JOIN bugtag ON relevant_bug.id=bugtag.bug),
59
60
    -- (bug.id, NULL) for all public bugs + (bug.id, viewer) for all
61
    -- (subscribers+assignee) on private bugs
62
    bug_viewers AS (
63
        SELECT relevant_bug.id, NULL::integer AS person
64
        FROM relevant_bug WHERE NOT relevant_bug.private
65
        UNION
66
        SELECT relevant_bug.id, assignee AS person
67
        FROM relevant_bug
68
        INNER JOIN bugtask ON relevant_bug.id=bugtask.bug
69
        WHERE relevant_bug.private and bugtask.assignee IS NOT NULL
70
        UNION
71
        SELECT relevant_bug.id, bugsubscription.person
72
        FROM relevant_bug INNER JOIN bugsubscription
73
            ON bugsubscription.bug=relevant_bug.id WHERE relevant_bug.private),
74
75
    -- (bugtask.(bug, product, productseries, distribution, distroseries,
76
    -- sourcepackagename, status, milestone) for all bugs + the same with
77
    -- sourcepackage squashed to NULL)
78
    tasks AS (
79
        SELECT
80
            bug, product, productseries, distribution, distroseries,
81
            sourcepackagename, status, importance,
82
            (EXISTS
83
                (SELECT TRUE
84
                FROM BugTask AS RelatedBugTask
85
                WHERE RelatedBugTask.bug = BugTask.bug
86
                AND RelatedBugTask.id != BugTask.id
87
                AND ((RelatedBugTask.bugwatch IS NOT NULL
88
                        AND RelatedBugTask.status IN (17, 25, 30))
89
                        OR (RelatedBugTask.product IS NOT NULL
90
                            AND RelatedBugTask.bugwatch IS NULL
91
                            AND RelatedBugTask.status IN (25, 30))))
92
                ) as fixed_upstream, milestone
93
        FROM bugtask
94
        UNION
95
        SELECT DISTINCT ON (
96
            bug, product, productseries, distribution, distroseries,
97
            sourcepackagename, milestone)
98
            bug, product, productseries, distribution, distroseries,
99
            NULL::integer as sourcepackagename,
100
            status, importance,
101
            (EXISTS
102
                (SELECT TRUE
103
                FROM BugTask AS RelatedBugTask
104
                WHERE RelatedBugTask.bug = BugTask.bug
105
                AND RelatedBugTask.id != BugTask.id
106
                AND ((RelatedBugTask.bugwatch IS NOT NULL
107
                        AND RelatedBugTask.status IN (17, 25, 30))
108
                        OR (RelatedBugTask.product IS NOT NULL
109
                            AND RelatedBugTask.bugwatch IS NULL
110
                            AND RelatedBugTask.status IN (25, 30))))
111
                ) as fixed_upstream, milestone
112
        FROM bugtask where sourcepackagename IS NOT NULL)
113
114
    -- Now combine
115
    SELECT
116
        count(*), product, productseries, distribution, distroseries,
117
        sourcepackagename, person, tag, status, importance,
118
        latest_patch_uploaded IS NOT NULL AS has_patch, fixed_upstream,
119
        milestone
120
    FROM relevant_bug
121
    INNER JOIN bug_tags ON relevant_bug.id=bug_tags.id
122
    INNER JOIN bug_viewers ON relevant_bug.id=bug_viewers.id
123
    INNER JOIN tasks on tasks.bug=relevant_bug.id
124
    GROUP BY
125
        product, productseries, distribution, distroseries,
126
        sourcepackagename, person, tag, status, importance, has_patch,
127
        fixed_upstream, milestone;
128
129
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
130
-- Rebuild indexes.
131
CREATE INDEX bugsummary__full__idx ON BugSummary (
132
    tag, status, product, productseries, distribution,
133
    distroseries, sourcepackagename, viewed_by, milestone,
134
    importance, has_patch, fixed_upstream);
135
-- Enforce uniqueness again.
136
CREATE UNIQUE INDEX bugsummary__product__unique
137
    ON BugSummary(
138
        product, status, importance, has_patch, fixed_upstream,
139
        COALESCE(tag, ''), COALESCE(milestone, -1), COALESCE(viewed_by, -1))
140
    WHERE product IS NOT NULL;
141
CREATE UNIQUE INDEX bugsummary__productseries__unique
142
    ON BugSummary(
143
        productseries, status, importance, has_patch, fixed_upstream,
144
        COALESCE(tag, ''), COALESCE(milestone, -1), COALESCE(viewed_by, -1))
145
    WHERE productseries IS NOT NULL;
146
CREATE UNIQUE INDEX bugsummary__distribution__unique
147
    ON BugSummary(
148
        distribution, status, importance, has_patch, fixed_upstream,
149
        COALESCE(sourcepackagename, -1),
150
        COALESCE(tag, ''), COALESCE(milestone, -1), COALESCE(viewed_by, -1))
151
    WHERE distribution IS NOT NULL;
152
CREATE UNIQUE INDEX bugsummary__distroseries__unique
153
    ON BugSummary(
154
        distroseries, status, importance, has_patch, fixed_upstream,
155
        COALESCE(sourcepackagename, -1),
156
        COALESCE(tag, ''), COALESCE(milestone, -1), COALESCE(viewed_by, -1))
157
    WHERE distroseries IS NOT NULL;
158
159
160
-- Rebuild relevant trigger functions.
161
CREATE OR REPLACE FUNCTION bugsummary_journal_ins(d bugsummary)
162
RETURNS VOID
163
LANGUAGE plpgsql AS
164
$$
165
BEGIN
166
    IF d.count <> 0 THEN
167
        INSERT INTO BugSummaryJournal (
168
            count, product, productseries, distribution,
169
            distroseries, sourcepackagename, viewed_by, tag,
170
            status, milestone,
171
            importance, has_patch, fixed_upstream)
172
        VALUES (
173
            d.count, d.product, d.productseries, d.distribution,
174
            d.distroseries, d.sourcepackagename, d.viewed_by, d.tag,
175
            d.status, d.milestone,
176
            d.importance, d.has_patch, d.fixed_upstream);
177
    END IF;
178
END;
179
$$;
180
181
COMMENT ON FUNCTION bugsummary_journal_ins(bugsummary) IS
182
'Add an entry into BugSummaryJournal';
183
184
185
CREATE OR REPLACE FUNCTION bugsummary_rollup_journal() RETURNS VOID
186
LANGUAGE plpgsql VOLATILE
187
SECURITY DEFINER SET search_path TO public AS
188
$$
189
DECLARE
190
    d bugsummary%ROWTYPE;
191
    max_id integer;
192
BEGIN
193
    -- Lock so we don't content with other invokations of this
194
    -- function. We can happily lock the BugSummary table for writes
195
    -- as this function is the only thing that updates that table.
196
    -- BugSummaryJournal remains unlocked so nothing should be blocked.
197
    LOCK TABLE BugSummary IN ROW EXCLUSIVE MODE;
198
199
    SELECT MAX(id) INTO max_id FROM BugSummaryJournal;
200
201
    FOR d IN
202
        SELECT
203
            NULL as id,
204
            SUM(count),
205
            product,
206
            productseries,
207
            distribution,
208
            distroseries,
209
            sourcepackagename,
210
            viewed_by,
211
            tag,
212
            status,
213
            milestone,
214
            importance,
215
            has_patch,
216
            fixed_upstream
217
        FROM BugSummaryJournal
218
        WHERE id <= max_id
219
        GROUP BY
220
            product, productseries, distribution, distroseries,
221
            sourcepackagename, viewed_by, tag, status, milestone,
7675.1202.9 by Stuart Bishop
Updates
222
            importance, has_patch, fixed_upstream
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
223
        HAVING sum(count) <> 0
224
    LOOP
225
        IF d.count < 0 THEN
226
            PERFORM bug_summary_dec(d);
227
        ELSIF d.count > 0 THEN
228
            PERFORM bug_summary_inc(d);
229
        END IF;
230
    END LOOP;
231
232
    DELETE FROM BugSummaryJournal WHERE id <= max_id;
233
END;
234
$$;
235
236
CREATE OR REPLACE FUNCTION bug_summary_dec(bugsummary) RETURNS VOID
237
LANGUAGE SQL AS
238
$$
239
    -- We own the row reference, so in the absence of bugs this cannot
240
    -- fail - just decrement the row.
241
    UPDATE BugSummary SET count = count + $1.count
242
    WHERE
243
        product IS NOT DISTINCT FROM $1.product
244
        AND productseries IS NOT DISTINCT FROM $1.productseries
245
        AND distribution IS NOT DISTINCT FROM $1.distribution
246
        AND distroseries IS NOT DISTINCT FROM $1.distroseries
247
        AND sourcepackagename IS NOT DISTINCT FROM $1.sourcepackagename
248
        AND viewed_by IS NOT DISTINCT FROM $1.viewed_by
249
        AND tag IS NOT DISTINCT FROM $1.tag
250
        AND status IS NOT DISTINCT FROM $1.status
251
        AND milestone IS NOT DISTINCT FROM $1.milestone
252
        AND importance IS NOT DISTINCT FROM $1.importance
253
        AND has_patch IS NOT DISTINCT FROM $1.has_patch
254
        AND fixed_upstream IS NOT DISTINCT FROM $1.fixed_upstream;
255
    -- gc the row (perhaps should be garbo but easy enough to add here:
256
    DELETE FROM bugsummary
257
    WHERE
258
        count=0
259
        AND product IS NOT DISTINCT FROM $1.product
260
        AND productseries IS NOT DISTINCT FROM $1.productseries
261
        AND distribution IS NOT DISTINCT FROM $1.distribution
262
        AND distroseries IS NOT DISTINCT FROM $1.distroseries
263
        AND sourcepackagename IS NOT DISTINCT FROM $1.sourcepackagename
264
        AND viewed_by IS NOT DISTINCT FROM $1.viewed_by
265
        AND tag IS NOT DISTINCT FROM $1.tag
266
        AND status IS NOT DISTINCT FROM $1.status
267
        AND milestone IS NOT DISTINCT FROM $1.milestone
268
        AND importance IS NOT DISTINCT FROM $1.importance
269
        AND has_patch IS NOT DISTINCT FROM $1.has_patch
270
        AND fixed_upstream IS NOT DISTINCT FROM $1.fixed_upstream;
271
    -- If its not found then someone else also dec'd and won concurrently.
272
$$;
273
274
CREATE OR REPLACE FUNCTION bug_summary_inc(d bugsummary) RETURNS VOID
275
LANGUAGE plpgsql AS
276
$$
277
BEGIN
278
    -- Shameless adaption from postgresql manual
279
    LOOP
280
        -- first try to update the row
281
        UPDATE BugSummary SET count = count + d.count
282
        WHERE
283
            product IS NOT DISTINCT FROM d.product
284
            AND productseries IS NOT DISTINCT FROM d.productseries
285
            AND distribution IS NOT DISTINCT FROM d.distribution
286
            AND distroseries IS NOT DISTINCT FROM d.distroseries
287
            AND sourcepackagename IS NOT DISTINCT FROM d.sourcepackagename
288
            AND viewed_by IS NOT DISTINCT FROM d.viewed_by
289
            AND tag IS NOT DISTINCT FROM d.tag
290
            AND status IS NOT DISTINCT FROM d.status
291
            AND milestone IS NOT DISTINCT FROM d.milestone
292
            AND importance IS NOT DISTINCT FROM d.importance
293
            AND has_patch IS NOT DISTINCT FROM d.has_patch
294
            AND fixed_upstream IS NOT DISTINCT FROM d.fixed_upstream;
295
        IF found THEN
296
            RETURN;
297
        END IF;
298
        -- not there, so try to insert the key
299
        -- if someone else inserts the same key concurrently,
300
        -- we could get a unique-key failure
301
        BEGIN
302
            INSERT INTO BugSummary(
303
                count, product, productseries, distribution,
304
                distroseries, sourcepackagename, viewed_by, tag,
305
                status, milestone,
306
                importance, has_patch, fixed_upstream)
307
            VALUES (
308
                d.count, d.product, d.productseries, d.distribution,
309
                d.distroseries, d.sourcepackagename, d.viewed_by, d.tag,
310
                d.status, d.milestone,
311
                d.importance, d.has_patch, d.fixed_upstream);
312
            RETURN;
313
        EXCEPTION WHEN unique_violation THEN
314
            -- do nothing, and loop to try the UPDATE again
315
        END;
316
    END LOOP;
317
END;
318
$$;
319
320
COMMENT ON FUNCTION bugsummary_rollup_journal() IS
321
'Collate and migrate rows from BugSummaryJournal to BugSummary';
322
323
324
CREATE OR REPLACE FUNCTION ensure_bugsummary_temp_journal() RETURNS VOID
325
LANGUAGE plpgsql VOLATILE AS
326
$$
327
DECLARE
328
BEGIN
329
    CREATE TEMPORARY TABLE bugsummary_temp_journal (
330
        LIKE bugsummary ) ON COMMIT DROP;
331
    ALTER TABLE bugsummary_temp_journal ALTER COLUMN id DROP NOT NULL;
332
EXCEPTION
333
    WHEN duplicate_table THEN
334
        NULL;
335
END;
336
$$;
337
338
COMMENT ON FUNCTION ensure_bugsummary_temp_journal() IS
339
'Create a temporary table bugsummary_temp_journal if it does not exist.';
340
341
342
CREATE OR REPLACE FUNCTION bug_summary_temp_journal_ins(d bugsummary)
343
RETURNS VOID LANGUAGE plpgsql AS
344
$$
345
BEGIN
346
    INSERT INTO BugSummary_Temp_Journal(
347
        count, product, productseries, distribution,
348
        distroseries, sourcepackagename, viewed_by, tag,
349
        status, milestone, importance, has_patch, fixed_upstream)
350
    VALUES (
351
        d.count, d.product, d.productseries, d.distribution,
352
        d.distroseries, d.sourcepackagename, d.viewed_by, d.tag,
353
        d.status, d.milestone, d.importance, d.has_patch, d.fixed_upstream);
354
    RETURN;
355
END;
356
$$;
357
358
COMMENT ON FUNCTION bug_summary_temp_journal_ins(bugsummary) IS
359
'Insert a BugSummary into the temporary journal';
360
361
362
-- Don't need these. Faster to just append rows to the journal
363
-- than attempt to update existing rows.
364
DROP FUNCTION bug_summary_temp_journal_dec(bugsummary);
365
DROP FUNCTION bug_summary_temp_journal_inc(bugsummary);
366
367
368
CREATE OR REPLACE FUNCTION bug_summary_flush_temp_journal() RETURNS VOID
369
LANGUAGE plpgsql VOLATILE AS
370
$$
371
DECLARE
372
    d bugsummary%ROWTYPE;
373
BEGIN
374
    -- may get called even though no summaries were made (for simplicity in the
375
    -- callers)
376
    PERFORM ensure_bugsummary_temp_journal();
377
    FOR d IN 
378
        SELECT
7675.1202.9 by Stuart Bishop
Updates
379
            NULL::integer AS id, SUM(count), product, productseries,
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
380
            distribution, distroseries, sourcepackagename,
381
            viewed_by, tag, status, milestone,
382
            importance, has_patch, fixed_upstream
383
        FROM BugSummary_temp_journal
384
        GROUP BY
385
            product, productseries,
386
            distribution, distroseries, sourcepackagename,
387
            viewed_by, tag, status, milestone, importance,
388
            has_patch, fixed_upstream
389
        HAVING SUM(count) <> 0
390
    LOOP
391
        IF d.count < 0 THEN
392
            PERFORM bug_summary_dec(d);
7675.1202.3 by Stuart Bishop
Updates
393
        ELSE
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
394
            PERFORM bug_summary_inc(d);
395
        END IF;
396
    END LOOP;
397
    TRUNCATE bugsummary_temp_journal;
398
END;
399
$$;
400
401
COMMENT ON FUNCTION bug_summary_flush_temp_journal() IS
402
'flush the temporary bugsummary journal into the bugsummary table';
403
404
405
CREATE OR REPLACE FUNCTION unsummarise_bug(BUG_ROW bug) RETURNS VOID
406
LANGUAGE plpgsql VOLATILE AS
407
$$
408
DECLARE
409
    d bugsummary%ROWTYPE;
410
BEGIN
411
    PERFORM ensure_bugsummary_temp_journal();
412
    FOR d IN SELECT * FROM bugsummary_locations(BUG_ROW) LOOP
413
        d.count = -1;
414
        PERFORM bug_summary_temp_journal_ins(d);
415
    END LOOP;
416
END;
417
$$;
418
419
CREATE OR REPLACE FUNCTION summarise_bug(BUG_ROW bug) RETURNS VOID
420
LANGUAGE plpgsql VOLATILE AS
421
$$
422
DECLARE
423
    d bugsummary%ROWTYPE;
424
BEGIN
425
    PERFORM ensure_bugsummary_temp_journal();
426
    FOR d IN SELECT * FROM bugsummary_locations(BUG_ROW) LOOP
427
        d.count = 1;
428
        PERFORM bug_summary_temp_journal_ins(d);
429
    END LOOP;
430
END;
431
$$;
432
433
434
CREATE OR REPLACE FUNCTION bug_maintain_bug_summary() RETURNS TRIGGER
435
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path TO public AS
436
$$
437
BEGIN
438
    -- There is no INSERT logic, as a bug will not have any summary
439
    -- information until BugTask rows have been attached.
440
    IF TG_OP = 'UPDATE' THEN
441
        IF OLD.duplicateof IS DISTINCT FROM NEW.duplicateof
442
            OR OLD.private IS DISTINCT FROM NEW.private
7675.1202.7 by Stuart Bishop
Update
443
            OR (OLD.latest_patch_uploaded IS NULL)
444
                <> (NEW.latest_patch_uploaded IS NULL) THEN
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
445
            PERFORM unsummarise_bug(OLD);
446
            PERFORM summarise_bug(NEW);
447
        END IF;
448
449
    ELSIF TG_OP = 'DELETE' THEN
450
        PERFORM unsummarise_bug(OLD);
451
    END IF;
452
453
    PERFORM bug_summary_flush_temp_journal();
454
    RETURN NULL; -- Ignored - this is an AFTER trigger
455
END;
456
$$;
457
458
459
CREATE OR REPLACE FUNCTION bugtask_maintain_bug_summary() RETURNS TRIGGER
460
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path TO public AS
461
$$
462
BEGIN
463
    -- This trigger only works if we are inserting, updating or deleting
464
    -- a single row per statement.
465
466
    -- Unlike bug_maintain_bug_summary, this trigger does not have access
467
    -- to the old bug when invoked as an AFTER trigger. To work around this
468
    -- we install this trigger as both a BEFORE and an AFTER trigger.
469
    IF TG_OP = 'INSERT' THEN
470
        IF TG_WHEN = 'BEFORE' THEN
471
            PERFORM unsummarise_bug(bug_row(NEW.bug));
472
        ELSE
473
            PERFORM summarise_bug(bug_row(NEW.bug));
474
        END IF;
475
        PERFORM bug_summary_flush_temp_journal();
476
        RETURN NEW;
477
478
    ELSIF TG_OP = 'DELETE' THEN
479
        IF TG_WHEN = 'BEFORE' THEN
480
            PERFORM unsummarise_bug(bug_row(OLD.bug));
481
        ELSE
482
            PERFORM summarise_bug(bug_row(OLD.bug));
483
        END IF;
484
        PERFORM bug_summary_flush_temp_journal();
485
        RETURN OLD;
486
487
    ELSE
488
        IF (OLD.product IS DISTINCT FROM NEW.product
489
            OR OLD.productseries IS DISTINCT FROM NEW.productseries
490
            OR OLD.distribution IS DISTINCT FROM NEW.distribution
491
            OR OLD.distroseries IS DISTINCT FROM NEW.distroseries
492
            OR OLD.sourcepackagename IS DISTINCT FROM NEW.sourcepackagename
493
            OR OLD.status IS DISTINCT FROM NEW.status
7675.1202.16 by Stuart Bishop
Fix trigger for importance, and add XXX explaining why fixed_upstream logic is currently broken
494
            OR OLD.importance IS DISTINCT FROM NEW.importance
7675.1202.7 by Stuart Bishop
Update
495
            OR OLD.bugwatch IS DISTINCT FROM NEW.bugwatch
496
            OR OLD.milestone IS DISTINCT FROM NEW.milestone) THEN
497
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
498
            IF TG_WHEN = 'BEFORE' THEN
499
                PERFORM unsummarise_bug(bug_row(OLD.bug));
500
                IF OLD.bug <> NEW.bug THEN
501
                    PERFORM unsummarise_bug(bug_row(NEW.bug));
502
                END IF;
503
            ELSE
504
                PERFORM summarise_bug(bug_row(OLD.bug));
505
                IF OLD.bug <> NEW.bug THEN
506
                    PERFORM summarise_bug(bug_row(NEW.bug));
507
                END IF;
508
            END IF;
509
        END IF;
510
        PERFORM bug_summary_flush_temp_journal();
511
        RETURN NEW;
512
    END IF;
513
END;
514
$$;
515
516
7675.1202.4 by Stuart Bishop
Updates
517
CREATE OR REPLACE FUNCTION bugsummary_locations(BUG_ROW bug)
518
RETURNS SETOF bugsummary LANGUAGE plpgsql AS
519
$$
520
BEGIN
521
    IF BUG_ROW.duplicateof IS NOT NULL THEN
522
        RETURN;
523
    END IF;
524
    RETURN QUERY
525
        SELECT
526
            CAST(NULL AS integer) AS id,
527
            CAST(1 AS integer) AS count,
528
            product, productseries, distribution, distroseries,
529
            sourcepackagename, person AS viewed_by, tag, status, milestone,
530
            importance,
531
            BUG_ROW.latest_patch_uploaded IS NOT NULL AS has_patch,
7675.1202.5 by Stuart Bishop
Updates
532
            (EXISTS (
7675.1202.17 by Stuart Bishop
A BugTask is not fixed_upstream if it is fixed, only if a related BugTask is fixed. Wierd.
533
                SELECT TRUE FROM BugTask AS RBT
7675.1202.4 by Stuart Bishop
Updates
534
                WHERE
7675.1202.17 by Stuart Bishop
A BugTask is not fixed_upstream if it is fixed, only if a related BugTask is fixed. Wierd.
535
                    RBT.bug = tasks.bug
536
                    -- This would just be 'RBT.id <> tasks.id', except
537
                    -- that the records from tasks are summaries and not
538
                    -- real bugtasks, and do not have an id.
539
                    AND (RBT.product IS DISTINCT FROM tasks.product
540
                        OR RBT.productseries
541
                            IS DISTINCT FROM tasks.productseries
542
                        OR RBT.distribution IS DISTINCT FROM tasks.distribution
543
                        OR RBT.distroseries IS DISTINCT FROM tasks.distroseries
544
                        OR RBT.sourcepackagename
545
                            IS DISTINCT FROM tasks.sourcepackagename)
546
                    -- Flagged as INVALID, FIXCOMMITTED or FIXRELEASED
547
                    -- via a bugwatch, or FIXCOMMITTED or FIXRELEASED on
548
                    -- the product.
7675.1202.4 by Stuart Bishop
Updates
549
                    AND ((bugwatch IS NOT NULL AND status IN (17, 25, 30))
550
                        OR (bugwatch IS NULL AND product IS NOT NULL
7675.1202.17 by Stuart Bishop
A BugTask is not fixed_upstream if it is fixed, only if a related BugTask is fixed. Wierd.
551
                            AND status IN (25, 30))))
552
                )::boolean AS fixed_upstream
7675.1202.4 by Stuart Bishop
Updates
553
        FROM bugsummary_tasks(BUG_ROW) AS tasks
554
        JOIN bugsummary_tags(BUG_ROW) AS bug_tags ON TRUE
555
        LEFT OUTER JOIN bugsummary_viewers(BUG_ROW) AS bug_viewers ON TRUE;
556
END;
557
$$;
558
7675.1202.5 by Stuart Bishop
Updates
559
COMMENT ON FUNCTION bugsummary_locations(bug) IS
560
'Calculate what BugSummary rows should exist for a given Bug.';
561
562
563
CREATE OR REPLACE FUNCTION bugsummary_tasks(BUG_ROW bug)
564
RETURNS SETOF bugtask LANGUAGE plpgsql STABLE AS
565
$$
566
DECLARE
567
    bt bugtask%ROWTYPE;
568
    r record;
569
BEGIN
570
    bt.bug = BUG_ROW.id;
571
572
    -- One row only for each target permutation - need to ignore other fields
573
    -- like date last modified to deal with conjoined masters and multiple
574
    -- sourcepackage tasks in a distro.
575
    FOR r IN
576
        SELECT
577
            product, productseries, distribution, distroseries,
7675.1202.16 by Stuart Bishop
Fix trigger for importance, and add XXX explaining why fixed_upstream logic is currently broken
578
            sourcepackagename, status, milestone, importance, bugwatch
7675.1202.5 by Stuart Bishop
Updates
579
        FROM BugTask WHERE bug=BUG_ROW.id
580
        UNION -- Implicit DISTINCT
581
        SELECT
582
            product, productseries, distribution, distroseries,
7675.1202.16 by Stuart Bishop
Fix trigger for importance, and add XXX explaining why fixed_upstream logic is currently broken
583
            NULL, status, milestone, importance, bugwatch
7675.1202.5 by Stuart Bishop
Updates
584
        FROM BugTask WHERE bug=BUG_ROW.id AND sourcepackagename IS NOT NULL
585
    LOOP
586
        bt.product = r.product;
587
        bt.productseries = r.productseries;
588
        bt.distribution = r.distribution;
589
        bt.distroseries = r.distroseries;
590
        bt.sourcepackagename = r.sourcepackagename;
591
        bt.status = r.status;
592
        bt.milestone = r.milestone;
593
        bt.importance = r.importance;
7675.1202.16 by Stuart Bishop
Fix trigger for importance, and add XXX explaining why fixed_upstream logic is currently broken
594
        bt.bugwatch = r.bugwatch;
7675.1202.5 by Stuart Bishop
Updates
595
        RETURN NEXT bt;
596
    END LOOP;
597
END;
598
$$;
599
600
COMMENT ON FUNCTION bugsummary_tasks(bug) IS
601
'Return all tasks for the bug + all sourcepackagename tasks again with the sourcepackagename squashed';
602
603
7675.1202.4 by Stuart Bishop
Updates
604
7675.1202.2 by Stuart Bishop
Draft of DB patch extending BugSummary
605
INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 75, 0);