~launchpad-pqm/launchpad/devel

7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
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
7675.1121.2 by Stuart Bishop
Attempt to fix patch-2208-65-0.sql against production data by making the BugSubscriptionFilter -> StructuralSubscription relationship ON DELETE CASCADE
6
-- Before we remove unwanted StructuralSubscription rows, we can tweak
7
-- some foreign key constraints to make this removal easier.
8
-- StructuralSubscription is referenced by BugSubscriptionFilter
9
-- BugSubscriptionFilter is referenced too by BugNotificationFilter, but
10
-- that relationship is already ON DELETE CASCADE.
11
ALTER TABLE BugSubscriptionFilter
12
    DROP CONSTRAINT bugsubscriptionfilter_structuralsubscription_fkey,
13
    ADD CONSTRAINT bugsubscriptionfilter__structuralsubscription__fk
14
        FOREIGN KEY (structuralsubscription)
15
        REFERENCES StructuralSubscription ON DELETE CASCADE;
16
17
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
18
-- WHAT ARE WE DOING? -----------------------------------------------------
19
20
-- These three errors have been observed, and are corrected here.
21
22
-- If StructuralSubscription.product is not NULL, the combination of
23
-- StructuralSubscription.product and StructuralSubscription.subscriber
24
-- should be unique.
25
26
-- If StructuralSubscription.project is not NULL, the combination of
27
-- StructuralSubscription.project and StructuralSubscription.subscriber
28
-- should be unique.
29
30
-- If StructuralSubscription.distribution and
31
-- StructuralSubscription.sourcepackagename are not NULL, the combination of
32
-- StructuralSubscription.distribution,
33
-- StructuralSubscription.sourcepackagename, and
34
-- StructuralSubscription.subscriber should be unique.
35
36
-- These have not been observed, but are prevented for safekeeping.
37
38
-- If StructuralSubscription.distribution is not NULL but
39
-- StructuralSubscription.sourcepackagename is NULL, the combination of
40
-- StructuralSubscription.distribution and
41
-- StructuralSubscription.subscriber should be unique.
42
43
-- If StructuralSubscription.distroseries is not NULL, the combination of
44
-- StructuralSubscription.distroseries and StructuralSubscription.subscriber
45
-- should be unique.
46
47
-- If StructuralSubscription.milestone is not NULL, the combination of
48
-- StructuralSubscription.milestone and StructuralSubscription.subscriber
49
-- should be unique.
50
51
-- If StructuralSubscription.productseries is not NULL, the combination of
52
-- StructuralSubscription.productseries and StructuralSubscription.subscriber
53
-- should be unique.
54
55
-- So, we want to eliminate dupes, and then set up constraints so they do not
56
-- come back.
57
58
-- ELIMINATE DUPES --------------------------------------------------------
59
60
-- First, we eliminate dupes.
61
62
-- We find duplicates and eliminate the ones that are older (on the basis
63
-- of the id being a smaller number).
64
65
-- This eliminates product dupes.  As an example, this is run on staging.
66
67
-- lpmain_staging=> SELECT Subscription.product,
68
--        Subscription.subscriber,
69
--        Subscription.id
70
-- FROM StructuralSubscription AS Subscription
71
-- WHERE EXISTS (
72
--    SELECT StructuralSubscription.product, StructuralSubscription.subscriber
73
--    FROM StructuralSubscription
74
--    WHERE
75
--        StructuralSubscription.product = Subscription.product
76
--        AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
77
--    GROUP BY StructuralSubscription.product,
78
--             StructuralSubscription.subscriber
79
--    HAVING Count(*)>1)
80
--    ORDER BY Subscription.product, Subscription.subscriber, Subscription.id;
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
81
--  product | subscriber |  id   
82
-- ---------+------------+-------
83
--     2461 |    2212151 |  7570
84
--     2461 |    2212151 |  7571
85
--     7533 |    1814750 |  5428
86
--     7533 |    1814750 |  5492
87
--     7534 |    1814750 |  5429
88
--     7534 |    1814750 |  5491
89
--     8269 |     242763 |  8191
90
--     8269 |     242763 |  8192
91
--     9868 |    3388985 | 25131
92
--     9868 |    3388985 | 25132
93
--    24395 |    3391740 | 21770
94
--    24395 |    3391740 | 23900
95
-- (12 rows)
96
-- 
97
-- lpmain_staging=> WITH duped_values AS
98
--     (SELECT Subscription.product,
99
--             Subscription.subscriber,
100
--             Subscription.id
101
--      FROM StructuralSubscription AS Subscription
102
--      WHERE EXISTS (                                                        
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
103
--         SELECT StructuralSubscription.product,
104
--                StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
105
--         FROM StructuralSubscription
106
--         WHERE                                               
107
--             StructuralSubscription.product = Subscription.product
108
--             AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
109
--         GROUP BY StructuralSubscription.product,
110
--                  StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
111
--         HAVING Count(*)>1))
112
--  SELECT duped_values.id
113
--  FROM duped_values
114
--  WHERE duped_values.id NOT IN
115
--     (SELECT MAX(duped_values.id)
116
--      FROM duped_values
117
--      GROUP BY duped_values.product, duped_values.subscriber);
118
--   id   
119
-- -------
120
--   5429
121
--   5428
122
--   8191
123
--  25131
124
--   7570
125
--  21770
126
-- (6 rows)
127
128
DELETE FROM StructuralSubscription WHERE
129
    StructuralSubscription.id IN 
