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.94.2) (envelope-from ) id 1urtRK-00EBAr-68 for pgsql-hackers@arkaria.postgresql.org; Fri, 29 Aug 2025 07:22:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1urtRJ-007N1U-JN for pgsql-hackers@arkaria.postgresql.org; Fri, 29 Aug 2025 07:22:26 +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.94.2) (envelope-from ) id 1urtRJ-007N1M-3z for pgsql-hackers@lists.postgresql.org; Fri, 29 Aug 2025 07:22:25 +0000 Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1urtRG-002K8f-2k for pgsql-hackers@postgresql.org; Fri, 29 Aug 2025 07:22:24 +0000 Received: by mail-pg1-x536.google.com with SMTP id 41be03b00d2f7-b476c67c5easo1274523a12.0 for ; Fri, 29 Aug 2025 00:22:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1756452142; x=1757056942; darn=postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=GnwcAWQCXUSsc5FJ7ANXTpNK3Lv+bHyQJ2KXXXqaywg=; b=Aett2QU2iShepaNmbqlEvGxFYpRVz7V+RZBpDEmTf4ODOdT3vw6DlTW9wWxSK9agfm l2T9+AAvN/H7+ViyNDhrJARLe5MevROM0lvecvalFuudbKen+6mNUUVDYVW5Ds7JEcQH 6UA7cgzf+BYSCekSk/aw9QZ0tS2ffXLD4iUPhbq7ldi2Kk0/CUk2WnyCNf52QAZyqagX 33irWajQ5ZdwcGcp4ZindaiNsz5f5MC+i4jDhSc5HN9djo9fLY56sxeRPuXmix2jomUt 9eS/kP0nJJX6IgT6kH9/GaZ2UBlP2D8+W8g3Ng5YFRmBOEKzQgPgtLgYE4qsqsC1p1He 3CWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756452142; x=1757056942; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=GnwcAWQCXUSsc5FJ7ANXTpNK3Lv+bHyQJ2KXXXqaywg=; b=egy9+b7CpPDzICRNXZFLaOsAwA+hlp11As4qwdDeBT3g8vSpjaUxrN/COpYRwwMTOA IeguG8na/Ma/4Myrnh3oQOeSQCqX4Nl7NzIDLPgl5ODSqfUhzAwswQZ+j3/SVlNygDJ0 CvlWZRl5Z69nyZSI/deoKNwC7yd3jA/jFsfn7PFRTMaN6PgAW2ZGb5XdFOyeZHa+qkY7 +zTLnRFvq2EqU2TwqZeFAT/rdtwSLu7e0iY3nY80V+jaTUyteRB3vKZcHodSpL6dG1Sd jcXAhzTxuGc9sfINPQoBxa/rNGJVfAaAViknsqa55diS6RBZYB5SzrFjqplPvI0Ur5MW NxAw== X-Forwarded-Encrypted: i=1; AJvYcCXLJyCQA2ZqQ1I/nSFS3X5o1m+KA0jyyP3k8eL/VSPRc4m0HwUhXohZLnNs6UfO1PxjtZmJUeKblsj8bZJK@postgresql.org X-Gm-Message-State: AOJu0YwaWNmKyH+DGyhRB/j+iArv+cipzM/veOOainbex9dn5Pc2V/YX li5oBPkB/dZ+VJxtrQq005hhchGemW9gQuHY11hRGSiyZgg8JfeMsp+U X-Gm-Gg: ASbGncsSQjpHVrqqN0WR8rg/CwqdW9XV8lmiMb6OseCdWiY8IrPwT01EumM5eVi1cWm BSpdaN51aU7XJyKtOHxGPb5MJOoJgBs1T5nBmrD9eXUB3Rcb6nCyewYphUx9hMiCeKiSrikeTPf NgY6qSM3RC4duokSmk+JkbuM1WhYkdoOH+PebQblKmgesvXaqILHZ8cemWVd/22c6FOB4PLoF+J 7PZ04cQZpl0L3PGHaKnPg9QbQoc4MDN5ghJmspfcHcUOnKQKb03eM5Z0JTeH76wkuvkCIhfvgax 7PBs4YdV1Q/iG5rTj1zMXFo15p9eEsBP5SvUc15XZfu0tHd9I39Ra6pD2RVoCnZqmUbkM+XUkWu ntDMcMMVtavZUfbp6rfM5CFTehUn+/Sl5rdhLFZRPO1w= X-Google-Smtp-Source: AGHT+IHbwqNfWc41WAYsAD3OHACOEIynlrQQ+4a4qtN9yst20iRkWYFavlHC/jYqVcU/MABKvSSkOg== X-Received: by 2002:a17:902:c952:b0:249:9f0:78bb with SMTP id d9443c01a7336-24909f07c80mr27097905ad.26.1756452142007; Fri, 29 Aug 2025 00:22:22 -0700 (PDT) Received: from smtpclient.apple ([142.171.105.12]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-24906390e6bsm15809835ad.96.2025.08.29.00.22.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Aug 2025 00:22:21 -0700 (PDT) From: Chao Li Message-Id: <290418A2-3A9B-4304-AAAD-4A40CFF1CB93@gmail.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_E42F463F-D643-4B54-84BD-39B58C6BFF88" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81\)) Subject: Re: SQL:2023 JSON simplified accessor support Date: Fri, 29 Aug 2025 15:22:04 +0800 In-Reply-To: Cc: jian he , Nikita Malakhov , Vik Fearing , Mark Dilger , Matheus Alcantara , Peter Eisentraut , Andrew Dunstan , Nikita Glukhov , PostgreSQL Hackers , "David E. Wheeler" To: Alexandra Wang References: <21fa36b4-6d56-4556-b524-9e3955b922c8@eisentraut.org> X-Mailer: Apple Mail (2.3826.700.81) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_E42F463F-D643-4B54-84BD-39B58C6BFF88 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Aug 26, 2025, at 11:52, Alexandra Wang = wrote: > = A few other comments: -static Node * -transformIndirection(ParseState *pstate, A_Indirection *ind) +Node * +transformIndirection(ParseState *pstate, A_Indirection *ind, + bool *trailing_star_expansion) { Node *last_srf =3D pstate->p_last_srf; Node *result =3D transformExprRecurse(pstate, ind->arg); @@ -454,12 +454,7 @@ transformIndirection(ParseState *pstate, = A_Indirection *ind) if (IsA(n, A_Indices)) subscripts =3D lappend(subscripts, n); else if (IsA(n, A_Star)) - { - ereport(ERROR, - = (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("row expansion via \"*\" = is not supported here"), - parser_errposition(pstate, = location))); - } + subscripts =3D lappend(subscripts, n); else { Assert(IsA(n, String)); Now, the 3 clauses are quite similar, the if-elseif-else can be = simplified as: If (!IsA(n, A_Indices) && !Is_A(n, A_Start)) Assert(IsA(n, String)); Subscripts =3D lappend(subscripts, n) +static bool +jsonb_check_jsonpath_needed(List *indirection) +{ + ListCell *lc; + + foreach(lc, indirection) + { + Node *accessor =3D lfirst(lc); + + if (IsA(accessor, String)) + return true; Like I mentioned in my previous comment, if we convert String (dot = notation) to Indices in rewritten phase, then jsonpath might be no = longer needed, and the code logic is much simplified. --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -244,7 +244,7 @@ transformContainerSubscripts(ParseState *pstate, Node = *containerBase, Oid = containerType, int32 = containerTypMod, - List = *indirection, + List = **indirection, bool = isAssignment) { SubscriptingRef *sbsref; @@ -280,7 +280,7 @@ transformContainerSubscripts(ParseState *pstate, * element. If any of the items are slice specifiers = (lower:upper), then * the subscript expression means a container slice operation. */ - foreach(idx, indirection) + foreach(idx, *indirection) { A_Indices *ai =3D lfirst_node(A_Indices, idx); Should this foreach be pull up to out of transformContainerSubscripts()? = Originally transformContainerSubscripts() runs only once, but now it=E2=80= =99s placed in a while loop, and every time this foreach needs to go = through the entire indirection list, which are duplicated computation. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_E42F463F-D643-4B54-84BD-39B58C6BFF88 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

On Aug 26, 2025, at 11:52, Alexandra Wang = <alexandra.wang.oss@gmail.com> wrote:

<v14-0002-Allow-Generic-Type-Subscripting-to-Acc= ept-Dot-No.patch><v14-0003-Export-jsonPathFromParseResult.patch&g= t;<v14-0001-Allow-transformation-of-only-a-sublist= -of-subscr.patch><v14-0005-Implement-read-only-dot-notation-for-j= sonb.patch><v14-0007-Implement-jsonb-wildcard-member-access= or.patch><v14-0006-Implement-Jsonb-subscripting-with-slic= ing.patch><v14-0004-Extract-coerce_jsonpath_subscript.patc= h>


A= few other comments:

-static Node = *
-transformIndirection(ParseState *pstate, A_Indirection = *ind)
+Node *
+transformIndirection(ParseState = *pstate, A_Indirection *ind,
+         =                     =            bool = *trailing_star_expansion)
 {
    =     Node       *last_srf =3D = pstate->p_last_srf;
        Node   =     *result =3D transformExprRecurse(pstate, = ind->arg);
@@ -454,12 +454,7 @@ = transformIndirection(ParseState *pstate, A_Indirection = *ind)
                = if (IsA(n, A_Indices))
          =               subscripts =3D = lappend(subscripts, n);
          =       else if (IsA(n, A_Star))
-     =           {
-       =                 = ereport(ERROR,
-             =                     =       = (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-     =                     =                errmsg("row = expansion via \"*\" is not supported here"),
-     =                     =               =  parser_errposition(pstate, location)));
-     =           }
+       =                 subscripts =3D = lappend(subscripts, n);
          =       else
          =       {
          =               Assert(IsA(n, = String));

Now, the 3 clauses are quite similar, = the if-elseif-else can be simplified as:

  =    If (!IsA(n, A_Indices) && !Is_A(n, = A_Start))
          Assert(IsA(n, = String));
     Subscripts =3D = lappend(subscripts, n)

+static = bool
+jsonb_check_jsonpath_needed(List = *indirection)
+{
+       ListCell =   *lc;
+
+       foreach(lc, = indirection)
+       {
+   =             Node       = *accessor =3D lfirst(lc);
+
+       =         if (IsA(accessor, String))
+ =                     =   return true;

Like I = mentioned in my previous comment, if we convert String (dot notation) to = Indices in rewritten phase, then jsonpath might be no longer needed, and = the code logic is much = simplified.


--- = a/src/backend/parser/parse_node.c
+++ = b/src/backend/parser/parse_node.c
@@ -244,7 +244,7 @@ = transformContainerSubscripts(ParseState *pstate,
    =                     =                     =              Node = *containerBase,
            =                     =                     =      Oid containerType,
      =                     =                     =            int32 = containerTypMod,
-             =                     =                     =    List *indirection,
+         =                     =                     =        List **indirection,
    =                     =                     =              bool = isAssignment)
 {
        = SubscriptingRef *sbsref;
@@ -280,7 +280,7 @@ = transformContainerSubscripts(ParseState *pstate,
    =      * element.  If any of the items are slice = specifiers (lower:upper), then
        =  * the subscript expression means a container slice = operation.
         */
- =       foreach(idx, indirection)
+     =   foreach(idx, *indirection)
        = {
                = A_Indices  *ai =3D lfirst_node(A_Indices, = idx);

Should this foreach be pull up to = out of transformContainerSubscripts()? Originally = transformContainerSubscripts() runs only once, but now it=E2=80=99s = placed in a while loop, and every time this foreach needs to go through = the entire indirection list, which are duplicated = computation.

Best regards,
--
Chao Li (Evan)
HighGo Software = Co., Ltd.
https://www.highgo.com/




= --Apple-Mail=_E42F463F-D643-4B54-84BD-39B58C6BFF88--