diff --git a/doc/src/sgml/bki.sgml b/doc/src/sgml/bki.sgml index 53a982bf60d..087a6827b00 100644 --- a/doc/src/sgml/bki.sgml +++ b/doc/src/sgml/bki.sgml @@ -271,6 +271,21 @@ + + + There is a special case for values of the + pg_proc.proargdefaults + field, which is of type pg_node_tree. The real + contents of that type are too complex for hand-written entries, + but what we need for proargdefaults is + typically just a list of Const nodes. Therefore, the bootstrap + backend will interpret a value given for that field according to + text array syntax, and then feed the array element values to the + datatype input routines for the corresponding input parameters' data + types, and finally build Const nodes from the datums. + + + Since hashes are unordered data structures, field order and line @@ -817,11 +832,11 @@ $ perl rewrite_dat_with_prokind.pl pg_proc.dat The following column types are supported directly by bootstrap.c: bool, bytea, char (1 byte), - name, int2, - int4, regproc, regclass, - regtype, text, - oid, tid, xid, - cid, int2vector, oidvector, + int2, int4, int8, + float4, float8, + name, regproc, text, + jsonb, oid, pg_node_tree, + int2vector, oidvector, _int4 (array), _text (array), _oid (array), _char (array), _aclitem (array). Although it is possible to create @@ -884,7 +899,7 @@ $ perl rewrite_dat_with_prokind.pl pg_proc.dat - insert ( oid_value value1 value2 ... ) + insert ( value1 value2 ... ) @@ -902,6 +917,13 @@ $ perl rewrite_dat_with_prokind.pl pg_proc.dat (To include a single quote in a value, write it twice. Escape-string-style backslash escapes are allowed in the string, too.) + + + In most cases a value + string is simply fed to the datatype input routine for the column's + data type, after de-quoting if needed. However there are exceptions + for certain fields, as detailed previously. + diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 7d32cd0e159..8d601c363b4 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -26,6 +26,7 @@ #include "bootstrap/bootstrap.h" #include "catalog/index.h" #include "catalog/pg_collation.h" +#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "common/link-canary.h" #include "miscadmin.h" @@ -46,6 +47,7 @@ static void CheckerModeMain(void); static void bootstrap_signals(void); static Form_pg_attribute AllocateAttribute(void); +static void InsertOneProargdefaultsValue(char *value); static void populate_typ_list(void); static Oid gettype(char *type); static void cleanup(void); @@ -91,38 +93,28 @@ static const struct typinfo TypInfo[] = { F_BYTEAIN, F_BYTEAOUT}, {"char", CHAROID, 0, 1, true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid, F_CHARIN, F_CHAROUT}, + {"cstring", CSTRINGOID, 0, -2, false, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid, + F_CSTRING_IN, F_CSTRING_OUT}, {"int2", INT2OID, 0, 2, true, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid, F_INT2IN, F_INT2OUT}, {"int4", INT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, F_INT4IN, F_INT4OUT}, + {"int8", INT8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid, + F_INT8IN, F_INT8OUT}, {"float4", FLOAT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, F_FLOAT4IN, F_FLOAT4OUT}, + {"float8", FLOAT8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid, + F_FLOAT8IN, F_FLOAT8OUT}, {"name", NAMEOID, CHAROID, NAMEDATALEN, false, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, C_COLLATION_OID, F_NAMEIN, F_NAMEOUT}, - {"regclass", REGCLASSOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, - F_REGCLASSIN, F_REGCLASSOUT}, {"regproc", REGPROCOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, F_REGPROCIN, F_REGPROCOUT}, - {"regtype", REGTYPEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, - F_REGTYPEIN, F_REGTYPEOUT}, - {"regrole", REGROLEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, - 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}, + {"jsonb", JSONBOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid, + F_JSONB_IN, F_JSONB_OUT}, {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, F_OIDIN, F_OIDOUT}, - {"oid8", OID8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid, - F_OID8IN, F_OID8OUT}, - {"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid, - F_TIDIN, F_TIDOUT}, - {"xid", XIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, - F_XIDIN, F_XIDOUT}, - {"cid", CIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, - F_CIDIN, F_CIDOUT}, {"pg_node_tree", PG_NODE_TREEOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID, F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT}, {"int2vector", INT2VECTOROID, INT2OID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, @@ -660,6 +652,7 @@ InsertOneTuple(void) void InsertOneValue(char *value, int i) { + Form_pg_attribute attr; Oid typoid; int16 typlen; bool typbyval; @@ -668,19 +661,42 @@ InsertOneValue(char *value, int i) Oid typioparam; Oid typinput; Oid typoutput; + Oid typcollation; Assert(i >= 0 && i < MAXATTR); elog(DEBUG4, "inserting column %d value \"%s\"", i, value); - typoid = TupleDescAttr(boot_reldesc->rd_att, i)->atttypid; + attr = TupleDescAttr(RelationGetDescr(boot_reldesc), i); + typoid = attr->atttypid; boot_get_type_io_data(typoid, &typlen, &typbyval, &typalign, &typdelim, &typioparam, - &typinput, &typoutput); + &typinput, &typoutput, + &typcollation); - values[i] = OidInputFunctionCall(typinput, value, typioparam, -1); + /* + * pg_node_tree values can't be inserted normally (pg_node_tree_in would + * just error out), so provide special cases for such columns that we + * would like to fill during bootstrap. + */ + if (typoid == PG_NODE_TREEOID) + { + /* pg_proc.proargdefaults */ + if (RelationGetRelid(boot_reldesc) == ProcedureRelationId && + i == Anum_pg_proc_proargdefaults - 1) + InsertOneProargdefaultsValue(value); + else /* maybe other cases later */ + elog(ERROR, "can't handle pg_node_tree input for %s.%s", + RelationGetRelationName(boot_reldesc), + NameStr(attr->attname)); + } + else + { + /* Normal case */ + values[i] = OidInputFunctionCall(typinput, value, typioparam, -1); + } /* * We use ereport not elog here so that parameters aren't evaluated unless @@ -691,6 +707,111 @@ InsertOneValue(char *value, int i) OidOutputFunctionCall(typoutput, values[i])))); } +/* ---------------- + * InsertOneProargdefaultsValue + * + * In general, proargdefaults can be a list of any expressions, but + * for bootstrap we only support a list of Const nodes. The input + * has the form of a text array, and we feed non-null elements to the + * typinput functions for the appropriate parameters. + * ---------------- + */ +static void +InsertOneProargdefaultsValue(char *value) +{ + int pronargs; + oidvector *proargtypes; + Datum arrayval; + Datum *array_datums; + bool *array_nulls; + int array_count; + List *proargdefaults; + char *nodestring; + + /* The pg_proc columns we need to use must have been filled already */ + StaticAssertDecl(Anum_pg_proc_pronargs < Anum_pg_proc_proargdefaults, + "pronargs must come before proargdefaults"); + StaticAssertDecl(Anum_pg_proc_pronargdefaults < Anum_pg_proc_proargdefaults, + "pronargdefaults must come before proargdefaults"); + StaticAssertDecl(Anum_pg_proc_proargtypes < Anum_pg_proc_proargdefaults, + "proargtypes must come before proargdefaults"); + if (Nulls[Anum_pg_proc_pronargs - 1]) + elog(ERROR, "pronargs must not be null"); + if (Nulls[Anum_pg_proc_proargtypes - 1]) + elog(ERROR, "proargtypes must not be null"); + pronargs = DatumGetInt16(values[Anum_pg_proc_pronargs - 1]); + proargtypes = DatumGetPointer(values[Anum_pg_proc_proargtypes - 1]); + Assert(pronargs == proargtypes->dim1); + + /* Parse the input string as an array value, then deconstruct to Datums */ + arrayval = OidFunctionCall3(F_ARRAY_IN, + CStringGetDatum(value), + ObjectIdGetDatum(CSTRINGOID), + Int32GetDatum(-1)); + deconstruct_array_builtin(DatumGetArrayTypeP(arrayval), CSTRINGOID, + &array_datums, &array_nulls, &array_count); + + /* The values should correspond to the last N argtypes */ + if (array_count > pronargs) + elog(ERROR, "too many proargdefaults entries"); + + /* Build the List of Const nodes */ + proargdefaults = NIL; + for (int i = 0; i < array_count; i++) + { + Oid argtype = proargtypes->values[pronargs - array_count + i]; + int16 typlen; + bool typbyval; + char typalign; + char typdelim; + Oid typioparam; + Oid typinput; + Oid typoutput; + Oid typcollation; + Datum defval; + bool defnull; + Const *defConst; + + boot_get_type_io_data(argtype, + &typlen, &typbyval, &typalign, + &typdelim, &typioparam, + &typinput, &typoutput, + &typcollation); + + defnull = array_nulls[i]; + if (defnull) + defval = (Datum) 0; + else + defval = OidInputFunctionCall(typinput, + DatumGetCString(array_datums[i]), + typioparam, -1); + + defConst = makeConst(argtype, + -1, /* never any typmod */ + typcollation, + typlen, + defval, + defnull, + typbyval); + proargdefaults = lappend(proargdefaults, defConst); + } + + /* + * Flatten the List to a node-tree string, then convert to a text datum, + * which is the storage representation of pg_node_tree. + */ + nodestring = nodeToString(proargdefaults); + values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodestring); + Nulls[Anum_pg_proc_proargdefaults - 1] = false; + + /* + * Hack: fill in pronargdefaults with the right value. This is surely + * ugly, but it beats making the programmer do it. + */ + values[Anum_pg_proc_pronargdefaults - 1] = Int16GetDatum(array_count); + Nulls[Anum_pg_proc_pronargdefaults - 1] = false; +} + /* ---------------- * InsertOneNull * ---------------- @@ -831,10 +952,11 @@ gettype(char *type) * boot_get_type_io_data * * Obtain type I/O information at bootstrap time. This intentionally has - * almost the same API as lsyscache.c's get_type_io_data, except that + * an API very close to that of lsyscache.c's get_type_io_data, except that * we only support obtaining the typinput and typoutput routines, not - * the binary I/O routines. It is exported so that array_in and array_out - * can be made to work during early bootstrap. + * the binary I/O routines, and we also return the type's collation. + * This is exported so that array_in and array_out can be made to work + * during early bootstrap. * ---------------- */ void @@ -845,7 +967,8 @@ boot_get_type_io_data(Oid typid, char *typdelim, Oid *typioparam, Oid *typinput, - Oid *typoutput) + Oid *typoutput, + Oid *typcollation) { if (Typ != NIL) { @@ -876,6 +999,8 @@ boot_get_type_io_data(Oid typid, *typinput = ap->am_typ.typinput; *typoutput = ap->am_typ.typoutput; + + *typcollation = ap->am_typ.typcollation; } else { @@ -904,6 +1029,8 @@ boot_get_type_io_data(Oid typid, *typinput = TypInfo[typeindex].inproc; *typoutput = TypInfo[typeindex].outproc; + + *typcollation = TypInfo[typeindex].collation; } } diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index eb9e31ae1bf..69699f8830a 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -7,7 +7,8 @@ * * This file redefines certain built-in functions that are impractical * to fully define in pg_proc.dat. In most cases that's because they use - * SQL-standard function bodies and/or default expressions. The node + * SQL-standard function bodies and/or default expressions. (But defaults + * that are just constants can be entered in pg_proc.dat.) The node * tree representations of those are too unreadable, platform-dependent, * and changeable to want to deal with them manually. Hence, we put stub * definitions of such functions into pg_proc.dat and then replace them @@ -66,13 +67,6 @@ CREATE OR REPLACE FUNCTION bit_length(text) IMMUTABLE PARALLEL SAFE STRICT COST 1 RETURN octet_length($1) * 8; -CREATE OR REPLACE FUNCTION - random_normal(mean float8 DEFAULT 0, stddev float8 DEFAULT 1) - RETURNS float8 - LANGUAGE internal - VOLATILE PARALLEL RESTRICTED STRICT COST 1 -AS 'drandom_normal'; - CREATE OR REPLACE FUNCTION log(numeric) RETURNS numeric LANGUAGE sql @@ -383,279 +377,6 @@ BEGIN ATOMIC SELECT * FROM ts_debug(get_current_ts_config(), $1); END; -CREATE OR REPLACE FUNCTION - pg_backup_start(label text, fast boolean DEFAULT false) - RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_backup_start' - PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION pg_backup_stop ( - wait_for_archive boolean DEFAULT true, OUT lsn pg_lsn, - OUT labelfile text, OUT spcmapfile text) - RETURNS record STRICT VOLATILE LANGUAGE internal as 'pg_backup_stop' - PARALLEL RESTRICTED; - -CREATE OR REPLACE FUNCTION - pg_promote(wait boolean DEFAULT true, wait_seconds integer DEFAULT 60) - RETURNS boolean STRICT VOLATILE LANGUAGE INTERNAL AS 'pg_promote' - PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION - pg_terminate_backend(pid integer, timeout int8 DEFAULT 0) - RETURNS boolean STRICT VOLATILE LANGUAGE INTERNAL AS 'pg_terminate_backend' - PARALLEL SAFE; - --- legacy definition for compatibility with 9.3 -CREATE OR REPLACE FUNCTION - json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false) - RETURNS anyelement LANGUAGE internal STABLE AS 'json_populate_record' PARALLEL SAFE; - --- legacy definition for compatibility with 9.3 -CREATE OR REPLACE FUNCTION - json_populate_recordset(base anyelement, from_json json, use_json_as_text boolean DEFAULT false) - RETURNS SETOF anyelement LANGUAGE internal STABLE ROWS 100 AS 'json_populate_recordset' PARALLEL SAFE; - -CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes( - IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}', - OUT lsn pg_lsn, OUT xid xid, OUT data text) -RETURNS SETOF RECORD -LANGUAGE INTERNAL -VOLATILE ROWS 1000 COST 1000 -AS 'pg_logical_slot_get_changes'; - -CREATE OR REPLACE FUNCTION pg_logical_slot_peek_changes( - IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}', - OUT lsn pg_lsn, OUT xid xid, OUT data text) -RETURNS SETOF RECORD -LANGUAGE INTERNAL -VOLATILE ROWS 1000 COST 1000 -AS 'pg_logical_slot_peek_changes'; - -CREATE OR REPLACE FUNCTION pg_logical_slot_get_binary_changes( - IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}', - OUT lsn pg_lsn, OUT xid xid, OUT data bytea) -RETURNS SETOF RECORD -LANGUAGE INTERNAL -VOLATILE ROWS 1000 COST 1000 -AS 'pg_logical_slot_get_binary_changes'; - -CREATE OR REPLACE FUNCTION pg_logical_slot_peek_binary_changes( - IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}', - OUT lsn pg_lsn, OUT xid xid, OUT data bytea) -RETURNS SETOF RECORD -LANGUAGE INTERNAL -VOLATILE ROWS 1000 COST 1000 -AS 'pg_logical_slot_peek_binary_changes'; - -CREATE OR REPLACE FUNCTION pg_logical_emit_message( - transactional boolean, - prefix text, - message text, - flush boolean DEFAULT false) -RETURNS pg_lsn -LANGUAGE INTERNAL -STRICT VOLATILE -AS 'pg_logical_emit_message_text'; - -CREATE OR REPLACE FUNCTION pg_logical_emit_message( - transactional boolean, - prefix text, - message bytea, - flush boolean DEFAULT false) -RETURNS pg_lsn -LANGUAGE INTERNAL -STRICT VOLATILE -AS 'pg_logical_emit_message_bytea'; - -CREATE OR REPLACE FUNCTION pg_create_physical_replication_slot( - IN slot_name name, IN immediately_reserve boolean DEFAULT false, - IN temporary boolean DEFAULT false, - OUT slot_name name, OUT lsn pg_lsn) -RETURNS RECORD -LANGUAGE INTERNAL -STRICT VOLATILE -AS 'pg_create_physical_replication_slot'; - -CREATE OR REPLACE FUNCTION pg_create_logical_replication_slot( - IN slot_name name, IN plugin name, - IN temporary boolean DEFAULT false, - IN twophase boolean DEFAULT false, - IN failover boolean DEFAULT false, - OUT slot_name name, OUT lsn pg_lsn) -RETURNS RECORD -LANGUAGE INTERNAL -STRICT VOLATILE -AS 'pg_create_logical_replication_slot'; - -CREATE OR REPLACE FUNCTION - make_interval(years int4 DEFAULT 0, months int4 DEFAULT 0, weeks int4 DEFAULT 0, - days int4 DEFAULT 0, hours int4 DEFAULT 0, mins int4 DEFAULT 0, - secs double precision DEFAULT 0.0) -RETURNS interval -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'make_interval'; - -CREATE OR REPLACE FUNCTION - jsonb_set(jsonb_in jsonb, path text[] , replacement jsonb, - create_if_missing boolean DEFAULT true) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_set'; - -CREATE OR REPLACE FUNCTION - jsonb_set_lax(jsonb_in jsonb, path text[] , replacement jsonb, - create_if_missing boolean DEFAULT true, - null_value_treatment text DEFAULT 'use_json_null') -RETURNS jsonb -LANGUAGE INTERNAL -CALLED ON NULL INPUT IMMUTABLE PARALLEL SAFE -AS 'jsonb_set_lax'; - -CREATE OR REPLACE FUNCTION - parse_ident(str text, strict boolean DEFAULT true) -RETURNS text[] -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'parse_ident'; - -CREATE OR REPLACE FUNCTION - jsonb_insert(jsonb_in jsonb, path text[] , replacement jsonb, - insert_after boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_insert'; - -CREATE OR REPLACE FUNCTION - jsonb_path_exists(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS boolean -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_path_exists'; - -CREATE OR REPLACE FUNCTION - jsonb_path_match(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS boolean -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_path_match'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS SETOF jsonb -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_path_query'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query_array(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_path_query_array'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query_first(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT IMMUTABLE PARALLEL SAFE -AS 'jsonb_path_query_first'; - -CREATE OR REPLACE FUNCTION - jsonb_path_exists_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS boolean -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_path_exists_tz'; - -CREATE OR REPLACE FUNCTION - jsonb_path_match_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS boolean -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_path_match_tz'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS SETOF jsonb -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_path_query_tz'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query_array_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_path_query_array_tz'; - -CREATE OR REPLACE FUNCTION - jsonb_path_query_first_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}', - silent boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_path_query_first_tz'; - -CREATE OR REPLACE FUNCTION - jsonb_strip_nulls(target jsonb, strip_in_arrays boolean DEFAULT false) -RETURNS jsonb -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'jsonb_strip_nulls'; - -CREATE OR REPLACE FUNCTION - json_strip_nulls(target json, strip_in_arrays boolean DEFAULT false) -RETURNS json -LANGUAGE INTERNAL -STRICT STABLE PARALLEL SAFE -AS 'json_strip_nulls'; - --- default normalization form is NFC, per SQL standard -CREATE OR REPLACE FUNCTION - "normalize"(text, text DEFAULT 'NFC') -RETURNS text -LANGUAGE internal -STRICT IMMUTABLE PARALLEL SAFE -AS 'unicode_normalize_func'; - -CREATE OR REPLACE FUNCTION - is_normalized(text, text DEFAULT 'NFC') -RETURNS boolean -LANGUAGE internal -STRICT IMMUTABLE PARALLEL SAFE -AS 'unicode_is_normalized'; - -CREATE OR REPLACE FUNCTION - pg_stat_reset_shared(target text DEFAULT NULL) -RETURNS void -LANGUAGE INTERNAL -CALLED ON NULL INPUT VOLATILE PARALLEL SAFE -AS 'pg_stat_reset_shared'; - -CREATE OR REPLACE FUNCTION - pg_stat_reset_slru(target text DEFAULT NULL) -RETURNS void -LANGUAGE INTERNAL -CALLED ON NULL INPUT VOLATILE PARALLEL SAFE -AS 'pg_stat_reset_slru'; - -CREATE OR REPLACE FUNCTION - pg_replication_origin_session_setup(node_name text, pid integer DEFAULT 0) -RETURNS void -LANGUAGE INTERNAL -STRICT VOLATILE PARALLEL UNSAFE -AS 'pg_replication_origin_session_setup'; -- -- The default permissions for functions mean that anyone can execute them. diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index b924a2d900b..1913b009d40 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -2492,6 +2492,7 @@ get_type_io_data(Oid typid, { Oid typinput; Oid typoutput; + Oid typcollation; boot_get_type_io_data(typid, typlen, @@ -2500,7 +2501,8 @@ get_type_io_data(Oid typid, typdelim, typioparam, &typinput, - &typoutput); + &typoutput, + &typcollation); switch (which_func) { case IOFunc_input: diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index 51680522afc..21447a3d661 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -53,7 +53,8 @@ extern void boot_get_type_io_data(Oid typid, char *typdelim, Oid *typioparam, Oid *typinput, - Oid *typoutput); + Oid *typoutput, + Oid *typcollation); union YYSTYPE; typedef void *yyscan_t; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 0bdd42a2b86..7be8afc10ed 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202602121 +#define CATALOG_VERSION_NO 202602181 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 83f6501df38..dac40992cbc 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -3499,6 +3499,7 @@ { oid => '6212', descr => 'random value from normal distribution', proname => 'random_normal', provolatile => 'v', proparallel => 'r', prorettype => 'float8', proargtypes => 'float8 float8', + proargnames => '{mean,stddev}', proargdefaults => '{0,1}', prosrc => 'drandom_normal' }, { oid => '6339', descr => 'random integer in range', proname => 'random', provolatile => 'v', proparallel => 'r', @@ -6174,6 +6175,7 @@ descr => 'statistics: reset collected statistics shared across the cluster', proname => 'pg_stat_reset_shared', proisstrict => 'f', provolatile => 'v', prorettype => 'void', proargtypes => 'text', + proargnames => '{target}', proargdefaults => '{NULL}', prosrc => 'pg_stat_reset_shared' }, { oid => '3776', descr => 'statistics: reset collected statistics for a single table or index in the current database or shared across all databases in the cluster', @@ -6193,6 +6195,7 @@ descr => 'statistics: reset collected statistics for a single SLRU', proname => 'pg_stat_reset_slru', proisstrict => 'f', provolatile => 'v', prorettype => 'void', proargtypes => 'text', proargnames => '{target}', + proargdefaults => '{NULL}', prosrc => 'pg_stat_reset_slru' }, { oid => '6170', descr => 'statistics: reset collected statistics for a single replication slot', @@ -6728,20 +6731,24 @@ { oid => '2096', descr => 'terminate a server process', proname => 'pg_terminate_backend', provolatile => 'v', prorettype => 'bool', proargtypes => 'int4 int8', proargnames => '{pid,timeout}', + proargdefaults => '{0}', prosrc => 'pg_terminate_backend' }, { oid => '2172', descr => 'prepare for taking an online backup', proname => 'pg_backup_start', provolatile => 'v', proparallel => 'r', prorettype => 'pg_lsn', proargtypes => 'text bool', + proargnames => '{label,fast}', proargdefaults => '{false}', prosrc => 'pg_backup_start' }, { oid => '2739', descr => 'finish taking an online backup', proname => 'pg_backup_stop', provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => 'bool', proallargtypes => '{bool,pg_lsn,text,text}', proargmodes => '{i,o,o,o}', proargnames => '{wait_for_archive,lsn,labelfile,spcmapfile}', + proargdefaults => '{true}', prosrc => 'pg_backup_stop' }, { oid => '3436', descr => 'promote standby server', proname => 'pg_promote', provolatile => 'v', prorettype => 'bool', proargtypes => 'bool int4', proargnames => '{wait,wait_seconds}', + proargdefaults => '{true,60}', prosrc => 'pg_promote' }, { oid => '2848', descr => 'switch to new wal file', proname => 'pg_switch_wal', provolatile => 'v', prorettype => 'pg_lsn', @@ -7517,7 +7524,8 @@ { oid => '1268', descr => 'parse qualified identifier to array of identifiers', proname => 'parse_ident', prorettype => '_text', proargtypes => 'text bool', - proargnames => '{str,strict}', prosrc => 'parse_ident' }, + proargnames => '{str,strict}', proargdefaults => '{true}', + prosrc => 'parse_ident' }, { oid => '2246', descr => '(internal)', proname => 'fmgr_internal_validator', provolatile => 's', @@ -9423,7 +9431,9 @@ proargtypes => 'anyelement', prosrc => 'to_json' }, { oid => '3261', descr => 'remove object fields with null values from json', proname => 'json_strip_nulls', prorettype => 'json', - proargtypes => 'json bool', prosrc => 'json_strip_nulls' }, + proargtypes => 'json bool', + proargnames => '{target,strip_in_arrays}', proargdefaults => '{false}', + prosrc => 'json_strip_nulls' }, { oid => '3947', proname => 'json_object_field', prorettype => 'json', @@ -9480,12 +9490,17 @@ { oid => '3960', descr => 'get record fields from a json object', proname => 'json_populate_record', proisstrict => 'f', provolatile => 's', prorettype => 'anyelement', proargtypes => 'anyelement json bool', + proargnames => '{base,from_json,use_json_as_text}', + proargdefaults => '{false}', prosrc => 'json_populate_record' }, { oid => '3961', descr => 'get set of records with fields from a json array of objects', proname => 'json_populate_recordset', prorows => '100', proisstrict => 'f', proretset => 't', provolatile => 's', prorettype => 'anyelement', - proargtypes => 'anyelement json bool', prosrc => 'json_populate_recordset' }, + proargtypes => 'anyelement json bool', + proargnames => '{base,from_json,use_json_as_text}', + proargdefaults => '{false}', + prosrc => 'json_populate_recordset' }, { oid => '3204', descr => 'get record fields from a json object', proname => 'json_to_record', provolatile => 's', prorettype => 'record', proargtypes => 'json', prosrc => 'json_to_record' }, @@ -10364,7 +10379,9 @@ prosrc => 'jsonb_build_object_noargs' }, { oid => '3262', descr => 'remove object fields with null values from jsonb', proname => 'jsonb_strip_nulls', prorettype => 'jsonb', - proargtypes => 'jsonb bool', prosrc => 'jsonb_strip_nulls' }, + proargtypes => 'jsonb bool', + proargnames => '{target,strip_in_arrays}', proargdefaults => '{false}', + prosrc => 'jsonb_strip_nulls' }, { oid => '3478', proname => 'jsonb_object_field', prorettype => 'jsonb', @@ -10538,16 +10555,25 @@ proargtypes => 'jsonb _text', prosrc => 'jsonb_delete_path' }, { oid => '5054', descr => 'Set part of a jsonb, handle NULL value', proname => 'jsonb_set_lax', proisstrict => 'f', prorettype => 'jsonb', - proargtypes => 'jsonb _text jsonb bool text', prosrc => 'jsonb_set_lax' }, + proargtypes => 'jsonb _text jsonb bool text', + proargnames => '{jsonb_in,path,replacement,create_if_missing,null_value_treatment}', + proargdefaults => '{true,use_json_null}', + prosrc => 'jsonb_set_lax' }, { oid => '3305', descr => 'Set part of a jsonb', proname => 'jsonb_set', prorettype => 'jsonb', - proargtypes => 'jsonb _text jsonb bool', prosrc => 'jsonb_set' }, + proargtypes => 'jsonb _text jsonb bool', + proargnames => '{jsonb_in,path,replacement,create_if_missing}', + proargdefaults => '{true}', + prosrc => 'jsonb_set' }, { oid => '3306', descr => 'Indented text from jsonb', proname => 'jsonb_pretty', prorettype => 'text', proargtypes => 'jsonb', prosrc => 'jsonb_pretty' }, { oid => '3579', descr => 'Insert value into a jsonb', proname => 'jsonb_insert', prorettype => 'jsonb', - proargtypes => 'jsonb _text jsonb bool', prosrc => 'jsonb_insert' }, + proargtypes => 'jsonb _text jsonb bool', + proargnames => '{jsonb_in,path,replacement,insert_after}', + proargdefaults => '{false}', + prosrc => 'jsonb_insert' }, # jsonpath { oid => '4001', descr => 'I/O', @@ -10565,42 +10591,66 @@ { oid => '4005', descr => 'jsonpath exists test', proname => 'jsonb_path_exists', prorettype => 'bool', - proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_exists' }, + proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', + prosrc => 'jsonb_path_exists' }, { oid => '4006', descr => 'jsonpath query', proname => 'jsonb_path_query', prorows => '1000', proretset => 't', prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_query' }, { oid => '4007', descr => 'jsonpath query wrapped into array', proname => 'jsonb_path_query_array', prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_query_array' }, { oid => '4008', descr => 'jsonpath query first item', proname => 'jsonb_path_query_first', prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_query_first' }, { oid => '4009', descr => 'jsonpath match', proname => 'jsonb_path_match', prorettype => 'bool', - proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_match' }, + proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', + prosrc => 'jsonb_path_match' }, { oid => '1177', descr => 'jsonpath exists test with timezone', proname => 'jsonb_path_exists_tz', provolatile => 's', prorettype => 'bool', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_exists_tz' }, { oid => '1179', descr => 'jsonpath query with timezone', proname => 'jsonb_path_query_tz', prorows => '1000', proretset => 't', provolatile => 's', prorettype => 'jsonb', - proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_query_tz' }, + proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', + prosrc => 'jsonb_path_query_tz' }, { oid => '1180', descr => 'jsonpath query wrapped into array with timezone', proname => 'jsonb_path_query_array_tz', provolatile => 's', prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_query_array_tz' }, { oid => '2023', descr => 'jsonpath query first item with timezone', proname => 'jsonb_path_query_first_tz', provolatile => 's', prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', prosrc => 'jsonb_path_query_first_tz' }, { oid => '2030', descr => 'jsonpath match with timezone', proname => 'jsonb_path_match_tz', provolatile => 's', prorettype => 'bool', - proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_match_tz' }, + proargtypes => 'jsonb jsonpath jsonb bool', + proargnames => '{target,path,vars,silent}', + proargdefaults => '{"{}",false}', + prosrc => 'jsonb_path_match_tz' }, { oid => '4010', descr => 'implementation of @? operator', proname => 'jsonb_path_exists_opr', prorettype => 'bool', @@ -11411,6 +11461,7 @@ proname => 'make_interval', prorettype => 'interval', proargtypes => 'int4 int4 int4 int4 int4 int4 float8', proargnames => '{years,months,weeks,days,hours,mins,secs}', + proargdefaults => '{0,0,0,0,0,0,0.0}', prosrc => 'make_interval' }, # spgist opclasses @@ -11511,6 +11562,7 @@ proallargtypes => '{name,bool,bool,name,pg_lsn}', proargmodes => '{i,i,i,o,o}', proargnames => '{slot_name,immediately_reserve,temporary,slot_name,lsn}', + proargdefaults => '{false,false}', prosrc => 'pg_create_physical_replication_slot' }, { oid => '4220', descr => 'copy a physical replication slot, changing temporality', @@ -11546,6 +11598,7 @@ proallargtypes => '{name,name,bool,bool,bool,name,pg_lsn}', proargmodes => '{i,i,i,i,i,o,o}', proargnames => '{slot_name,plugin,temporary,twophase,failover,slot_name,lsn}', + proargdefaults => '{false,false,false}', prosrc => 'pg_create_logical_replication_slot' }, { oid => '4222', descr => 'copy a logical replication slot, changing temporality and plugin', @@ -11578,6 +11631,7 @@ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,text}', proargmodes => '{i,i,i,v,o,o,o}', proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}', + proargdefaults => '{"{}"}', prosrc => 'pg_logical_slot_get_changes' }, { oid => '3783', descr => 'get binary changes from replication slot', proname => 'pg_logical_slot_get_binary_changes', procost => '1000', @@ -11587,6 +11641,7 @@ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,bytea}', proargmodes => '{i,i,i,v,o,o,o}', proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}', + proargdefaults => '{"{}"}', prosrc => 'pg_logical_slot_get_binary_changes' }, { oid => '3784', descr => 'peek at changes from replication slot', proname => 'pg_logical_slot_peek_changes', procost => '1000', @@ -11596,6 +11651,7 @@ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,text}', proargmodes => '{i,i,i,v,o,o,o}', proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}', + proargdefaults => '{"{}"}', prosrc => 'pg_logical_slot_peek_changes' }, { oid => '3785', descr => 'peek at binary changes from replication slot', proname => 'pg_logical_slot_peek_binary_changes', procost => '1000', @@ -11605,6 +11661,7 @@ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,bytea}', proargmodes => '{i,i,i,v,o,o,o}', proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}', + proargdefaults => '{"{}"}', prosrc => 'pg_logical_slot_peek_binary_changes' }, { oid => '3878', descr => 'advance logical replication slot', proname => 'pg_replication_slot_advance', provolatile => 'v', @@ -11615,10 +11672,14 @@ { oid => '3577', descr => 'emit a textual logical decoding message', proname => 'pg_logical_emit_message', provolatile => 'v', proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'bool text text bool', + proargnames => '{transactional,prefix,message,flush}', + proargdefaults => '{false}', prosrc => 'pg_logical_emit_message_text' }, { oid => '3578', descr => 'emit a binary logical decoding message', proname => 'pg_logical_emit_message', provolatile => 'v', proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'bool text bytea bool', + proargnames => '{transactional,prefix,message,flush}', + proargdefaults => '{false}', prosrc => 'pg_logical_emit_message_bytea' }, { oid => '6344', descr => 'sync replication slots from the primary to the standby', @@ -12268,6 +12329,7 @@ descr => 'configure session to maintain replication progress tracking for the passed in origin', proname => 'pg_replication_origin_session_setup', provolatile => 'v', proparallel => 'u', prorettype => 'void', proargtypes => 'text int4', + proargnames => '{node_name,pid}', proargdefaults => '{0}', prosrc => 'pg_replication_origin_session_setup' }, { oid => '6007', descr => 'teardown configured replication progress tracking', @@ -12518,10 +12580,12 @@ { oid => '4350', descr => 'Unicode normalization', proname => 'normalize', prorettype => 'text', proargtypes => 'text text', + proargdefaults => '{NFC}', prosrc => 'unicode_normalize_func' }, { oid => '4351', descr => 'check Unicode normalization', proname => 'is_normalized', prorettype => 'bool', proargtypes => 'text text', + proargdefaults => '{NFC}', prosrc => 'unicode_is_normalized' }, { oid => '6198', descr => 'unescape Unicode characters',