Skip to content

[pull] master from postgres:master #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions contrib/postgres_fdw/deparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
Expand Down Expand Up @@ -455,6 +456,11 @@ foreign_expr_walker(Node *node,
AuthIdRelationId, fpinfo))
return false;
break;
case REGDATABASEOID:
if (!is_shippable(DatumGetObjectId(c->constvalue),
DatabaseRelationId, fpinfo))
return false;
break;
}
}

Expand Down
15 changes: 13 additions & 2 deletions doc/src/sgml/datatype.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -4737,6 +4737,10 @@ INSERT INTO mytable VALUES(-1); -- fails
<primary>regconfig</primary>
</indexterm>

<indexterm zone="datatype-oid">
<primary>regdatabase</primary>
</indexterm>

<indexterm zone="datatype-oid">
<primary>regdictionary</primary>
</indexterm>
Expand Down Expand Up @@ -4878,6 +4882,13 @@ SELECT * FROM pg_attribute
<entry><literal>english</literal></entry>
</row>

<row>
<entry><type>regdatabase</type></entry>
<entry><structname>pg_database</structname></entry>
<entry>database name</entry>
<entry><literal>template1</literal></entry>
</row>

<row>
<entry><type>regdictionary</type></entry>
<entry><structname>pg_ts_dict</structname></entry>
Expand Down Expand Up @@ -5049,8 +5060,8 @@ WHERE ...
be dropped without first removing the default expression. The
alternative of <literal>nextval('my_seq'::text)</literal> does not
create a dependency.
(<type>regrole</type> is an exception to this property. Constants of this
type are not allowed in stored expressions.)
(<type>regdatabase</type> and <type>regrole</type> are exceptions to this
property. Constants of these types are not allowed in stored expressions.)
</para>

<para>
Expand Down
17 changes: 17 additions & 0 deletions doc/src/sgml/func.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -26750,6 +26750,23 @@ SELECT currval(pg_get_serial_sequence('sometable', 'id'));
</para></entry>
</row>

<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
<primary>to_regdatabase</primary>
</indexterm>
<function>to_regdatabase</function> ( <type>text</type> )
<returnvalue>regdatabase</returnvalue>
</para>
<para>
Translates a textual database name to its OID. A similar result is
obtained by casting the string to type <type>regdatabase</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
not found.
</para></entry>
</row>

<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
Expand Down
3 changes: 2 additions & 1 deletion doc/src/sgml/ref/pgupgrade.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,8 @@ psql --username=postgres --file=script.sql postgres
<member><type>regproc</type></member>
<member><type>regprocedure</type></member>
</simplelist>
(<type>regclass</type>, <type>regrole</type>, and <type>regtype</type> can be upgraded.)
(<type>regclass</type>, <type>regdatabase</type>, <type>regrole</type>, and
<type>regtype</type> can be upgraded.)
</para>

<para>
Expand Down
2 changes: 2 additions & 0 deletions src/backend/bootstrap/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 11 additions & 0 deletions src/backend/catalog/dependency.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
118 changes: 118 additions & 0 deletions src/backend/utils/adt/regproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
*
Expand Down
2 changes: 2 additions & 0 deletions src/backend/utils/adt/selfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/backend/utils/cache/catcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/bin/pg_upgrade/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ static DataTypesUsageChecks data_types_usage_checks[] =
/* pg_class.oid is preserved, so 'regclass' is OK */
" 'regcollation', "
" 'regconfig', "
/* pg_database.oid is preserved, so 'regdatabase' is OK */
" 'regdictionary', "
" 'regnamespace', "
" 'regoper', "
Expand Down
2 changes: 1 addition & 1 deletion src/include/catalog/catversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@
*/

/* yyyymmddN */
#define CATALOG_VERSION_NO 202506291
#define CATALOG_VERSION_NO 202506301

#endif
14 changes: 14 additions & 0 deletions src/include/catalog/pg_cast.dat
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,20 @@
castcontext => 'a', castmethod => 'f' },
{ castsource => 'regnamespace', casttarget => 'int4', castfunc => '0',
castcontext => 'a', castmethod => 'b' },
{ castsource => 'oid', casttarget => 'regdatabase', castfunc => '0',
castcontext => 'i', castmethod => 'b' },
{ castsource => 'regdatabase', casttarget => 'oid', castfunc => '0',
castcontext => 'i', castmethod => 'b' },
{ castsource => 'int8', casttarget => 'regdatabase', castfunc => 'oid',
castcontext => 'i', castmethod => 'f' },
{ castsource => 'int2', casttarget => 'regdatabase', castfunc => 'int4(int2)',
castcontext => 'i', castmethod => 'f' },
{ castsource => 'int4', casttarget => 'regdatabase', castfunc => '0',
castcontext => 'i', castmethod => 'b' },
{ castsource => 'regdatabase', casttarget => 'int8', castfunc => 'int8(oid)',
castcontext => 'a', castmethod => 'f' },
{ castsource => 'regdatabase', casttarget => 'int4', castfunc => '0',
castcontext => 'a', castmethod => 'b' },

