Remove old RULE privilege completely.
[pgsql.git] / src / test / regress / expected / misc_functions.out
blob35fb72f302b57eeccd52c38427bae1f3039302c5
1 -- directory paths and dlsuffix are passed to us in environment variables
2 \getenv libdir PG_LIBDIR
3 \getenv dlsuffix PG_DLSUFFIX
4 \set regresslib :libdir '/regress' :dlsuffix
5 -- Function to assist with verifying EXPLAIN which includes costs.  A series
6 -- of bool flags allows control over which portions are masked out
7 CREATE FUNCTION explain_mask_costs(query text, do_analyze bool,
8     hide_costs bool, hide_row_est bool, hide_width bool) RETURNS setof text
9 LANGUAGE plpgsql AS
11 DECLARE
12     ln text;
13     analyze_str text;
14 BEGIN
15     IF do_analyze = true THEN
16         analyze_str := 'on';
17     ELSE
18         analyze_str := 'off';
19     END IF;
21     -- avoid jit related output by disabling it
22     SET LOCAL jit = 0;
24     FOR ln IN
25         EXECUTE format('explain (analyze %s, costs on, summary off, timing off) %s',
26             analyze_str, query)
27     LOOP
28         IF hide_costs = true THEN
29             ln := regexp_replace(ln, 'cost=\d+\.\d\d\.\.\d+\.\d\d', 'cost=N..N');
30         END IF;
32         IF hide_row_est = true THEN
33             -- don't use 'g' so that we leave the actual rows intact
34             ln := regexp_replace(ln, 'rows=\d+', 'rows=N');
35         END IF;
37         IF hide_width = true THEN
38             ln := regexp_replace(ln, 'width=\d+', 'width=N');
39         END IF;
41         RETURN NEXT ln;
42     END LOOP;
43 END;
44 $$;
46 -- num_nulls()
48 SELECT num_nonnulls(NULL);
49  num_nonnulls 
50 --------------
51             0
52 (1 row)
54 SELECT num_nonnulls('1');
55  num_nonnulls 
56 --------------
57             1
58 (1 row)
60 SELECT num_nonnulls(NULL::text);
61  num_nonnulls 
62 --------------
63             0
64 (1 row)
66 SELECT num_nonnulls(NULL::text, NULL::int);
67  num_nonnulls 
68 --------------
69             0
70 (1 row)
72 SELECT num_nonnulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL);
73  num_nonnulls 
74 --------------
75             4
76 (1 row)
78 SELECT num_nonnulls(VARIADIC '{1,2,NULL,3}'::int[]);
79  num_nonnulls 
80 --------------
81             3
82 (1 row)
84 SELECT num_nonnulls(VARIADIC '{"1","2","3","4"}'::text[]);
85  num_nonnulls 
86 --------------
87             4
88 (1 row)
90 SELECT num_nonnulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i));
91  num_nonnulls 
92 --------------
93            99
94 (1 row)
96 SELECT num_nulls(NULL);
97  num_nulls 
98 -----------
99          1
100 (1 row)
102 SELECT num_nulls('1');
103  num_nulls 
104 -----------
105          0
106 (1 row)
108 SELECT num_nulls(NULL::text);
109  num_nulls 
110 -----------
111          1
112 (1 row)
114 SELECT num_nulls(NULL::text, NULL::int);
115  num_nulls 
116 -----------
117          2
118 (1 row)
120 SELECT num_nulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL);
121  num_nulls 
122 -----------
123          3
124 (1 row)
126 SELECT num_nulls(VARIADIC '{1,2,NULL,3}'::int[]);
127  num_nulls 
128 -----------
129          1
130 (1 row)
132 SELECT num_nulls(VARIADIC '{"1","2","3","4"}'::text[]);
133  num_nulls 
134 -----------
135          0
136 (1 row)
138 SELECT num_nulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i));
139  num_nulls 
140 -----------
141          1
142 (1 row)
144 -- special cases
145 SELECT num_nonnulls(VARIADIC NULL::text[]);
146  num_nonnulls 
147 --------------
148              
149 (1 row)
151 SELECT num_nonnulls(VARIADIC '{}'::int[]);
152  num_nonnulls 
153 --------------
154             0
155 (1 row)
157 SELECT num_nulls(VARIADIC NULL::text[]);
158  num_nulls 
159 -----------
160           
161 (1 row)
163 SELECT num_nulls(VARIADIC '{}'::int[]);
164  num_nulls 
165 -----------
166          0
167 (1 row)
169 -- should fail, one or more arguments is required
170 SELECT num_nonnulls();
171 ERROR:  function num_nonnulls() does not exist
172 LINE 1: SELECT num_nonnulls();
173                ^
174 HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
175 SELECT num_nulls();
176 ERROR:  function num_nulls() does not exist
177 LINE 1: SELECT num_nulls();
178                ^
179 HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
181 -- canonicalize_path()
183 CREATE FUNCTION test_canonicalize_path(text)
184    RETURNS text
185    AS :'regresslib'
186    LANGUAGE C STRICT IMMUTABLE;
187 SELECT test_canonicalize_path('/');
188  test_canonicalize_path 
189 ------------------------
191 (1 row)
193 SELECT test_canonicalize_path('/./abc/def/');
194  test_canonicalize_path 
195 ------------------------
196  /abc/def
197 (1 row)
199 SELECT test_canonicalize_path('/./../abc/def');
200  test_canonicalize_path 
201 ------------------------
202  /abc/def
203 (1 row)
205 SELECT test_canonicalize_path('/./../../abc/def/');
206  test_canonicalize_path 
207 ------------------------
208  /abc/def
209 (1 row)
211 SELECT test_canonicalize_path('/abc/.././def/ghi');
212  test_canonicalize_path 
213 ------------------------
214  /def/ghi
215 (1 row)
217 SELECT test_canonicalize_path('/abc/./../def/ghi//');
218  test_canonicalize_path 
219 ------------------------
220  /def/ghi
221 (1 row)
223 SELECT test_canonicalize_path('/abc/def/../..');
224  test_canonicalize_path 
225 ------------------------
227 (1 row)
229 SELECT test_canonicalize_path('/abc/def/../../..');
230  test_canonicalize_path 
231 ------------------------
233 (1 row)
235 SELECT test_canonicalize_path('/abc/def/../../../../ghi/jkl');
236  test_canonicalize_path 
237 ------------------------
238  /ghi/jkl
239 (1 row)
241 SELECT test_canonicalize_path('.');
242  test_canonicalize_path 
243 ------------------------
245 (1 row)
247 SELECT test_canonicalize_path('./');
248  test_canonicalize_path 
249 ------------------------
251 (1 row)
253 SELECT test_canonicalize_path('./abc/..');
254  test_canonicalize_path 
255 ------------------------
257 (1 row)
259 SELECT test_canonicalize_path('abc/../');
260  test_canonicalize_path 
261 ------------------------
263 (1 row)
265 SELECT test_canonicalize_path('abc/../def');
266  test_canonicalize_path 
267 ------------------------
268  def
269 (1 row)
271 SELECT test_canonicalize_path('..');
272  test_canonicalize_path 
273 ------------------------
274  ..
275 (1 row)
277 SELECT test_canonicalize_path('../abc/def');
278  test_canonicalize_path 
279 ------------------------
280  ../abc/def
281 (1 row)
283 SELECT test_canonicalize_path('../abc/..');
284  test_canonicalize_path 
285 ------------------------
286  ..
287 (1 row)
289 SELECT test_canonicalize_path('../abc/../def');
290  test_canonicalize_path 
291 ------------------------
292  ../def
293 (1 row)
295 SELECT test_canonicalize_path('../abc/../../def/ghi');
296  test_canonicalize_path 
297 ------------------------
298  ../../def/ghi
299 (1 row)
301 SELECT test_canonicalize_path('./abc/./def/.');
302  test_canonicalize_path 
303 ------------------------
304  abc/def
305 (1 row)
307 SELECT test_canonicalize_path('./abc/././def/.');
308  test_canonicalize_path 
309 ------------------------
310  abc/def
311 (1 row)
313 SELECT test_canonicalize_path('./abc/./def/.././ghi/../../../jkl/mno');
314  test_canonicalize_path 
315 ------------------------
316  ../jkl/mno
317 (1 row)
320 -- pg_log_backend_memory_contexts()
322 -- Memory contexts are logged and they are not returned to the function.
323 -- Furthermore, their contents can vary depending on the timing. However,
324 -- we can at least verify that the code doesn't fail, and that the
325 -- permissions are set properly.
327 SELECT pg_log_backend_memory_contexts(pg_backend_pid());
328  pg_log_backend_memory_contexts 
329 --------------------------------
331 (1 row)
333 SELECT pg_log_backend_memory_contexts(pid) FROM pg_stat_activity
334   WHERE backend_type = 'checkpointer';
335  pg_log_backend_memory_contexts 
336 --------------------------------
338 (1 row)
340 CREATE ROLE regress_log_memory;
341 SELECT has_function_privilege('regress_log_memory',
342   'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- no
343  has_function_privilege 
344 ------------------------
346 (1 row)
348 GRANT EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer)
349   TO regress_log_memory;
350 SELECT has_function_privilege('regress_log_memory',
351   'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- yes
352  has_function_privilege 
353 ------------------------
355 (1 row)
357 SET ROLE regress_log_memory;
358 SELECT pg_log_backend_memory_contexts(pg_backend_pid());
359  pg_log_backend_memory_contexts 
360 --------------------------------
362 (1 row)
364 RESET ROLE;
365 REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer)
366   FROM regress_log_memory;
367 DROP ROLE regress_log_memory;
369 -- Test some built-in SRFs
371 -- The outputs of these are variable, so we can't just print their results
372 -- directly, but we can at least verify that the code doesn't fail.
374 select setting as segsize
375 from pg_settings where name = 'wal_segment_size'
376 \gset
377 select count(*) > 0 as ok from pg_ls_waldir();
378  ok 
379 ----
381 (1 row)
383 -- Test ProjectSet as well as FunctionScan
384 select count(*) > 0 as ok from (select pg_ls_waldir()) ss;
385  ok 
386 ----
388 (1 row)
390 -- Test not-run-to-completion cases.
391 select * from pg_ls_waldir() limit 0;
392  name | size | modification 
393 ------+------+--------------
394 (0 rows)
396 select count(*) > 0 as ok from (select * from pg_ls_waldir() limit 1) ss;
397  ok 
398 ----
400 (1 row)
402 select (w).size = :segsize as ok
403 from (select pg_ls_waldir() w) ss where length((w).name) = 24 limit 1;
404  ok 
405 ----
407 (1 row)
409 select count(*) >= 0 as ok from pg_ls_archive_statusdir();
410  ok 
411 ----
413 (1 row)
415 -- pg_read_file()
416 select length(pg_read_file('postmaster.pid')) > 20;
417  ?column? 
418 ----------
420 (1 row)
422 select length(pg_read_file('postmaster.pid', 1, 20));
423  length 
424 --------
425      20
426 (1 row)
428 -- Test missing_ok
429 select pg_read_file('does not exist'); -- error
430 ERROR:  could not open file "does not exist" for reading: No such file or directory
431 select pg_read_file('does not exist', true) IS NULL; -- ok
432  ?column? 
433 ----------
435 (1 row)
437 -- Test invalid argument
438 select pg_read_file('does not exist', 0, -1); -- error
439 ERROR:  requested length cannot be negative
440 select pg_read_file('does not exist', 0, -1, true); -- error
441 ERROR:  requested length cannot be negative
442 -- pg_read_binary_file()
443 select length(pg_read_binary_file('postmaster.pid')) > 20;
444  ?column? 
445 ----------
447 (1 row)
449 select length(pg_read_binary_file('postmaster.pid', 1, 20));
450  length 
451 --------
452      20
453 (1 row)
455 -- Test missing_ok
456 select pg_read_binary_file('does not exist'); -- error
457 ERROR:  could not open file "does not exist" for reading: No such file or directory
458 select pg_read_binary_file('does not exist', true) IS NULL; -- ok
459  ?column? 
460 ----------
462 (1 row)
464 -- Test invalid argument
465 select pg_read_binary_file('does not exist', 0, -1); -- error
466 ERROR:  requested length cannot be negative
467 select pg_read_binary_file('does not exist', 0, -1, true); -- error
468 ERROR:  requested length cannot be negative
469 -- pg_stat_file()
470 select size > 20, isdir from pg_stat_file('postmaster.pid');
471  ?column? | isdir 
472 ----------+-------
473  t        | f
474 (1 row)
476 -- pg_ls_dir()
477 select * from (select pg_ls_dir('.') a) a where a = 'base' limit 1;
478   a   
479 ------
480  base
481 (1 row)
483 -- Test missing_ok (second argument)
484 select pg_ls_dir('does not exist', false, false); -- error
485 ERROR:  could not open directory "does not exist": No such file or directory
486 select pg_ls_dir('does not exist', true, false); -- ok
487  pg_ls_dir 
488 -----------
489 (0 rows)
491 -- Test include_dot_dirs (third argument)
492 select count(*) = 1 as dot_found
493   from pg_ls_dir('.', false, true) as ls where ls = '.';
494  dot_found 
495 -----------
497 (1 row)
499 select count(*) = 1 as dot_found
500   from pg_ls_dir('.', false, false) as ls where ls = '.';
501  dot_found 
502 -----------
504 (1 row)
506 -- pg_timezone_names()
507 select * from (select (pg_timezone_names()).name) ptn where name='UTC' limit 1;
508  name 
509 ------
510  UTC
511 (1 row)
513 -- pg_tablespace_databases()
514 select count(*) > 0 from
515   (select pg_tablespace_databases(oid) as pts from pg_tablespace
516    where spcname = 'pg_default') pts
517   join pg_database db on pts.pts = db.oid;
518  ?column? 
519 ----------
521 (1 row)
524 -- Test replication slot directory functions
526 CREATE ROLE regress_slot_dir_funcs;
527 -- Not available by default.
528 SELECT has_function_privilege('regress_slot_dir_funcs',
529   'pg_ls_logicalsnapdir()', 'EXECUTE');
530  has_function_privilege 
531 ------------------------
533 (1 row)
535 SELECT has_function_privilege('regress_slot_dir_funcs',
536   'pg_ls_logicalmapdir()', 'EXECUTE');
537  has_function_privilege 
538 ------------------------
540 (1 row)
542 SELECT has_function_privilege('regress_slot_dir_funcs',
543   'pg_ls_replslotdir(text)', 'EXECUTE');
544  has_function_privilege 
545 ------------------------
547 (1 row)
549 GRANT pg_monitor TO regress_slot_dir_funcs;
550 -- Role is now part of pg_monitor, so these are available.
551 SELECT has_function_privilege('regress_slot_dir_funcs',
552   'pg_ls_logicalsnapdir()', 'EXECUTE');
553  has_function_privilege 
554 ------------------------
556 (1 row)
558 SELECT has_function_privilege('regress_slot_dir_funcs',
559   'pg_ls_logicalmapdir()', 'EXECUTE');
560  has_function_privilege 
561 ------------------------
563 (1 row)
565 SELECT has_function_privilege('regress_slot_dir_funcs',
566   'pg_ls_replslotdir(text)', 'EXECUTE');
567  has_function_privilege 
568 ------------------------
570 (1 row)
572 DROP ROLE regress_slot_dir_funcs;
574 -- Test adding a support function to a subject function
576 CREATE FUNCTION my_int_eq(int, int) RETURNS bool
577   LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE
578   AS $$int4eq$$;
579 -- By default, planner does not think that's selective
580 EXPLAIN (COSTS OFF)
581 SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1
582 WHERE my_int_eq(a.unique2, 42);
583                   QUERY PLAN                  
584 ----------------------------------------------
585  Hash Join
586    Hash Cond: (b.unique1 = a.unique1)
587    ->  Seq Scan on tenk1 b
588    ->  Hash
589          ->  Seq Scan on tenk1 a
590                Filter: my_int_eq(unique2, 42)
591 (6 rows)
593 -- With support function that knows it's int4eq, we get a different plan
594 CREATE FUNCTION test_support_func(internal)
595     RETURNS internal
596     AS :'regresslib', 'test_support_func'
597     LANGUAGE C STRICT;
598 ALTER FUNCTION my_int_eq(int, int) SUPPORT test_support_func;
599 EXPLAIN (COSTS OFF)
600 SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1
601 WHERE my_int_eq(a.unique2, 42);
602                    QUERY PLAN                    
603 -------------------------------------------------
604  Nested Loop
605    ->  Seq Scan on tenk1 a
606          Filter: my_int_eq(unique2, 42)
607    ->  Index Scan using tenk1_unique1 on tenk1 b
608          Index Cond: (unique1 = a.unique1)
609 (5 rows)
611 -- Also test non-default rowcount estimate
612 CREATE FUNCTION my_gen_series(int, int) RETURNS SETOF integer
613   LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE
614   AS $$generate_series_int4$$
615   SUPPORT test_support_func;
616 EXPLAIN (COSTS OFF)
617 SELECT * FROM tenk1 a JOIN my_gen_series(1,1000) g ON a.unique1 = g;
618                QUERY PLAN               
619 ----------------------------------------
620  Hash Join
621    Hash Cond: (g.g = a.unique1)
622    ->  Function Scan on my_gen_series g
623    ->  Hash
624          ->  Seq Scan on tenk1 a
625 (5 rows)
627 EXPLAIN (COSTS OFF)
628 SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g;
629                    QUERY PLAN                    
630 -------------------------------------------------
631  Nested Loop
632    ->  Function Scan on my_gen_series g
633    ->  Index Scan using tenk1_unique1 on tenk1 a
634          Index Cond: (unique1 = g.g)
635 (4 rows)
638 -- Test the SupportRequestRows support function for generate_series_timestamp()
640 -- Ensure the row estimate matches the actual rows
641 SELECT explain_mask_costs($$
642 SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '1 day') g(s);$$,
643 true, true, false, true);
644                                     explain_mask_costs                                    
645 ------------------------------------------------------------------------------------------
646  Function Scan on generate_series g  (cost=N..N rows=30 width=N) (actual rows=30 loops=1)
647 (1 row)
649 -- As above but with generate_series_timestamp
650 SELECT explain_mask_costs($$
651 SELECT * FROM generate_series(TIMESTAMP '2024-02-01', TIMESTAMP '2024-03-01', INTERVAL '1 day') g(s);$$,
652 true, true, false, true);
653                                     explain_mask_costs                                    
654 ------------------------------------------------------------------------------------------
655  Function Scan on generate_series g  (cost=N..N rows=30 width=N) (actual rows=30 loops=1)
656 (1 row)
658 -- As above but with generate_series_timestamptz_at_zone()
659 SELECT explain_mask_costs($$
660 SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '1 day', 'UTC') g(s);$$,
661 true, true, false, true);
662                                     explain_mask_costs                                    
663 ------------------------------------------------------------------------------------------
664  Function Scan on generate_series g  (cost=N..N rows=30 width=N) (actual rows=30 loops=1)
665 (1 row)
667 -- Ensure the estimated and actual row counts match when the range isn't
668 -- evenly divisible by the step
669 SELECT explain_mask_costs($$
670 SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '7 day') g(s);$$,
671 true, true, false, true);
672                                    explain_mask_costs                                   
673 ----------------------------------------------------------------------------------------
674  Function Scan on generate_series g  (cost=N..N rows=5 width=N) (actual rows=5 loops=1)
675 (1 row)
677 -- Ensure the estimates match when step is decreasing
678 SELECT explain_mask_costs($$
679 SELECT * FROM generate_series(TIMESTAMPTZ '2024-03-01', TIMESTAMPTZ '2024-02-01', INTERVAL '-1 day') g(s);$$,
680 true, true, false, true);
681                                     explain_mask_costs                                    
682 ------------------------------------------------------------------------------------------
683  Function Scan on generate_series g  (cost=N..N rows=30 width=N) (actual rows=30 loops=1)
684 (1 row)
686 -- Ensure an empty range estimates 1 row
687 SELECT explain_mask_costs($$
688 SELECT * FROM generate_series(TIMESTAMPTZ '2024-03-01', TIMESTAMPTZ '2024-02-01', INTERVAL '1 day') g(s);$$,
689 true, true, false, true);
690                                    explain_mask_costs                                   
691 ----------------------------------------------------------------------------------------
692  Function Scan on generate_series g  (cost=N..N rows=1 width=N) (actual rows=0 loops=1)
693 (1 row)
695 -- Ensure we get the default row estimate for infinity values
696 SELECT explain_mask_costs($$
697 SELECT * FROM generate_series(TIMESTAMPTZ '-infinity', TIMESTAMPTZ 'infinity', INTERVAL '1 day') g(s);$$,
698 false, true, false, true);
699                         explain_mask_costs                         
700 -------------------------------------------------------------------
701  Function Scan on generate_series g  (cost=N..N rows=1000 width=N)
702 (1 row)
704 -- Ensure the row estimate behaves correctly when step size is zero.
705 -- We expect generate_series_timestamp() to throw the error rather than in
706 -- the support function.
707 SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '0 day') g(s);
708 ERROR:  step size cannot equal zero
709 -- Test functions for control data
710 SELECT count(*) > 0 AS ok FROM pg_control_checkpoint();
711  ok 
712 ----
714 (1 row)
716 SELECT count(*) > 0 AS ok FROM pg_control_init();
717  ok 
718 ----
720 (1 row)
722 SELECT count(*) > 0 AS ok FROM pg_control_recovery();
723  ok 
724 ----
726 (1 row)
728 SELECT count(*) > 0 AS ok FROM pg_control_system();
729  ok 
730 ----
732 (1 row)
734 -- pg_split_walfile_name, pg_walfile_name & pg_walfile_name_offset
735 SELECT * FROM pg_split_walfile_name(NULL);
736  segment_number | timeline_id 
737 ----------------+-------------
738                 |            
739 (1 row)
741 SELECT * FROM pg_split_walfile_name('invalid');
742 ERROR:  invalid WAL file name "invalid"
743 SELECT segment_number > 0 AS ok_segment_number, timeline_id
744   FROM pg_split_walfile_name('000000010000000100000000');
745  ok_segment_number | timeline_id 
746 -------------------+-------------
747  t                 |           1
748 (1 row)
750 SELECT segment_number > 0 AS ok_segment_number, timeline_id
751   FROM pg_split_walfile_name('ffffffFF00000001000000af');
752  ok_segment_number | timeline_id 
753 -------------------+-------------
754  t                 |  4294967295
755 (1 row)
757 SELECT setting::int8 AS segment_size
758 FROM pg_settings
759 WHERE name = 'wal_segment_size'
760 \gset
761 SELECT segment_number, file_offset
762 FROM pg_walfile_name_offset('0/0'::pg_lsn + :segment_size),
763      pg_split_walfile_name(file_name);
764  segment_number | file_offset 
765 ----------------+-------------
766               1 |           0
767 (1 row)
769 SELECT segment_number, file_offset
770 FROM pg_walfile_name_offset('0/0'::pg_lsn + :segment_size + 1),
771      pg_split_walfile_name(file_name);
772  segment_number | file_offset 
773 ----------------+-------------
774               1 |           1
775 (1 row)
777 SELECT segment_number, file_offset = :segment_size - 1
778 FROM pg_walfile_name_offset('0/0'::pg_lsn + :segment_size - 1),
779      pg_split_walfile_name(file_name);
780  segment_number | ?column? 
781 ----------------+----------
782               0 | t
783 (1 row)
785 -- pg_current_logfile
786 CREATE ROLE regress_current_logfile;
787 -- not available by default
788 SELECT has_function_privilege('regress_current_logfile',
789   'pg_current_logfile()', 'EXECUTE');
790  has_function_privilege 
791 ------------------------
793 (1 row)
795 GRANT pg_monitor TO regress_current_logfile;
796 -- role has privileges of pg_monitor and can execute the function
797 SELECT has_function_privilege('regress_current_logfile',
798   'pg_current_logfile()', 'EXECUTE');
799  has_function_privilege 
800 ------------------------
802 (1 row)
804 DROP ROLE regress_current_logfile;
805 -- pg_column_toast_chunk_id
806 CREATE TABLE test_chunk_id (a TEXT, b TEXT STORAGE EXTERNAL);
807 INSERT INTO test_chunk_id VALUES ('x', repeat('x', 8192));
808 SELECT t.relname AS toastrel FROM pg_class c
809   LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
810   WHERE c.relname = 'test_chunk_id'
811 \gset
812 SELECT pg_column_toast_chunk_id(a) IS NULL,
813   pg_column_toast_chunk_id(b) IN (SELECT chunk_id FROM pg_toast.:toastrel)
814   FROM test_chunk_id;
815  ?column? | ?column? 
816 ----------+----------
817  t        | t
818 (1 row)
820 DROP TABLE test_chunk_id;
821 DROP FUNCTION explain_mask_costs(text, bool, bool, bool, bool);