130
        (WITH duped_values AS
131
            (SELECT Subscription.product,
132
                    Subscription.subscriber,
133
                    Subscription.id
134
             FROM StructuralSubscription AS Subscription
135
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
136
                SELECT StructuralSubscription.product,
137
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
138
                FROM StructuralSubscription
139
                WHERE
140
                    StructuralSubscription.product = Subscription.product
141
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
142
                GROUP BY StructuralSubscription.product,
143
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
144
                HAVING Count(*)>1))
145
         SELECT duped_values.id
146
         FROM duped_values
147
         WHERE duped_values.id NOT IN
148
            (SELECT MAX(duped_values.id)
149
             FROM duped_values
150
             GROUP BY duped_values.product, duped_values.subscriber));
151
152
-- Now we eliminate project dupes.  This, like most of the variations,
153
-- is a copy-and-paste job, replacing "product" with "project".
154
155
DELETE FROM StructuralSubscription WHERE
156
    StructuralSubscription.id IN 
157
        (WITH duped_values AS
158
            (SELECT Subscription.project,
159
                    Subscription.subscriber,
160
                    Subscription.id
161
             FROM StructuralSubscription AS Subscription
162
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
163
                SELECT StructuralSubscription.project,
164
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
165
                FROM StructuralSubscription
166
                WHERE
167
                    StructuralSubscription.project = Subscription.project
168
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
169
                GROUP BY StructuralSubscription.project,
170
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
171
                HAVING Count(*)>1))
172
         SELECT duped_values.id
173
         FROM duped_values
174
         WHERE duped_values.id NOT IN
175
            (SELECT MAX(duped_values.id)
176
             FROM duped_values
177
             GROUP BY duped_values.project, duped_values.subscriber));
178
179
-- Now we eliminate distroseries dupes.  They don't exist on staging, but
180
-- there's nothing keeping them from happening, so this is just to make sure.
181
-- This is another copy and paste job.
182
183
DELETE FROM StructuralSubscription WHERE
184
    StructuralSubscription.id IN 
185
        (WITH duped_values AS
186
            (SELECT Subscription.distroseries,
187
                    Subscription.subscriber,
188
                    Subscription.id
189
             FROM StructuralSubscription AS Subscription
190
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
191
                SELECT StructuralSubscription.distroseries,
192
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
193
                FROM StructuralSubscription
194
                WHERE
195
                    StructuralSubscription.distroseries = Subscription.distroseries
196
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
197
                GROUP BY StructuralSubscription.distroseries,
198
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
199
                HAVING Count(*)>1))
200
         SELECT duped_values.id
