On 2026-03-06 Fr 11:53 AM, Tom Lane wrote:
Andrew Dunstan <[email protected]> writes:
On 2026-03-06 Fr 11:01 AM, Tom Lane wrote:
If we need a TypInfo[] entry for ANY, let's just add it.
But I haven't seen any use cases?
Well, I guess that raises the question of what we get if we now do
CREATE OR REPLACE FUNCTION foo(x int, VARIADIC y "any" DEFAULT NULL);
which is the use case I was trying to avoid :-)
Turns out it sets the type to "unknown" and the constlen to -2.
Hmm.  Not sure if that matters or not.  In any case, my objection
to the proposed patch was its side-effects on defaults that are of
regular data types.  I don't think we want to change that behavior.


Yeah. Here for posterity is a patch for that. But I won't pursue it because ...



What exactly would be the use case for a default like the above?
I can see the point of, say, trying to merge the two variants of
jsonb_build_array:

CREATE FUNCTION pg_catalog.jsonb_build_array(VARIADIC "any") ...

CREATE FUNCTION pg_catalog.jsonb_build_array() ...

but introducing a default wouldn't help us do that, because it'd
still end up looking like a 1-argument call not a no-argument call.

                        


I was looking at it from the perspective of the pg_get_database_ddl patch. But that seems a bit baroque. I think we can make life a lot simpler here by using "VARIADIC options TEXT DEFAULT NULL".


cheers


andrew

--
Andrew Dunstan
EDB: https://www.enterprisedb.com
commit 4376af40df1
Author: Andrew Dunstan <[email protected]>
Date:   Fri Mar 6 09:53:23 2026 -0500

    Allow NULL defaults for pseudo-type parameters in pg_proc.dat
    
    InsertOneProargdefaultsValue() called boot_get_type_io_data() for
    every default value entry, including NULLs.  This failed for types
    not present in the bootstrap TypInfo[] array (such as pseudo-type
    "any"), even though NULL defaults never need a type input function.
    
    Fix by handling NULL defaults separately: look up the type metadata
    (typlen, typbyval, typcollation) from TypInfo or the Typ cache if
    available, so that known types get correct Const node metadata
    matching what the SQL parser would produce.  For types not found
    (e.g. "any" during early bootstrap), fall back to "unknown" type,
    which matches the SQL parser's treatment of untyped NULL literals in
    CREATE FUNCTION ... DEFAULT NULL.
    
    This enables functions with VARIADIC "any" DEFAULT NULL to specify
    their defaults directly in pg_proc.dat, without needing a
    system_functions.sql wrapper.

diff --git a/src/backend/bootstrap/bootstrap.c 
b/src/backend/bootstrap/bootstrap.c
index e7699be55aa..f979d44a640 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -772,19 +772,70 @@ InsertOneProargdefaultsValue(char *value)
                bool            defnull;
                Const      *defConst;
 
-               boot_get_type_io_data(argtype,
-                                                         &typlen, &typbyval, 
&typalign,
-                                                         &typdelim, 
&typioparam,
-                                                         &typinput, &typoutput,
-                                                         &typcollation);
-
                defnull = array_nulls[i];
                if (defnull)
+               {
+                       /*
+                        * For NULL defaults, we need the type metadata (typlen 
etc)
+                        * but not the I/O functions.  Look up the type if 
possible;
+                        * if it's not available yet (e.g. pseudo-types not in
+                        * TypInfo[]), fall back to "unknown" type, matching 
what
+                        * the SQL parser produces for untyped NULL literals.
+                        */
+                       bool    found = false;
+
                        defval = (Datum) 0;
+                       if (Typ != NIL)
+                       {
+                               ListCell   *lc;
+
+                               foreach(lc, Typ)
+                               {
+                                       struct typmap *ap = lfirst(lc);
+
+                                       if (ap->am_oid == argtype)
+                                       {
+                                               typlen = ap->am_typ.typlen;
+                                               typbyval = ap->am_typ.typbyval;
+                                               typcollation = 
ap->am_typ.typcollation;
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               for (int j = 0; j < n_types; j++)
+                               {
+                                       if (TypInfo[j].oid == argtype)
+                                       {
+                                               typlen = TypInfo[j].len;
+                                               typbyval = TypInfo[j].byval;
+                                               typcollation = 
TypInfo[j].collation;
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (!found)
+                       {
+                               argtype = UNKNOWNOID;
+                               typlen = -2;
+                               typbyval = false;
+                               typcollation = InvalidOid;
+                       }
+               }
                else
+               {
+                       boot_get_type_io_data(argtype,
+                                                                 &typlen, 
&typbyval, &typalign,
+                                                                 &typdelim, 
&typioparam,
+                                                                 &typinput, 
&typoutput,
+                                                                 
&typcollation);
                        defval = OidInputFunctionCall(typinput,
                                                                                
  DatumGetCString(array_datums[i]),
                                                                                
  typioparam, -1);
+               }
 
                defConst = makeConst(argtype,
                                                         -1,    /* never any 
typmod */

Reply via email to