Merge lp:~wgrant/launchpad/postgresql-9.5-9.6 into lp:launchpad
- postgresql-9.5-9.6
- Merge into devel
Status: | Merged |
---|---|
Merged at revision: | 18275 |
Proposed branch: | lp:~wgrant/launchpad/postgresql-9.5-9.6 |
Merge into: | lp:launchpad |
Diff against target: |
542 lines (+360/-118) 6 files modified
database/schema/patch-2209-11-1.sql (+2/-2) database/schema/patch-2209-21-4.sql (+6/-108) database/schema/patch-2209-30-1.sql (+1/-1) database/schema/patch-2209-81-0.sql (+346/-0) lib/lp/services/database/doc/textsearching.txt (+4/-6) utilities/launchpad-database-setup (+1/-1) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/postgresql-9.5-9.6 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | db | Approve | |
Review via email: mp+310767@code.launchpad.net |
Commit message
Update database schema for PostgreSQL 9.5 and 9.6.
Description of the change
Update database schema for PostgreSQL 9.5 and 9.6. 9.3 still works, and 9.4 probably does too but it's not in any supported Ubuntu release so I don't much care.
There are three classes of PostgreSQL change that required us to adapt:
- IS vs == operator precedence changed in 9.5.
- tsquery parsing now treats '<' as the start of a phrase search operator as of 9.6.
- A couple of system tables' columns changed in 9.4 and 9.6.
Check constraints are stored parsed, so changing history without a fresh patch is fine. But for functions we need to replace them entirely: http://
Patch 2209-21-4's creation of update_
at application time, and wasn't depended on by any later patches, so
I've deleted that bit of history. For new databases the function won't
exist until 2209-81-0.
Text search query parsing has changed subtly: any '<' characters are
stripped ('<' begins 9.6's new phrase operator), meaning that terms such
as XML tags are no longer ignored. But such searches were already pretty
broken, and this arguably makes them slightly better.
Colin Watson (cjwatson) : | # |
Preview Diff
1 | === modified file 'database/schema/patch-2209-11-1.sql' |
2 | --- database/schema/patch-2209-11-1.sql 2012-02-16 09:45:47 +0000 |
3 | +++ database/schema/patch-2209-11-1.sql 2016-11-14 12:11:11 +0000 |
4 | @@ -17,7 +17,7 @@ |
5 | product integer REFERENCES product, |
6 | distribution integer REFERENCES distribution, |
7 | type integer NOT NULL, |
8 | - CONSTRAINT has_target CHECK (product IS NULL != distribution IS NULL) |
9 | + CONSTRAINT has_target CHECK ((product IS NULL) != (distribution IS NULL)) |
10 | ); |
11 | |
12 | CREATE UNIQUE INDEX accesspolicy__product__type__key |
13 | @@ -29,7 +29,7 @@ |
14 | id serial PRIMARY KEY, |
15 | bug integer REFERENCES bug, |
16 | branch integer, -- FK to be added later. |
17 | - CONSTRAINT has_artifact CHECK (bug IS NULL != branch IS NULL) |
18 | + CONSTRAINT has_artifact CHECK ((bug IS NULL) != (branch IS NULL)) |
19 | ); |
20 | |
21 | CREATE UNIQUE INDEX accessartifact__bug__key |
22 | |
23 | === modified file 'database/schema/patch-2209-21-4.sql' |
24 | --- database/schema/patch-2209-21-4.sql 2012-06-01 12:02:00 +0000 |
25 | +++ database/schema/patch-2209-21-4.sql 2016-11-14 12:11:11 +0000 |
26 | @@ -1,110 +1,8 @@ |
27 | -CREATE OR REPLACE FUNCTION update_database_disk_utilization() RETURNS void |
28 | - LANGUAGE sql SECURITY DEFINER |
29 | - SET search_path TO public |
30 | - AS $$ |
31 | - INSERT INTO DatabaseDiskUtilization |
32 | - SELECT |
33 | - CURRENT_TIMESTAMP AT TIME ZONE 'UTC', |
34 | - namespace, name, |
35 | - sub_namespace, sub_name, |
36 | - kind, |
37 | - (namespace || '.' || name || COALESCE( |
38 | - '/' || sub_namespace || '.' || sub_name, '')) AS sort, |
39 | - (stat).table_len, |
40 | - (stat).tuple_count, |
41 | - (stat).tuple_len, |
42 | - (stat).tuple_percent, |
43 | - (stat).dead_tuple_count, |
44 | - (stat).dead_tuple_len, |
45 | - (stat).dead_tuple_percent, |
46 | - (stat).free_space, |
47 | - (stat).free_percent |
48 | - FROM ( |
49 | - -- Tables |
50 | - SELECT |
51 | - pg_namespace.nspname AS namespace, |
52 | - pg_class.relname AS name, |
53 | - NULL AS sub_namespace, |
54 | - NULL AS sub_name, |
55 | - pg_class.relkind AS kind, |
56 | - pgstattuple(pg_class.oid) AS stat |
57 | - FROM pg_class, pg_namespace |
58 | - WHERE |
59 | - pg_class.relnamespace = pg_namespace.oid |
60 | - AND pg_class.relkind = 'r' |
61 | - AND pg_table_is_visible(pg_class.oid) |
62 | - |
63 | - UNION ALL |
64 | - |
65 | - -- Indexes |
66 | - SELECT |
67 | - pg_namespace_table.nspname AS namespace, |
68 | - pg_class_table.relname AS name, |
69 | - pg_namespace_index.nspname AS sub_namespace, |
70 | - pg_class_index.relname AS sub_name, |
71 | - pg_class_index.relkind AS kind, |
72 | - pgstattuple(pg_class_index.oid) AS stat |
73 | - FROM |
74 | - pg_namespace AS pg_namespace_table, |
75 | - pg_namespace AS pg_namespace_index, |
76 | - pg_class AS pg_class_table, |
77 | - pg_class AS pg_class_index, |
78 | - pg_index, |
79 | - pg_am |
80 | - WHERE |
81 | - pg_class_index.relkind = 'i' |
82 | - AND pg_am.amname <> 'gin' -- pgstattuple doesn't support GIN |
83 | - AND pg_table_is_visible(pg_class_table.oid) |
84 | - AND pg_class_index.relnamespace = pg_namespace_index.oid |
85 | - AND pg_class_table.relnamespace = pg_namespace_table.oid |
86 | - AND pg_class_index.relam = pg_am.oid |
87 | - AND pg_index.indexrelid = pg_class_index.oid |
88 | - AND pg_index.indrelid = pg_class_table.oid |
89 | - |
90 | - UNION ALL |
91 | - |
92 | - -- TOAST tables |
93 | - SELECT |
94 | - pg_namespace_table.nspname AS namespace, |
95 | - pg_class_table.relname AS name, |
96 | - pg_namespace_toast.nspname AS sub_namespace, |
97 | - pg_class_toast.relname AS sub_name, |
98 | - pg_class_toast.relkind AS kind, |
99 | - pgstattuple(pg_class_toast.oid) AS stat |
100 | - FROM |
101 | - pg_namespace AS pg_namespace_table, |
102 | - pg_namespace AS pg_namespace_toast, |
103 | - pg_class AS pg_class_table, |
104 | - pg_class AS pg_class_toast |
105 | - WHERE |
106 | - pg_class_toast.relnamespace = pg_namespace_toast.oid |
107 | - AND pg_table_is_visible(pg_class_table.oid) |
108 | - AND pg_class_table.relnamespace = pg_namespace_table.oid |
109 | - AND pg_class_toast.oid = pg_class_table.reltoastrelid |
110 | - |
111 | - UNION ALL |
112 | - |
113 | - -- TOAST indexes |
114 | - SELECT |
115 | - pg_namespace_table.nspname AS namespace, |
116 | - pg_class_table.relname AS name, |
117 | - pg_namespace_index.nspname AS sub_namespace, |
118 | - pg_class_index.relname AS sub_name, |
119 | - pg_class_index.relkind AS kind, |
120 | - pgstattuple(pg_class_index.oid) AS stat |
121 | - FROM |
122 | - pg_namespace AS pg_namespace_table, |
123 | - pg_namespace AS pg_namespace_index, |
124 | - pg_class AS pg_class_table, |
125 | - pg_class AS pg_class_index, |
126 | - pg_class AS pg_class_toast |
127 | - WHERE |
128 | - pg_class_table.relnamespace = pg_namespace_table.oid |
129 | - AND pg_table_is_visible(pg_class_table.oid) |
130 | - AND pg_class_index.relnamespace = pg_namespace_index.oid |
131 | - AND pg_class_table.reltoastrelid = pg_class_toast.oid |
132 | - AND pg_class_index.oid = pg_class_toast.reltoastidxid |
133 | - ) AS whatever; |
134 | -$$; |
135 | +SET client_min_messages = ERROR; |
136 | + |
137 | +-- This patch originally added update_database_disk_utilization(), but |
138 | +-- it failed to apply on PostgreSQL >=9.5. It has been replaced with a |
139 | +-- more compatible version in 2209-81-0. Deleting history is gross, but |
140 | +-- we can get away without properly altering it. |
141 | |
142 | INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 21, 4); |
143 | |
144 | === modified file 'database/schema/patch-2209-30-1.sql' |
145 | --- database/schema/patch-2209-30-1.sql 2012-08-23 23:51:58 +0000 |
146 | +++ database/schema/patch-2209-30-1.sql 2016-11-14 12:11:11 +0000 |
147 | @@ -12,7 +12,7 @@ |
148 | -- If type is set, then either product or distribution must be set and person must be null. |
149 | ALTER TABLE accesspolicy ADD CONSTRAINT has_target |
150 | CHECK ( |
151 | - (type IS NOT NULL AND (product IS NULL <> distribution IS NULL) AND person IS NULL) |
152 | + (type IS NOT NULL AND ((product IS NULL) <> (distribution IS NULL)) AND person IS NULL) |
153 | OR |
154 | (type IS NULL AND person IS NOT NULL and product IS NULL AND distribution IS NULL) ); |
155 | |
156 | |
157 | === added file 'database/schema/patch-2209-81-0.sql' |
158 | --- database/schema/patch-2209-81-0.sql 1970-01-01 00:00:00 +0000 |
159 | +++ database/schema/patch-2209-81-0.sql 2016-11-14 12:11:11 +0000 |
160 | @@ -0,0 +1,346 @@ |
161 | +SET client_min_messages = ERROR; |
162 | + |
163 | +-- Update functions for PostgreSQL 9.5 and 9.6 support, in addition to 9.3. |
164 | + |
165 | + |
166 | +-- From 2209-00-0 |
167 | +CREATE OR REPLACE FUNCTION update_branch_name_cache() RETURNS trigger |
168 | + LANGUAGE plpgsql |
169 | + AS $$ |
170 | +DECLARE |
171 | + needs_update boolean := FALSE; |
172 | +BEGIN |
173 | + IF TG_OP = 'INSERT' THEN |
174 | + needs_update := TRUE; |
175 | + ELSIF (NEW.owner_name IS NULL |
176 | + OR NEW.unique_name IS NULL |
177 | + OR OLD.owner_name <> NEW.owner_name |
178 | + OR OLD.unique_name <> NEW.unique_name |
179 | + OR ((NEW.target_suffix IS NULL) <> (OLD.target_suffix IS NULL)) |
180 | + OR COALESCE(OLD.target_suffix, '') <> COALESCE(NEW.target_suffix, '') |
181 | + OR OLD.name <> NEW.name |
182 | + OR OLD.owner <> NEW.owner |
183 | + OR COALESCE(OLD.product, -1) <> COALESCE(NEW.product, -1) |
184 | + OR COALESCE(OLD.distroseries, -1) <> COALESCE(NEW.distroseries, -1) |
185 | + OR COALESCE(OLD.sourcepackagename, -1) |
186 | + <> COALESCE(NEW.sourcepackagename, -1)) THEN |
187 | + needs_update := TRUE; |
188 | + END IF; |
189 | + |
190 | + IF needs_update THEN |
191 | + SELECT |
192 | + Person.name AS owner_name, |
193 | + COALESCE(Product.name, SPN.name) AS target_suffix, |
194 | + '~' || Person.name || '/' || COALESCE( |
195 | + Product.name, |
196 | + Distribution.name || '/' || Distroseries.name |
197 | + || '/' || SPN.name, |
198 | + '+junk') || '/' || NEW.name AS unique_name |
199 | + INTO NEW.owner_name, NEW.target_suffix, NEW.unique_name |
200 | + FROM Person |
201 | + LEFT OUTER JOIN DistroSeries ON NEW.distroseries = DistroSeries.id |
202 | + LEFT OUTER JOIN Product ON NEW.product = Product.id |
203 | + LEFT OUTER JOIN Distribution |
204 | + ON Distroseries.distribution = Distribution.id |
205 | + LEFT OUTER JOIN SourcepackageName AS SPN |
206 | + ON SPN.id = NEW.sourcepackagename |
207 | + WHERE Person.id = NEW.owner; |
208 | + END IF; |
209 | + |
210 | + RETURN NEW; |
211 | +END; |
212 | +$$; |
213 | + |
214 | + |
215 | +-- From 2209-21-4 |
216 | +CREATE OR REPLACE FUNCTION update_database_disk_utilization() RETURNS void |
217 | + LANGUAGE sql SECURITY DEFINER |
218 | + SET search_path TO public |
219 | + AS $$ |
220 | + INSERT INTO DatabaseDiskUtilization |
221 | + SELECT |
222 | + CURRENT_TIMESTAMP AT TIME ZONE 'UTC', |
223 | + namespace, name, |
224 | + sub_namespace, sub_name, |
225 | + kind, |
226 | + (namespace || '.' || name || COALESCE( |
227 | + '/' || sub_namespace || '.' || sub_name, '')) AS sort, |
228 | + (stat).table_len, |
229 | + (stat).tuple_count, |
230 | + (stat).tuple_len, |
231 | + (stat).tuple_percent, |
232 | + (stat).dead_tuple_count, |
233 | + (stat).dead_tuple_len, |
234 | + (stat).dead_tuple_percent, |
235 | + (stat).free_space, |
236 | + (stat).free_percent |
237 | + FROM ( |
238 | + -- Tables |
239 | + SELECT |
240 | + pg_namespace.nspname AS namespace, |
241 | + pg_class.relname AS name, |
242 | + NULL AS sub_namespace, |
243 | + NULL AS sub_name, |
244 | + pg_class.relkind AS kind, |
245 | + pgstattuple(pg_class.oid) AS stat |
246 | + FROM pg_class, pg_namespace |
247 | + WHERE |
248 | + pg_class.relnamespace = pg_namespace.oid |
249 | + AND pg_class.relkind = 'r' |
250 | + AND pg_table_is_visible(pg_class.oid) |
251 | + |
252 | + UNION ALL |
253 | + |
254 | + -- Indexes |
255 | + SELECT |
256 | + pg_namespace_table.nspname AS namespace, |
257 | + pg_class_table.relname AS name, |
258 | + pg_namespace_index.nspname AS sub_namespace, |
259 | + pg_class_index.relname AS sub_name, |
260 | + pg_class_index.relkind AS kind, |
261 | + pgstattuple(pg_class_index.oid) AS stat |
262 | + FROM |
263 | + pg_namespace AS pg_namespace_table, |
264 | + pg_namespace AS pg_namespace_index, |
265 | + pg_class AS pg_class_table, |
266 | + pg_class AS pg_class_index, |
267 | + pg_index, |
268 | + pg_am |
269 | + WHERE |
270 | + pg_class_index.relkind = 'i' |
271 | + AND pg_am.amname <> 'gin' -- pgstattuple doesn't support GIN |
272 | + AND pg_table_is_visible(pg_class_table.oid) |
273 | + AND pg_class_index.relnamespace = pg_namespace_index.oid |
274 | + AND pg_class_table.relnamespace = pg_namespace_table.oid |
275 | + AND pg_class_index.relam = pg_am.oid |
276 | + AND pg_index.indexrelid = pg_class_index.oid |
277 | + AND pg_index.indrelid = pg_class_table.oid |
278 | + |
279 | + UNION ALL |
280 | + |
281 | + -- TOAST tables |
282 | + SELECT |
283 | + pg_namespace_table.nspname AS namespace, |
284 | + pg_class_table.relname AS name, |
285 | + pg_namespace_toast.nspname AS sub_namespace, |
286 | + pg_class_toast.relname AS sub_name, |
287 | + pg_class_toast.relkind AS kind, |
288 | + pgstattuple(pg_class_toast.oid) AS stat |
289 | + FROM |
290 | + pg_namespace AS pg_namespace_table, |
291 | + pg_namespace AS pg_namespace_toast, |
292 | + pg_class AS pg_class_table, |
293 | + pg_class AS pg_class_toast |
294 | + WHERE |
295 | + pg_class_toast.relnamespace = pg_namespace_toast.oid |
296 | + AND pg_table_is_visible(pg_class_table.oid) |
297 | + AND pg_class_table.relnamespace = pg_namespace_table.oid |
298 | + AND pg_class_toast.oid = pg_class_table.reltoastrelid |
299 | + |
300 | + UNION ALL |
301 | + |
302 | + -- TOAST indexes |
303 | + SELECT |
304 | + pg_namespace_table.nspname AS namespace, |
305 | + pg_class_table.relname AS name, |
306 | + pg_namespace_index.nspname AS sub_namespace, |
307 | + pg_class_index.relname AS sub_name, |
308 | + pg_class_index.relkind AS kind, |
309 | + pgstattuple(pg_class_index.oid) AS stat |
310 | + FROM |
311 | + pg_namespace AS pg_namespace_table, |
312 | + pg_namespace AS pg_namespace_index, |
313 | + pg_class AS pg_class_table, |
314 | + pg_class AS pg_class_index, |
315 | + pg_class AS pg_class_toast, |
316 | + pg_index |
317 | + WHERE |
318 | + pg_class_table.relnamespace = pg_namespace_table.oid |
319 | + AND pg_table_is_visible(pg_class_table.oid) |
320 | + AND pg_class_index.relnamespace = pg_namespace_index.oid |
321 | + AND pg_class_table.reltoastrelid = pg_class_toast.oid |
322 | + AND pg_class_index.oid = pg_index.indexrelid |
323 | + AND pg_index.indrelid = pg_class_toast.oid |
324 | + ) AS whatever; |
325 | +$$; |
326 | + |
327 | + |
328 | +-- From 2209-24-3 |
329 | +CREATE OR REPLACE FUNCTION _ftq(text) RETURNS text |
330 | + LANGUAGE plpythonu IMMUTABLE STRICT |
331 | + AS $_$ |
332 | + import re |
333 | + |
334 | + # I think this method would be more robust if we used a real |
335 | + # tokenizer and parser to generate the query string, but we need |
336 | + # something suitable for use as a stored procedure which currently |
337 | + # means no external dependancies. |
338 | + |
339 | + # Convert to Unicode |
340 | + query = args[0].decode('utf8') |
341 | + ## plpy.debug('1 query is %s' % repr(query)) |
342 | + |
343 | + # Replace tsquery operators with ' '. '<' begins all the phrase |
344 | + # search operators, and a standalone '>' is fine. |
345 | + query = re.sub('[|&!<]', ' ', query) |
346 | + |
347 | + # Normalize whitespace |
348 | + query = re.sub("(?u)\s+"," ", query) |
349 | + |
350 | + # Convert AND, OR, NOT to tsearch2 punctuation |
351 | + query = re.sub(r"(?u)\bAND\b", "&", query) |
352 | + query = re.sub(r"(?u)\bOR\b", "|", query) |
353 | + query = re.sub(r"(?u)\bNOT\b", " !", query) |
354 | + ## plpy.debug('2 query is %s' % repr(query)) |
355 | + |
356 | + # Deal with unwanted punctuation. |
357 | + # ':' is used in queries to specify a weight of a word. |
358 | + # '\' is treated differently in to_tsvector() and to_tsquery(). |
359 | + punctuation = r'[:\\]' |
360 | + query = re.sub(r"(?u)%s+" % (punctuation,), " ", query) |
361 | + ## plpy.debug('3 query is %s' % repr(query)) |
362 | + |
363 | + # Now that we have handle case sensitive booleans, convert to lowercase |
364 | + query = query.lower() |
365 | + |
366 | + # Remove unpartnered bracket on the left and right |
367 | + query = re.sub(r"(?ux) ^ ( [^(]* ) \)", r"(\1)", query) |
368 | + query = re.sub(r"(?ux) \( ( [^)]* ) $", r"(\1)", query) |
369 | + |
370 | + # Remove spurious brackets |
371 | + query = re.sub(r"(?u)\(([^\&\|]*?)\)", r" \1 ", query) |
372 | + ## plpy.debug('5 query is %s' % repr(query)) |
373 | + |
374 | + # Insert & between tokens without an existing boolean operator |
375 | + # ( not proceeded by (|&! |
376 | + query = re.sub(r"(?u)(?<![\(\|\&\!])\s*\(", "&(", query) |
377 | + ## plpy.debug('6 query is %s' % repr(query)) |
378 | + # ) not followed by )|& |
379 | + query = re.sub(r"(?u)\)(?!\s*(\)|\||\&|\s*$))", ")&", query) |
380 | + ## plpy.debug('6.1 query is %s' % repr(query)) |
381 | + # Whitespace not proceded by (|&! not followed by &| |
382 | + query = re.sub(r"(?u)(?<![\(\|\&\!\s])\s+(?![\&\|\s])", "&", query) |
383 | + ## plpy.debug('7 query is %s' % repr(query)) |
384 | + |
385 | + # Detect and repair syntax errors - we are lenient because |
386 | + # this input is generally from users. |
387 | + |
388 | + # Fix unbalanced brackets |
389 | + openings = query.count("(") |
390 | + closings = query.count(")") |
391 | + if openings > closings: |
392 | + query = query + " ) "*(openings-closings) |
393 | + elif closings > openings: |
394 | + query = " ( "*(closings-openings) + query |
395 | + ## plpy.debug('8 query is %s' % repr(query)) |
396 | + |
397 | + # Strip ' character that do not have letters on both sides |
398 | + query = re.sub(r"(?u)((?<!\w)'|'(?!\w))", "", query) |
399 | + |
400 | + # Brackets containing nothing but whitespace and booleans, recursive |
401 | + last = "" |
402 | + while last != query: |
403 | + last = query |
404 | + query = re.sub(r"(?u)\([\s\&\|\!]*\)", "", query) |
405 | + ## plpy.debug('9 query is %s' % repr(query)) |
406 | + |
407 | + # An & or | following a ( |
408 | + query = re.sub(r"(?u)(?<=\()[\&\|\s]+", "", query) |
409 | + ## plpy.debug('10 query is %s' % repr(query)) |
410 | + |
411 | + # An &, | or ! immediatly before a ) |
412 | + query = re.sub(r"(?u)[\&\|\!\s]*[\&\|\!]+\s*(?=\))", "", query) |
413 | + ## plpy.debug('11 query is %s' % repr(query)) |
414 | + |
415 | + # An &,| or ! followed by another boolean. |
416 | + query = re.sub(r"(?ux) \s* ( [\&\|\!] ) [\s\&\|]+", r"\1", query) |
417 | + ## plpy.debug('12 query is %s' % repr(query)) |
418 | + |
419 | + # Leading & or | |
420 | + query = re.sub(r"(?u)^[\s\&\|]+", "", query) |
421 | + ## plpy.debug('13 query is %s' % repr(query)) |
422 | + |
423 | + # Trailing &, | or ! |
424 | + query = re.sub(r"(?u)[\&\|\!\s]+$", "", query) |
425 | + ## plpy.debug('14 query is %s' % repr(query)) |
426 | + |
427 | + # If we have nothing but whitespace and tsearch2 operators, |
428 | + # return NULL. |
429 | + if re.search(r"(?u)^[\&\|\!\s\(\)]*$", query) is not None: |
430 | + return None |
431 | + |
432 | + # Convert back to UTF-8 |
433 | + query = query.encode('utf8') |
434 | + ## plpy.debug('15 query is %s' % repr(query)) |
435 | + |
436 | + return query or None |
437 | + $_$; |
438 | + |
439 | + |
440 | +-- From 2209-53-1 |
441 | +CREATE OR REPLACE FUNCTION activity() |
442 | +RETURNS SETOF pg_stat_activity |
443 | +VOLATILE SECURITY DEFINER SET search_path = public |
444 | +LANGUAGE plpgsql AS $$ |
445 | +DECLARE |
446 | + a pg_stat_activity%ROWTYPE; |
447 | +BEGIN |
448 | + IF EXISTS ( |
449 | + SELECT 1 FROM pg_attribute WHERE |
450 | + attrelid = |
451 | + (SELECT oid FROM pg_class |
452 | + WHERE relname = 'pg_stat_activity') |
453 | + AND attname = 'wait_event_type') THEN |
454 | + -- >= 9.6 |
455 | + RETURN QUERY SELECT |
456 | + datid, datname, pid, usesysid, usename, application_name, |
457 | + client_addr, client_hostname, client_port, backend_start, |
458 | + xact_start, query_start, state_change, wait_event_type, |
459 | + wait_event, state, backend_xid, backend_xmin, |
460 | + CASE |
461 | + WHEN query LIKE '<IDLE>%' |
462 | + OR query LIKE 'autovacuum:%' |
463 | + THEN query |
464 | + ELSE |
465 | + '<HIDDEN>' |
466 | + END AS query |
467 | + FROM pg_catalog.pg_stat_activity; |
468 | + ELSIF EXISTS ( |
469 | + SELECT 1 FROM pg_attribute WHERE |
470 | + attrelid = |
471 | + (SELECT oid FROM pg_class |
472 | + WHERE relname = 'pg_stat_activity') |
473 | + AND attname = 'backend_xid') THEN |
474 | + -- >= 9.4 |
475 | + RETURN QUERY SELECT |
476 | + datid, datname, pid, usesysid, usename, application_name, |
477 | + client_addr, client_hostname, client_port, backend_start, |
478 | + xact_start, query_start, state_change, waiting, state, |
479 | + backend_xid, backend_xmin, |
480 | + CASE |
481 | + WHEN query LIKE '<IDLE>%' |
482 | + OR query LIKE 'autovacuum:%' |
483 | + THEN query |
484 | + ELSE |
485 | + '<HIDDEN>' |
486 | + END AS query |
487 | + FROM pg_catalog.pg_stat_activity; |
488 | + ELSE |
489 | + -- >= 9.2; anything older is unsupported |
490 | + RETURN QUERY SELECT |
491 | + datid, datname, pid, usesysid, usename, application_name, |
492 | + client_addr, client_hostname, client_port, backend_start, |
493 | + xact_start, query_start, state_change, waiting, state, |
494 | + CASE |
495 | + WHEN query LIKE '<IDLE>%' |
496 | + OR query LIKE 'autovacuum:%' |
497 | + THEN query |
498 | + ELSE |
499 | + '<HIDDEN>' |
500 | + END AS query |
501 | + FROM pg_catalog.pg_stat_activity; |
502 | + END IF; |
503 | +END; |
504 | +$$; |
505 | + |
506 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 81, 0); |
507 | |
508 | === modified file 'lib/lp/services/database/doc/textsearching.txt' |
509 | --- lib/lp/services/database/doc/textsearching.txt 2016-01-26 15:47:37 +0000 |
510 | +++ lib/lp/services/database/doc/textsearching.txt 2016-11-14 12:11:11 +0000 |
511 | @@ -340,14 +340,12 @@ |
512 | |
513 | XXX Abel Deuring 2012-06-20 bug=1015519: XML tags cannot be searched. |
514 | |
515 | - >>> print search_same('foo <bar> baz') |
516 | - FTI data: 'baz':2 'foo':1 query: 'foo' & 'baz' match: True |
517 | - |
518 | -More specifically, tags are simply dropped from the FTI data and from |
519 | -search queries. |
520 | +Tags are simply dropped from the FTI data. The terms show up without |
521 | +brackets in parsed queries as a consequence of phrase operator stripping |
522 | +added for PostgreSQL 9.6. |
523 | |
524 | >>> print search('some text <div>whatever</div>', '<div>') |
525 | - FTI data: 'text':2 'whatev':3 query: None match: None |
526 | + FTI data: 'text':2 'whatev':3 query: 'div' match: False |
527 | |
528 | Of course, omitting '<' and '>'from the query does not help. |
529 | |
530 | |
531 | === modified file 'utilities/launchpad-database-setup' |
532 | --- utilities/launchpad-database-setup 2014-12-20 16:38:50 +0000 |
533 | +++ utilities/launchpad-database-setup 2016-11-14 12:11:11 +0000 |
534 | @@ -18,7 +18,7 @@ |
535 | # https://dev.launchpad.net/DatabaseSetup which are intended for |
536 | # initial Launchpad setup on an otherwise unconfigured postgresql instance |
537 | |
538 | -for pgversion in 9.1 9.3 |
539 | +for pgversion in 9.3 9.5 9.6 |
540 | do |
541 | sudo grep -qs "^auto" /etc/postgresql/$pgversion/main/start.conf |
542 | if [ $? -eq 0 ]; then |