201
         FROM duped_values
202
         WHERE duped_values.id NOT IN
203
            (SELECT MAX(duped_values.id)
204
             FROM duped_values
205
             GROUP BY duped_values.distroseries, duped_values.subscriber));
206
207
-- Now we eliminate milestone dupes.  This again does not have matches on
208
-- staging, and is again a copy-and-paste job.
209
210
DELETE FROM StructuralSubscription WHERE
211
    StructuralSubscription.id IN 
212
        (WITH duped_values AS
213
            (SELECT Subscription.milestone,
214
                    Subscription.subscriber,
215
                    Subscription.id
216
             FROM StructuralSubscription AS Subscription
217
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
218
                SELECT StructuralSubscription.milestone,
219
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
220
                FROM StructuralSubscription
221
                WHERE
222
                    StructuralSubscription.milestone = Subscription.milestone
223
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
224
                GROUP BY StructuralSubscription.milestone,
225
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
226
                HAVING Count(*)>1))
227
         SELECT duped_values.id
228
         FROM duped_values
229
         WHERE duped_values.id NOT IN
230
            (SELECT MAX(duped_values.id)
231
             FROM duped_values
232
             GROUP BY duped_values.milestone, duped_values.subscriber));
233
234
-- Now we eliminate productseries dupes.  This again does not have matches on
235
-- staging, and is again a copy-and-paste job.
236
237
DELETE FROM StructuralSubscription WHERE
238
    StructuralSubscription.id IN 
239
        (WITH duped_values AS
240
            (SELECT Subscription.productseries,
241
                    Subscription.subscriber,
242
                    Subscription.id
243
             FROM StructuralSubscription AS Subscription
244
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
245
                SELECT StructuralSubscription.productseries,
246
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
247
                FROM StructuralSubscription
248
                WHERE
249
                    StructuralSubscription.productseries = Subscription.productseries
250
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
251
                GROUP BY StructuralSubscription.productseries,
252
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
253
                HAVING Count(*)>1))
254
         SELECT duped_values.id
255
         FROM duped_values
256
         WHERE duped_values.id NOT IN
257
            (SELECT MAX(duped_values.id)
258
             FROM duped_values
259
             GROUP BY duped_values.productseries, duped_values.subscriber));
260
261
-- Now we need to eliminate distribution and sourcepackagename dupes.  These
262
-- involve a bit more modification of the pattern, though it is still the
263
-- same basic idea.
264
265
-- This is the distribution.  It has no matches on staging.
266
267
DELETE FROM StructuralSubscription WHERE
268
    StructuralSubscription.id IN 
269
        (WITH duped_values AS
270
            (SELECT Subscription.distribution,
271
                    Subscription.subscriber,
272
                    Subscription.id
273
             FROM StructuralSubscription AS Subscription
274
             WHERE EXISTS (
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
275
                SELECT StructuralSubscription.distribution,
276
                       StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
277
                FROM StructuralSubscription
278
                WHERE
279
                    StructuralSubscription.distribution = Subscription.distribution
280
                    AND StructuralSubscription.subscriber = Subscription.subscriber
7675.1117.4 by Gary Poster
fix tests by adding support for merging structural subscriptions
281
-- These are the two new lines.
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
282
                    AND StructuralSubscription.sourcepackagename IS NULL
7675.1117.4 by Gary Poster
fix tests by adding support for merging structural subscriptions
283
                    AND Subscription.sourcepackagename IS NULL
7675.1117.2 by Gary Poster
break a few lines to get closer to our line limit goals
284
                GROUP BY StructuralSubscription.distribution,
285
                         StructuralSubscription.subscriber
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
286
                HAVING Count(*)>1))
287
         SELECT duped_values.id
288
         FROM duped_values
289
         WHERE duped_values.id NOT IN
290
            (SELECT MAX(duped_values.id)
291
             FROM duped_values
292
             GROUP BY duped_values.distribution, duped_values.subscriber));
293
294
-- This is the sourcepackagename.  It *does* have matches on staging.
295
296
DELETE FROM StructuralSubscription WHERE
297
    StructuralSubscription.id IN 
