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); |