1 /*-------------------------------------------------------------------------
2 *
3 * misc.c
4 *
5 *
6 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/misc.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 #include "postgres.h"
16
17 #include <sys/file.h>
18 #include <signal.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <math.h>
22 #include <unistd.h>
23
24 #include "access/sysattr.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/catalog.h"
27 #include "catalog/pg_tablespace.h"
28 #include "catalog/pg_type.h"
29 #include "commands/dbcommands.h"
30 #include "commands/tablespace.h"
31 #include "common/keywords.h"
32 #include "funcapi.h"
33 #include "miscadmin.h"
34 #include "pgstat.h"
35 #include "parser/scansup.h"
36 #include "postmaster/syslogger.h"
37 #include "rewrite/rewriteHandler.h"
38 #include "storage/fd.h"
39 #include "storage/pmsignal.h"
40 #include "storage/proc.h"
41 #include "storage/procarray.h"
42 #include "utils/lsyscache.h"
43 #include "utils/ruleutils.h"
44 #include "tcop/tcopprot.h"
45 #include "utils/acl.h"
46 #include "utils/builtins.h"
47 #include "utils/timestamp.h"
48
49
50 /*
51 * Common subroutine for num_nulls() and num_nonnulls().
52 * Returns true if successful, false if function should return NULL.
53 * If successful, total argument count and number of nulls are
54 * returned into *nargs and *nulls.
55 */
56 static bool
count_nulls(FunctionCallInfo fcinfo,int32 * nargs,int32 * nulls)57 count_nulls(FunctionCallInfo fcinfo,
58 int32 *nargs, int32 *nulls)
59 {
60 int32 count = 0;
61 int i;
62
63 /* Did we get a VARIADIC array argument, or separate arguments? */
64 if (get_fn_expr_variadic(fcinfo->flinfo))
65 {
66 ArrayType *arr;
67 int ndims,
68 nitems,
69 *dims;
70 bits8 *bitmap;
71
72 Assert(PG_NARGS() == 1);
73
74 /*
75 * If we get a null as VARIADIC array argument, we can't say anything
76 * useful about the number of elements, so return NULL. This behavior
77 * is consistent with other variadic functions - see concat_internal.
78 */
79 if (PG_ARGISNULL(0))
80 return false;
81
82 /*
83 * Non-null argument had better be an array. We assume that any call
84 * context that could let get_fn_expr_variadic return true will have
85 * checked that a VARIADIC-labeled parameter actually is an array. So
86 * it should be okay to just Assert that it's an array rather than
87 * doing a full-fledged error check.
88 */
89 Assert(OidIsValid(get_base_element_type(get_fn_expr_argtype(fcinfo->flinfo, 0))));
90
91 /* OK, safe to fetch the array value */
92 arr = PG_GETARG_ARRAYTYPE_P(0);
93
94 /* Count the array elements */
95 ndims = ARR_NDIM(arr);
96 dims = ARR_DIMS(arr);
97 nitems = ArrayGetNItems(ndims, dims);
98
99 /* Count those that are NULL */
100 bitmap = ARR_NULLBITMAP(arr);
101 if (bitmap)
102 {
103 int bitmask = 1;
104
105 for (i = 0; i < nitems; i++)
106 {
107 if ((*bitmap & bitmask) == 0)
108 count++;
109
110 bitmask <<= 1;
111 if (bitmask == 0x100)
112 {
113 bitmap++;
114 bitmask = 1;
115 }
116 }
117 }
118
119 *nargs = nitems;
120 *nulls = count;
121 }
122 else
123 {
124 /* Separate arguments, so just count 'em */
125 for (i = 0; i < PG_NARGS(); i++)
126 {
127 if (PG_ARGISNULL(i))
128 count++;
129 }
130
131 *nargs = PG_NARGS();
132 *nulls = count;
133 }
134
135 return true;
136 }
137
138 /*
139 * num_nulls()
140 * Count the number of NULL arguments
141 */
142 Datum
pg_num_nulls(PG_FUNCTION_ARGS)143 pg_num_nulls(PG_FUNCTION_ARGS)
144 {
145 int32 nargs,
146 nulls;
147
148 if (!count_nulls(fcinfo, &nargs, &nulls))
149 PG_RETURN_NULL();
150
151 PG_RETURN_INT32(nulls);
152 }
153
154 /*
155 * num_nonnulls()
156 * Count the number of non-NULL arguments
157 */
158 Datum
pg_num_nonnulls(PG_FUNCTION_ARGS)159 pg_num_nonnulls(PG_FUNCTION_ARGS)
160 {
161 int32 nargs,
162 nulls;
163
164 if (!count_nulls(fcinfo, &nargs, &nulls))
165 PG_RETURN_NULL();
166
167 PG_RETURN_INT32(nargs - nulls);
168 }
169
170
171 /*
172 * current_database()
173 * Expose the current database to the user
174 */
175 Datum
current_database(PG_FUNCTION_ARGS)176 current_database(PG_FUNCTION_ARGS)
177 {
178 Name db;
179
180 db = (Name) palloc(NAMEDATALEN);
181
182 namestrcpy(db, get_database_name(MyDatabaseId));
183 PG_RETURN_NAME(db);
184 }
185
186
187 /*
188 * current_query()
189 * Expose the current query to the user (useful in stored procedures)
190 * We might want to use ActivePortal->sourceText someday.
191 */
192 Datum
current_query(PG_FUNCTION_ARGS)193 current_query(PG_FUNCTION_ARGS)
194 {
195 /* there is no easy way to access the more concise 'query_string' */
196 if (debug_query_string)
197 PG_RETURN_TEXT_P(cstring_to_text(debug_query_string));
198 else
199 PG_RETURN_NULL();
200 }
201
202 /*
203 * Send a signal to another backend.
204 *
205 * The signal is delivered if the user is either a superuser or the same
206 * role as the backend being signaled. For "dangerous" signals, an explicit
207 * check for superuser needs to be done prior to calling this function.
208 *
209 * Returns 0 on success, 1 on general failure, 2 on normal permission error
210 * and 3 if the caller needs to be a superuser.
211 *
212 * In the event of a general failure (return code 1), a warning message will
213 * be emitted. For permission errors, doing that is the responsibility of
214 * the caller.
215 */
216 #define SIGNAL_BACKEND_SUCCESS 0
217 #define SIGNAL_BACKEND_ERROR 1
218 #define SIGNAL_BACKEND_NOPERMISSION 2
219 #define SIGNAL_BACKEND_NOSUPERUSER 3
220 static int
pg_signal_backend(int pid,int sig)221 pg_signal_backend(int pid, int sig)
222 {
223 PGPROC *proc = BackendPidGetProc(pid);
224
225 /*
226 * BackendPidGetProc returns NULL if the pid isn't valid; but by the time
227 * we reach kill(), a process for which we get a valid proc here might
228 * have terminated on its own. There's no way to acquire a lock on an
229 * arbitrary process to prevent that. But since so far all the callers of
230 * this mechanism involve some request for ending the process anyway, that
231 * it might end on its own first is not a problem.
232 */
233 if (proc == NULL)
234 {
235 /*
236 * This is just a warning so a loop-through-resultset will not abort
237 * if one backend terminated on its own during the run.
238 */
239 ereport(WARNING,
240 (errmsg("PID %d is not a PostgreSQL server process", pid)));
241 return SIGNAL_BACKEND_ERROR;
242 }
243
244 /* Only allow superusers to signal superuser-owned backends. */
245 if (superuser_arg(proc->roleId) && !superuser())
246 return SIGNAL_BACKEND_NOSUPERUSER;
247
248 /* Users can signal backends they have role membership in. */
249 if (!has_privs_of_role(GetUserId(), proc->roleId) &&
250 !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID))
251 return SIGNAL_BACKEND_NOPERMISSION;
252
253 /*
254 * Can the process we just validated above end, followed by the pid being
255 * recycled for a new process, before reaching here? Then we'd be trying
256 * to kill the wrong thing. Seems near impossible when sequential pid
257 * assignment and wraparound is used. Perhaps it could happen on a system
258 * where pid re-use is randomized. That race condition possibility seems
259 * too unlikely to worry about.
260 */
261
262 /* If we have setsid(), signal the backend's whole process group */
263 #ifdef HAVE_SETSID
264 if (kill(-pid, sig))
265 #else
266 if (kill(pid, sig))
267 #endif
268 {
269 /* Again, just a warning to allow loops */
270 ereport(WARNING,
271 (errmsg("could not send signal to process %d: %m", pid)));
272 return SIGNAL_BACKEND_ERROR;
273 }
274 return SIGNAL_BACKEND_SUCCESS;
275 }
276
277 /*
278 * Signal to cancel a backend process. This is allowed if you are a member of
279 * the role whose process is being canceled.
280 *
281 * Note that only superusers can signal superuser-owned processes.
282 */
283 Datum
pg_cancel_backend(PG_FUNCTION_ARGS)284 pg_cancel_backend(PG_FUNCTION_ARGS)
285 {
286 int r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
287
288 if (r == SIGNAL_BACKEND_NOSUPERUSER)
289 ereport(ERROR,
290 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
291 (errmsg("must be a superuser to cancel superuser query"))));
292
293 if (r == SIGNAL_BACKEND_NOPERMISSION)
294 ereport(ERROR,
295 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
296 (errmsg("must be a member of the role whose query is being canceled or member of pg_signal_backend"))));
297
298 PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
299 }
300
301 /*
302 * Signal to terminate a backend process. This is allowed if you are a member
303 * of the role whose process is being terminated.
304 *
305 * Note that only superusers can signal superuser-owned processes.
306 */
307 Datum
pg_terminate_backend(PG_FUNCTION_ARGS)308 pg_terminate_backend(PG_FUNCTION_ARGS)
309 {
310 int r = pg_signal_backend(PG_GETARG_INT32(0), SIGTERM);
311
312 if (r == SIGNAL_BACKEND_NOSUPERUSER)
313 ereport(ERROR,
314 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
315 (errmsg("must be a superuser to terminate superuser process"))));
316
317 if (r == SIGNAL_BACKEND_NOPERMISSION)
318 ereport(ERROR,
319 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
320 (errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend"))));
321
322 PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
323 }
324
325 /*
326 * Signal to reload the database configuration
327 *
328 * Permission checking for this function is managed through the normal
329 * GRANT system.
330 */
331 Datum
pg_reload_conf(PG_FUNCTION_ARGS)332 pg_reload_conf(PG_FUNCTION_ARGS)
333 {
334 if (kill(PostmasterPid, SIGHUP))
335 {
336 ereport(WARNING,
337 (errmsg("failed to send signal to postmaster: %m")));
338 PG_RETURN_BOOL(false);
339 }
340
341 PG_RETURN_BOOL(true);
342 }
343
344
345 /*
346 * Rotate log file
347 *
348 * This function is kept to support adminpack 1.0.
349 */
350 Datum
pg_rotate_logfile(PG_FUNCTION_ARGS)351 pg_rotate_logfile(PG_FUNCTION_ARGS)
352 {
353 if (!superuser())
354 ereport(ERROR,
355 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
356 (errmsg("must be superuser to rotate log files with adminpack 1.0"),
357 errhint("Consider using pg_logfile_rotate(), which is part of core, instead."))));
358
359 if (!Logging_collector)
360 {
361 ereport(WARNING,
362 (errmsg("rotation not possible because log collection not active")));
363 PG_RETURN_BOOL(false);
364 }
365
366 SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
367 PG_RETURN_BOOL(true);
368 }
369
370 /*
371 * Rotate log file
372 *
373 * Permission checking for this function is managed through the normal
374 * GRANT system.
375 */
376 Datum
pg_rotate_logfile_v2(PG_FUNCTION_ARGS)377 pg_rotate_logfile_v2(PG_FUNCTION_ARGS)
378 {
379 if (!Logging_collector)
380 {
381 ereport(WARNING,
382 (errmsg("rotation not possible because log collection not active")));
383 PG_RETURN_BOOL(false);
384 }
385
386 SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
387 PG_RETURN_BOOL(true);
388 }
389
390 /* Function to find out which databases make use of a tablespace */
391
392 Datum
pg_tablespace_databases(PG_FUNCTION_ARGS)393 pg_tablespace_databases(PG_FUNCTION_ARGS)
394 {
395 Oid tablespaceOid = PG_GETARG_OID(0);
396 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
397 bool randomAccess;
398 TupleDesc tupdesc;
399 Tuplestorestate *tupstore;
400 char *location;
401 DIR *dirdesc;
402 struct dirent *de;
403 MemoryContext oldcontext;
404
405 /* check to see if caller supports us returning a tuplestore */
406 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
407 ereport(ERROR,
408 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
409 errmsg("set-valued function called in context that cannot accept a set")));
410 if (!(rsinfo->allowedModes & SFRM_Materialize))
411 ereport(ERROR,
412 (errcode(ERRCODE_SYNTAX_ERROR),
413 errmsg("materialize mode required, but it is not allowed in this context")));
414
415 /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
416 oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
417
418 tupdesc = CreateTemplateTupleDesc(1, false);
419 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_tablespace_databases",
420 OIDOID, -1, 0);
421
422 randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
423 tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
424
425 rsinfo->returnMode = SFRM_Materialize;
426 rsinfo->setResult = tupstore;
427 rsinfo->setDesc = tupdesc;
428
429 MemoryContextSwitchTo(oldcontext);
430
431 if (tablespaceOid == GLOBALTABLESPACE_OID)
432 {
433 ereport(WARNING,
434 (errmsg("global tablespace never has databases")));
435 /* return empty tuplestore */
436 return (Datum) 0;
437 }
438
439 if (tablespaceOid == DEFAULTTABLESPACE_OID)
440 location = psprintf("base");
441 else
442 location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
443 TABLESPACE_VERSION_DIRECTORY);
444
445 dirdesc = AllocateDir(location);
446
447 if (!dirdesc)
448 {
449 /* the only expected error is ENOENT */
450 if (errno != ENOENT)
451 ereport(ERROR,
452 (errcode_for_file_access(),
453 errmsg("could not open directory \"%s\": %m",
454 location)));
455 ereport(WARNING,
456 (errmsg("%u is not a tablespace OID", tablespaceOid)));
457 /* return empty tuplestore */
458 return (Datum) 0;
459 }
460
461 while ((de = ReadDir(dirdesc, location)) != NULL)
462 {
463 Oid datOid = atooid(de->d_name);
464 char *subdir;
465 bool isempty;
466 Datum values[1];
467 bool nulls[1];
468
469 /* this test skips . and .., but is awfully weak */
470 if (!datOid)
471 continue;
472
473 /* if database subdir is empty, don't report tablespace as used */
474
475 subdir = psprintf("%s/%s", location, de->d_name);
476 isempty = directory_is_empty(subdir);
477 pfree(subdir);
478
479 if (isempty)
480 continue; /* indeed, nothing in it */
481
482 values[0] = ObjectIdGetDatum(datOid);
483 nulls[0] = false;
484
485 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
486 }
487
488 FreeDir(dirdesc);
489 return (Datum) 0;
490 }
491
492
493 /*
494 * pg_tablespace_location - get location for a tablespace
495 */
496 Datum
pg_tablespace_location(PG_FUNCTION_ARGS)497 pg_tablespace_location(PG_FUNCTION_ARGS)
498 {
499 Oid tablespaceOid = PG_GETARG_OID(0);
500 char sourcepath[MAXPGPATH];
501 char targetpath[MAXPGPATH];
502 int rllen;
503
504 /*
505 * It's useful to apply this function to pg_class.reltablespace, wherein
506 * zero means "the database's default tablespace". So, rather than
507 * throwing an error for zero, we choose to assume that's what is meant.
508 */
509 if (tablespaceOid == InvalidOid)
510 tablespaceOid = MyDatabaseTableSpace;
511
512 /*
513 * Return empty string for the cluster's default tablespaces
514 */
515 if (tablespaceOid == DEFAULTTABLESPACE_OID ||
516 tablespaceOid == GLOBALTABLESPACE_OID)
517 PG_RETURN_TEXT_P(cstring_to_text(""));
518
519 #if defined(HAVE_READLINK) || defined(WIN32)
520
521 /*
522 * Find the location of the tablespace by reading the symbolic link that
523 * is in pg_tblspc/<oid>.
524 */
525 snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
526
527 rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
528 if (rllen < 0)
529 ereport(ERROR,
530 (errcode_for_file_access(),
531 errmsg("could not read symbolic link \"%s\": %m",
532 sourcepath)));
533 if (rllen >= sizeof(targetpath))
534 ereport(ERROR,
535 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
536 errmsg("symbolic link \"%s\" target is too long",
537 sourcepath)));
538 targetpath[rllen] = '\0';
539
540 PG_RETURN_TEXT_P(cstring_to_text(targetpath));
541 #else
542 ereport(ERROR,
543 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
544 errmsg("tablespaces are not supported on this platform")));
545 PG_RETURN_NULL();
546 #endif
547 }
548
549 /*
550 * pg_sleep - delay for N seconds
551 */
552 Datum
pg_sleep(PG_FUNCTION_ARGS)553 pg_sleep(PG_FUNCTION_ARGS)
554 {
555 float8 secs = PG_GETARG_FLOAT8(0);
556 float8 endtime;
557
558 /*
559 * We sleep using WaitLatch, to ensure that we'll wake up promptly if an
560 * important signal (such as SIGALRM or SIGINT) arrives. Because
561 * WaitLatch's upper limit of delay is INT_MAX milliseconds, and the user
562 * might ask for more than that, we sleep for at most 10 minutes and then
563 * loop.
564 *
565 * By computing the intended stop time initially, we avoid accumulation of
566 * extra delay across multiple sleeps. This also ensures we won't delay
567 * less than the specified time when WaitLatch is terminated early by a
568 * non-query-canceling signal such as SIGHUP.
569 */
570 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
571
572 endtime = GetNowFloat() + secs;
573
574 for (;;)
575 {
576 float8 delay;
577 long delay_ms;
578
579 CHECK_FOR_INTERRUPTS();
580
581 delay = endtime - GetNowFloat();
582 if (delay >= 600.0)
583 delay_ms = 600000;
584 else if (delay > 0.0)
585 delay_ms = (long) ceil(delay * 1000.0);
586 else
587 break;
588
589 (void) WaitLatch(MyLatch,
590 WL_LATCH_SET | WL_TIMEOUT,
591 delay_ms,
592 WAIT_EVENT_PG_SLEEP);
593 ResetLatch(MyLatch);
594 }
595
596 PG_RETURN_VOID();
597 }
598
599 /* Function to return the list of grammar keywords */
600 Datum
pg_get_keywords(PG_FUNCTION_ARGS)601 pg_get_keywords(PG_FUNCTION_ARGS)
602 {
603 FuncCallContext *funcctx;
604
605 if (SRF_IS_FIRSTCALL())
606 {
607 MemoryContext oldcontext;
608 TupleDesc tupdesc;
609
610 funcctx = SRF_FIRSTCALL_INIT();
611 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
612
613 tupdesc = CreateTemplateTupleDesc(3, false);
614 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
615 TEXTOID, -1, 0);
616 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
617 CHAROID, -1, 0);
618 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "catdesc",
619 TEXTOID, -1, 0);
620
621 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
622
623 MemoryContextSwitchTo(oldcontext);
624 }
625
626 funcctx = SRF_PERCALL_SETUP();
627
628 if (funcctx->call_cntr < NumScanKeywords)
629 {
630 char *values[3];
631 HeapTuple tuple;
632
633 /* cast-away-const is ugly but alternatives aren't much better */
634 values[0] = (char *) ScanKeywords[funcctx->call_cntr].name;
635
636 switch (ScanKeywords[funcctx->call_cntr].category)
637 {
638 case UNRESERVED_KEYWORD:
639 values[1] = "U";
640 values[2] = _("unreserved");
641 break;
642 case COL_NAME_KEYWORD:
643 values[1] = "C";
644 values[2] = _("unreserved (cannot be function or type name)");
645 break;
646 case TYPE_FUNC_NAME_KEYWORD:
647 values[1] = "T";
648 values[2] = _("reserved (can be function or type name)");
649 break;
650 case RESERVED_KEYWORD:
651 values[1] = "R";
652 values[2] = _("reserved");
653 break;
654 default: /* shouldn't be possible */
655 values[1] = NULL;
656 values[2] = NULL;
657 break;
658 }
659
660 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
661
662 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
663 }
664
665 SRF_RETURN_DONE(funcctx);
666 }
667
668
669 /*
670 * Return the type of the argument.
671 */
672 Datum
pg_typeof(PG_FUNCTION_ARGS)673 pg_typeof(PG_FUNCTION_ARGS)
674 {
675 PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));
676 }
677
678
679 /*
680 * Implementation of the COLLATE FOR expression; returns the collation
681 * of the argument.
682 */
683 Datum
pg_collation_for(PG_FUNCTION_ARGS)684 pg_collation_for(PG_FUNCTION_ARGS)
685 {
686 Oid typeid;
687 Oid collid;
688
689 typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
690 if (!typeid)
691 PG_RETURN_NULL();
692 if (!type_is_collatable(typeid) && typeid != UNKNOWNOID)
693 ereport(ERROR,
694 (errcode(ERRCODE_DATATYPE_MISMATCH),
695 errmsg("collations are not supported by type %s",
696 format_type_be(typeid))));
697
698 collid = PG_GET_COLLATION();
699 if (!collid)
700 PG_RETURN_NULL();
701 PG_RETURN_TEXT_P(cstring_to_text(generate_collation_name(collid)));
702 }
703
704
705 /*
706 * pg_relation_is_updatable - determine which update events the specified
707 * relation supports.
708 *
709 * This relies on relation_is_updatable() in rewriteHandler.c, which see
710 * for additional information.
711 */
712 Datum
pg_relation_is_updatable(PG_FUNCTION_ARGS)713 pg_relation_is_updatable(PG_FUNCTION_ARGS)
714 {
715 Oid reloid = PG_GETARG_OID(0);
716 bool include_triggers = PG_GETARG_BOOL(1);
717
718 PG_RETURN_INT32(relation_is_updatable(reloid, NIL, include_triggers, NULL));
719 }
720
721 /*
722 * pg_column_is_updatable - determine whether a column is updatable
723 *
724 * This function encapsulates the decision about just what
725 * information_schema.columns.is_updatable actually means. It's not clear
726 * whether deletability of the column's relation should be required, so
727 * we want that decision in C code where we could change it without initdb.
728 */
729 Datum
pg_column_is_updatable(PG_FUNCTION_ARGS)730 pg_column_is_updatable(PG_FUNCTION_ARGS)
731 {
732 Oid reloid = PG_GETARG_OID(0);
733 AttrNumber attnum = PG_GETARG_INT16(1);
734 AttrNumber col = attnum - FirstLowInvalidHeapAttributeNumber;
735 bool include_triggers = PG_GETARG_BOOL(2);
736 int events;
737
738 /* System columns are never updatable */
739 if (attnum <= 0)
740 PG_RETURN_BOOL(false);
741
742 events = relation_is_updatable(reloid, NIL, include_triggers,
743 bms_make_singleton(col));
744
745 /* We require both updatability and deletability of the relation */
746 #define REQ_EVENTS ((1 << CMD_UPDATE) | (1 << CMD_DELETE))
747
748 PG_RETURN_BOOL((events & REQ_EVENTS) == REQ_EVENTS);
749 }
750
751
752 /*
753 * Is character a valid identifier start?
754 * Must match scan.l's {ident_start} character class.
755 */
756 static bool
is_ident_start(unsigned char c)757 is_ident_start(unsigned char c)
758 {
759 /* Underscores and ASCII letters are OK */
760 if (c == '_')
761 return true;
762 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
763 return true;
764 /* Any high-bit-set character is OK (might be part of a multibyte char) */
765 if (IS_HIGHBIT_SET(c))
766 return true;
767 return false;
768 }
769
770 /*
771 * Is character a valid identifier continuation?
772 * Must match scan.l's {ident_cont} character class.
773 */
774 static bool
is_ident_cont(unsigned char c)775 is_ident_cont(unsigned char c)
776 {
777 /* Can be digit or dollar sign ... */
778 if ((c >= '0' && c <= '9') || c == '$')
779 return true;
780 /* ... or an identifier start character */
781 return is_ident_start(c);
782 }
783
784 /*
785 * parse_ident - parse a SQL qualified identifier into separate identifiers.
786 * When strict mode is active (second parameter), then any chars after
787 * the last identifier are disallowed.
788 */
789 Datum
parse_ident(PG_FUNCTION_ARGS)790 parse_ident(PG_FUNCTION_ARGS)
791 {
792 text *qualname = PG_GETARG_TEXT_PP(0);
793 bool strict = PG_GETARG_BOOL(1);
794 char *qualname_str = text_to_cstring(qualname);
795 ArrayBuildState *astate = NULL;
796 char *nextp;
797 bool after_dot = false;
798
799 /*
800 * The code below scribbles on qualname_str in some cases, so we should
801 * reconvert qualname if we need to show the original string in error
802 * messages.
803 */
804 nextp = qualname_str;
805
806 /* skip leading whitespace */
807 while (scanner_isspace(*nextp))
808 nextp++;
809
810 for (;;)
811 {
812 char *curname;
813 bool missing_ident = true;
814
815 if (*nextp == '"')
816 {
817 char *endp;
818
819 curname = nextp + 1;
820 for (;;)
821 {
822 endp = strchr(nextp + 1, '"');
823 if (endp == NULL)
824 ereport(ERROR,
825 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
826 errmsg("string is not a valid identifier: \"%s\"",
827 text_to_cstring(qualname)),
828 errdetail("String has unclosed double quotes.")));
829 if (endp[1] != '"')
830 break;
831 memmove(endp, endp + 1, strlen(endp));
832 nextp = endp;
833 }
834 nextp = endp + 1;
835 *endp = '\0';
836
837 if (endp - curname == 0)
838 ereport(ERROR,
839 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
840 errmsg("string is not a valid identifier: \"%s\"",
841 text_to_cstring(qualname)),
842 errdetail("Quoted identifier must not be empty.")));
843
844 astate = accumArrayResult(astate, CStringGetTextDatum(curname),
845 false, TEXTOID, CurrentMemoryContext);
846 missing_ident = false;
847 }
848 else if (is_ident_start((unsigned char) *nextp))
849 {
850 char *downname;
851 int len;
852 text *part;
853
854 curname = nextp++;
855 while (is_ident_cont((unsigned char) *nextp))
856 nextp++;
857
858 len = nextp - curname;
859
860 /*
861 * We don't implicitly truncate identifiers. This is useful for
862 * allowing the user to check for specific parts of the identifier
863 * being too long. It's easy enough for the user to get the
864 * truncated names by casting our output to name[].
865 */
866 downname = downcase_identifier(curname, len, false, false);
867 part = cstring_to_text_with_len(downname, len);
868 astate = accumArrayResult(astate, PointerGetDatum(part), false,
869 TEXTOID, CurrentMemoryContext);
870 missing_ident = false;
871 }
872
873 if (missing_ident)
874 {
875 /* Different error messages based on where we failed. */
876 if (*nextp == '.')
877 ereport(ERROR,
878 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
879 errmsg("string is not a valid identifier: \"%s\"",
880 text_to_cstring(qualname)),
881 errdetail("No valid identifier before \".\".")));
882 else if (after_dot)
883 ereport(ERROR,
884 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
885 errmsg("string is not a valid identifier: \"%s\"",
886 text_to_cstring(qualname)),
887 errdetail("No valid identifier after \".\".")));
888 else
889 ereport(ERROR,
890 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
891 errmsg("string is not a valid identifier: \"%s\"",
892 text_to_cstring(qualname))));
893 }
894
895 while (scanner_isspace(*nextp))
896 nextp++;
897
898 if (*nextp == '.')
899 {
900 after_dot = true;
901 nextp++;
902 while (scanner_isspace(*nextp))
903 nextp++;
904 }
905 else if (*nextp == '\0')
906 {
907 break;
908 }
909 else
910 {
911 if (strict)
912 ereport(ERROR,
913 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
914 errmsg("string is not a valid identifier: \"%s\"",
915 text_to_cstring(qualname))));
916 break;
917 }
918 }
919
920 PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
921 }
922
923 /*
924 * pg_current_logfile
925 *
926 * Report current log file used by log collector by scanning current_logfiles.
927 */
928 Datum
pg_current_logfile(PG_FUNCTION_ARGS)929 pg_current_logfile(PG_FUNCTION_ARGS)
930 {
931 FILE *fd;
932 char lbuffer[MAXPGPATH];
933 char *logfmt;
934
935 /* The log format parameter is optional */
936 if (PG_NARGS() == 0 || PG_ARGISNULL(0))
937 logfmt = NULL;
938 else
939 {
940 logfmt = text_to_cstring(PG_GETARG_TEXT_PP(0));
941
942 if (strcmp(logfmt, "stderr") != 0 && strcmp(logfmt, "csvlog") != 0)
943 ereport(ERROR,
944 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
945 errmsg("log format \"%s\" is not supported", logfmt),
946 errhint("The supported log formats are \"stderr\" and \"csvlog\".")));
947 }
948
949 fd = AllocateFile(LOG_METAINFO_DATAFILE, "r");
950 if (fd == NULL)
951 {
952 if (errno != ENOENT)
953 ereport(ERROR,
954 (errcode_for_file_access(),
955 errmsg("could not read file \"%s\": %m",
956 LOG_METAINFO_DATAFILE)));
957 PG_RETURN_NULL();
958 }
959
960 #ifdef WIN32
961 /* syslogger.c writes CRLF line endings on Windows */
962 _setmode(_fileno(fd), _O_TEXT);
963 #endif
964
965 /*
966 * Read the file to gather current log filename(s) registered by the
967 * syslogger.
968 */
969 while (fgets(lbuffer, sizeof(lbuffer), fd) != NULL)
970 {
971 char *log_format;
972 char *log_filepath;
973 char *nlpos;
974
975 /* Extract log format and log file path from the line. */
976 log_format = lbuffer;
977 log_filepath = strchr(lbuffer, ' ');
978 if (log_filepath == NULL)
979 {
980 /* Uh oh. No space found, so file content is corrupted. */
981 elog(ERROR,
982 "missing space character in \"%s\"", LOG_METAINFO_DATAFILE);
983 break;
984 }
985
986 *log_filepath = '\0';
987 log_filepath++;
988 nlpos = strchr(log_filepath, '\n');
989 if (nlpos == NULL)
990 {
991 /* Uh oh. No newline found, so file content is corrupted. */
992 elog(ERROR,
993 "missing newline character in \"%s\"", LOG_METAINFO_DATAFILE);
994 break;
995 }
996 *nlpos = '\0';
997
998 if (logfmt == NULL || strcmp(logfmt, log_format) == 0)
999 {
1000 FreeFile(fd);
1001 PG_RETURN_TEXT_P(cstring_to_text(log_filepath));
1002 }
1003 }
1004
1005 /* Close the current log filename file. */
1006 FreeFile(fd);
1007
1008 PG_RETURN_NULL();
1009 }
1010
1011 /*
1012 * Report current log file used by log collector (1 argument version)
1013 *
1014 * note: this wrapper is necessary to pass the sanity check in opr_sanity,
1015 * which checks that all built-in functions that share the implementing C
1016 * function take the same number of arguments
1017 */
1018 Datum
pg_current_logfile_1arg(PG_FUNCTION_ARGS)1019 pg_current_logfile_1arg(PG_FUNCTION_ARGS)
1020 {
1021 return pg_current_logfile(fcinfo);
1022 }
1023
1024 /*
1025 * SQL wrapper around RelationGetReplicaIndex().
1026 */
1027 Datum
pg_get_replica_identity_index(PG_FUNCTION_ARGS)1028 pg_get_replica_identity_index(PG_FUNCTION_ARGS)
1029 {
1030 Oid reloid = PG_GETARG_OID(0);
1031 Oid idxoid;
1032 Relation rel;
1033
1034 rel = heap_open(reloid, AccessShareLock);
1035 idxoid = RelationGetReplicaIndex(rel);
1036 heap_close(rel, AccessShareLock);
1037
1038 if (OidIsValid(idxoid))
1039 PG_RETURN_OID(idxoid);
1040 else
1041 PG_RETURN_NULL();
1042 }
1043