298
        (WITH duped_values AS
299
            (SELECT Subscription.distribution,
300
                    Subscription.sourcepackagename,
301
                    Subscription.subscriber,
302
                    Subscription.id
303
             FROM StructuralSubscription AS Subscription
304
             WHERE EXISTS (
305
                SELECT StructuralSubscription.distribution,
306
                       StructuralSubscription.sourcepackagename,
307
                       StructuralSubscription.subscriber
308
                FROM StructuralSubscription
309
                WHERE
310
                    StructuralSubscription.distribution = Subscription.distribution
311
                    AND StructuralSubscription.sourcepackagename = Subscription.sourcepackagename
312
                    AND StructuralSubscription.subscriber = Subscription.subscriber
313
                GROUP BY StructuralSubscription.distribution,
314
                         StructuralSubscription.sourcepackagename,
315
                         StructuralSubscription.subscriber
316
                HAVING Count(*)>1))
317
         SELECT duped_values.id
318
         FROM duped_values
319
         WHERE duped_values.id NOT IN
320
            (SELECT MAX(duped_values.id)
321
             FROM duped_values
322
             GROUP BY duped_values.distribution,
323
                      duped_values.sourcepackagename,
324
                      duped_values.subscriber));
325
326
327
-- CREATE CONSTRAINTS ----------------------------------------------------
328
7675.1117.3 by Gary Poster
incorporate changes from DB review
329
CREATE UNIQUE INDEX structuralsubscription__product__subscriber__key
330
ON StructuralSubscription(product, subscriber) WHERE product IS NOT NULL;
331
332
CREATE UNIQUE INDEX structuralsubscription__project__subscriber__key
333
ON StructuralSubscription(project, subscriber) WHERE project IS NOT NULL;
334
335
-- This represents a subscription to a sourcepackage within a distribution.
7675.1117.1 by Gary Poster
clean up bad structural subscriptions and set up constraints so they do not happen again.
336
CREATE UNIQUE INDEX
7675.1117.3 by Gary Poster
incorporate changes from DB review
337
    structuralsubscription__distribution__sourcepackagename__subscriber__key
338
ON StructuralSubscription(distribution, sourcepackagename, subscriber)
339
WHERE distribution IS NOT NULL AND sourcepackagename IS NOT NULL;
340
341
-- This represents a subscription to an entire distribution.  Even though this
342
-- kind of distribution subsumes a sourcepackage distrubution (above), the
343
-- configuration may be very different, so they are not necessarily redundant.
344
CREATE UNIQUE INDEX structuralsubscription__distribution__subscriber__key
345
ON StructuralSubscription(distribution, subscriber)
346
WHERE distribution IS NOT NULL AND sourcepackagename IS NULL;
347
348
CREATE UNIQUE INDEX structuralsubscription__distroseries__subscriber__key
349
ON StructuralSubscription(distroseries, subscriber)
350
WHERE distroseries IS NOT NULL;
351
352
-- NB. Currently we can't subscribe to a (distroseries, sourcepackagename)
353
-- so no need for the second partial distroseries index like the two
354
-- distribution indexes.
355
356
CREATE UNIQUE INDEX structuralsubscription__milestone__subscriber__key
357
ON StructuralSubscription(milestone, subscriber)
358
WHERE milestone IS NOT NULL;
359
360
CREATE UNIQUE INDEX structuralsubscription__productseries__subscriber__key
361
ON StructuralSubscription(productseries, subscriber)
362
WHERE productseries IS NOT NULL;
363
364
-- Drop obsolete indexes - the above constraints make them redundant.
365
DROP INDEX structuralsubscription__distribution__sourcepackagename__idx;
366
DROP INDEX structuralsubscription__distroseries__idx;
367
DROP INDEX structuralsubscription__milestone__idx;
368
DROP INDEX structuralsubscription__product__idx;
369
DROP INDEX structuralsubscription__productseries__idx;
370
DROP INDEX structuralsubscription__project__idx;
371
372
INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 65, 0);