mirror of
https://github.com/postgres/postgres.git
synced 2025-10-25 13:17:41 +03:00
Add new OID alias type regdatabase.
This provides a convenient way to look up a database's OID. For
example, the query
SELECT * FROM pg_shdepend
WHERE dbid = (SELECT oid FROM pg_database
WHERE datname = current_database());
can now be simplified to
SELECT * FROM pg_shdepend
WHERE dbid = current_database()::regdatabase;
Like the regrole type, regdatabase has cluster-wide scope, so we
disallow regdatabase constants from appearing in stored
expressions.
Bumps catversion.
Author: Ian Lawrence Barwick <barwick@gmail.com>
Reviewed-by: Greg Sabino Mullane <htamfids@gmail.com>
Reviewed-by: Jian He <jian.universality@gmail.com>
Reviewed-by: Fabrízio de Royes Mello <fabriziomello@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/aBpjJhyHpM2LYcG0%40nathan
This commit is contained in:
@@ -109,6 +109,8 @@ static const struct typinfo TypInfo[] = {
|
||||
F_REGROLEIN, F_REGROLEOUT},
|
||||
{"regnamespace", REGNAMESPACEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
|
||||
F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
|
||||
{"regdatabase", REGDATABASEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
|
||||
F_REGDATABASEIN, F_REGDATABASEOUT},
|
||||
{"text", TEXTOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
|
||||
F_TEXTIN, F_TEXTOUT},
|
||||
{"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
|
||||
|
||||
@@ -1850,6 +1850,17 @@ find_expr_references_walker(Node *node,
|
||||
errmsg("constant of the type %s cannot be used here",
|
||||
"regrole")));
|
||||
break;
|
||||
|
||||
/*
|
||||
* Dependencies for regdatabase should be shared among all
|
||||
* databases, so explicitly inhibit to have dependencies.
|
||||
*/
|
||||
case REGDATABASEOID:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("constant of the type %s cannot be used here",
|
||||
"regdatabase")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "catalog/pg_ts_config.h"
|
||||
#include "catalog/pg_ts_dict.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/dbcommands.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
@@ -1763,6 +1764,123 @@ regnamespacesend(PG_FUNCTION_ARGS)
|
||||
return oidsend(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* regdatabasein - converts database name to database OID
|
||||
*
|
||||
* We also accept a numeric OID, for symmetry with the output routine.
|
||||
*
|
||||
* '-' signifies unknown (OID 0). In all other cases, the input must
|
||||
* match an existing pg_database entry.
|
||||
*/
|
||||
Datum
|
||||
regdatabasein(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *db_name_or_oid = PG_GETARG_CSTRING(0);
|
||||
Node *escontext = fcinfo->context;
|
||||
Oid result;
|
||||
List *names;
|
||||
|
||||
/* Handle "-" or numeric OID */
|
||||
if (parseDashOrOid(db_name_or_oid, &result, escontext))
|
||||
PG_RETURN_OID(result);
|
||||
|
||||
/* The rest of this wouldn't work in bootstrap mode */
|
||||
if (IsBootstrapProcessingMode())
|
||||
elog(ERROR, "regdatabase values must be OIDs in bootstrap mode");
|
||||
|
||||
/* Normal case: see if the name matches any pg_database entry. */
|
||||
names = stringToQualifiedNameList(db_name_or_oid, escontext);
|
||||
if (names == NIL)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
if (list_length(names) != 1)
|
||||
ereturn(escontext, (Datum) 0,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("invalid name syntax")));
|
||||
|
||||
result = get_database_oid(strVal(linitial(names)), true);
|
||||
|
||||
if (!OidIsValid(result))
|
||||
ereturn(escontext, (Datum) 0,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("database \"%s\" does not exist",
|
||||
strVal(linitial(names)))));
|
||||
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* to_regdatabase - converts database name to database OID
|
||||
*
|
||||
* If the name is not found, we return NULL.
|
||||
*/
|
||||
Datum
|
||||
to_regdatabase(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *db_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
||||
Datum result;
|
||||
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||
|
||||
if (!DirectInputFunctionCallSafe(regdatabasein, db_name,
|
||||
InvalidOid, -1,
|
||||
(Node *) &escontext,
|
||||
&result))
|
||||
PG_RETURN_NULL();
|
||||
PG_RETURN_DATUM(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* regdatabaseout - converts database OID to database name
|
||||
*/
|
||||
Datum
|
||||
regdatabaseout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid dboid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
|
||||
if (dboid == InvalidOid)
|
||||
{
|
||||
result = pstrdup("-");
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
result = get_database_name(dboid);
|
||||
|
||||
if (result)
|
||||
{
|
||||
/* pstrdup is not really necessary, but it avoids a compiler warning */
|
||||
result = pstrdup(quote_identifier(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If OID doesn't match any database, return it numerically */
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", dboid);
|
||||
}
|
||||
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* regdatabaserecv - converts external binary format to regdatabase
|
||||
*/
|
||||
Datum
|
||||
regdatabaserecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as oidrecv, so share code */
|
||||
return oidrecv(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* regdatabasesend - converts regdatabase to binary format
|
||||
*/
|
||||
Datum
|
||||
regdatabasesend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as oidsend, so share code */
|
||||
return oidsend(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* text_regclass: convert text to regclass
|
||||
*
|
||||
|
||||
@@ -4619,6 +4619,7 @@ convert_to_scalar(Datum value, Oid valuetypid, Oid collid, double *scaledvalue,
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
case REGNAMESPACEOID:
|
||||
case REGDATABASEOID:
|
||||
*scaledvalue = convert_numeric_to_scalar(value, valuetypid,
|
||||
&failure);
|
||||
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid,
|
||||
@@ -4751,6 +4752,7 @@ convert_numeric_to_scalar(Datum value, Oid typid, bool *failure)
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
case REGNAMESPACEOID:
|
||||
case REGDATABASEOID:
|
||||
/* we can treat OIDs as integers... */
|
||||
return (double) DatumGetObjectId(value);
|
||||
}
|
||||
|
||||
1
src/backend/utils/cache/catcache.c
vendored
1
src/backend/utils/cache/catcache.c
vendored
@@ -317,6 +317,7 @@ GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEq
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
case REGNAMESPACEOID:
|
||||
case REGDATABASEOID:
|
||||
*hashfunc = int4hashfast;
|
||||
*fasteqfunc = int4eqfast;
|
||||
*eqfunc = F_OIDEQ;
|
||||
|
||||
Reference in New Issue
Block a user