*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 16576,16581 **** SELECT collation for ('foo' COLLATE "de_DE");
--- 16576,16594 ----
text
set parameter and return new value
+
+
+
+ pg_hba_lookup
+
+ pg_hba_lookup(database> text>,
+ user> text>
+ [, address> text>]
+ [, hostname> text>)
+
+ record
+ Returns all matching row entries of pg_hba.conf
+
***************
*** 16633,16638 **** SELECT set_config('log_statement_stats', 'off', false);
--- 16646,16667 ----
+
+ pg_hba_lookup returns a set of records
+ containing the line number, type, database, user, address,
+ hostname, method and options that are satisfied with the given
+ input values. Typical usages include:
+
+ SELECT pg_hba_lookup('test_database', 'test_user');
+
+ pg_hba_lookup
+ --------------------------------------------------------------
+ (84,local,"[""all""]","[""all""]",,,trust,{})
+ (86,local,"[""test_database""]","[""test_user""]",,,trust,{})
+ (1 row)
+
+
+
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
***************
*** 25,39 ****
--- 25,45 ----
#include
#include
+ #include "access/htup_details.h"
#include "catalog/pg_collation.h"
+ #include "catalog/pg_type.h"
+ #include "funcapi.h"
#include "libpq/ip.h"
#include "libpq/libpq.h"
+ #include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "regex/regex.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "utils/acl.h"
+ #include "utils/builtins.h"
#include "utils/guc.h"
+ #include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
***************
*** 74,79 **** typedef struct HbaToken
--- 80,95 ----
bool quoted;
} HbaToken;
+ typedef enum hba_lookup_args_mode
+ {
+ TWO_ARGS_MODE=0,
+ THREE_ARGS_MODE,
+ FOUR_ARGS_MODE
+ }hba_lookup_args_mode;
+
+ /* Flag to indicate the failure of reloading pg_hba.conf file */
+ bool load_hba_failure = false;
+
/*
* pre-parsed content of HBA config file: list of HbaLine structs.
* parsed_hba_context is the memory context where it lives.
***************
*** 100,105 **** static List *tokenize_inc_file(List *tokens, const char *outer_filename,
--- 116,125 ----
static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
int line_num);
+ static void hba_getvalues_for_line(HbaLine *hba, Datum *values, bool *nulls);
+ static bool pg_hba_match(HbaLine *hba, char *database, char *user, struct sockaddr_storage *addr,
+ char *hostname, bool ssl_inuse, hba_lookup_args_mode args_mode);
+
/*
* isblank() exists in the ISO C99 spec, but it's not very portable yet,
* so provide our own version.
***************
*** 2233,2235 **** hba_getauthmethod(hbaPort *port)
--- 2253,2826 ----
{
check_hba(port);
}
+
+
+ /* LDAP supports 10 currently, keep this well above the most any method needs */
+ #define MAX_OPTIONS 12
+
+ /*
+ * Fill in suitable values to build a tuple representing the
+ * HbaLine provided
+ */
+ static void
+ hba_getvalues_for_line(HbaLine *hba, Datum *values, bool *nulls)
+ {
+ int index = 0;
+ JsonbInState result;
+ JsonbValue v;
+ char *str;
+ int len;
+
+ /* line_number */
+ values[index] = Int32GetDatum(hba->linenumber);
+
+ /* method */
+ index++;
+ switch (hba->auth_method)
+ {
+ case uaReject:
+ values[index] = CStringGetTextDatum("reject");
+ break;
+ case uaTrust:
+ values[index] = CStringGetTextDatum("trust");
+ break;
+ case uaIdent:
+ values[index] = CStringGetTextDatum("ident");
+ break;
+ case uaPassword:
+ values[index] = CStringGetTextDatum("password");
+ break;
+ case uaMD5:
+ values[index] = CStringGetTextDatum("md5");
+ break;
+ case uaGSS:
+ values[index] = CStringGetTextDatum("gss");
+ break;
+ case uaSSPI:
+ values[index] = CStringGetTextDatum("sspi");
+ break;
+ case uaPAM:
+ values[index] = CStringGetTextDatum("pam");
+ break;
+ case uaLDAP:
+ values[index] = CStringGetTextDatum("ldap");
+ break;
+ case uaCert:
+ values[index] = CStringGetTextDatum("cert");
+ break;
+ case uaRADIUS:
+ values[index] = CStringGetTextDatum("radius");
+ break;
+ case uaPeer:
+ values[index] = CStringGetTextDatum("peer");
+ break;
+ default:
+ elog(ERROR, "unexpected authentication method in parsed HBA entry");
+ break;
+ }
+
+ /* options */
+ index++;
+ memset(&result, 0, sizeof(JsonbInState));
+ result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
+
+ if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
+ {
+ if (hba->include_realm)
+ {
+ str = pstrdup("include_realm");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(BoolGetDatum(true), false, &result, BOOLOID, false);
+ }
+
+ if (hba->krb_realm)
+ {
+ str = pstrdup("krb_realm");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->krb_realm), false, &result, TEXTOID, false);
+ }
+ }
+
+ if (hba->usermap)
+ {
+ str = pstrdup("map");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->usermap), false, &result, TEXTOID, false);
+ }
+
+ if (hba->auth_method == uaLDAP)
+ {
+ if (hba->ldapserver)
+ {
+ str = pstrdup("ldapserver");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapserver), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapport)
+ {
+ str = pstrdup("ldapport");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(Int32GetDatum(hba->ldapport), false, &result, INT4OID, false);
+ }
+
+ if (hba->ldaptls)
+ {
+ str = pstrdup("ldaptls");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(BoolGetDatum(true), false, &result, BOOLOID, false);
+ }
+
+ if (hba->ldapprefix)
+ {
+ str = pstrdup("ldapprefix");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapprefix), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapsuffix)
+ {
+ str = pstrdup("ldapsuffix");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapsuffix), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapbasedn)
+ {
+ str = pstrdup("ldapbasedn");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapbasedn), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapbinddn)
+ {
+ str = pstrdup("ldapbinddn");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapbinddn), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapbindpasswd)
+ {
+ str = pstrdup("ldapbindpasswd");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapbindpasswd), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapsearchattribute)
+ {
+ str = pstrdup("ldapsearchattribute");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->ldapsearchattribute), false, &result, TEXTOID, false);
+ }
+
+ if (hba->ldapscope)
+ {
+ str = pstrdup("ldapscope");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(Int32GetDatum(hba->ldapscope), false, &result, INT4OID, false);
+ }
+ }
+
+ if (hba->auth_method == uaRADIUS)
+ {
+ if (hba->radiusserver)
+ {
+ str = pstrdup("radiusserver");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->radiusserver), false, &result, TEXTOID, false);
+ }
+
+ if (hba->radiussecret)
+ {
+ str = pstrdup("radiussecret");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->radiussecret), false, &result, TEXTOID, false);
+ }
+
+ if (hba->radiusidentifier)
+ {
+ str = pstrdup("radiusidentifier");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(CStringGetTextDatum(hba->radiusidentifier), false, &result, TEXTOID, false);
+ }
+
+ if (hba->radiusport)
+ {
+ str = pstrdup("radiusport");
+ len = strlen(str);
+
+ v.type = jbvString;
+
+ v.val.string.len = len;
+ v.val.string.val = str;
+
+ result.res = pushJsonbValue(&result.parseState, WJB_KEY, &v);
+ add_jsonb(Int32GetDatum(hba->radiusport), false, &result, INT4OID, false);
+ }
+ }
+
+ result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
+ values[index] = PointerGetDatum(JsonbValueToJsonb(result.res));
+ }
+
+ static bool
+ pg_hba_match(HbaLine *hba, char *database, char *user, struct sockaddr_storage *addr,
+ char *hostname, bool ssl_inuse, hba_lookup_args_mode args_mode)
+ {
+ Oid roleid;
+
+ if (ssl_inuse)
+ {
+ #ifdef USE_SSL
+ if (EnableSSL && hba->conntype != ctHostSSL)
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non SSL connection type.",
+ hba->linenumber)));
+ return false;
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("hostssl requires SSL to be turned on"),
+ errhint("Set ssl = on in postgresql.conf.")));
+ return false;
+ }
+ #else
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("hostssl is not supported by this build"),
+ errhint("Compile with --with-openssl to use SSL connections.")));
+ return false;
+ #endif
+ }
+
+ /* Get the target role's OID. Note we do not error out for bad role. */
+ roleid = get_role_oid(user, true);
+
+ if (!check_db(database, user, roleid, hba->databases))
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non matching database.",
+ hba->linenumber)));
+ return false;
+ }
+
+ if (!check_role(user, roleid, hba->roles))
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non matching role.",
+ hba->linenumber)));
+ return false;
+ }
+
+ if (args_mode != TWO_ARGS_MODE)
+ {
+ /* Check IP address */
+ switch (hba->ip_cmp_method)
+ {
+ case ipCmpMask:
+ if (hostname && hba->hostname)
+ {
+ if (!hostname_match(hostname, hba->hostname))
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non matching hostname.",
+ hba->linenumber)));
+ return false;
+ }
+ }
+ else
+ {
+ if (!check_ip((SockAddr *)addr,
+ (struct sockaddr *) & hba->addr,
+ (struct sockaddr *) & hba->mask))
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non matching IP.",
+ hba->linenumber)));
+ return false;
+ }
+ }
+ break;
+ case ipCmpAll:
+ break;
+ case ipCmpSameHost:
+ case ipCmpSameNet:
+ if (!check_same_host_or_net((SockAddr *)addr,
+ hba->ip_cmp_method))
+ {
+ ereport(NOTICE, (errmsg("Skipped %d Hba line, because of non matching SameHost/SameNet.",
+ hba->linenumber)));
+ return false;
+ }
+ break;
+ default: /* Not reachable case*/
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ /*
+ * SQL-accessible SRF to return all the settings from the pg_hba.conf
+ * file.
+ */
+ Datum
+ pg_hba_lookup_2args(PG_FUNCTION_ARGS)
+ {
+ return pg_hba_lookup(fcinfo);
+ }
+
+ /*
+ * SQL-accessible SRF to return all the settings from the pg_hba.conf
+ * file.
+ */
+ Datum
+ pg_hba_lookup_3args(PG_FUNCTION_ARGS)
+ {
+ return pg_hba_lookup(fcinfo);
+ }
+
+ #define NUM_PG_HBA_CONF_ATTS 3
+
+ /*
+ * SQL-accessible SRF to return all the settings from the pg_hba.conf
+ * file.
+ */
+ Datum
+ pg_hba_lookup(PG_FUNCTION_ARGS)
+ {
+ char *user;
+ char *database;
+ char *address = NULL;
+ bool ssl_inuse = false;
+ TupleDesc tupdesc;
+ ListCell *line;
+ Datum values[NUM_PG_HBA_CONF_ATTS];
+ bool nulls[NUM_PG_HBA_CONF_ATTS];
+ HeapTuple tuple;
+ Datum result;
+ struct sockaddr_storage addr;
+ char *hostname = NULL;
+ hba_lookup_args_mode args_mode = TWO_ARGS_MODE; /* Minimum number of arguments */
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("only superuser can view pg_hba.conf settings"))));
+
+ if (PG_ARGISNULL(0))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ (errmsg("database name is required to match pg_hba configuration entry"))));
+ else
+ database = TextDatumGetCString(PG_GETARG_DATUM(0));
+
+ if (PG_ARGISNULL(1))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ (errmsg("user name is required to match pg_hba configuration entry"))));
+ else
+ user = TextDatumGetCString(PG_GETARG_DATUM(1));
+
+ if (PG_NARGS() != 2)
+ {
+ struct addrinfo *gai_result;
+ struct addrinfo hints;
+ int ret;
+
+ args_mode = THREE_ARGS_MODE;
+ if (!PG_ARGISNULL(2))
+ address = TextDatumGetCString(PG_GETARG_DATUM(2));
+
+ /* Get the IP address either way */
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ hints.ai_addrlen = 0;
+ hints.ai_canonname = NULL;
+ hints.ai_addr = NULL;
+ hints.ai_next = NULL;
+
+ ret = pg_getaddrinfo_all(address, NULL, &hints, &gai_result);
+ if (ret == 0 && gai_result)
+ memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
+ else if (ret == EAI_NONAME)
+ hostname = pstrdup(address);
+ else
+ {
+ ereport(ERROR,
+ (errmsg("invalid IP address \"%s\": %s",
+ address, gai_strerror(ret))));
+ if (gai_result)
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
+ return false;
+ }
+
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
+
+ if (PG_NARGS() != 3)
+ {
+ args_mode = FOUR_ARGS_MODE;
+ if (!PG_ARGISNULL(3))
+ ssl_inuse = DatumGetBool(PG_GETARG_DATUM(3));
+ }
+ }
+
+ if (load_hba_failure)
+ ereport(WARNING,
+ (errmsg("There was some failure in reloading pg_hba.conf file. "
+ "The pg_hba.conf settings data may contains stale information")));
+
+ /* Create the tupledesc */
+ tupdesc = CreateTemplateTupleDesc(NUM_PG_HBA_CONF_ATTS, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber)1, "line_number",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber)2, "method",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber)3, "options",
+ JSONBOID, -1, 0);
+ BlessTupleDesc(tupdesc);
+
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, true, sizeof(nulls));
+
+ /*
+ * Loop through the list and deparse each entry as it comes, and returns
+ * the first matched entry.
+ */
+ foreach(line, parsed_hba_lines)
+ {
+ HbaLine *hba = (HbaLine *)lfirst(line);
+
+ CHECK_FOR_INTERRUPTS();
+
+ if (pg_hba_match(hba, database, user, &addr, hostname, ssl_inuse, args_mode))
+ {
+ /* Get the next parsed hba line values */
+ MemSet(nulls, false, sizeof(nulls));
+ hba_getvalues_for_line(hba, values, nulls);
+ break;
+ }
+ }
+
+ /* build a tuple */
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+ PG_RETURN_DATUM(result);
+ }
+
+
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
***************
*** 4005,4010 **** PostgresMain(int argc, char *argv[],
--- 4005,4023 ----
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Reload authentication config files too to refresh
+ * pg_hba_conf view data.
+ */
+ if (!load_hba())
+ {
+ ereport(DEBUG1,
+ (errmsg("Falure in reloading pg_hba.conf, pg_hba_conf view may show stale information")));
+ load_hba_failure = true;
+ }
+
+ load_hba_failure = false;
}
/*
*** a/src/backend/utils/adt/jsonb.c
--- b/src/backend/utils/adt/jsonb.c
***************
*** 28,39 ****
#include "utils/syscache.h"
#include "utils/typcache.h"
- typedef struct JsonbInState
- {
- JsonbParseState *parseState;
- JsonbValue *res;
- } JsonbInState;
-
/* unlike with json categories, we need to treat json and jsonb differently */
typedef enum /* type categories for datum_to_jsonb */
{
--- 28,33 ----
***************
*** 83,89 **** static void jsonb_categorize_type(Oid typoid,
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
JsonbTypeCategory tcategory, Oid outfuncoid,
bool key_scalar);
! static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
Oid val_type, bool key_scalar);
static JsonbParseState *clone_parse_state(JsonbParseState *state);
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
--- 77,83 ----
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
JsonbTypeCategory tcategory, Oid outfuncoid,
bool key_scalar);
! void add_jsonb(Datum val, bool is_null, JsonbInState *result,
Oid val_type, bool key_scalar);
static JsonbParseState *clone_parse_state(JsonbParseState *state);
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
***************
*** 1113,1119 **** composite_to_jsonb(Datum composite, JsonbInState *result)
* lookups only once.
*/
! static void
add_jsonb(Datum val, bool is_null, JsonbInState *result,
Oid val_type, bool key_scalar)
{
--- 1107,1113 ----
* lookups only once.
*/
! void
add_jsonb(Datum val, bool is_null, JsonbInState *result,
Oid val_type, bool key_scalar)
{
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3079,3084 **** DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 0 f f f f
--- 3079,3090 ----
DESCR("SHOW ALL as a function");
DATA(insert OID = 3329 ( pg_show_all_file_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{25,23,23,25,25,16,25}" "{o,o,o,o,o,o,o}" "{sourcefile,sourceline,seqno,name,setting,applied,error}" _null_ _null_ show_all_file_settings _null_ _null_ _null_ ));
DESCR("show config file settings");
+ DATA(insert OID = 3997 (pg_hba_lookup PGNSP PGUID 12 1 1000 0 0 f f f f t t v u 2 0 2249 "25 25" "{25,25,23,25,3802}" "{i,i,o,o,o}" "{database,user,line_number,method,options}" _null_ _null_ pg_hba_lookup_2args _null_ _null_ _null_));
+ DESCR("view client authentication settings");
+ DATA(insert OID = 3998 (pg_hba_lookup PGNSP PGUID 12 1 1000 0 0 f f f f t t v u 3 0 2249 "25 25 25" "{25,25,25,23,25,3802}" "{i,i,i,o,o,o}" "{database,user,address,line_number,method,options}" _null_ _null_ pg_hba_lookup_3args _null_ _null_ _null_));
+ DESCR("view client authentication settings");
+ DATA(insert OID = 3999 (pg_hba_lookup PGNSP PGUID 12 1 1000 0 0 f f f f t t v u 4 0 2249 "25 25 25 16" "{25,25,25,16,23,25,3802}" "{i,i,i,i,o,o,o}" "{database,user,address,ssl_inuse,line_number,method,options}" _null_ _null_ pg_hba_lookup _null_ _null_ _null_));
+ DESCR("view client authentication settings");
DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ _null_ pg_lock_status _null_ _null_ _null_ ));
DESCR("view system lock information");
DATA(insert OID = 1065 ( pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ ));
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
***************
*** 96,101 **** typedef struct IdentLine
--- 96,103 ----
/* kluge to avoid including libpq/libpq-be.h here */
typedef struct Port hbaPort;
+ extern bool load_hba_failure;
+
extern bool load_hba(void);
extern bool load_ident(void);
extern void hba_getauthmethod(hbaPort *port);
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 1123,1128 **** extern Datum set_config_by_name(PG_FUNCTION_ARGS);
--- 1123,1133 ----
extern Datum show_all_settings(PG_FUNCTION_ARGS);
extern Datum show_all_file_settings(PG_FUNCTION_ARGS);
+ /* hba.c */
+ extern Datum pg_hba_lookup_2args(PG_FUNCTION_ARGS);
+ extern Datum pg_hba_lookup_3args(PG_FUNCTION_ARGS);
+ extern Datum pg_hba_lookup(PG_FUNCTION_ARGS);
+
/* rls.c */
extern Datum row_security_active(PG_FUNCTION_ARGS);
extern Datum row_security_active_name(PG_FUNCTION_ARGS);
*** a/src/include/utils/json.h
--- b/src/include/utils/json.h
***************
*** 43,49 **** extern Datum json_object(PG_FUNCTION_ARGS);
extern Datum json_object_two_arg(PG_FUNCTION_ARGS);
extern void escape_json(StringInfo buf, const char *str);
-
extern Datum json_typeof(PG_FUNCTION_ARGS);
/* functions in jsonfuncs.c */
--- 43,48 ----
*** a/src/include/utils/jsonb.h
--- b/src/include/utils/jsonb.h
***************
*** 343,348 **** typedef struct JsonbIterator
--- 343,354 ----
struct JsonbIterator *parent;
} JsonbIterator;
+ typedef struct JsonbInState
+ {
+ JsonbParseState *parseState;
+ JsonbValue *res;
+ } JsonbInState;
+
/* I/O routines */
extern Datum jsonb_in(PG_FUNCTION_ARGS);
extern Datum jsonb_out(PG_FUNCTION_ARGS);
***************
*** 428,433 **** extern bool JsonbDeepContains(JsonbIterator **val,
--- 434,441 ----
extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);
/* jsonb.c support functions */
+ void add_jsonb(Datum val, bool is_null, JsonbInState *result,
+ Oid val_type, bool key_scalar);
extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
int estimated_len);
extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
*** a/src/test/regress/expected/rules.out
--- b/src/test/regress/expected/rules.out
***************
*** 1327,1332 **** pg_group| SELECT pg_authid.rolname AS groname,
--- 1327,1344 ----
WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist
FROM pg_authid
WHERE (NOT pg_authid.rolcanlogin);
+ pg_hba_conf| SELECT a.line_number,
+ a.type,
+ a.keyword_databases,
+ a.databases,
+ a.keyword_users,
+ a.users,
+ a.address,
+ a.compare_method,
+ a.hostname,
+ a.method,
+ a.options
+ FROM pg_hba_conf() a(line_number, type, keyword_databases, databases, keyword_users, users, address, compare_method, hostname, method, options);
pg_indexes| SELECT n.nspname AS schemaname,
c.relname AS tablename,
i.relname AS indexname,