Fix oversight in previous error-reporting patch; mustn't pfree path string
[PostgreSQL.git] / src / backend / utils / adt / misc.c
blob2d9b7b66cba49843661239c378f529a706e0b97e
1 /*-------------------------------------------------------------------------
3 * misc.c
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include <sys/file.h>
18 #include <signal.h>
19 #include <dirent.h>
20 #include <math.h>
22 #include "access/xact.h"
23 #include "catalog/pg_type.h"
24 #include "catalog/pg_tablespace.h"
25 #include "commands/dbcommands.h"
26 #include "funcapi.h"
27 #include "miscadmin.h"
28 #include "parser/keywords.h"
29 #include "postmaster/syslogger.h"
30 #include "storage/fd.h"
31 #include "storage/pmsignal.h"
32 #include "storage/procarray.h"
33 #include "utils/builtins.h"
34 #include "tcop/tcopprot.h"
36 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
40 * current_database()
41 * Expose the current database to the user
43 Datum
44 current_database(PG_FUNCTION_ARGS)
46 Name db;
48 db = (Name) palloc(NAMEDATALEN);
50 namestrcpy(db, get_database_name(MyDatabaseId));
51 PG_RETURN_NAME(db);
56 * current_query()
57 * Expose the current query to the user (useful in stored procedures)
59 Datum
60 current_query(PG_FUNCTION_ARGS)
62 if (debug_query_string)
63 PG_RETURN_TEXT_P(cstring_to_text(debug_query_string));
64 else
65 PG_RETURN_NULL();
69 * Functions to send signals to other backends.
71 static bool
72 pg_signal_backend(int pid, int sig)
74 if (!superuser())
75 ereport(ERROR,
76 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
77 (errmsg("must be superuser to signal other server processes"))));
79 if (!IsBackendPid(pid))
82 * This is just a warning so a loop-through-resultset will not abort
83 * if one backend terminated on it's own during the run
85 ereport(WARNING,
86 (errmsg("PID %d is not a PostgreSQL server process", pid)));
87 return false;
90 /* If we have setsid(), signal the backend's whole process group */
91 #ifdef HAVE_SETSID
92 if (kill(-pid, sig))
93 #else
94 if (kill(pid, sig))
95 #endif
97 /* Again, just a warning to allow loops */
98 ereport(WARNING,
99 (errmsg("could not send signal to process %d: %m", pid)));
100 return false;
102 return true;
105 Datum
106 pg_cancel_backend(PG_FUNCTION_ARGS)
108 PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGINT));
111 Datum
112 pg_terminate_backend(PG_FUNCTION_ARGS)
114 PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
117 Datum
118 pg_reload_conf(PG_FUNCTION_ARGS)
120 if (!superuser())
121 ereport(ERROR,
122 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
123 (errmsg("must be superuser to signal the postmaster"))));
125 if (kill(PostmasterPid, SIGHUP))
127 ereport(WARNING,
128 (errmsg("failed to send signal to postmaster: %m")));
129 PG_RETURN_BOOL(false);
132 PG_RETURN_BOOL(true);
137 * Rotate log file
139 Datum
140 pg_rotate_logfile(PG_FUNCTION_ARGS)
142 if (!superuser())
143 ereport(ERROR,
144 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
145 (errmsg("must be superuser to rotate log files"))));
147 if (!Logging_collector)
149 ereport(WARNING,
150 (errmsg("rotation not possible because log collection not active")));
151 PG_RETURN_BOOL(false);
154 SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
155 PG_RETURN_BOOL(true);
158 /* Function to find out which databases make use of a tablespace */
160 typedef struct
162 char *location;
163 DIR *dirdesc;
164 } ts_db_fctx;
166 Datum
167 pg_tablespace_databases(PG_FUNCTION_ARGS)
169 FuncCallContext *funcctx;
170 struct dirent *de;
171 ts_db_fctx *fctx;
173 if (SRF_IS_FIRSTCALL())
175 MemoryContext oldcontext;
176 Oid tablespaceOid = PG_GETARG_OID(0);
178 funcctx = SRF_FIRSTCALL_INIT();
179 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
181 fctx = palloc(sizeof(ts_db_fctx));
184 * size = tablespace dirname length + dir sep char + oid + terminator
186 fctx->location = (char *) palloc(10 + 10 + 1);
187 if (tablespaceOid == GLOBALTABLESPACE_OID)
189 fctx->dirdesc = NULL;
190 ereport(WARNING,
191 (errmsg("global tablespace never has databases")));
193 else
195 if (tablespaceOid == DEFAULTTABLESPACE_OID)
196 sprintf(fctx->location, "base");
197 else
198 sprintf(fctx->location, "pg_tblspc/%u", tablespaceOid);
200 fctx->dirdesc = AllocateDir(fctx->location);
202 if (!fctx->dirdesc)
204 /* the only expected error is ENOENT */
205 if (errno != ENOENT)
206 ereport(ERROR,
207 (errcode_for_file_access(),
208 errmsg("could not open directory \"%s\": %m",
209 fctx->location)));
210 ereport(WARNING,
211 (errmsg("%u is not a tablespace OID", tablespaceOid)));
214 funcctx->user_fctx = fctx;
215 MemoryContextSwitchTo(oldcontext);
218 funcctx = SRF_PERCALL_SETUP();
219 fctx = (ts_db_fctx *) funcctx->user_fctx;
221 if (!fctx->dirdesc) /* not a tablespace */
222 SRF_RETURN_DONE(funcctx);
224 while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
226 char *subdir;
227 DIR *dirdesc;
228 Oid datOid = atooid(de->d_name);
230 /* this test skips . and .., but is awfully weak */
231 if (!datOid)
232 continue;
234 /* if database subdir is empty, don't report tablespace as used */
236 /* size = path length + dir sep char + file name + terminator */
237 subdir = palloc(strlen(fctx->location) + 1 + strlen(de->d_name) + 1);
238 sprintf(subdir, "%s/%s", fctx->location, de->d_name);
239 dirdesc = AllocateDir(subdir);
240 while ((de = ReadDir(dirdesc, subdir)) != NULL)
242 if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
243 break;
245 FreeDir(dirdesc);
246 pfree(subdir);
248 if (!de)
249 continue; /* indeed, nothing in it */
251 SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(datOid));
254 FreeDir(fctx->dirdesc);
255 SRF_RETURN_DONE(funcctx);
260 * pg_sleep - delay for N seconds
262 Datum
263 pg_sleep(PG_FUNCTION_ARGS)
265 float8 secs = PG_GETARG_FLOAT8(0);
266 float8 endtime;
269 * We break the requested sleep into segments of no more than 1 second, to
270 * put an upper bound on how long it will take us to respond to a cancel
271 * or die interrupt. (Note that pg_usleep is interruptible by signals on
272 * some platforms but not others.) Also, this method avoids exposing
273 * pg_usleep's upper bound on allowed delays.
275 * By computing the intended stop time initially, we avoid accumulation of
276 * extra delay across multiple sleeps. This also ensures we won't delay
277 * less than the specified time if pg_usleep is interrupted by other
278 * signals such as SIGHUP.
281 #ifdef HAVE_INT64_TIMESTAMP
282 #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
283 #else
284 #define GetNowFloat() GetCurrentTimestamp()
285 #endif
287 endtime = GetNowFloat() + secs;
289 for (;;)
291 float8 delay;
293 CHECK_FOR_INTERRUPTS();
294 delay = endtime - GetNowFloat();
295 if (delay >= 1.0)
296 pg_usleep(1000000L);
297 else if (delay > 0.0)
298 pg_usleep((long) ceil(delay * 1000000.0));
299 else
300 break;
303 PG_RETURN_VOID();
306 /* Function to return the list of grammar keywords */
307 Datum
308 pg_get_keywords(PG_FUNCTION_ARGS)
310 FuncCallContext *funcctx;
312 if (SRF_IS_FIRSTCALL())
314 MemoryContext oldcontext;
315 TupleDesc tupdesc;
317 funcctx = SRF_FIRSTCALL_INIT();
318 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
320 tupdesc = CreateTemplateTupleDesc(3, false);
321 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
322 TEXTOID, -1, 0);
323 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
324 CHAROID, -1, 0);
325 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "catdesc",
326 TEXTOID, -1, 0);
328 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
330 MemoryContextSwitchTo(oldcontext);
333 funcctx = SRF_PERCALL_SETUP();
335 if (&ScanKeywords[funcctx->call_cntr] < LastScanKeyword)
337 char *values[3];
338 HeapTuple tuple;
340 /* cast-away-const is ugly but alternatives aren't much better */
341 values[0] = (char *) ScanKeywords[funcctx->call_cntr].name;
343 switch (ScanKeywords[funcctx->call_cntr].category)
345 case UNRESERVED_KEYWORD:
346 values[1] = "U";
347 values[2] = _("Unreserved");
348 break;
349 case COL_NAME_KEYWORD:
350 values[1] = "C";
351 values[2] = _("Column name");
352 break;
353 case TYPE_FUNC_NAME_KEYWORD:
354 values[1] = "T";
355 values[2] = _("Type or function name");
356 break;
357 case RESERVED_KEYWORD:
358 values[1] = "R";
359 values[2] = _("Reserved");
360 break;
361 default: /* shouldn't be possible */
362 values[1] = NULL;
363 values[2] = NULL;
364 break;
367 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
369 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
372 SRF_RETURN_DONE(funcctx);
377 * Return the type of the argument.
379 Datum
380 pg_typeof(PG_FUNCTION_ARGS)
382 PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));