Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vfXIH-002cB8-0d for pgsql-hackers@arkaria.postgresql.org; Tue, 13 Jan 2026 05:50:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vfXIG-0034J7-0x for pgsql-hackers@arkaria.postgresql.org; Tue, 13 Jan 2026 05:50:16 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vfXIF-0034Iz-2n for pgsql-hackers@lists.postgresql.org; Tue, 13 Jan 2026 05:50:16 +0000 Received: from mail-pg1-x52c.google.com ([2607:f8b0:4864:20::52c]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vfXID-0009AK-1y for pgsql-hackers@lists.postgresql.org; Tue, 13 Jan 2026 05:50:15 +0000 Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-bc29d64b39dso2631985a12.3 for ; Mon, 12 Jan 2026 21:50:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768283413; x=1768888213; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=F/WfHmh8Y+29CA40n3AMuMvKC8niga8BAhsiy8g2x3w=; b=PI1RHNa9N0QJHKCftH0e4xf1YKHvADwoOYx7hdfc7CZeM2UzgnJlVTycrWNbHDy54u Cwr8QXUxgnJaQuiywtDQtjMY00n1eWCH0I+CczsYCKmn6OkA0oUpr0iLkabiyOEfNy48 oU0bg5koc2oc8mnSqjWn14WCQg0RtchjfiNUBNRO7frwba25m3ZxMZmA7TcxcNyQbbrJ 4eInsuBsIHhXn4km4hx9ISirEYzg1tKIRaxhxhv7R+pE0I1kPcIzBufSIhlFAHspwFMN s1NZtT8o9HvnTp75kJVWpzjO2pfcsZDd7lJh3JeDJ91BVAs0nYAZQlpgjBfW2BQJ0D1A gXRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768283413; x=1768888213; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=F/WfHmh8Y+29CA40n3AMuMvKC8niga8BAhsiy8g2x3w=; b=U3ocr+D7SUc0KQXzaNSBCd6mC27cy4qZhUqimrSzs9T8O+yRNAn9jXft1pxt7aLxwp tRy0iLLA3Mx+Yh0voZa5GRspChsS3AXW7wzWUy56i+zszjoAQZYJIVbs9eEIrm4Ep1rp nbrLrod1sRe9Fj0yZE1+aBYgFUzT+sOmPOVArBd+9G/PswusNJ16wsZYQSSyOzy6uLgu DkEcw2mvAi7lP317RutzeN1Kg1VzXcGKFZPolrV9GZb87UkuUyv6EksoIiliHa7l/PdV gFZbqYp8sPOLNuzhnp6y3f87FcKMsRB8sxzJv+2i6gv1ztJvcGdQe5wAxy53Fe0/TyFH e7zA== X-Forwarded-Encrypted: i=1; AJvYcCUGgjLUWGL4OAMCtzKWc326Rxz68uJRplkEPd6p9E+BwmYPWkhNBBUZtpcrQobc8TAAs2HrzHk8vfUpkMaw@lists.postgresql.org X-Gm-Message-State: AOJu0YwJ/aLdkBNF9VVp82Mrkq3N8ENzn+G/mn7KP1VsuGKvFmvoJdmN qXLWeSQHv5fIowEjGDaXbX7H8Oo+BQ2RU59TQAaMVTqVW9NyQLkOzKyAJhBtw2opErBiEFSFZaD QQGtMlJo3OY+LNAhdfUPy0UMlVxjXWF0= X-Gm-Gg: AY/fxX5nSPWH4M+5RgtJ9sp3CCrdEdKCWn9MM9aIrv8P+3MOfGqiyZMlhi+rmus2OBZ WaI1m2WnA3NFtJMejaiZ9urGRTl7louc+F3gihoXRiuQFqFUsqvLB4qEIq5FLimK3gRz9DRhHoK VO63aULijJgDNOYEsXY8AMiiIMgjKbyWG3R79BQdtcId2i7vjfiDgBF+E6ijyDzuIlaMoFhnGsm fm8Em+jK4pefRlF/ca034cwlbdmVZ4Lk6YeJ5oHxMHjOvt3gUOuH3RAlbqmE2S8uTorqDKbXQ== X-Google-Smtp-Source: AGHT+IF1jsK6MF1o9Ak1NT6lPqiVdDeYvoaREAdsf32lDHhgXTUuHeFoMCP0IFSFyi0tMfPpRpCq7IsDBZNa4pOxv00= X-Received: by 2002:a17:90b:574d:b0:32e:7c34:70cf with SMTP id 98e67ed59e1d1-34f68cf020fmr16641888a91.36.1768283413291; Mon, 12 Jan 2026 21:50:13 -0800 (PST) MIME-Version: 1.0 References: <04afcd1f-ed7d-4c0a-add1-50e3719ccbf9@postgresfriends.org> <762ae707-7fdc-43d8-a77a-3a10d12ce21d@postgresfriends.org> In-Reply-To: From: Amul Sul Date: Tue, 13 Jan 2026 11:19:36 +0530 X-Gm-Features: AZwV_QhciXas2EQ6VOCxA0Q8KFFhFfrW1Hv6ZLFSztuKAIRo1mB0GFQxuoZoBk8 Message-ID: Subject: Re: CAST(... ON DEFAULT) - WIP build on top of Error-Safe User Functions To: jian he Cc: Kirill Reshke , Corey Huinker , Vik Fearing , Isaac Morland , pgsql-hackers@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, Jan 5, 2026 at 11:31=E2=80=AFAM jian he wrote: > > On Fri, Jan 2, 2026 at 2:08=E2=80=AFPM Amul Sul wrote= : > > > transformTypeCast transforms a TypeCast node and may produce one of the > following nodes: FuncExpr, CollateExpr, CoerceToDomain, ArrayCoerceExpr, = or > CoerceViaIO. > > To avoid EEOP_SAFETY_CAST, the returned node would need an > additional field to store the transformed DEFAULT expression. > This implies adding such a field to the aforementioned node types; otherw= ise, > the information about the transformed default expression would be lost. > > However, adding an extra field to nodes such as FuncExpr seems not doable= . > It is not generally applicable to FuncExpr, but rather only relevant to a > specific usage scenario. In addition, it may introduce unnecessary overhe= ad. > > > T_SafeTypeCastExpr is still needed for holding the transformed cast expre= ssion > and default expression, I think. > Oh okay. > [...] > However, we can add a field to node TypeCast for the raw default expressi= on. > transformTypeSafeCast seems not needed, so I consolidated > the parsing analysis into transformTypeCast. > Yeah, but I am a bit unsure about the naming (i.e., raw_default) and the comment stating this is an "untransformed DEFAULT expression". What is the status of the arg member of the TypeCast structure -- is it transformed or untransformed? If that is also untransformed, we can simply drop "untransformed" word from the comment and rename raw_default to something more descriptive, such as defaultExpr. Currently, raw_default doesn't clearly indicate that it represents an expression, IMO. Also, a few comments still refer to old transformTypeSafeCast(), which needs to be corrected. > > In that way, you can simply call ExecInitExprSafe() from > > ExecInitExpr() and pass NULL for the escontext. This reduces code > > duplication, since most of the code is similar except for the > > aforementioned initialization lines. > > > > now i changed it to: > > ExprState * > ExecInitExpr(Expr *node, PlanState *parent) > { > return ExecInitExprExtended(node, NULL, parent); > } > > ExprState * > ExecInitExprExtended(Expr *node, Node *escontext, PlanState *parent) > Yes, that looks like what I was thinking, but with the Node *escontext at the last position. I am not fully confident that the v17-0022 patch is complete. I believe there is a good chance to improve the patch in terms of coding, formatting, function and variable naming, as well as some refactoring and optimization that I still need to think on. Here are a few comments: + /* + * The collation of DEFAULT expression must match the collation of = the + * target type. + */ + defColl =3D exprCollation(defexpr); + + if (OidIsValid(targetTypecoll) && OidIsValid(defColl) && + targetTypecoll !=3D defColl) + ereport(ERROR, + errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("the collation of CAST DEFAULT expression conflicts with target type collation"), What if one collation is an invalid OID and the other is valid? Shouldn't we throw an error in that case? -- + SafeTypeCastState *stcstate; + + stcstate =3D palloc0(sizeof(SafeTypeCastState)); + stcstate->stcexpr =3D stcexpr; + stcstate->escontext.type =3D T_ErrorSaveContext; + state->escontext =3D &stcstate->escontext; Can't we reuse the state->escontext pointer in the SafeTypeCastState instead of allocating a separate ErrorSaveContext? -- + ErrorSaveContext *saved_escontext; + + saved_escontext =3D state->escontext; + + state->escontext =3D NULL; + + ExecInitExprRec((Expr *) stcstate->stcexpr->default_expr, + state, resv, resnull); + + state->escontext =3D saved_escontext; Here should be some comment explanation as to why you are setting state->escontext =3D NULL, and why that is needed for the default expression initialization but not for the case_expr evaluation. -- + + fmgr_info(functionId, &flinfo); + + return InputFunctionCallSafe(&flinfo, str, typioparam, typmod, + escontext, result); Remove the empty line between these two for consistency with other function's formatting. -- + ? errhint("Safe type cast for user-defined types are not yet supported") + : errhint("Explicit cast is defined but definition is not error safe"), Hints should end with a period. -- + /* + * Here, we cannot deparsing cast_expr directly, since + * transformTypeSafeCast may have folded it into a simple + * constant or NULL. Instead, we use source_expr and + * default_expr to reconstruct the CAST DEFAULT clause. + */ I am wondering how other places handle expression deparsing; do they hold the original expression along with the transformed expression? Also, why are we only folding constants from the source_expr but not from the default expression? Regards, Amul