diff options
Diffstat (limited to 'contrib/adminpack/adminpack.c')
-rw-r--r-- | contrib/adminpack/adminpack.c | 80 |
1 files changed, 38 insertions, 42 deletions
diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c index 26b33219b73..db0b033956e 100644 --- a/contrib/adminpack/adminpack.c +++ b/contrib/adminpack/adminpack.c @@ -45,11 +45,6 @@ PG_FUNCTION_INFO_V1(pg_file_rename); PG_FUNCTION_INFO_V1(pg_file_unlink); PG_FUNCTION_INFO_V1(pg_logdir_ls); -typedef struct -{ - char *location; - DIR *dirdesc; -} directory_fctx; /*----------------------- * some helper functions @@ -281,9 +276,14 @@ pg_file_unlink(PG_FUNCTION_ARGS) Datum pg_logdir_ls(PG_FUNCTION_ARGS) { - FuncCallContext *funcctx; + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + bool randomAccess; + TupleDesc tupdesc; + Tuplestorestate *tupstore; + AttInMetadata *attinmeta; + DIR *dirdesc; struct dirent *de; - directory_fctx *fctx; + MemoryContext oldcontext; if (!superuser()) ereport(ERROR, @@ -293,43 +293,39 @@ pg_logdir_ls(PG_FUNCTION_ARGS) if (strcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log") != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'")))); - - if (SRF_IS_FIRSTCALL()) - { - MemoryContext oldcontext; - TupleDesc tupdesc; - - funcctx = SRF_FIRSTCALL_INIT(); - oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"))); - fctx = palloc(sizeof(directory_fctx)); - - tupdesc = CreateTemplateTupleDesc(2, false); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime", - TIMESTAMPOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename", - TEXTOID, -1, 0); + /* check to see if caller supports us returning a tuplestore */ + if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("set-valued function called in context that cannot accept a set"))); + if (!(rsinfo->allowedModes & SFRM_Materialize)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("materialize mode required, but it is not allowed in this context"))); - funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */ + oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory); - fctx->location = pstrdup(Log_directory); - fctx->dirdesc = AllocateDir(fctx->location); + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime", + TIMESTAMPOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename", + TEXTOID, -1, 0); - if (!fctx->dirdesc) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read directory \"%s\": %m", - fctx->location))); + randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0; + tupstore = tuplestore_begin_heap(randomAccess, false, work_mem); + rsinfo->returnMode = SFRM_Materialize; + rsinfo->setResult = tupstore; + rsinfo->setDesc = tupdesc; - funcctx->user_fctx = fctx; - MemoryContextSwitchTo(oldcontext); - } + MemoryContextSwitchTo(oldcontext); - funcctx = SRF_PERCALL_SETUP(); - fctx = (directory_fctx *) funcctx->user_fctx; + attinmeta = TupleDescGetAttInMetadata(tupdesc); - while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL) + dirdesc = AllocateDir(Log_directory); + while ((de = ReadDir(dirdesc, Log_directory)) != NULL) { char *values[2]; HeapTuple tuple; @@ -366,13 +362,13 @@ pg_logdir_ls(PG_FUNCTION_ARGS) /* Seems the timestamp is OK; prepare and return tuple */ values[0] = timestampbuf; - values[1] = psprintf("%s/%s", fctx->location, de->d_name); + values[1] = psprintf("%s/%s", Log_directory, de->d_name); - tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + tuple = BuildTupleFromCStrings(attinmeta, values); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + tuplestore_puttuple(tupstore, tuple); } - FreeDir(fctx->dirdesc); - SRF_RETURN_DONE(funcctx); + FreeDir(dirdesc); + return (Datum) 0; } |