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:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user