1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-04 20:11:56 +03:00

Add system view pg_ident_file_mappings

This view is similar to pg_hba_file_rules view, except that it is
associated with the parsing of pg_ident.conf.  Similarly to its cousin,
this view is useful to check via SQL if changes planned in pg_ident.conf
would work upon reload or restart, or to diagnose a previous failure.

Bumps catalog version.

Author: Julien Rouhaud
Reviewed-by: Aleksander Alekseev, Michael Paquier
Discussion: https://postgr.es/m/20220223045959.35ipdsvbxcstrhya@jrouhaud
This commit is contained in:
Michael Paquier
2022-03-29 10:15:48 +09:00
parent 091a971bb5
commit a2c84990be
12 changed files with 305 additions and 17 deletions

View File

@@ -28,6 +28,9 @@ static ArrayType *get_hba_options(HbaLine *hba);
static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
int lineno, HbaLine *hba, const char *err_msg);
static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
static void fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
int lineno, IdentLine *ident, const char *err_msg);
static void fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
/*
@@ -426,3 +429,136 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
/* Number of columns in pg_ident_file_mappings view */
#define NUM_PG_IDENT_FILE_MAPPINGS_ATTS 5
/*
* fill_ident_line: build one row of pg_ident_file_mappings view, add it to
* tuplestore
*
* tuple_store: where to store data
* tupdesc: tuple descriptor for the view
* lineno: pg_ident.conf line number (must always be valid)
* ident: parsed line data (can be NULL, in which case err_msg should be set)
* err_msg: error message (NULL if none)
*
* Note: leaks memory, but we don't care since this is run in a short-lived
* memory context.
*/
static void
fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
int lineno, IdentLine *ident, const char *err_msg)
{
Datum values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
bool nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
HeapTuple tuple;
int index;
Assert(tupdesc->natts == NUM_PG_IDENT_FILE_MAPPINGS_ATTS);
memset(values, 0, sizeof(values));
memset(nulls, 0, sizeof(nulls));
index = 0;
/* line_number */
values[index++] = Int32GetDatum(lineno);
if (ident != NULL)
{
values[index++] = CStringGetTextDatum(ident->usermap);
values[index++] = CStringGetTextDatum(ident->ident_user);
values[index++] = CStringGetTextDatum(ident->pg_role);
}
else
{
/* no parsing result, so set relevant fields to nulls */
memset(&nulls[1], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 2) * sizeof(bool));
}
/* error */
if (err_msg)
values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = CStringGetTextDatum(err_msg);
else
nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = true;
tuple = heap_form_tuple(tupdesc, values, nulls);
tuplestore_puttuple(tuple_store, tuple);
}
/*
* Read the pg_ident.conf file and fill the tuplestore with view records.
*/
static void
fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
{
FILE *file;
List *ident_lines = NIL;
ListCell *line;
MemoryContext linecxt;
MemoryContext identcxt;
MemoryContext oldcxt;
/*
* In the unlikely event that we can't open pg_ident.conf, we throw an
* error, rather than trying to report it via some sort of view entry.
* (Most other error conditions should result in a message in a view
* entry.)
*/
file = AllocateFile(IdentFileName, "r");
if (file == NULL)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open usermap file \"%s\": %m",
IdentFileName)));
linecxt = tokenize_auth_file(HbaFileName, file, &ident_lines, DEBUG3);
FreeFile(file);
/* Now parse all the lines */
identcxt = AllocSetContextCreate(CurrentMemoryContext,
"ident parser context",
ALLOCSET_SMALL_SIZES);
oldcxt = MemoryContextSwitchTo(identcxt);
foreach(line, ident_lines)
{
TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
IdentLine *identline = NULL;
/* don't parse lines that already have errors */
if (tok_line->err_msg == NULL)
identline = parse_ident_line(tok_line, DEBUG3);
fill_ident_line(tuple_store, tupdesc, tok_line->line_num, identline,
tok_line->err_msg);
}
/* Free tokenizer memory */
MemoryContextDelete(linecxt);
/* Free parse_ident_line memory */
MemoryContextSwitchTo(oldcxt);
MemoryContextDelete(identcxt);
}
/*
* SQL-accessible SRF to return all the entries in the pg_ident.conf file.
*/
Datum
pg_ident_file_mappings(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsi;
/*
* Build tuplestore to hold the result rows. We must use the Materialize
* mode to be safe against HBA file changes while the cursor is open. It's
* also more efficient than having to look up our current position in the
* parsed list every time.
*/
SetSingleFuncCall(fcinfo, 0);
/* Fill the tuplestore */
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
fill_ident_view(rsi->setResult, rsi->setDesc);
PG_RETURN_NULL();
}