-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathpowa--5.0.1--5.0.2.sql
393 lines (344 loc) · 14.5 KB
/
powa--5.0.1--5.0.2.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION powa" to load this file. \quit
CREATE OR REPLACE FUNCTION @[email protected]_take_snapshot(_srvid integer = 0) RETURNS integer
AS $PROC$
DECLARE
purgets timestamp with time zone;
purge_seq bigint;
r record;
v_state text;
v_msg text;
v_detail text;
v_hint text;
v_context text;
v_title text = 'PoWA - ';
v_rowcount bigint;
v_nb_err int = 0;
v_errs text[] = '{}';
v_pattern text = '@[email protected]_take_snapshot(%s): function %s.%I failed:
state : %s
message: %s
detail : %s
hint : %s
context: %s';
v_pattern_simple text = '@[email protected]_take_snapshot(%s): function %s.%I failed: %s';
v_pattern_cat text = '@[email protected]_take_snapshot(%s): function @[email protected]_catalog_generic_snapshot for catalog %s failed:
state : %s
message: %s
detail : %s
hint : %s
context: %s';
v_pattern_cat_simple text = '@[email protected]_take_snapshot(%s): function @[email protected]_catalog_generic_snapshot for catalog %s failed: %s';
v_coalesce bigint;
v_catname text;
BEGIN
PERFORM set_config('application_name',
v_title || ' snapshot database list',
false);
PERFORM @[email protected]_log('start of powa_take_snapshot(' || _srvid || ')');
PERFORM @[email protected]_prevent_concurrent_snapshot(_srvid);
UPDATE @[email protected]_snapshot_metas
SET coalesce_seq = coalesce_seq + 1,
errors = NULL,
snapts = now()
WHERE srvid = _srvid
RETURNING coalesce_seq INTO purge_seq;
PERFORM @[email protected]_log(format('coalesce_seq(%s): %s', _srvid, purge_seq));
IF (_srvid = 0) THEN
SELECT current_setting('powa.coalesce') INTO v_coalesce;
ELSE
SELECT powa_coalesce
FROM @[email protected]_servers
WHERE id = _srvid
INTO v_coalesce;
END IF;
-- For all enabled snapshot functions in the powa_functions table, execute
FOR r IN SELECT CASE external
WHEN true THEN quote_ident(nsp.nspname)
ELSE '@extschema@'
END AS schema, function_name AS funcname
FROM @[email protected]_all_functions AS pf
LEFT JOIN pg_extension AS ext ON pf.kind = 'extension'
AND ext.extname = pf.name
LEFT JOIN pg_namespace AS nsp ON nsp.oid = ext.extnamespace
WHERE operation='snapshot'
AND enabled
AND srvid = _srvid
ORDER BY priority, name
LOOP
-- Call all of them, for the current srvid
BEGIN
PERFORM @[email protected]_log(format('calling snapshot function: %s.%I',
r.schema, r.funcname));
PERFORM set_config('application_name',
v_title || quote_ident(r.funcname) || '(' || _srvid || ')', false);
EXECUTE format('SELECT %s.%I(%s)', r.schema, r.funcname, _srvid);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_state = RETURNED_SQLSTATE,
v_msg = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL,
v_hint = PG_EXCEPTION_HINT,
v_context = PG_EXCEPTION_CONTEXT;
RAISE warning '%', format(v_pattern, _srvid, r.schema, r.funcname,
v_state, v_msg, v_detail, v_hint, v_context);
v_errs := array_append(v_errs, format(v_pattern_simple, _srvid,
r.schema, r.funcname, v_msg));
v_nb_err = v_nb_err + 1;
END;
END LOOP;
-- Coalesce datas if needed. The _srvid % 20 is there to avoid having all coalesces run at once
IF ( ((purge_seq + (_srvid % 20) ) % v_coalesce ) = 0 )
THEN
PERFORM @[email protected]_log(
format('coalesce needed, srvid: %s - seq: %s - coalesce seq: %s',
_srvid, purge_seq, v_coalesce ));
FOR r IN SELECT CASE external
WHEN true THEN quote_ident(nsp.nspname)
ELSE '@extschema@'
END AS schema, function_name AS funcname
FROM @[email protected]_all_functions AS pf
LEFT JOIN pg_extension AS ext ON pf.kind = 'extension'
AND ext.extname = pf.name
LEFT JOIN pg_namespace AS nsp ON nsp.oid = ext.extnamespace
WHERE operation='aggregate'
AND enabled
AND srvid = _srvid
ORDER BY priority, name
LOOP
-- Call all of them, for the current srvid
BEGIN
PERFORM @[email protected]_log(format('calling aggregate function: %s.%I(%s)',
r.schema, r.funcname, _srvid));
PERFORM set_config('application_name',
v_title || quote_ident(r.funcname) || '(' || _srvid || ')',
false);
EXECUTE format('SELECT %s.%I(%s)', r.schema, r.funcname, _srvid);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_state = RETURNED_SQLSTATE,
v_msg = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL,
v_hint = PG_EXCEPTION_HINT,
v_context = PG_EXCEPTION_CONTEXT;
RAISE warning '%', format(v_pattern, _srvid, r.schema, r.funcname,
v_state, v_msg, v_detail, v_hint, v_context);
v_errs := array_append(v_errs, format(v_pattern_simple, _srvid,
r.schema, r.funcname, v_msg));
v_nb_err = v_nb_err + 1;
END;
END LOOP;
PERFORM set_config('application_name',
v_title || 'UPDATE powa_snapshot_metas.aggets',
false);
UPDATE @[email protected]_snapshot_metas
SET aggts = now()
WHERE srvid = _srvid;
END IF;
-- We also purge, at the pass after the coalesce
-- The _srvid % 20 is there to avoid having all purges run at once
IF ( ((purge_seq + (_srvid % 20)) % v_coalesce) = 1 )
THEN
PERFORM @[email protected]_log(
format('purge needed, srvid: %s - seq: %s coalesce seq: %s',
_srvid, purge_seq, v_coalesce));
FOR r IN SELECT CASE external
WHEN true THEN quote_ident(nsp.nspname)
ELSE '@extschema@'
END AS schema, function_name AS funcname
FROM @[email protected]_all_functions AS pf
LEFT JOIN pg_extension AS ext ON pf.kind = 'extension'
AND ext.extname = pf.name
LEFT JOIN pg_namespace AS nsp ON nsp.oid = ext.extnamespace
WHERE operation='purge'
AND enabled
AND srvid = _srvid
ORDER BY priority, name
LOOP
-- Call all of them, for the current srvid
BEGIN
PERFORM @[email protected]_log(format('calling purge function: %s.%I(%s)',
r.schema, r.funcname, _srvid));
PERFORM set_config('application_name',
v_title || quote_ident(r.funcname) || '(' || _srvid || ')',
false);
EXECUTE format('SELECT %s.%I(%s)', r.schema, r.funcname, _srvid);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_state = RETURNED_SQLSTATE,
v_msg = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL,
v_hint = PG_EXCEPTION_HINT,
v_context = PG_EXCEPTION_CONTEXT;
RAISE warning '%', format(v_pattern, _srvid, r.schema, r.funcname,
v_state, v_msg, v_detail, v_hint, v_context);
v_errs := array_append(v_errs, format(v_pattern_simple, _srvid,
r.schema, r.funcname, v_msg));
v_nb_err = v_nb_err + 1;
END;
END LOOP;
PERFORM set_config('application_name',
v_title || 'UPDATE powa_snapshot_metas.purgets',
false);
UPDATE @[email protected]_snapshot_metas
SET purgets = now()
WHERE srvid = _srvid;
END IF;
-- and finally we call the snapshot function for the per-db catalog import,
-- if this is a remote server
IF (_srvid != 0) THEN
FOR v_catname IN SELECT catname FROM @[email protected]_catalogs ORDER BY priority
LOOP
PERFORM @[email protected]_log(format('calling catalog function: %s.%I(%s, %s)',
'@extschema@', 'powa_catalog_generic_snapshot', _srvid, v_catname));
PERFORM set_config('application_name',
v_title || quote_ident('powa_catalog_generic_snapshot')
|| '(' || _srvid || ', ' || v_catname || ')', false);
BEGIN
PERFORM @[email protected]_catalog_generic_snapshot(_srvid, v_catname);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_state = RETURNED_SQLSTATE,
v_msg = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL,
v_hint = PG_EXCEPTION_HINT,
v_context = PG_EXCEPTION_CONTEXT;
RAISE warning '%', format(v_pattern_cat, _srvid, v_catname,
v_state, v_msg, v_detail, v_hint, v_context);
v_errs := array_append(v_errs, format(v_pattern_cat_simple, _srvid,
v_catname, v_msg));
v_nb_err = v_nb_err + 1;
END;
END LOOP;
END IF;
IF (v_nb_err > 0) THEN
UPDATE @[email protected]_snapshot_metas
SET errors = v_errs
WHERE srvid = _srvid;
END IF;
PERFORM @[email protected]_log('end of powa_take_snapshot(' || _srvid || ')');
PERFORM set_config('application_name',
v_title || 'snapshot finished',
false);
return v_nb_err;
END;
$PROC$ LANGUAGE plpgsql
SET search_path = pg_catalog; /* end of powa_take_snapshot(int) */
CREATE OR REPLACE FUNCTION @[email protected]_check_created_extensions()
RETURNS event_trigger
LANGUAGE plpgsql
AS $_$
DECLARE
v_extname text;
v_res bool;
BEGIN
SELECT extname INTO v_extname
FROM pg_event_trigger_ddl_commands() d
JOIN pg_extension e ON d.classid = 'pg_extension'::regclass
AND d.objid = e.oid
JOIN @[email protected]_extensions p USING (extname)
WHERE d.object_type = 'extension';
-- Bail out if this isn't a known extension
IF (v_extname IS NULL) THEN
RETURN;
END IF;
RAISE LOG 'powa: automatically activing extension %', v_extname;
SELECT @[email protected]_activate_extension(0, v_extname) INTO v_res;
IF (NOT v_res) THEN
RAISE WARNING 'Could not automatically activate extension "%"', v_extname;
END IF;
END;
$_$
SET search_path = pg_catalog; /* end of powa_check_created_extensions */
CREATE OR REPLACE FUNCTION @[email protected]_check_dropped_extensions()
RETURNS event_trigger
LANGUAGE plpgsql
AS $_$
DECLARE
v_extname text;
v_state text;
v_msg text;
v_detail text;
v_hint text;
v_context text;
BEGIN
-- We unregister extensions regardless the "enabled" field
FOR v_extname IN SELECT pe.extname
FROM pg_event_trigger_dropped_objects() d
LEFT JOIN @[email protected]_extensions pe ON pe.extname = d.object_name
WHERE d.object_type = 'extension'
LOOP
BEGIN
RAISE LOG 'powa: automatically deactiving extension %', v_extname;
PERFORM @[email protected]_deactivate_extension(0, v_extname);
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_state = RETURNED_SQLSTATE,
v_msg = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL,
v_hint = PG_EXCEPTION_HINT,
v_context = PG_EXCEPTION_CONTEXT;
RAISE WARNING 'Could not deactivate extension %:"
state : %
message: %
detail : %
hint : %
context: %', v_extname, v_state, v_msg, v_detail, v_hint,
v_context;
END;
END LOOP;
END;
$_$
SET search_path = pg_catalog; /* end of powa_check_dropped_extensions */
CREATE OR REPLACE FUNCTION @[email protected]_user_functions_aggregate(_srvid integer)
RETURNS void AS $PROC$
DECLARE
v_funcname text := format('@extschema@.%I(%s)',
'powa_user_functions_aggregate', _srvid);
v_rowcount bigint;
BEGIN
PERFORM @[email protected]_log('running powa_user_functions_aggregate(' || _srvid ||')');
PERFORM @[email protected]_prevent_concurrent_snapshot(_srvid);
-- aggregate user_functions table
INSERT INTO @[email protected]_user_functions_history
(srvid, dbid, funcid, coalesce_range, records,
mins_in_range, maxs_in_range)
SELECT srvid, dbid, funcid,
tstzrange(min((record).ts), max((record).ts),'[]'),
array_agg(record),
ROW(min((record).ts), min((record).calls),min((record).total_time),
min((record).self_time))::@[email protected]_user_functions_history_record,
ROW(max((record).ts), max((record).calls),max((record).total_time),
max((record).self_time))::@[email protected]_user_functions_history_record
FROM @[email protected]_user_functions_history_current
WHERE srvid = _srvid
GROUP BY srvid, dbid, funcid;
GET DIAGNOSTICS v_rowcount = ROW_COUNT;
PERFORM @[email protected]_log(format('%s - (powa_user_functions_history_current) rowcount: %s',
v_funcname, v_rowcount));
DELETE FROM @[email protected]_user_functions_history_current WHERE srvid = _srvid;
-- aggregate user_functions_db table
INSERT INTO @[email protected]_user_functions_history_db
(srvid, dbid, coalesce_range, records, mins_in_range, maxs_in_range)
SELECT srvid, dbid,
tstzrange(min((record).ts), max((record).ts),'[]'),
array_agg(record),
ROW(min((record).ts), min((record).calls),min((record).total_time),
min((record).self_time))::@[email protected]_user_functions_history_record,
ROW(max((record).ts), max((record).calls),max((record).total_time),
max((record).self_time))::@[email protected]_user_functions_history_record
FROM @[email protected]_user_functions_history_current_db
WHERE srvid = _srvid
GROUP BY srvid, dbid;
GET DIAGNOSTICS v_rowcount = ROW_COUNT;
PERFORM @[email protected]_log(format('%s - (powa_user_functions_history_current_db) rowcount: %s',
v_funcname, v_rowcount));
DELETE FROM @[email protected]_user_functions_history_current_db WHERE srvid = _srvid;
END;
$PROC$ LANGUAGE plpgsql
SET search_path = pg_catalog; /* end of powa_user_functions_aggregate */