# String category
{ castsource => 'text', casttarget => 'bpchar', castfunc => '0',
Expand Down
17 changes: 17 additions & 0 deletions src/include/catalog/pg_proc.dat
Original file line number Diff line number Diff line change
Expand Up @@ -7455,6 +7455,17 @@
prorettype => 'regnamespace', proargtypes => 'text',
prosrc => 'to_regnamespace' },

{ oid => '8321', descr => 'I/O',
proname => 'regdatabasein', provolatile => 's', prorettype => 'regdatabase',
proargtypes => 'cstring', prosrc => 'regdatabasein' },
{ oid => '8322', descr => 'I/O',
proname => 'regdatabaseout', provolatile => 's', prorettype => 'cstring',
proargtypes => 'regdatabase', prosrc => 'regdatabaseout' },
{ oid => '8323', descr => 'convert database name to regdatabase',
proname => 'to_regdatabase', provolatile => 's',
prorettype => 'regdatabase', proargtypes => 'text',
prosrc => 'to_regdatabase' },

{ oid => '6210', descr => 'test whether string is valid input for data type',
proname => 'pg_input_is_valid', provolatile => 's', prorettype => 'bool',
proargtypes => 'text text', prosrc => 'pg_input_is_valid' },
Expand Down Expand Up @@ -8313,6 +8324,12 @@
{ oid => '4088', descr => 'I/O',
proname => 'regnamespacesend', prorettype => 'bytea',
proargtypes => 'regnamespace', prosrc => 'regnamespacesend' },
{ oid => '8324', descr => 'I/O',
proname => 'regdatabaserecv', prorettype => 'regdatabase',
proargtypes => 'internal', prosrc => 'regdatabaserecv' },
{ oid => '8325', descr => 'I/O',
proname => 'regdatabasesend', prorettype => 'bytea',
proargtypes => 'regdatabase', prosrc => 'regdatabasesend' },
{ oid => '2456', descr => 'I/O',
proname => 'bit_recv', prorettype => 'bit',
proargtypes => 'internal oid int4', prosrc => 'bit_recv' },
Expand Down
5 changes: 5 additions & 0 deletions src/include/catalog/pg_type.dat
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@
typinput => 'regnamespacein', typoutput => 'regnamespaceout',
typreceive => 'regnamespacerecv', typsend => 'regnamespacesend',
typalign => 'i' },
{ oid => '8326', array_type_oid => '8327', descr => 'registered database',
typname => 'regdatabase', typlen => '4', typbyval => 't', typcategory => 'N',
typinput => 'regdatabasein', typoutput => 'regdatabaseout',
typreceive => 'regdatabaserecv', typsend => 'regdatabasesend',
typalign => 'i' },

# uuid
{ oid => '2950', array_type_oid => '2951', descr => 'UUID',
Expand Down
36 changes: 36 additions & 0 deletions src/pl/plpgsql/src/expected/plpgsql_misc.out
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,39 @@ do $$ declare x public.foo%rowtype; begin end $$;
ERROR: relation "public.foo" does not exist
CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 1
do $$ declare x public.misc_table%rowtype; begin end $$;
-- Test handling of an unreserved keyword as a variable name
-- and record field name.
do $$
declare
execute int;
r record;
begin
execute := 10;
raise notice 'execute = %', execute;
select 1 as strict into r;
raise notice 'r.strict = %', r.strict;
end $$;
NOTICE: execute = 10
NOTICE: r.strict = 1
-- Test handling of a reserved keyword as a record field name.
do $$ declare r record;
begin
select 1 as x, 2 as foreach into r;
raise notice 'r.x = %', r.x;
raise notice 'r.foreach = %', r.foreach; -- fails
end $$;
NOTICE: r.x = 1
ERROR: field name "foreach" is a reserved key word
LINE 1: r.foreach
^
HINT: Use double quotes to quote it.
QUERY: r.foreach
CONTEXT: PL/pgSQL function inline_code_block line 5 at RAISE
do $$ declare r record;
begin
select 1 as x, 2 as foreach into r;
raise notice 'r.x = %', r.x;
raise notice 'r."foreach" = %', r."foreach"; -- ok
end $$;
NOTICE: r.x = 1
NOTICE: r."foreach" = 2
Loading