-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathaiven_extras--1.1.16--1.1.17.sql
More file actions
632 lines (564 loc) · 20.3 KB
/
Copy pathaiven_extras--1.1.16--1.1.17.sql
File metadata and controls
632 lines (564 loc) · 20.3 KB
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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
DO LANGUAGE plpgsql
$OUTER$
DECLARE
my_schema pg_catalog.TEXT := pg_catalog.quote_ident(pg_catalog.current_schema());
old_path pg_catalog.TEXT := pg_catalog.current_setting('search_path');
BEGIN
-- for safety, transiently set search_path to just pg_catalog+pg_temp
PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true);
PERFORM 1
FROM pg_catalog.pg_type AS t JOIN pg_catalog.pg_roles AS r ON (r.oid OPERATOR(pg_catalog.=) t.typowner)
WHERE r.rolsuper
AND t.typnamespace OPERATOR(pg_catalog.=) 'aiven_extras'::regnamespace
AND t.typname OPERATOR(pg_catalog.=) 'aiven_pg_subscription';
IF NOT FOUND THEN
CREATE TYPE aiven_extras.aiven_pg_subscription AS (
subdbid OID,
subname NAME,
subowner OID,
subenabled BOOLEAN,
subconninfo TEXT,
subslotname NAME,
subsynccommit TEXT,
subpublications TEXT[]
);
END IF;
PERFORM 1
FROM pg_catalog.pg_type AS t JOIN pg_catalog.pg_roles AS r ON (r.oid = t.typowner)
WHERE r.rolsuper
AND typnamespace OPERATOR(pg_catalog.=) 'aiven_extras'::regnamespace
AND typname OPERATOR(pg_catalog.=) 'aiven_pg_stat_replication';
IF NOT FOUND THEN
CREATE TYPE aiven_extras.aiven_pg_stat_replication AS (
pid INT,
usesysid OID,
usename NAME,
application_name TEXT,
client_addr INET,
client_hostname TEXT,
client_port INT,
backend_start TIMESTAMP WITH TIME ZONE,
backend_xmin XID,
state TEXT,
sent_lsn PG_LSN,
write_lsn PG_LSN,
flush_lsn PG_LSN,
replay_lsn PG_LSN,
write_lag INTERVAL,
flush_lag INTERVAL,
replay_lag INTERVAL,
sync_priority INTEGER,
sync_state TEXT
);
END IF;
DROP FUNCTION IF EXISTS aiven_extras.dblink_record_execute(TEXT, TEXT);
CREATE FUNCTION aiven_extras.dblink_record_execute(TEXT, TEXT)
RETURNS SETOF record LANGUAGE c
PARALLEL RESTRICTED STRICT
AS '$libdir/dblink', $$dblink_record$$;
DROP FUNCTION IF EXISTS aiven_extras.dblink_slot_create_or_drop(TEXT, TEXT, TEXT);
CREATE FUNCTION aiven_extras.dblink_slot_create_or_drop(
arg_connection_string TEXT,
arg_slot_name TEXT,
arg_action TEXT
)
RETURNS VOID LANGUAGE plpgsql
SET search_path = pg_catalog
AS $$
DECLARE
l_clear_search_path TEXT := 'SET search_path TO pg_catalog, pg_temp;';
l_slot_existence_query TEXT := pg_catalog.format('SELECT TRUE FROM pg_catalog.pg_replication_slots WHERE slot_name OPERATOR(pg_catalog.=) %L', arg_slot_name);
l_slot_action_query TEXT;
l_slot_exists BOOLEAN;
BEGIN
SELECT res INTO l_slot_exists
FROM aiven_extras.dblink_record_execute(
arg_connection_string,
l_clear_search_path || l_slot_existence_query
) AS d (res BOOLEAN);
IF arg_action OPERATOR(pg_catalog.=) 'create' AND l_slot_exists IS NOT TRUE THEN
l_slot_action_query := pg_catalog.format('SELECT TRUE FROM pg_catalog.pg_create_logical_replication_slot(%L, %L, FALSE)', arg_slot_name, 'pgoutput');
ELSIF arg_action OPERATOR(pg_catalog.=) 'drop' AND l_slot_exists IS TRUE THEN
l_slot_action_query := pg_catalog.format('SELECT TRUE FROM pg_catalog.pg_drop_replication_slot(%L)', arg_slot_name);
END IF;
IF l_slot_action_query IS NOT NULL THEN
PERFORM 1
FROM aiven_extras.dblink_record_execute(
arg_connection_string,
l_clear_search_path || l_slot_action_query
) AS d (res BOOLEAN);
END IF;
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_create_subscription(TEXT, TEXT, TEXT, TEXT, BOOLEAN, BOOLEAN, TEXT);
DROP FUNCTION IF EXISTS aiven_extras.pg_create_subscription(TEXT, TEXT, TEXT, TEXT, BOOLEAN, BOOLEAN);
CREATE FUNCTION aiven_extras.pg_create_subscription(
arg_subscription_name TEXT,
arg_connection_string TEXT,
arg_publication_name TEXT,
arg_slot_name TEXT,
arg_slot_create BOOLEAN = FALSE,
arg_copy_data BOOLEAN = TRUE,
arg_origin TEXT = 'any'
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
DECLARE
pg_version INT;
create_subscription_cmd TEXT;
BEGIN
-- Get the PostgreSQL version
SELECT pg_catalog.current_setting('server_version_num')::INT INTO pg_version;
IF pg_version OPERATOR(pg_catalog.<) 160000 AND arg_origin OPERATOR(pg_catalog.<>) 'any' THEN
RAISE EXCEPTION 'PostgreSQL version must be 16 or higher to specify origin other than "any". Current version: %', pg_version;
END IF;
IF arg_origin OPERATOR(pg_catalog.<>) 'any' AND arg_origin OPERATOR(pg_catalog.<>) 'none' THEN
RAISE EXCEPTION 'Invalid origin: %. Origin must be either "any" or "none".', arg_origin;
END IF;
IF (arg_slot_create IS TRUE) THEN
PERFORM aiven_extras.dblink_slot_create_or_drop(arg_connection_string, arg_slot_name, 'create');
END IF;
-- PG16 and later: Include the origin parameter only if it's 'none', as its default is any
IF pg_version OPERATOR(pg_catalog.>=) 160000 AND arg_origin OPERATOR(pg_catalog.=) 'none' THEN
create_subscription_cmd := pg_catalog.format(
'CREATE SUBSCRIPTION %I CONNECTION %L PUBLICATION %I WITH (slot_name=%L, create_slot=FALSE, copy_data=%s, origin=%L)',
arg_subscription_name, arg_connection_string, arg_publication_name, arg_slot_name, arg_copy_data::TEXT, arg_origin);
ELSE
create_subscription_cmd := pg_catalog.format(
'CREATE SUBSCRIPTION %I CONNECTION %L PUBLICATION %I WITH (slot_name=%L, create_slot=FALSE, copy_data=%s)',
arg_subscription_name, arg_connection_string, arg_publication_name, arg_slot_name, arg_copy_data::TEXT);
END IF;
-- Execute the CREATE SUBSCRIPTION command
EXECUTE create_subscription_cmd;
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_alter_subscription_disable(TEXT);
CREATE FUNCTION aiven_extras.pg_alter_subscription_disable(
arg_subscription_name TEXT
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I DISABLE', arg_subscription_name);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_alter_subscription_enable(TEXT);
CREATE FUNCTION aiven_extras.pg_alter_subscription_enable(
arg_subscription_name TEXT
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I ENABLE', arg_subscription_name);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_alter_subscription_refresh_publication(TEXT, BOOLEAN);
CREATE FUNCTION aiven_extras.pg_alter_subscription_refresh_publication(
arg_subscription_name TEXT,
arg_copy_data BOOLEAN = TRUE
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
PERFORM aiven_extras.dblink_record_execute(
pg_catalog.format('user=%L dbname=%L port=%L', current_user, pg_catalog.current_database(), (SELECT setting FROM pg_catalog.pg_settings WHERE name OPERATOR(pg_catalog.=) 'port')),
pg_catalog.format('ALTER SUBSCRIPTION %I REFRESH PUBLICATION WITH (copy_data=%s)', arg_subscription_name, arg_copy_data::TEXT)
);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_drop_subscription(TEXT);
DROP FUNCTION IF EXISTS aiven_extras.pg_drop_subscription(TEXT, BOOLEAN);
CREATE FUNCTION aiven_extras.pg_drop_subscription(
arg_subscription_name TEXT,
arg_drop_repl_slot BOOLEAN = TRUE
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
DECLARE
l_slot_name TEXT;
l_subconninfo TEXT;
BEGIN
SELECT subslotname, subconninfo
INTO l_slot_name, l_subconninfo
FROM pg_catalog.pg_subscription
WHERE subname = arg_subscription_name;
IF l_slot_name IS NULL AND l_subconninfo IS NULL THEN
RAISE EXCEPTION 'No subscription found for name: %', arg_subscription_name;
END IF;
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I DISABLE', arg_subscription_name);
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I SET (slot_name = NONE)', arg_subscription_name);
EXECUTE pg_catalog.format('DROP SUBSCRIPTION %I', arg_subscription_name);
IF (arg_drop_repl_slot IS TRUE) THEN
PERFORM aiven_extras.dblink_slot_create_or_drop(l_subconninfo, l_slot_name, 'drop');
END IF;
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_create_publication_for_all_tables(TEXT, TEXT);
CREATE FUNCTION aiven_extras.pg_create_publication_for_all_tables(
arg_publication_name TEXT,
arg_publish TEXT
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
EXECUTE pg_catalog.format('CREATE PUBLICATION %I FOR ALL TABLES WITH (publish = %I)', arg_publication_name, arg_publish);
EXECUTE pg_catalog.format('ALTER PUBLICATION %I OWNER TO %I', arg_publication_name, session_user);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.pg_list_all_subscriptions();
CREATE FUNCTION aiven_extras.pg_list_all_subscriptions()
RETURNS SETOF aiven_extras.aiven_pg_subscription LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN QUERY
SELECT subdbid, subname, subowner, subenabled, subconninfo, subslotname, subsynccommit, subpublications
FROM pg_catalog.pg_subscription;
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.session_replication_role(TEXT);
CREATE FUNCTION aiven_extras.session_replication_role(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('session_replication_role', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.auto_explain_load();
CREATE FUNCTION aiven_extras.auto_explain_load()
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
LOAD 'auto_explain';
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_analyze(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_analyze(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_analyze', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_format(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_format(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_format', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_min_duration(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_min_duration(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_min_duration', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_timing(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_timing(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_timing', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_buffers(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_buffers(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_buffers', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_verbose(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_verbose(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_verbose', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_auto_explain_log_nested_statements(TEXT);
CREATE FUNCTION aiven_extras.set_auto_explain_log_nested_statements(
arg_parameter TEXT
)
RETURNS TEXT LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN pg_catalog.set_config('auto_explain.log_nested_statements', arg_parameter, false);
END
$$;
DROP FUNCTION IF EXISTS aiven_extras.claim_public_schema_ownership();
CREATE FUNCTION aiven_extras.claim_public_schema_ownership()
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
EXECUTE pg_catalog.format('ALTER SCHEMA public OWNER TO %I', session_user);
END;
$$;
-- Temporarily clear out the view so we can replace the function behind it
CREATE OR REPLACE VIEW aiven_extras.pg_stat_replication AS
SELECT
NULL::INT AS pid,
NULL::OID AS usesysid,
NULL::NAME AS usename,
NULL::TEXT AS application_name,
NULL::INET AS client_addr,
NULL::TEXT AS client_hostname,
NULL::INT AS client_port,
NULL::TIMESTAMPTZ AS backend_start,
NULL::XID AS backend_xmin,
NULL::TEXT AS state,
NULL::PG_LSN AS sent_lsn,
NULL::PG_LSN AS write_lsn,
NULL::PG_LSN AS flush_lsn,
NULL::PG_LSN AS replay_lsn,
NULL::INTERVAL AS write_lag,
NULL::INTERVAL AS flush_lag,
NULL::INTERVAL AS replay_lag,
NULL::INTEGER AS sync_priority,
NULL::TEXT AS sync_state;
DROP FUNCTION IF EXISTS aiven_extras.pg_stat_replication_list();
CREATE FUNCTION aiven_extras.pg_stat_replication_list()
RETURNS SETOF aiven_extras.aiven_pg_stat_replication LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
BEGIN
RETURN QUERY
SELECT pid, usesysid, usename, application_name, client_addr, client_hostname, client_port,
backend_start, backend_xmin, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag,
flush_lag, replay_lag, sync_priority, sync_state
FROM pg_catalog.pg_stat_replication
WHERE usename OPERATOR(pg_catalog.=) session_user;
END;
$$;
CREATE OR REPLACE VIEW aiven_extras.pg_stat_replication AS
SELECT pid, usesysid, usename, application_name, client_addr, client_hostname, client_port,
backend_start, backend_xmin, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag,
flush_lag, replay_lag, sync_priority, sync_state
FROM aiven_extras.pg_stat_replication_list();
DROP FUNCTION IF EXISTS aiven_extras.pg_create_publication(TEXT, TEXT, VARIADIC TEXT[]);
CREATE FUNCTION aiven_extras.pg_create_publication(
arg_publication_name TEXT,
arg_publish TEXT,
VARIADIC arg_tables TEXT[] DEFAULT ARRAY[]::TEXT[]
)
RETURNS VOID LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog
AS $$
DECLARE
l_ident TEXT;
l_table_count INT;
l_tables_command TEXT;
l_parsed_ident TEXT[];
l_parsed_arg_tables TEXT[];
BEGIN
l_table_count = pg_catalog.array_length(arg_tables, 1);
IF l_table_count OPERATOR(pg_catalog.>=) 1
THEN
l_parsed_arg_tables = ARRAY[]::TEXT[];
l_tables_command = 'CREATE PUBLICATION %I FOR TABLE ';
FOREACH l_ident IN ARRAY arg_tables LOOP
l_parsed_ident = parse_ident(l_ident);
ASSERT pg_catalog.array_length(l_parsed_ident, 1) OPERATOR(pg_catalog.<=) 2, 'Only simple table names or tables qualified with schema names allowed';
-- Make sure we pass in a simple list of identifiers, so separate the tables from parent schemas
IF pg_catalog.array_length(l_parsed_ident, 1) OPERATOR(pg_catalog.=) 2
THEN
l_tables_command = l_tables_command || '%I.%I, ';
ELSE
l_tables_command = l_tables_command || '%I, ';
END IF;
l_parsed_arg_tables = l_parsed_arg_tables || l_parsed_ident;
END LOOP;
-- Remove trailing comma and whitespace, add the rest
l_tables_command = pg_catalog.left(l_tables_command, -2) || ' WITH (publish = %I)';
EXECUTE pg_catalog.format(l_tables_command, VARIADIC array[arg_publication_name] || l_parsed_arg_tables || arg_publish);
ELSE
EXECUTE pg_catalog.format('CREATE PUBLICATION %I WITH (publish = %I)', arg_publication_name, arg_publish);
END IF;
EXECUTE pg_catalog.format('ALTER PUBLICATION %I OWNER TO %I', arg_publication_name, session_user);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_pgaudit_parameter(TEXT, TEXT, TEXT);
CREATE FUNCTION aiven_extras.set_pgaudit_parameter(
arg_parameter TEXT,
arg_database TEXT,
arg_value TEXT
)
RETURNS VOID LANGUAGE plpgsql
SET search_path = pg_catalog
AS $$
BEGIN
IF pg_catalog.current_setting('server_version_num')::int OPERATOR(pg_catalog.>=) 150000 THEN
RAISE WARNING 'This function is deprecated, changing superuser-reserved GUC is now grantable to roles';
END IF;
IF COALESCE(
(SELECT usesuper
FROM pg_catalog.pg_database d
JOIN pg_catalog.pg_user u
ON (u.usesysid OPERATOR(pg_catalog.=) d.datdba)
WHERE d.datname OPERATOR(pg_catalog.=) arg_database
LIMIT 1
),
TRUE
) THEN
RAISE EXCEPTION 'Invalid database: %', arg_database;
ELSIF arg_parameter NOT IN (
'log',
'log_catalog',
'log_max_string_length',
'log_nested_statements',
'log_parameter',
'log_relation',
'log_statement',
'log_statement_once'
) THEN
RAISE EXCEPTION 'Invalid parameter: %', arg_parameter;
END IF;
EXECUTE pg_catalog.format('ALTER DATABASE %I SET pgaudit.%I = %L',
arg_database,
arg_parameter,
arg_value
);
END;
$$;
DROP FUNCTION IF EXISTS aiven_extras.set_pgaudit_role_parameter(TEXT, TEXT, TEXT);
CREATE FUNCTION aiven_extras.set_pgaudit_role_parameter(
arg_parameter TEXT,
arg_role TEXT,
arg_value TEXT
)
RETURNS VOID LANGUAGE plpgsql
SET search_path = pg_catalog
AS $$
BEGIN
IF pg_catalog.current_setting('server_version_num')::int OPERATOR(pg_catalog.>=) 150000 THEN
RAISE WARNING 'This function is deprecated, changing superuser-reserved GUC is now grantable to roles';
END IF;
IF COALESCE(
(SELECT rolsuper
FROM pg_catalog.pg_roles
WHERE rolname OPERATOR(pg_catalog.=) arg_role
LIMIT 1
),
FALSE
) THEN
RAISE EXCEPTION 'Configuring superuser roles not allowed: %', arg_role;
ELSIF arg_parameter NOT IN (
'log',
'log_catalog',
'log_max_string_length',
'log_nested_statements',
'log_parameter',
'log_relation',
'log_statement',
'log_statement_once'
) THEN
RAISE EXCEPTION 'Invalid parameter: %', arg_parameter;
END IF;
EXECUTE pg_catalog.format('ALTER ROLE %I SET pgaudit.%I = %L',
arg_role,
arg_parameter,
arg_value
);
END;
$$;
DO $$
BEGIN
IF pg_catalog.current_setting('server_version_num')::int OPERATOR(pg_catalog.<) 150000 THEN
ALTER FUNCTION aiven_extras.set_pgaudit_parameter(text, text, text) SECURITY DEFINER;
ALTER FUNCTION aiven_extras.set_pgaudit_role_parameter(text, text, text) SECURITY DEFINER;
ELSE
ALTER FUNCTION aiven_extras.set_pgaudit_parameter(text, text, text) SECURITY INVOKER;
ALTER FUNCTION aiven_extras.set_pgaudit_role_parameter(text, text, text) SECURITY INVOKER;
END IF;
END;
$$ language plpgsql;
DROP FUNCTION IF EXISTS aiven_extras.explain_statement(TEXT);
CREATE FUNCTION aiven_extras.explain_statement(
arg_query TEXT,
OUT execution_plan JSON
)
RETURNS SETOF JSON
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql
AS $$
DECLARE
curs REFCURSOR;
plan JSON;
BEGIN
OPEN curs FOR EXECUTE pg_catalog.concat('EXPLAIN (FORMAT JSON) ', arg_query);
FETCH curs INTO plan;
CLOSE curs;
RETURN QUERY SELECT plan;
END;
$$;
-- THIS LINE ALWAYS NEEDS TO BE EXECUTED LAST IN FILE
PERFORM pg_catalog.set_config('search_path', old_path, true);
-- NO MORE CODE AFTER THIS
END;
$OUTER$;
-- standby slots functions
DROP FUNCTION IF EXISTS aiven_extras.pg_create_logical_replication_slot_on_standby(name, name, boolean, boolean, boolean, boolean);
CREATE FUNCTION aiven_extras.pg_create_logical_replication_slot_on_standby(
slot_name name,
plugin name,
temporary boolean DEFAULT false,
twophase boolean DEFAULT false,
failover boolean DEFAULT false,
synced boolean DEFAULT false,
OUT slot_name name, OUT lsn pg_lsn)
AS 'MODULE_PATHNAME', 'standby_slot_create'
LANGUAGE C;
DROP FUNCTION IF EXISTS aiven_extras.truncate_freespace_map(regclass);