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 1vDpXE-00HB6W-J5 for pgsql-hackers@arkaria.postgresql.org; Tue, 28 Oct 2025 19:39:12 +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 1vDpXB-00EmhB-UQ for pgsql-hackers@arkaria.postgresql.org; Tue, 28 Oct 2025 19:39:08 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vDpXB-00Emh3-2r for pgsql-hackers@lists.postgresql.org; Tue, 28 Oct 2025 19:39:08 +0000 Received: from fhigh-a3-smtp.messagingengine.com ([103.168.172.154]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vDpX6-004khS-15 for pgsql-hackers@lists.postgresql.org; Tue, 28 Oct 2025 19:39:06 +0000 Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 655261400388; Tue, 28 Oct 2025 15:39:00 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-04.internal (MEProxy); Tue, 28 Oct 2025 15:39:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=justatheory.com; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1761680340; x= 1761766740; bh=ujhlj17j9fPT0aICSn4+gw9V9CZfhSqFfK/9pG1XCtQ=; b=W KO8jksa7Q9vJ2m1mKCW2+I+p4BEyaSepsgCf3PtKFvvWBIZynNjNmZUbZ7lZABir l/uv7wa6GNUf+B8aqXItVzR0gpeuJmC7lIQMEu6iN8dVFR9cWuoERuTkM3HSS3Im wYnneIt8DJ0iGDXDtvUeYqAypOz0uvZic8tl59QCRNn1vCg/9j9IY/huqj/sa4CB 1gk9cmA7mLkpOVa/JKt+ps6zUZ2OGLbd0d5kMxfuDeuKbdqoY1prH+cLKwBezYas 2yHClaOhsEWmp3d/Q/EX1M1bfAlWtILJzsy2mO5eGOh20CZbfzQnvrPbmj5VIMLL SdZKuUatLVFay6btCVRSg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1761680340; x=1761766740; bh=ujhlj17j9fPT0aICSn4+gw9V9CZfhSqFfK/ 9pG1XCtQ=; b=RT7/5FdX1SU2EWW4NY2qT5LcWYPnB97KirGvCOAKBEPA8jFCPjd 1vfkDgTFcBbd9QaSBBkrhKxTdnZBnzMVjfOyL3v2mX/LCbjlvCB6PyGiGexVRvgg qYh6AHI9F4gNjxHzm+vluRX5kxeagFDW1UgYqEeKWlL1Vyebvo1Y3UNKUSZ0Isli B0j8eNb+1QlgsuGhXMGCQ5KLUkSU3w8xbiGe60WkqainvB3VhZ1XHajOwrQGHEcp IfRxGX0SbuJu+CbEq/jEyVUjTs7lV3IpjhrP8rJUF+ZFrb1ZO1//0u9JZ5OW3CzA iA5TKfYzkppj0W7LDtZ32as8NpbxFA/3Frg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduiedujeduucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffktgggufffjgevvfhfofesghdtmherhhdtjeenucfhrhhomhepfdffrghvihgu ucfgrdcuhghhvggvlhgvrhdfuceouggrvhhiugesjhhushhtrghthhgvohhrhidrtghomh eqnecuggftrfgrthhtvghrnhepveeivdehtdekueelieegkeettdegheejhefhueeuvddu ieevtdfgtdevhfdtleeknecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrg hilhhfrhhomhepuggrvhhiugesjhhushhtrghthhgvohhrhidrtghomhdpnhgspghrtghp thhtohepledpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtoheplhhirdgvvhgrnhdrtg hhrghosehgmhgrihhlrdgtohhmpdhrtghpthhtoheprghlvhhhvghrrhgvsehkuhhrihhl vghmuhdruggvpdhrtghpthhtohepfhhlohhrvghnthhsrdhtshgvlhgrihesghhmrghilh drtghomhdprhgtphhtthhopehtghhlsehsshhsrdhpghhhrdhprgdruhhspdhrtghpthht ohepphgvthgvrhesvghishgvnhhtrhgruhhtrdhorhhgpdhrtghpthhtoheprhhosggvrh htmhhhrggrshesghhmrghilhdrtghomhdprhgtphhtthhopegrvghkohhrohhtkhhovhes ghhmrghilhdrtghomhdprhgtphhtthhopehpghhsqhhlqdhhrggtkhgvrhhssehlihhsth hsrdhpohhsthhgrhgvshhqlhdrohhrghdprhgtphhtthhopegrnhgurhgvfiesughunhhs lhgrnhgvrdhnvght X-ME-Proxy: Feedback-ID: i7c334307:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 28 Oct 2025 15:38:58 -0400 (EDT) From: "David E. Wheeler" Message-Id: <3DC56A6A-9525-4C05-B45A-9A135A66BC34@justatheory.com> Content-Type: multipart/signed; boundary="Apple-Mail=_4A68DAED-BAF2-44DD-A14C-6875A89E054F"; protocol="application/pgp-signature"; micalg=pgp-sha256 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81\)) Subject: Re: PATCH: jsonpath string methods: lower, upper, initcap, l/r/btrim, replace, split_part Date: Tue, 28 Oct 2025 15:38:47 -0400 In-Reply-To: <87530674-E6B6-4C97-A704-78C7E07CF01F@gmail.com> Cc: =?utf-8?Q?=C3=81lvaro_Herrera?= , Florents Tselai , Tom Lane , Peter Eisentraut , Robert Haas , Alexander Korotkov , pgsql-hackers , Andrew Dunstan To: Chao Li References: <202510210803.3b3vfvygxtjl@alvherre.pgsql> <87530674-E6B6-4C97-A704-78C7E07CF01F@gmail.com> 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=_4A68DAED-BAF2-44DD-A14C-6875A89E054F Content-Type: multipart/mixed; boundary="Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B" --Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 On Oct 22, 2025, at 22:43, Chao Li wrote: > I wonder if there is some consideration for the order? Feels that = jpiSttLtrim and the following jpiStrXXX should be placed above = jpiTimeXXX. I wouldn=E2=80=99t think the order would matter. > I know =E2=80=9Cb=E2=80=9D in =E2=80=9Cbtrim=E2=80=9D stands for = =E2=80=9Cboth=E2=80=9D, just curious why trim both side function is = named =E2=80=9Cbtrim()=E2=80=9D? In most of programming languages I am = aware of, trim() is the choice. This patch uses existing Postgres functions, of which btrim is one[1]. > + default: > + ; > + /* cant' happen */ > + } > ```=20 >=20 > As =E2=80=9Cdefault=E2=80=9D clause has a comment =E2=80=9Ccan=E2=80=99t= happen=E2=80=9D, I believe =E2=80=9Cbreak=E2=80=9D is missing in the = case clause. >=20 > Also, do we want to add an assert in default to report a message in = case it happens? Good call, will change. > 6 - jsonpath_exec.c > ``` > + resStr =3D TextDatumGetCString(DirectFunctionCall3Coll(replace_text, > + C_COLLATION_OID, > + CStringGetTextDatum(tmp), > + CStringGetTextDatum(from_str), > + CStringGetTextDatum(to_str))); > ``` >=20 > For trim functions, DEFAULT_COLLATION_OID used. Why C_COLLATION_OID is = used for replace and split_part? I don=E2=80=99t see anything mentioned = in your changes to the doc (func-json.sgml). Intuitively that makes sense to me. Tests pass if I change it. Will = update the patch. > 7 - jsonpath_exec.c > ``` > + if (!(jb =3D getScalar(jb, jbvString))) > + RETURN_ERROR(ereport(ERROR, > + (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION), > + errmsg("jsonpath item method .%s() can only be applied to a = string", > + jspOperationName(jsp->type))))); > ``` >=20 > ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION seems wrong, = this is a string function, not a date time function. Yes. Maybe `ERRCODE_INVALID_PARAMETER_VALUE`? There=E2=80=99s also = `ERRCODE_INVALID_JSON_TEXT`, but I think that=E2=80=99s about invalid = bytes in a JSON string. > The two nested =E2=80=9Cswitch (jsp->type)=E2=80=9D are quit = redundant. We can pull up the second one, and simplify the first one, = something like: Well they assign different values to `func`: ltrim, rtrim, btrim when no = arg vs ltrim1, rtrim1, btrim1 when there is an argument. > 9 - jsonpath_exec.c > ``` > + if (elem.type !=3D jpiString) > + elog(ERROR, "invalid jsonpath item type for .replace() from"); > + > + from_str =3D jspGetString(&elem, &from_len); > + > + jspGetRightArg(jsp, &elem); > + if (elem.type !=3D jpiString) > + elog(ERROR, "invalid jsonpath item type for .replace() to"); > ``` >=20 > In these two elog(), do we want to log the invalid type? As I see in = the =E2=80=9Cdefault=E2=80=9D clause, jsp->type is logged: > ``` > + default: > + elog(ERROR, "unsupported jsonpath item type: %d", jsp->type); > ``` I think it=E2=80=99s going on precedents such as ``` if (elem.type !=3D jpiNumeric) elog(ERROR, "invalid jsonpath item type for .decimal() = precision"); ``` And also the date time method execution: ``` (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION), errmsg("jsonpath item method .%s() can only be applied to a string", jspOperationName(jsp->type))))); ``` I see types mentioned only in the context of failed numeric conversions = (ERRCODE_NON_NUMERIC_SQL_JSON_ITEM). Updated patches attached. Best, David --Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B Content-Disposition: attachment; filename=v14-0001-Rename-jsonpath-method-arg-tokens.patch Content-Type: application/octet-stream; name=v14-0001-Rename-jsonpath-method-arg-tokens.patch; x-unix-mode=0644 Content-Transfer-Encoding: quoted-printable =46rom=209a89826825a7098e0a1c17a84d92774e1965868f=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20"David=20E.=20Wheeler"=20= =0ADate:=20Mon,=202=20Jun=202025=2017:14:10=20= -0400=0ASubject:=20[PATCH=20v14=201/2]=20Rename=20jsonpath=20method=20= arg=20tokens=0A=0ARename=20the=20`csv_`=20tokens=20to=20`int_`,=20= because=20they=20represent=20signed=20or=0Aunsigned=20integers,=20as=20= follows:=0A=0A*=20=20=20`csv_elem`=20=3D>=20`int_elem`=0A*=20=20=20= `csv_list`=20=3D>=20`int_list`=0A*=20=20=20`opt_csv_list`=20=3D>=20= `opt_int_list`=0A=0ARename=20the=20`datetime_precision`=20tokens=20to=20= `uint_arg`,=20as=20they=20represent=0Aunsigned=20integers=20and=20will=20= be=20useful=20for=20other=20methods=20in=20the=20future,=20as=0Afollows:=0A= =0A*=20=20=20`datetime_precision`=20=3D>=20`uint_elem`=0A*=20=20=20= `opt_datetime_precision`=20=3D>=20`opt_uint_arg`=0A=0ARename=20the=20= `datetime_template`=20tokens=20to=20`str_arg`,=20as=20they=20represent=0A= strings=20and=20will=20be=20useful=20for=20other=20methods=20in=20the=20= future,=20as=20follows:=0A=0A*=20=20=20`datetime_template`=20=3D>=20= `str_elem`=0A*=20=20=20`opt_datetime_template`=20=3D>=20`opt_str_arg`=0A= ---=0A=20src/backend/utils/adt/jsonpath_gram.y=20|=2042=20= +++++++++++++--------------=0A=201=20file=20changed,=2021=20= insertions(+),=2021=20deletions(-)=0A=0Adiff=20--git=20= a/src/backend/utils/adt/jsonpath_gram.y=20= b/src/backend/utils/adt/jsonpath_gram.y=0Aindex=20= 499745a8fef..0b16cec18c4=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_gram.y=0A+++=20= b/src/backend/utils/adt/jsonpath_gram.y=0A@@=20-92,10=20+92,10=20@@=20= static=20bool=20makeItemLikeRegex(JsonPathParseItem=20*expr,=0A=20%type=09= =09=09scalar_value=20path_primary=20expr=20array_accessor=0A=20=09= =09=09=09=09any_path=20accessor_op=20key=20predicate=20= delimited_predicate=0A=20=09=09=09=09=09index_elem=20starts_with_initial=20= expr_or_predicate=0A-=09=09=09=09=09datetime_template=20= opt_datetime_template=20csv_elem=0A-=09=09=09=09=09datetime_precision=20= opt_datetime_precision=0A+=09=09=09=09=09str_elem=20opt_str_arg=20= int_elem=0A+=09=09=09=09=09uint_elem=20opt_uint_arg=0A=20=0A-%type=09= =09=09accessor_expr=20csv_list=20opt_csv_list=0A+%type=09=09= =09accessor_expr=20int_list=20opt_int_list=0A=20=0A=20%type=09=09= index_list=0A=20=0A@@=20-254,7=20+254,7=20@@=20accessor_op:=0A=20=09|=20= '.'=20any_path=09=09=09=09=09{=20$$=20=3D=20$2;=20}=0A=20=09|=20'.'=20= method=20'('=20')'=09=09=09{=20$$=20=3D=20makeItemType($2);=20}=0A=20=09= |=20'?'=20'('=20predicate=20')'=09=09=09{=20$$=20=3D=20= makeItemUnary(jpiFilter,=20$3);=20}=0A-=09|=20'.'=20DECIMAL_P=20'('=20= opt_csv_list=20')'=0A+=09|=20'.'=20DECIMAL_P=20'('=20opt_int_list=20')'=0A= =20=09=09{=0A=20=09=09=09if=20(list_length($4)=20=3D=3D=200)=0A=20=09=09=09= =09$$=20=3D=20makeItemBinary(jpiDecimal,=20NULL,=20NULL);=0A@@=20-268,19=20= +268,19=20@@=20accessor_op:=0A=20=09=09=09=09=09=09=20errmsg("invalid=20= input=20syntax=20for=20type=20%s",=20"jsonpath"),=0A=20=09=09=09=09=09=09= =20errdetail(".decimal()=20can=20only=20have=20an=20optional=20= precision[,scale].")));=0A=20=09=09}=0A-=09|=20'.'=20DATETIME_P=20'('=20= opt_datetime_template=20')'=0A+=09|=20'.'=20DATETIME_P=20'('=20= opt_str_arg=20')'=0A=20=09=09{=20$$=20=3D=20makeItemUnary(jpiDatetime,=20= $4);=20}=0A-=09|=20'.'=20TIME_P=20'('=20opt_datetime_precision=20')'=0A+=09= |=20'.'=20TIME_P=20'('=20opt_uint_arg=20')'=0A=20=09=09{=20$$=20=3D=20= makeItemUnary(jpiTime,=20$4);=20}=0A-=09|=20'.'=20TIME_TZ_P=20'('=20= opt_datetime_precision=20')'=0A+=09|=20'.'=20TIME_TZ_P=20'('=20= opt_uint_arg=20')'=0A=20=09=09{=20$$=20=3D=20makeItemUnary(jpiTimeTz,=20= $4);=20}=0A-=09|=20'.'=20TIMESTAMP_P=20'('=20opt_datetime_precision=20= ')'=0A+=09|=20'.'=20TIMESTAMP_P=20'('=20opt_uint_arg=20')'=0A=20=09=09{=20= $$=20=3D=20makeItemUnary(jpiTimestamp,=20$4);=20}=0A-=09|=20'.'=20= TIMESTAMP_TZ_P=20'('=20opt_datetime_precision=20')'=0A+=09|=20'.'=20= TIMESTAMP_TZ_P=20'('=20opt_uint_arg=20')'=0A=20=09=09{=20$$=20=3D=20= makeItemUnary(jpiTimestampTz,=20$4);=20}=0A=20=09;=0A=20=0A-csv_elem:=0A= +int_elem:=0A=20=09INT_P=0A=20=09=09{=20$$=20=3D=20makeItemNumeric(&$1);=20= }=0A=20=09|=20'+'=20INT_P=20%prec=20UMINUS=0A@@=20-289,31=20+289,31=20@@=20= csv_elem:=0A=20=09=09{=20$$=20=3D=20makeItemUnary(jpiMinus,=20= makeItemNumeric(&$2));=20}=0A=20=09;=0A=20=0A-csv_list:=0A-=09csv_elem=09= =09=09=09=09=09{=20$$=20=3D=20list_make1($1);=20}=0A-=09|=20csv_list=20= ','=20csv_elem=09=09=09{=20$$=20=3D=20lappend($1,=20$3);=20}=0A= +int_list:=0A+=09int_elem=09=09=09=09=09=09{=20$$=20=3D=20= list_make1($1);=20}=0A+=09|=20int_list=20','=20int_elem=09=09=09{=20$$=20= =3D=20lappend($1,=20$3);=20}=0A=20=09;=0A=20=0A-opt_csv_list:=0A-=09= csv_list=09=09=09=09=09=09{=20$$=20=3D=20$1;=20}=0A+opt_int_list:=0A+=09= int_list=09=09=09=09=09=09{=20$$=20=3D=20$1;=20}=0A=20=09|=20/*=20EMPTY=20= */=09=09=09=09=09{=20$$=20=3D=20NULL;=20}=0A=20=09;=0A=20=0A= -datetime_precision:=0A+uint_elem:=0A=20=09INT_P=09=09=09=09=09=09=09{=20= $$=20=3D=20makeItemNumeric(&$1);=20}=0A=20=09;=0A=20=0A= -opt_datetime_precision:=0A-=09datetime_precision=09=09=09=09{=20$$=20=3D=20= $1;=20}=0A+opt_uint_arg:=0A+=09uint_elem=09=09=09=09=09=09{=20$$=20=3D=20= $1;=20}=0A=20=09|=20/*=20EMPTY=20*/=09=09=09=09=09{=20$$=20=3D=20NULL;=20= }=0A=20=09;=0A=20=0A-datetime_template:=0A+str_elem:=0A=20=09STRING_P=09=09= =09=09=09=09{=20$$=20=3D=20makeItemString(&$1);=20}=0A=20=09;=0A=20=0A= -opt_datetime_template:=0A-=09datetime_template=09=09=09=09{=20$$=20=3D=20= $1;=20}=0A+opt_str_arg:=0A+=09str_elem=09=09=09=09=09=09{=20$$=20=3D=20= $1;=20}=0A=20=09|=20/*=20EMPTY=20*/=09=09=09=09=09{=20$$=20=3D=20NULL;=20= }=0A=20=09;=0A=20=0A--=20=0A2.51.0=0A=0A= --Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B Content-Disposition: attachment; filename=v14-0002-Add-additional-jsonpath-string-methods.patch Content-Type: application/octet-stream; name=v14-0002-Add-additional-jsonpath-string-methods.patch; x-unix-mode=0644 Content-Transfer-Encoding: quoted-printable =46rom=2050e867f73fcff05d3919014db67e65ec21b322ef=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Florents=20Tselai=20= =0ADate:=20Fri,=2011=20Jul=202025=2014:04:28=20= -0400=0ASubject:=20[PATCH=20v14=202/2]=20Add=20additional=20jsonpath=20= string=20methods=0A=0AAdd=20the=20following=20jsonpath=20methods:=0A=0A*=20= =20=20l/r/btrim()=0A*=20=20=20lower(),=20upper()=0A*=20=20=20initcap()=0A= *=20=20=20replace()=0A*=20=20=20split_part()=0A=0AEach=20simply=20= dispatches=20to=20the=20standard=20string=20processing=20functions.=0A= These=20depend=20on=20the=20locale,=20but=20since=20it's=20set=20at=20= `initdb`,=20they=20can=20be=0Aconsidered=20immutable=20and=20therefore=20= allowed=20in=20any=20jsonpath=20expression.=0A---=0A=20= doc/src/sgml/func/func-json.sgml=20=20=20=20=20=20=20=20=20=20=20=20=20|=20= 140=20+++++++=0A=20src/backend/utils/adt/jsonpath.c=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20117=20+++++-=0A=20= src/backend/utils/adt/jsonpath_exec.c=20=20=20=20=20=20=20=20|=20209=20= ++++++++++=0A=20src/backend/utils/adt/jsonpath_gram.y=20=20=20=20=20=20=20= =20|=20=2028=20+-=0A=20src/backend/utils/adt/jsonpath_scan.l=20=20=20=20=20= =20=20=20|=20=20=208=20+=0A=20src/include/utils/jsonpath.h=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=20=208=20+=0A=20= src/test/regress/expected/jsonb_jsonpath.out=20|=20399=20= +++++++++++++++++++=0A=20src/test/regress/expected/jsonpath.out=20=20=20=20= =20=20=20|=20137=20+++++++=0A=20src/test/regress/sql/jsonb_jsonpath.sql=20= =20=20=20=20=20|=20109=20+++++=0A=20src/test/regress/sql/jsonpath.sql=20=20= =20=20=20=20=20=20=20=20=20=20|=20=2031=20++=0A=2010=20files=20changed,=20= 1181=20insertions(+),=205=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/func/func-json.sgml=20b/doc/src/sgml/func/func-json.sgml=0A= index=20b9316ba0ee5..49031820c4b=20100644=0A---=20= a/doc/src/sgml/func/func-json.sgml=0A+++=20= b/doc/src/sgml/func/func-json.sgml=0A@@=20-2781,6=20+2781,146=20@@=20= ERROR:=20=20jsonpath=20member=20accessor=20can=20only=20be=20applied=20= to=20an=20object=0A=20=20=20=20=20=20=20=20=20[{"id":=200,=20= "key":=20"x",=20"value":=20"20"},=20{"id":=200,=20"key":=20"y",=20= "value":=2032}]=0A=20=20=20=20=20=20=20=20=0A= =20=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= lower()=0A+=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20converted=20to=20all=20lower=20case=20according=20to=20the=20= rules=20of=20the=20database's=20locale.=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"TOM"',=20'$.lower()')=0A+=20=20=20=20= =20=20=20=20"tom"=0A+=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= upper()=0A+=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20converted=20to=20all=20upper=20case=20according=20to=20the=20= rules=20of=20the=20database's=20locale.=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"tom"',=20'$.upper()')=0A+=20=20=20=20= =20=20=20=20"TOM"=0A+=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= initcap()=0A+=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20with=20the=20first=20letter=20of=20each=20word=20converted=20= to=20upper=20case=0A+=20=20=20=20=20=20=20=20according=20to=20the=20= rules=20of=20the=20database's=20locale.=20Words=20are=20sequences=0A+=20=20= =20=20=20=20=20=20of=20alphanumeric=20characters=20separated=20by=20= non-alphanumeric=20characters.=0A+=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"hi=20THOMAS"',=20'$.initcap()')=0A= +=20=20=20=20=20=20=20=20"Hi=20Thomas"=0A+=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=0A+=0A+=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20string=20.=20= replace(from,=20= to)=0A+=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20with=20all=20occurrences=20of=20substring=20from=20replaced=20= with=20substring=20to.=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"abcdefabcdef"',=20'$.replace("cd",=20= "XX")')=0A+=20=20=20=20=20=20=20=20= "abXXefabXXef"=0A+=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= split_part(delimiter,=20= n)=0A+=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20split=20at=20occurrences=20of=20= delimiter=0A+=20=20=20=20=20=20=20=20and=20= returns=20the=20n'th=20field=20(counting=20= from=0A+=20=20=20=20=20=20=20=20one)=20or,=20when=20= n=20is=20negative,=20returns=20the=0A+=20=20=20= =20=20=20=20=20|n|'th-from-last=20field.=0A+=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20jsonb_path_query('"abc~@~def~@~ghi"',=20= '$.split_part("~@~",=202)')=0A+=20=20=20=20=20=20=20=20= "def"=0A+=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"abc,def,ghi,jkl"',=20'$.split_part(",",=20= 2)')=0A+=20=20=20=20=20=20=20=20= "ghi"=0A+=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=0A= +=20=20=20=20=20=20=20=20string=20= .=20= ltrim(characters)=0A+=20=20= =20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20with=20the=20longest=20string=20containing=20only=20spaces=20= or=20the=0A+=20=20=20=20=20=20=20=20characters=20in=20= characters=20removed=20from=20the=0A+=20=20=20= =20=20=20=20=20start=20of=20string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20jsonb_path_query('"=20=20hello"',=20= '$.ltrim()')=0A+=20=20=20=20=20=20=20=20= "hello"=0A+=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"zzzytest"',=20'$.ltrim("xyz")')=0A= +=20=20=20=20=20=20=20=20"test"=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= rtrim([=20characters=20])=0A= +=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20with=20the=20longest=20string=20containing=20only=20spaces=20= or=20the=0A+=20=20=20=20=20=20=20=20characters=20in=20= characters=20removed=20from=20the=0A+=20=20=20= =20=20=20=20=20end=20of=20string=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"hello=20=20"',=20'$.rtrim()')=0A+=20= =20=20=20=20=20=20=20"hello"=0A+=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"testxxzx"',=20'$.rtrim("xyz")')=0A= +=20=20=20=20=20=20=20=20"test"=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=0A+=20=20=20=20=20= =20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= string=20.=20= btrim([=20characters=20])=0A= +=20=20=20=20=20=20=20=20= string=0A+=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20String=20with=20the=20longest=20string=20containing=20only=20spaces=20= or=20the=0A+=20=20=20=20=20=20=20=20characters=20in=20= characters=20removed=20from=20the=0A+=20=20=20= =20=20=20=20=20start=20and=20end=20of=20= string=0A+=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"=20=20hello=20=20"',=20= '$.btrim()')=0A+=20=20=20=20=20=20=20=20= "hello"=0A+=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= jsonb_path_query('"xyxtrimyyx"',=20'$.btrim("xyz")')=0A= +=20=20=20=20=20=20=20=20"trim"=0A+=20=20=20=20= =20=20=20=0A+=20=20=20=20=20=20=0A+=0A=20=20=20=20=20= =20=0A=20=20=20=20=20=0A=20=20=20=20=0Adiff=20= --git=20a/src/backend/utils/adt/jsonpath.c=20= b/src/backend/utils/adt/jsonpath.c=0Aindex=20762f7e8a09d..f3f2119a4a8=20= 100644=0A---=20a/src/backend/utils/adt/jsonpath.c=0A+++=20= b/src/backend/utils/adt/jsonpath.c=0A@@=20-298,6=20+298,8=20@@=20= flattenJsonPathParseItem(StringInfo=20buf,=20int=20*result,=20struct=20= Node=20*escontext,=0A=20=09=09case=20jpiMod:=0A=20=09=09case=20= jpiStartsWith:=0A=20=09=09case=20jpiDecimal:=0A+=09=09case=20= jpiStrReplace:=0A+=09=09case=20jpiStrSplitPart:=0A=20=09=09=09{=0A=20=09=09= =09=09/*=0A=20=09=09=09=09=20*=20First,=20reserve=20place=20for=20= left/right=20arg's=20positions,=20then=0A@@=20-362,6=20+364,9=20@@=20= flattenJsonPathParseItem(StringInfo=20buf,=20int=20*result,=20struct=20= Node=20*escontext,=0A=20=09=09case=20jpiTimeTz:=0A=20=09=09case=20= jpiTimestamp:=0A=20=09=09case=20jpiTimestampTz:=0A+=09=09case=20= jpiStrLtrim:=0A+=09=09case=20jpiStrRtrim:=0A+=09=09case=20jpiStrBtrim:=0A= =20=09=09=09{=0A=20=09=09=09=09int32=09=09arg=20=3D=20= reserveSpaceForItemPointer(buf);=0A=20=0A@@=20-457,6=20+462,9=20@@=20= flattenJsonPathParseItem(StringInfo=20buf,=20int=20*result,=20struct=20= Node=20*escontext,=0A=20=09=09case=20jpiInteger:=0A=20=09=09case=20= jpiNumber:=0A=20=09=09case=20jpiStringFunc:=0A+=09=09case=20jpiStrLower:=0A= +=09=09case=20jpiStrUpper:=0A+=09=09case=20jpiStrInitcap:=0A=20=09=09=09= break;=0A=20=09=09default:=0A=20=09=09=09elog(ERROR,=20"unrecognized=20= jsonpath=20item=20type:=20%d",=20item->type);=0A@@=20-831,6=20+839,60=20= @@=20printJsonPathItem(StringInfo=20buf,=20JsonPathItem=20*v,=20bool=20= inKey,=0A=20=09=09=09}=0A=20=09=09=09appendStringInfoChar(buf,=20')');=0A= =20=09=09=09break;=0A+=09=09case=20jpiStrReplace:=0A+=09=09=09= appendStringInfoString(buf,=20".replace(");=0A+=09=09=09jspGetLeftArg(v,=20= &elem);=0A+=09=09=09printJsonPathItem(buf,=20&elem,=20false,=20false);=0A= +=09=09=09appendStringInfoChar(buf,=20',');=0A+=09=09=09= jspGetRightArg(v,=20&elem);=0A+=09=09=09printJsonPathItem(buf,=20&elem,=20= false,=20false);=0A+=09=09=09appendStringInfoChar(buf,=20')');=0A+=09=09=09= break;=0A+=09=09case=20jpiStrSplitPart:=0A+=09=09=09= appendStringInfoString(buf,=20".split_part(");=0A+=09=09=09= jspGetLeftArg(v,=20&elem);=0A+=09=09=09printJsonPathItem(buf,=20&elem,=20= false,=20false);=0A+=09=09=09appendStringInfoChar(buf,=20',');=0A+=09=09=09= jspGetRightArg(v,=20&elem);=0A+=09=09=09printJsonPathItem(buf,=20&elem,=20= false,=20false);=0A+=09=09=09appendStringInfoChar(buf,=20')');=0A+=09=09=09= break;=0A+=09=09case=20jpiStrLower:=0A+=09=09=09= appendStringInfoString(buf,=20".lower()");=0A+=09=09=09break;=0A+=09=09= case=20jpiStrUpper:=0A+=09=09=09appendStringInfoString(buf,=20= ".upper()");=0A+=09=09=09break;=0A+=09=09case=20jpiStrInitcap:=0A+=09=09=09= appendStringInfoString(buf,=20".initcap()");=0A+=09=09=09break;=0A+=09=09= case=20jpiStrLtrim:=0A+=09=09=09appendStringInfoString(buf,=20= ".ltrim(");=0A+=09=09=09if=20(v->content.arg)=0A+=09=09=09{=0A+=09=09=09=09= jspGetArg(v,=20&elem);=0A+=09=09=09=09printJsonPathItem(buf,=20&elem,=20= false,=20false);=0A+=09=09=09}=0A+=09=09=09appendStringInfoChar(buf,=20= ')');=0A+=09=09=09break;=0A+=09=09case=20jpiStrRtrim:=0A+=09=09=09= appendStringInfoString(buf,=20".rtrim(");=0A+=09=09=09if=20= (v->content.arg)=0A+=09=09=09{=0A+=09=09=09=09jspGetArg(v,=20&elem);=0A+=09= =09=09=09printJsonPathItem(buf,=20&elem,=20false,=20false);=0A+=09=09=09= }=0A+=09=09=09appendStringInfoChar(buf,=20')');=0A+=09=09=09break;=0A+=09= =09case=20jpiStrBtrim:=0A+=09=09=09appendStringInfoString(buf,=20= ".btrim(");=0A+=09=09=09if=20(v->content.arg)=0A+=09=09=09{=0A+=09=09=09=09= jspGetArg(v,=20&elem);=0A+=09=09=09=09printJsonPathItem(buf,=20&elem,=20= false,=20false);=0A+=09=09=09}=0A+=09=09=09appendStringInfoChar(buf,=20= ')');=0A+=09=09=09break;=0A=20=09=09default:=0A=20=09=09=09elog(ERROR,=20= "unrecognized=20jsonpath=20item=20type:=20%d",=20v->type);=0A=20=09}=0A= @@=20-906,6=20+968,12=20@@=20jspOperationName(JsonPathItemType=20type)=0A= =20=09=09=09return=20"number";=0A=20=09=09case=20jpiStringFunc:=0A=20=09=09= =09return=20"string";=0A+=09=09case=20jpiStrReplace:=0A+=09=09=09return=20= "replace";=0A+=09=09case=20jpiStrLower:=0A+=09=09=09return=20"lower";=0A= +=09=09case=20jpiStrUpper:=0A+=09=09=09return=20"upper";=0A=20=09=09case=20= jpiTime:=0A=20=09=09=09return=20"time";=0A=20=09=09case=20jpiTimeTz:=0A= @@=20-914,6=20+982,16=20@@=20jspOperationName(JsonPathItemType=20type)=0A= =20=09=09=09return=20"timestamp";=0A=20=09=09case=20jpiTimestampTz:=0A=20= =09=09=09return=20"timestamp_tz";=0A+=09=09case=20jpiStrLtrim:=0A+=09=09=09= return=20"ltrim";=0A+=09=09case=20jpiStrRtrim:=0A+=09=09=09return=20= "rtrim";=0A+=09=09case=20jpiStrBtrim:=0A+=09=09=09return=20"btrim";=0A+=09= =09case=20jpiStrInitcap:=0A+=09=09=09return=20"initcap";=0A+=09=09case=20= jpiStrSplitPart:=0A+=09=09=09return=20"split_part";=0A=20=09=09default:=0A= =20=09=09=09elog(ERROR,=20"unrecognized=20jsonpath=20item=20type:=20%d",=20= type);=0A=20=09=09=09return=20NULL;=0A@@=20-1016,6=20+1094,9=20@@=20= jspInitByBuffer(JsonPathItem=20*v,=20char=20*base,=20int32=20pos)=0A=20=09= =09case=20jpiInteger:=0A=20=09=09case=20jpiNumber:=0A=20=09=09case=20= jpiStringFunc:=0A+=09=09case=20jpiStrLower:=0A+=09=09case=20jpiStrUpper:=0A= +=09=09case=20jpiStrInitcap:=0A=20=09=09=09break;=0A=20=09=09case=20= jpiString:=0A=20=09=09case=20jpiKey:=0A@@=20-1041,6=20+1122,8=20@@=20= jspInitByBuffer(JsonPathItem=20*v,=20char=20*base,=20int32=20pos)=0A=20=09= =09case=20jpiMod:=0A=20=09=09case=20jpiStartsWith:=0A=20=09=09case=20= jpiDecimal:=0A+=09=09case=20jpiStrReplace:=0A+=09=09case=20= jpiStrSplitPart:=0A=20=09=09=09read_int32(v->content.args.left,=20base,=20= pos);=0A=20=09=09=09read_int32(v->content.args.right,=20base,=20pos);=0A=20= =09=09=09break;=0A@@=20-1055,6=20+1138,9=20@@=20= jspInitByBuffer(JsonPathItem=20*v,=20char=20*base,=20int32=20pos)=0A=20=09= =09case=20jpiTimeTz:=0A=20=09=09case=20jpiTimestamp:=0A=20=09=09case=20= jpiTimestampTz:=0A+=09=09case=20jpiStrLtrim:=0A+=09=09case=20= jpiStrRtrim:=0A+=09=09case=20jpiStrBtrim:=0A=20=09=09=09= read_int32(v->content.arg,=20base,=20pos);=0A=20=09=09=09break;=0A=20=09=09= case=20jpiIndexArray:=0A@@=20-1090,7=20+1176,10=20@@=20= jspGetArg(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20=09=09=20=20=20= v->type=20=3D=3D=20jpiTime=20||=0A=20=09=09=20=20=20v->type=20=3D=3D=20= jpiTimeTz=20||=0A=20=09=09=20=20=20v->type=20=3D=3D=20jpiTimestamp=20||=0A= -=09=09=20=20=20v->type=20=3D=3D=20jpiTimestampTz);=0A+=09=09=20=20=20= v->type=20=3D=3D=20jpiTimestampTz=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrLtrim=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20jpiStrRtrim=20||=0A= +=09=09=20=20=20v->type=20=3D=3D=20jpiStrBtrim);=0A=20=0A=20=09= jspInitByBuffer(a,=20v->base,=20v->content.arg);=0A=20}=0A@@=20-1149,10=20= +1238,18=20@@=20jspGetNext(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20=09= =09=09=20=20=20v->type=20=3D=3D=20jpiInteger=20||=0A=20=09=09=09=20=20=20= v->type=20=3D=3D=20jpiNumber=20||=0A=20=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStringFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20jpiStrReplace=20= ||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20jpiStrLower=20||=0A+=09=09=09=20= =20=20v->type=20=3D=3D=20jpiStrUpper=20||=0A=20=09=09=09=20=20=20v->type=20= =3D=3D=20jpiTime=20||=0A=20=09=09=09=20=20=20v->type=20=3D=3D=20= jpiTimeTz=20||=0A=20=09=09=09=20=20=20v->type=20=3D=3D=20jpiTimestamp=20= ||=0A-=09=09=09=20=20=20v->type=20=3D=3D=20jpiTimestampTz);=0A+=09=09=09=20= =20=20v->type=20=3D=3D=20jpiTimestampTz=20||=0A+=09=09=09=20=20=20= v->type=20=3D=3D=20jpiStrLtrim=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrRtrim=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20jpiStrBtrim=20= ||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20jpiStrInitcap=20||=0A+=09=09=09= =20=20=20v->type=20=3D=3D=20jpiStrSplitPart);=0A=20=0A=20=09=09if=20(a)=0A= =20=09=09=09jspInitByBuffer(a,=20v->base,=20v->nextPos);=0A@@=20-1179,7=20= +1276,9=20@@=20jspGetLeftArg(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20= =09=09=20=20=20v->type=20=3D=3D=20jpiDiv=20||=0A=20=09=09=20=20=20= v->type=20=3D=3D=20jpiMod=20||=0A=20=09=09=20=20=20v->type=20=3D=3D=20= jpiStartsWith=20||=0A-=09=09=20=20=20v->type=20=3D=3D=20jpiDecimal);=0A+=09= =09=20=20=20v->type=20=3D=3D=20jpiDecimal=20||=0A+=09=09=20=20=20v->type=20= =3D=3D=20jpiStrReplace=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrSplitPart);=0A=20=0A=20=09jspInitByBuffer(a,=20v->base,=20= v->content.args.left);=0A=20}=0A@@=20-1201,7=20+1300,9=20@@=20= jspGetRightArg(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20=09=09=20=20=20= v->type=20=3D=3D=20jpiDiv=20||=0A=20=09=09=20=20=20v->type=20=3D=3D=20= jpiMod=20||=0A=20=09=09=20=20=20v->type=20=3D=3D=20jpiStartsWith=20||=0A= -=09=09=20=20=20v->type=20=3D=3D=20jpiDecimal);=0A+=09=09=20=20=20= v->type=20=3D=3D=20jpiDecimal=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrReplace=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrSplitPart);=0A=20=0A=20=09jspInitByBuffer(a,=20v->base,=20= v->content.args.right);=0A=20}=0A@@=20-1501,6=20+1602,14=20@@=20= jspIsMutableWalker(JsonPathItem=20*jpi,=20struct=20= JsonPathMutableContext=20*cxt)=0A=20=09=09=09case=20jpiInteger:=0A=20=09=09= =09case=20jpiNumber:=0A=20=09=09=09case=20jpiStringFunc:=0A+=09=09=09= case=20jpiStrReplace:=0A+=09=09=09case=20jpiStrLower:=0A+=09=09=09case=20= jpiStrUpper:=0A+=09=09=09case=20jpiStrLtrim:=0A+=09=09=09case=20= jpiStrRtrim:=0A+=09=09=09case=20jpiStrBtrim:=0A+=09=09=09case=20= jpiStrInitcap:=0A+=09=09=09case=20jpiStrSplitPart:=0A=20=09=09=09=09= status=20=3D=20jpdsNonDateTime;=0A=20=09=09=09=09break;=0A=20=0Adiff=20= --git=20a/src/backend/utils/adt/jsonpath_exec.c=20= b/src/backend/utils/adt/jsonpath_exec.c=0Aindex=20= 8156695e97e..093374867ea=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_exec.c=0A+++=20= b/src/backend/utils/adt/jsonpath_exec.c=0A@@=20-302,6=20+302,8=20@@=20= static=20JsonPathExecResult=20= executeNumericItemMethod(JsonPathExecContext=20*cxt,=0A=20=09=09=09=09=09= =09=09=09=09=09=09=09=20=20=20JsonValueList=20*found);=0A=20static=20= JsonPathExecResult=20executeDateTimeMethod(JsonPathExecContext=20*cxt,=20= JsonPathItem=20*jsp,=0A=20=09=09=09=09=09=09=09=09=09=09=09=09JsonbValue=20= *jb,=20JsonValueList=20*found);=0A+static=20JsonPathExecResult=20= executeStringInternalMethod(JsonPathExecContext=20*cxt,=20JsonPathItem=20= *jsp,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=20=20JsonbValue=20*jb,=20= JsonValueList=20*found);=0A=20static=20JsonPathExecResult=20= executeKeyValueMethod(JsonPathExecContext=20*cxt,=0A=20=09=09=09=09=09=09= =09=09=09=09=09=09JsonPathItem=20*jsp,=20JsonbValue=20*jb,=20= JsonValueList=20*found);=0A=20static=20JsonPathExecResult=20= appendBoolResult(JsonPathExecContext=20*cxt,=0A@@=20-1661,6=20+1663,23=20= @@=20executeItemOptUnwrapTarget(JsonPathExecContext=20*cxt,=20= JsonPathItem=20*jsp,=0A=20=09=09=09}=0A=20=09=09=09break;=0A=20=0A+=09=09= case=20jpiStrLtrim:=0A+=09=09case=20jpiStrLower:=0A+=09=09case=20= jpiStrUpper:=0A+=09=09case=20jpiStrReplace:=0A+=09=09case=20jpiStrRtrim:=0A= +=09=09case=20jpiStrBtrim:=0A+=09=09case=20jpiStrInitcap:=0A+=09=09case=20= jpiStrSplitPart:=0A+=09=09=09{=0A+=09=09=09=09if=20(unwrap=20&&=20= JsonbType(jb)=20=3D=3D=20jbvArray)=0A+=09=09=09=09=09return=20= executeItemUnwrapTargetArray(cxt,=20jsp,=20jb,=20found,=20false);=0A+=0A= +=09=09=09=09return=20executeStringInternalMethod(cxt,=20jsp,=20jb,=20= found);=0A+=09=09=09}=0A+=09=09=09break;=0A+=0A+=0A=20=09=09default:=0A=20= =09=09=09elog(ERROR,=20"unrecognized=20jsonpath=20item=20type:=20%d",=20= jsp->type);=0A=20=09}=0A@@=20-2794,6=20+2813,196=20@@=20= executeDateTimeMethod(JsonPathExecContext=20*cxt,=20JsonPathItem=20*jsp,=0A= =20=09return=20executeNextItem(cxt,=20jsp,=20&elem,=20jb,=20found,=20= hasNext);=0A=20}=0A=20=0A+/*=0A+=20*=20Implementation=20of=20.upper(),=20= lower()=20et.=20al.=20methods,=0A+=20*=20that=20forward=20their=20actual=20= implementation=20to=20internal=20functions.=0A+=20*/=0A+static=20= JsonPathExecResult=0A+executeStringInternalMethod(JsonPathExecContext=20= *cxt,=20JsonPathItem=20*jsp,=0A+=09=09=09=09=09=09=09JsonbValue=20*jb,=20= JsonValueList=20*found)=0A+{=0A+=09JsonbValue=09jbvbuf;=0A+=09bool=09=09= hasNext;=0A+=09JsonPathExecResult=20res=20=3D=20jperNotFound;=0A+=09= JsonPathItem=20elem;=0A+=09Datum=09=09str;=09=09=09/*=20Datum=20= representation=20for=20the=20current=20string=0A+=09=09=09=09=09=09=09=09= =20*=20value.=20The=20first=20argument=20to=20internal=0A+=09=09=09=09=09= =09=09=09=20*=20functions=20*/=0A+=09char=09=20=20=20*tmp=20=3D=20NULL;=0A= +=09char=09=20=20=20*resStr=20=3D=20NULL;=0A+=0A+=09Assert(jsp->type=20= =3D=3D=20jpiStrLower=20||=0A+=09=09=20=20=20jsp->type=20=3D=3D=20= jpiStrUpper=20||=0A+=09=09=20=20=20jsp->type=20=3D=3D=20jpiStrReplace=20= ||=0A+=09=09=20=20=20jsp->type=20=3D=3D=20jpiStrLtrim=20||=0A+=09=09=20=20= =20jsp->type=20=3D=3D=20jpiStrRtrim=20||=0A+=09=09=20=20=20jsp->type=20= =3D=3D=20jpiStrBtrim=20||=0A+=09=09=20=20=20jsp->type=20=3D=3D=20= jpiStrInitcap=20||=0A+=09=09=20=20=20jsp->type=20=3D=3D=20= jpiStrSplitPart);=0A+=0A+=09if=20(!(jb=20=3D=20getScalar(jb,=20= jbvString)))=0A+=09=09RETURN_ERROR(ereport(ERROR,=0A+=09=09=09=09=09=09=09= =20(errcode(ERRCODE_INVALID_PARAMETER_VALUE),=0A+=09=09=09=09=09=09=09=20= =20errmsg("jsonpath=20item=20method=20.%s()=20can=20only=20be=20applied=20= to=20a=20string",=0A+=09=09=09=09=09=09=09=09=09=20= jspOperationName(jsp->type)))));=0A+=0A+=09tmp=20=3D=20= pnstrdup(jb->val.string.val,=20jb->val.string.len);=0A+=09str=20=3D=20= CStringGetTextDatum(tmp);=0A+=0A+=09/*=20Internal=20string=20functions=20= that=20accept=20no=20arguments=20*/=0A+=09switch=20(jsp->type)=0A+=09{=0A= +=09=09case=20jpiStrLtrim:=0A+=09=09case=20jpiStrRtrim:=0A+=09=09case=20= jpiStrBtrim:=0A+=09=09=09{=0A+=09=09=09=09char=09=20=20=20= *characters_str;=0A+=09=09=09=09int=09=09=09characters_len;=0A+=09=09=09=09= PGFunction=09func=20=3D=20NULL;=0A+=0A+=09=09=09=09if=20= (jsp->content.arg)=0A+=09=09=09=09{=0A+=09=09=09=09=09switch=20= (jsp->type)=0A+=09=09=09=09=09{=0A+=09=09=09=09=09=09case=20jpiStrLtrim:=0A= +=09=09=09=09=09=09=09func=20=3D=20ltrim;=0A+=09=09=09=09=09=09=09break;=0A= +=09=09=09=09=09=09case=20jpiStrRtrim:=0A+=09=09=09=09=09=09=09func=20=3D=20= rtrim;=0A+=09=09=09=09=09=09=09break;=0A+=09=09=09=09=09=09case=20= jpiStrBtrim:=0A+=09=09=09=09=09=09=09func=20=3D=20btrim;=0A+=09=09=09=09=09= =09=09break;=0A+=09=09=09=09=09=09default:;=0A+=09=09=09=09=09}=0A+=09=09= =09=09=09jspGetArg(jsp,=20&elem);=0A+=09=09=09=09=09if=20(elem.type=20!=3D= =20jpiString)=0A+=09=09=09=09=09=09elog(ERROR,=20"invalid=20jsonpath=20= item=20type=20for=20.%s()=20argument",=20jspOperationName(jsp->type));=0A= +=0A+=09=09=09=09=09characters_str=20=3D=20jspGetString(&elem,=20= &characters_len);=0A+=09=09=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall2Coll(func,=0A+=09=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=20DEFAULT_COLLATION_OID,=20str,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09=20= CStringGetTextDatum(characters_str)));=0A+=09=09=09=09=09break;=0A+=09=09= =09=09}=0A+=0A+=09=09=09=09switch=20(jsp->type)=0A+=09=09=09=09{=0A+=09=09= =09=09=09case=20jpiStrLtrim:=0A+=09=09=09=09=09=09func=20=3D=20ltrim1;=0A= +=09=09=09=09=09=09break;=0A+=09=09=09=09=09case=20jpiStrRtrim:=0A+=09=09= =09=09=09=09func=20=3D=20rtrim1;=0A+=09=09=09=09=09=09break;=0A+=09=09=09= =09=09case=20jpiStrBtrim:=0A+=09=09=09=09=09=09func=20=3D=20btrim1;=0A+=09= =09=09=09=09=09break;=0A+=09=09=09=09=09default:;=0A+=09=09=09=09}=0A+=09= =09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(func,=0A+=09=09=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=20DEFAULT_COLLATION_OID,=20str));=0A+=09=09= =09=09break;=0A+=09=09=09}=0A+=0A+=09=09case=20jpiStrLower:=0A+=09=09=09= resStr=20=3D=20TextDatumGetCString(DirectFunctionCall1Coll(lower,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiStrUpper:=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(upper,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiStrInitcap:=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(initcap,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiStrReplace:=0A+=09=09=09{=0A+=09=09=09=09char=09=20=20=20*from_str,=0A= +=09=09=09=09=09=09=20=20=20*to_str;=0A+=09=09=09=09int=09=09=09= from_len,=0A+=09=09=09=09=09=09=09to_len;=0A+=0A+=09=09=09=09= jspGetLeftArg(jsp,=20&elem);=0A+=09=09=09=09if=20(elem.type=20!=3D=20= jpiString)=0A+=09=09=09=09=09elog(ERROR,=20"invalid=20jsonpath=20item=20= type=20for=20.replace()=20from");=0A+=0A+=09=09=09=09from_str=20=3D=20= jspGetString(&elem,=20&from_len);=0A+=0A+=09=09=09=09jspGetRightArg(jsp,=20= &elem);=0A+=09=09=09=09if=20(elem.type=20!=3D=20jpiString)=0A+=09=09=09=09= =09elog(ERROR,=20"invalid=20jsonpath=20item=20type=20for=20.replace()=20= to");=0A+=0A+=09=09=09=09to_str=20=3D=20jspGetString(&elem,=20&to_len);=0A= +=0A+=09=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall3Coll(replace_text,=0A+=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=09=20DEFAULT_COLLATION_OID,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=09=09=09=20= CStringGetTextDatum(tmp),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09=09= =09=09=20CStringGetTextDatum(from_str),=0A+=09=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09=09=20CStringGetTextDatum(to_str)));=0A+=09=09=09=09= break;=0A+=09=09=09}=0A+=09=09case=20jpiStrSplitPart:=0A+=09=09=09{=0A+=09= =09=09=09char=09=20=20=20*from_str;=0A+=09=09=09=09Numeric=09=09n;=0A+=09= =09=09=09int=09=09=09from_len;=0A+=0A+=09=09=09=09jspGetLeftArg(jsp,=20= &elem);=0A+=09=09=09=09if=20(elem.type=20!=3D=20jpiString)=0A+=09=09=09=09= =09elog(ERROR,=20"invalid=20jsonpath=20item=20type=20for=20= .split_part()");=0A+=0A+=09=09=09=09from_str=20=3D=20jspGetString(&elem,=20= &from_len);=0A+=0A+=09=09=09=09jspGetRightArg(jsp,=20&elem);=0A+=09=09=09= =09if=20(elem.type=20!=3D=20jpiNumeric)=0A+=09=09=09=09=09elog(ERROR,=20= "invalid=20jsonpath=20item=20type=20for=20.split_part()");=0A+=0A+=09=09=09= =09n=20=3D=20jspGetNumeric(&elem);=0A+=0A+=09=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall3Coll(split_part,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=20C_COLLATION_OID,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=20CStringGetTextDatum(tmp),=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=09=09=09=09=09=20= CStringGetTextDatum(from_str),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09= =09=09=09=09=20DirectFunctionCall1(numeric_int4,=20= NumericGetDatum(n))));=0A+=09=09=09=09break;=0A+=09=09=09}=0A+=09=09= default:=0A+=09=09=09elog(ERROR,=20"unsupported=20jsonpath=20item=20= type:=20%d",=20jsp->type);=0A+=09}=0A+=0A+=09if=20(resStr)=0A+=09=09res=20= =3D=20jperOk;=0A+=0A+=09hasNext=20=3D=20jspGetNext(jsp,=20&elem);=0A+=0A= +=09if=20(!hasNext=20&&=20!found)=0A+=09=09return=20res;=0A+=0A+=09jb=20= =3D=20hasNext=20?=20&jbvbuf=20:=20palloc(sizeof(*jb));=0A+=0A+=09/*=20= Create=20the=20appropriate=20jb=20value=20to=20return=20*/=0A+=09switch=20= (jsp->type)=0A+=09{=0A+=09=09=09/*=20Cases=20for=20functions=20that=20= return=20text=20*/=0A+=09=09case=20jpiStrLower:=0A+=09=09case=20= jpiStrUpper:=0A+=09=09case=20jpiStrReplace:=0A+=09=09case=20jpiStrLtrim:=0A= +=09=09case=20jpiStrRtrim:=0A+=09=09case=20jpiStrBtrim:=0A+=09=09case=20= jpiStrInitcap:=0A+=09=09case=20jpiStrSplitPart:=0A+=09=09=09jb->type=20=3D= =20jbvString;=0A+=09=09=09jb->val.string.val=20=3D=20resStr;=0A+=09=09=09= jb->val.string.len=20=3D=20strlen(jb->val.string.val);=0A+=09=09=09= break;=0A+=09=09default:=0A+=09=09=09;=0A+=09=09=09/*=20do=20nothing=20= */=0A+=09=09=09Assert(false);=0A+=09}=0A+=0A+=09return=20= executeNextItem(cxt,=20jsp,=20&elem,=20jb,=20found,=20hasNext);=0A+}=0A+=0A= =20/*=0A=20=20*=20Implementation=20of=20.keyvalue()=20method.=0A=20=20*=0A= diff=20--git=20a/src/backend/utils/adt/jsonpath_gram.y=20= b/src/backend/utils/adt/jsonpath_gram.y=0Aindex=20= 0b16cec18c4..53bf779e152=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_gram.y=0A+++=20= b/src/backend/utils/adt/jsonpath_gram.y=0A@@=20-86,6=20+86,8=20@@=20= static=20bool=20makeItemLikeRegex(JsonPathParseItem=20*expr,=0A=20%token=09= =09=09DATETIME_P=0A=20%token=09=09=09BIGINT_P=20BOOLEAN_P=20= DATE_P=20DECIMAL_P=20INTEGER_P=20NUMBER_P=0A=20%token=09=09=09= STRINGFUNC_P=20TIME_P=20TIME_TZ_P=20TIMESTAMP_P=20TIMESTAMP_TZ_P=0A= +%token=09=09=09STR_REPLACE_P=20STR_LOWER_P=20STR_UPPER_P=20= STR_LTRIM_P=20STR_RTRIM_P=20STR_BTRIM_P=0A+=09=09=09=09=09STR_INITCAP_P=20= STR_SPLIT_PART_P=0A=20=0A=20%type=09=09result=0A=20=0A@@=20-95,7=20= +97,7=20@@=20static=20bool=20makeItemLikeRegex(JsonPathParseItem=20= *expr,=0A=20=09=09=09=09=09str_elem=20opt_str_arg=20int_elem=0A=20=09=09=09= =09=09uint_elem=20opt_uint_arg=0A=20=0A-%type=09=09=09= accessor_expr=20int_list=20opt_int_list=0A+%type=09=09=09= accessor_expr=20int_list=20opt_int_list=20str_int_args=20str_str_args=0A=20= =0A=20%type=09=09index_list=0A=20=0A@@=20-278,6=20+280,16=20@@=20= accessor_op:=0A=20=09=09{=20$$=20=3D=20makeItemUnary(jpiTimestamp,=20= $4);=20}=0A=20=09|=20'.'=20TIMESTAMP_TZ_P=20'('=20opt_uint_arg=20')'=0A=20= =09=09{=20$$=20=3D=20makeItemUnary(jpiTimestampTz,=20$4);=20}=0A+=09|=20= '.'=20STR_REPLACE_P=20'('=20str_str_args=20')'=0A+=09=09{=20$$=20=3D=20= makeItemBinary(jpiStrReplace,=20linitial($4),=20lsecond($4));=20}=0A+=09= |=20'.'=20STR_SPLIT_PART_P=20'('=20str_int_args=20')'=0A+=09=09{=20$$=20= =3D=20makeItemBinary(jpiStrSplitPart,=20linitial($4),=20lsecond($4));=20= }=0A+=09|=20'.'=20STR_LTRIM_P=20'('=20opt_str_arg=20')'=0A+=09=09{=20$$=20= =3D=20makeItemUnary(jpiStrLtrim,=20$4);=20}=0A+=09|=20'.'=20STR_RTRIM_P=20= '('=20opt_str_arg=20')'=0A+=09=09{=20$$=20=3D=20= makeItemUnary(jpiStrRtrim,=20$4);=20}=0A+=09|=20'.'=20STR_BTRIM_P=20'('=20= opt_str_arg=20')'=0A+=09=09{=20$$=20=3D=20makeItemUnary(jpiStrBtrim,=20= $4);=20}=0A=20=09;=0A=20=0A=20int_elem:=0A@@=20-317,6=20+329,14=20@@=20= opt_str_arg:=0A=20=09|=20/*=20EMPTY=20*/=09=09=09=09=09{=20$$=20=3D=20= NULL;=20}=0A=20=09;=0A=20=0A+str_int_args:=0A+=09str_elem=20','=20= int_elem=09=09=09{=20$$=20=3D=20list_make2($1,=20$3);=20}=0A+=09;=0A+=0A= +str_str_args:=0A+=09str_elem=20','=20str_elem=20=09=09=09{=20$$=20=3D=20= list_make2($1,=20$3);=20}=0A+=09;=0A+=0A=20key:=0A=20=09key_name=09=09=09= =09=09=09{=20$$=20=3D=20makeItemKey(&$1);=20}=0A=20=09;=0A@@=20-357,6=20= +377,9=20@@=20key_name:=0A=20=09|=20TIME_TZ_P=0A=20=09|=20TIMESTAMP_P=0A=20= =09|=20TIMESTAMP_TZ_P=0A+=09|=20STR_LTRIM_P=0A+=09|=20STR_RTRIM_P=0A+=09= |=20STR_BTRIM_P=0A=20=09;=0A=20=0A=20method:=0A@@=20-373,6=20+396,9=20@@=20= method:=0A=20=09|=20INTEGER_P=09=09=09=09=09=09{=20$$=20=3D=20= jpiInteger;=20}=0A=20=09|=20NUMBER_P=09=09=09=09=09=09{=20$$=20=3D=20= jpiNumber;=20}=0A=20=09|=20STRINGFUNC_P=09=09=09=09=09{=20$$=20=3D=20= jpiStringFunc;=20}=0A+=09|=20STR_LOWER_P=09=09=09=09=09{=20$$=20=3D=20= jpiStrLower;=20}=0A+=09|=20STR_UPPER_P=09=09=09=09=09{=20$$=20=3D=20= jpiStrUpper;=20}=0A+=09|=20STR_INITCAP_P=09=09=09=09=09{=20$$=20=3D=20= jpiStrInitcap;=20}=0A=20=09;=0A=20%%=0A=20=0Adiff=20--git=20= a/src/backend/utils/adt/jsonpath_scan.l=20= b/src/backend/utils/adt/jsonpath_scan.l=0Aindex=20= c7aab83eeb4..69c61f98500=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_scan.l=0A+++=20= b/src/backend/utils/adt/jsonpath_scan.l=0A@@=20-413,8=20+413,13=20@@=20= static=20const=20JsonPathKeyword=20keywords[]=20=3D=20{=0A=20=09{4,=20= true,=20TRUE_P,=20"true"},=0A=20=09{4,=20false,=20TYPE_P,=20"type"},=0A=20= =09{4,=20false,=20WITH_P,=20"with"},=0A+=09{5,=20false,=20STR_BTRIM_P,=20= "btrim"},=0A=20=09{5,=20true,=20FALSE_P,=20"false"},=0A=20=09{5,=20= false,=20FLOOR_P,=20"floor"},=0A+=09{5,=20false,=20STR_LOWER_P,=20= "lower"},=0A+=09{5,=20false,=20STR_LTRIM_P,=20"ltrim"},=0A+=09{5,=20= false,=20STR_RTRIM_P,=20"rtrim"},=0A+=09{5,=20false,=20STR_UPPER_P,=20= "upper"},=0A=20=09{6,=20false,=20BIGINT_P,=20"bigint"},=0A=20=09{6,=20= false,=20DOUBLE_P,=20"double"},=0A=20=09{6,=20false,=20EXISTS_P,=20= "exists"},=0A@@=20-425,13=20+430,16=20@@=20static=20const=20= JsonPathKeyword=20keywords[]=20=3D=20{=0A=20=09{7,=20false,=20BOOLEAN_P,=20= "boolean"},=0A=20=09{7,=20false,=20CEILING_P,=20"ceiling"},=0A=20=09{7,=20= false,=20DECIMAL_P,=20"decimal"},=0A+=09{7,=20false,=20STR_INITCAP_P,=20= "initcap"},=0A=20=09{7,=20false,=20INTEGER_P,=20"integer"},=0A+=09{7,=20= false,=20STR_REPLACE_P,=20"replace"},=0A=20=09{7,=20false,=20TIME_TZ_P,=20= "time_tz"},=0A=20=09{7,=20false,=20UNKNOWN_P,=20"unknown"},=0A=20=09{8,=20= false,=20DATETIME_P,=20"datetime"},=0A=20=09{8,=20false,=20KEYVALUE_P,=20= "keyvalue"},=0A=20=09{9,=20false,=20TIMESTAMP_P,=20"timestamp"},=0A=20=09= {10,=20false,=20LIKE_REGEX_P,=20"like_regex"},=0A+=09{10,false,=20= STR_SPLIT_PART_P,=20"split_part"},=0A=20=09{12,=20false,=20= TIMESTAMP_TZ_P,=20"timestamp_tz"},=0A=20};=0A=20=0Adiff=20--git=20= a/src/include/utils/jsonpath.h=20b/src/include/utils/jsonpath.h=0Aindex=20= 23a76d233e9..2d0c53f7b06=20100644=0A---=20a/src/include/utils/jsonpath.h=0A= +++=20b/src/include/utils/jsonpath.h=0A@@=20-115,6=20+115,14=20@@=20= typedef=20enum=20JsonPathItemType=0A=20=09jpiTimeTz,=09=09=09=09=09/*=20= .time_tz()=20item=20method=20*/=0A=20=09jpiTimestamp,=09=09=09=09/*=20= .timestamp()=20item=20method=20*/=0A=20=09jpiTimestampTz,=09=09=09=09/*=20= .timestamp_tz()=20item=20method=20*/=0A+=09jpiStrReplace,=09=09=09=09/*=20= .replace()=20item=20method=20*/=0A+=09jpiStrLower,=09=09=09=09/*=20= .lower()=20item=20method=20*/=0A+=09jpiStrUpper,=09=09=09=09/*=20= .upper()=20item=20method=20*/=0A+=09jpiStrLtrim,=09=09=09=09/*=20= .ltrim()=20item=20method=20*/=0A+=09jpiStrRtrim,=09=09=09=09/*=20= .rtrim()=20item=20method=20*/=0A+=09jpiStrBtrim,=09=09=09=09/*=20= .btrim()=20item=20method=20*/=0A+=09jpiStrInitcap,=09=09=09=09/*=20= .initcap()=20item=20method=20*/=0A+=09jpiStrSplitPart,=09=09=09/*=20= .split_part()=20item=20method=20*/=0A=20}=20JsonPathItemType;=0A=20=0A=20= /*=20XQuery=20regex=20mode=20flags=20for=20LIKE_REGEX=20predicate=20*/=0A= diff=20--git=20a/src/test/regress/expected/jsonb_jsonpath.out=20= b/src/test/regress/expected/jsonb_jsonpath.out=0Aindex=20= 4bcd4e91a29..cea539717f9=20100644=0A---=20= a/src/test/regress/expected/jsonb_jsonpath.out=0A+++=20= b/src/test/regress/expected/jsonb_jsonpath.out=0A@@=20-2723,6=20= +2723,405=20@@=20select=20jsonb_path_query('"2023-08-15=2012:34:56"',=20= '$.timestamp().string()');=0A=20(1=20row)=0A=20=0A=20rollback;=0A+--=20= test=20.ltrim()=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20= "',=20'$.ltrim("=20")');=0A+=20jsonb_path_query=20=0A+------------------=0A= +=20"hello=20=20=20"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20= =20hello=20=20=20"',=20'$.ltrim("=20")');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"hello=20=20=20"=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.ltrim()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"hello=20=20=20"=0A+(1=20= row)=0A+=0A+select=20jsonb_path_query('"zzzytest"',=20'$.ltrim("xyz")');=0A= +=20jsonb_path_query=20=0A+------------------=0A+=20"test"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('null',=20'$.ltrim()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('null',=20'$.ltrim()',=20silent=20=3D>= =20true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A= +=0A+select=20jsonb_path_query('[]',=20'$.ltrim()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('[]',=20'strict=20$.ltrim()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('{}',=20'$.ltrim()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('[]',=20'strict=20$.ltrim()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('{}',=20'$.ltrim()',=20silent=20=3D>=20true);=0A= +=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('1.23',=20'$.ltrim()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('"1.23"',=20'$.ltrim()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23"=0A+(1=20row)=0A+=0A= +select=20jsonb_path_query('"1.23aaa"',=20'$.ltrim()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23aaa"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('1234',=20'$.ltrim()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('true',=20'$.ltrim()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.ltrim()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('1234',=20'$.ltrim().type()');=0A= +ERROR:=20=20jsonpath=20item=20method=20.ltrim()=20can=20only=20be=20= applied=20to=20a=20string=0A+select=20jsonb_path_query('[2,=20true]',=20= '$.ltrim()');=0A+ERROR:=20=20jsonpath=20item=20method=20.ltrim()=20can=20= only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query_array('["=20=20maybe=20=20",=20"=20=20yes",=20"=20=20= no"]',=20'$[*].ltrim()');=0A+=20=20jsonb_path_query_array=20=20=0A= +--------------------------=0A+=20["maybe=20=20",=20"yes",=20"no"]=0A+(1=20= row)=0A+=0A+select=20jsonb_path_query_array('["=20=20maybe=20=20",=20"=20= =20yes",=20"=20=20no"]',=20'$[*].ltrim().type()');=0A+=20=20=20=20=20= jsonb_path_query_array=20=20=20=20=20=0A= +--------------------------------=0A+=20["string",=20"string",=20= "string"]=0A+(1=20row)=0A+=0A+--=20test=20.rtrim()=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.rtrim("=20")');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"=20=20=20hello"=0A+(1=20= row)=0A+=0A+select=20jsonb_path_query('"testxxzx"',=20'$.rtrim("xyz")');=0A= +=20jsonb_path_query=20=0A+------------------=0A+=20"test"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20"',=20= '$.rtrim()');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20"=20=20= =20hello"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20=20hello=20= =20=20"',=20'$.rtrim()');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"=20=20=20hello"=0A+(1=20row)=0A+=0A+--=20test=20= .btrim()=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20"',=20= '$.btrim("=20")');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= "hello"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"xyxtrimyyx"',=20= '$.btrim("xyz")');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= "trim"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20=20hello=20=20= =20"',=20'$.btrim()');=0A+=20jsonb_path_query=20=0A+------------------=0A= +=20"hello"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.btrim()');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"hello"=0A+(1=20row)=0A+=0A+--=20test=20= .lower()=0A+select=20jsonb_path_query('null',=20'$.lower()');=0A+ERROR:=20= =20jsonpath=20item=20method=20.lower()=20can=20only=20be=20applied=20to=20= a=20string=0A+select=20jsonb_path_query('null',=20'$.lower()',=20silent=20= =3D>=20true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20= rows)=0A+=0A+select=20jsonb_path_query('[]',=20'$.lower()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('[]',=20'strict=20$.lower()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.lower()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('{}',=20'$.lower()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.lower()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('[]',=20'strict=20$.lower()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('{}',=20'$.lower()',=20silent=20=3D>=20true);=0A= +=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('1.23',=20'$.lower()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.lower()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('"1.23"',=20'$.lower()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23"=0A+(1=20row)=0A+=0A= +select=20jsonb_path_query('"1.23aaa"',=20'$.lower()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23aaa"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('1234',=20'$.lower()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.lower()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('true',=20'$.lower()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.lower()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('1234',=20'$.lower().type()');=0A= +ERROR:=20=20jsonpath=20item=20method=20.lower()=20can=20only=20be=20= applied=20to=20a=20string=0A+select=20jsonb_path_query('[2,=20true]',=20= '$.lower()');=0A+ERROR:=20=20jsonpath=20item=20method=20.lower()=20can=20= only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20'$[*].lower()');=0A= +=20jsonb_path_query_array=20=0A+------------------------=0A+=20= ["maybe",=20"yes",=20"no"]=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20= '$[*].lower().type()');=0A+=20=20=20=20=20jsonb_path_query_array=20=20=20= =20=20=0A+--------------------------------=0A+=20["string",=20"string",=20= "string"]=0A+(1=20row)=0A+=0A+--=20test=20.upper()=0A+select=20= jsonb_path_query('null',=20'$.upper()');=0A+ERROR:=20=20jsonpath=20item=20= method=20.upper()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('null',=20'$.upper()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('[]',=20'$.upper()');=0A+=20jsonb_path_query=20= =0A+------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('[]',=20'strict=20$.upper()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.upper()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('{}',=20'$.upper()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.upper()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('[]',=20'strict=20$.upper()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('{}',=20'$.upper()',=20silent=20=3D>=20true);=0A= +=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('1.23',=20'$.upper()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.upper()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('"1.23"',=20'$.upper()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23"=0A+(1=20row)=0A+=0A= +select=20jsonb_path_query('"1.23aaa"',=20'$.upper()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23AAA"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('1234',=20'$.upper()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.upper()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('true',=20'$.upper()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.upper()=20can=20only=20be=20applied=20to=20a=20= string=0A+select=20jsonb_path_query('1234',=20'$.upper().type()');=0A= +ERROR:=20=20jsonpath=20item=20method=20.upper()=20can=20only=20be=20= applied=20to=20a=20string=0A+select=20jsonb_path_query('[2,=20true]',=20= '$.upper()');=0A+ERROR:=20=20jsonpath=20item=20method=20.upper()=20can=20= only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20'$[*].upper()');=0A= +=20jsonb_path_query_array=20=0A+------------------------=0A+=20= ["MAYBE",=20"YES",=20"NO"]=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20= '$[*].upper().type()');=0A+=20=20=20=20=20jsonb_path_query_array=20=20=20= =20=20=0A+--------------------------------=0A+=20["string",=20"string",=20= "string"]=0A+(1=20row)=0A+=0A+--=20test=20.initcap()=0A+select=20= jsonb_path_query('null',=20'$.initcap()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.initcap()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('null',=20'$.initcap()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('[]',=20'$.initcap()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('[]',=20'strict=20$.initcap()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.initcap()=20can=20only=20be=20applied=20to=20= a=20string=0A+select=20jsonb_path_query('{}',=20'$.initcap()');=0A= +ERROR:=20=20jsonpath=20item=20method=20.initcap()=20can=20only=20be=20= applied=20to=20a=20string=0A+select=20jsonb_path_query('[]',=20'strict=20= $.initcap()',=20silent=20=3D>=20true);=0A+=20jsonb_path_query=20=0A= +------------------=0A+(0=20rows)=0A+=0A+select=20jsonb_path_query('{}',=20= '$.initcap()',=20silent=20=3D>=20true);=0A+=20jsonb_path_query=20=0A= +------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('1.23',=20'$.initcap()');=0A+ERROR:=20=20jsonpath=20= item=20method=20.initcap()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('"1.23"',=20'$.initcap()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23"=0A+(1=20row)=0A+=0A= +select=20jsonb_path_query('"1.23aaa"',=20'$.initcap()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"1.23aaa"=0A+(1=20row)=0A= +=0A+select=20jsonb_path_query('1234',=20'$.initcap()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.initcap()=20can=20only=20be=20applied=20to=20= a=20string=0A+select=20jsonb_path_query('true',=20'$.initcap()');=0A= +ERROR:=20=20jsonpath=20item=20method=20.initcap()=20can=20only=20be=20= applied=20to=20a=20string=0A+select=20jsonb_path_query('1234',=20= '$.initcap().type()');=0A+ERROR:=20=20jsonpath=20item=20method=20= .initcap()=20can=20only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query('[2,=20true]',=20'$.initcap()');=0A+ERROR:=20=20= jsonpath=20item=20method=20.initcap()=20can=20only=20be=20applied=20to=20= a=20string=0A+select=20jsonb_path_query('["maybe=20yes",=20"probably=20= no"]',=20'$.initcap()');=0A+=20jsonb_path_query=20=0A+------------------=0A= +=20"Maybe=20Yes"=0A+=20"Probably=20No"=0A+(2=20rows)=0A+=0A+--=20Test=20= .replace()=0A+select=20jsonb_path_query('null',=20'$.replace("x",=20= "bye")');=0A+ERROR:=20=20jsonpath=20item=20method=20.replace()=20can=20= only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query('null',=20'$.replace("x",=20"bye")',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('["x",=20"y",=20"z"]',=20'$.replace("x",=20= "bye")');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20"bye"=0A= +=20"y"=0A+=20"z"=0A+(3=20rows)=0A+=0A+select=20jsonb_path_query('{}',=20= '$.replace("x",=20"bye")');=0A+ERROR:=20=20jsonpath=20item=20method=20= .replace()=20can=20only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query('[]',=20'strict=20$.replace("x",=20"bye")',=20silent=20= =3D>=20true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20= rows)=0A+=0A+select=20jsonb_path_query('{}',=20'$.replace("x",=20= "bye")',=20silent=20=3D>=20true);=0A+=20jsonb_path_query=20=0A= +------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('1.23',=20'$.replace("x",=20"bye")');=0A+ERROR:=20=20= jsonpath=20item=20method=20.replace()=20can=20only=20be=20applied=20to=20= a=20string=0A+select=20jsonb_path_query('"hello=20world"',=20= '$.replace("hello","bye")');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"bye=20world"=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query('"hello=20world"',=20'$.replace("hello","bye")=20starts=20= with=20"bye"');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= true=0A+(1=20row)=0A+=0A+--=20Test=20.split_part()=0A+select=20= jsonb_path_query('"abc~@~def~@~ghi"',=20'$.split_part("~@~",=202)');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"def"=0A+(1=20row)=0A+=0A= +select=20jsonb_path_query('"abc,def,ghi,jkl"',=20'$.split_part(",",=20= -2)');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20"ghi"=0A+(1=20= row)=0A+=0A+--=20Test=20string=20methods=20play=20nicely=20together=0A= +select=20jsonb_path_query('"hello=20world"',=20= '$.replace("hello","bye").upper()');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"BYE=20WORLD"=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query('"hElLo=20WorlD"',=20= '$.lower().upper().lower().replace("hello","bye")');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"bye=20world"=0A+(1=20= row)=0A+=0A+select=20jsonb_path_query('"hElLo=20WorlD"',=20= '$.upper().lower().upper().replace("HELLO",=20"BYE")');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"BYE=20WORLD"=0A+(1=20= row)=0A+=0A+select=20jsonb_path_query('"hElLo=20WorlD"',=20= '$.lower().upper().lower().replace("hello","bye")=20starts=20with=20= "bye"');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20true=0A= +(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20=20hElLo=20WorlD=20= "',=20'$.btrim().lower().upper().lower().replace("hello","bye")=20starts=20= with=20"bye"');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= true=0A+(1=20row)=0A+=0A=20--=20Test=20.time()=0A=20select=20= jsonb_path_query('null',=20'$.time()');=0A=20ERROR:=20=20jsonpath=20item=20= method=20.time()=20can=20only=20be=20applied=20to=20a=20string=0Adiff=20= --git=20a/src/test/regress/expected/jsonpath.out=20= b/src/test/regress/expected/jsonpath.out=0Aindex=20= fd9bd755f52..a13022feabd=20100644=0A---=20= a/src/test/regress/expected/jsonpath.out=0A+++=20= b/src/test/regress/expected/jsonpath.out=0A@@=20-435,6=20+435,143=20@@=20= select=20'$.string()'::jsonpath;=0A=20=20$.string()=0A=20(1=20row)=0A=20=0A= +select=20'$.replace("hello","bye")'::jsonpath;=0A+=20=20=20=20=20=20=20=20= =20jsonpath=20=20=20=20=20=20=20=20=20=0A+--------------------------=0A+=20= $.replace("hello","bye")=0A+(1=20row)=0A+=0A+select=20= '$.lower()'::jsonpath;=0A+=20jsonpath=20=20=0A+-----------=0A+=20= $.lower()=0A+(1=20row)=0A+=0A+select=20'$.upper()'::jsonpath;=0A+=20= jsonpath=20=20=0A+-----------=0A+=20$.upper()=0A+(1=20row)=0A+=0A+select=20= '$.lower().upper().lower().replace("hello","bye")'::jsonpath;=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20jsonpath=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A= +--------------------------------------------------=0A+=20= $.lower().upper().lower().replace("hello","bye")=0A+(1=20row)=0A+=0A= +select=20'$.ltrim()'::jsonpath;=0A+=20jsonpath=20=20=0A+-----------=0A+=20= $.ltrim()=0A+(1=20row)=0A+=0A+select=20'$.ltrim("xyz")'::jsonpath;=0A+=20= =20=20=20jsonpath=20=20=20=20=0A+----------------=0A+=20$.ltrim("xyz")=0A= +(1=20row)=0A+=0A+select=20'$.rtrim()'::jsonpath;=0A+=20jsonpath=20=20=0A= +-----------=0A+=20$.rtrim()=0A+(1=20row)=0A+=0A+select=20= '$.rtrim("xyz")'::jsonpath;=0A+=20=20=20=20jsonpath=20=20=20=20=0A= +----------------=0A+=20$.rtrim("xyz")=0A+(1=20row)=0A+=0A+select=20= '$.btrim()'::jsonpath;=0A+=20jsonpath=20=20=0A+-----------=0A+=20= $.btrim()=0A+(1=20row)=0A+=0A+select=20'$.btrim("xyz")'::jsonpath;=0A+=20= =20=20=20jsonpath=20=20=20=20=0A+----------------=0A+=20$.btrim("xyz")=0A= +(1=20row)=0A+=0A+select=20'$.initcap()'::jsonpath;=0A+=20=20jsonpath=20=20= =20=0A+-------------=0A+=20$.initcap()=0A+(1=20row)=0A+=0A+select=20= '$.split_part("~@~",=202)'::jsonpath;=0A+=20=20=20=20=20=20=20jsonpath=20= =20=20=20=20=20=20=20=0A+-----------------------=0A+=20= $.split_part("~@~",2)=0A+(1=20row)=0A+=0A+--=20Parse=20errors=0A+select=20= '$.replace("hello")'::jsonpath;=0A+ERROR:=20=20syntax=20error=20at=20or=20= near=20")"=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.replace("hello")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20^=0A+select=20'$.replace()'::jsonpath;=0A+ERROR:=20=20syntax=20= error=20at=20or=20near=20")"=20of=20jsonpath=20input=0A+LINE=201:=20= select=20'$.replace()'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20^=0A+select=20'$.replace("hello","bye","extra")'::jsonpath;=0A= +ERROR:=20=20syntax=20error=20at=20or=20near=20","=20of=20jsonpath=20= input=0A+LINE=201:=20select=20= '$.replace("hello","bye","extra")'::jsonpath;=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20^=0A+select=20'$.split_part("~@~")'::jsonpath;=0A= +ERROR:=20=20syntax=20error=20at=20or=20near=20")"=20of=20jsonpath=20= input=0A+LINE=201:=20select=20'$.split_part("~@~")'::jsonpath;=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20^=0A+select=20= '$.split_part()'::jsonpath;=0A+ERROR:=20=20syntax=20error=20at=20or=20= near=20")"=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.split_part()'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20^=0A+select=20'$.split_part("~@~",=20"hi")'::jsonpath;=0A+ERROR:=20=20= syntax=20error=20at=20or=20near=20"""=20of=20jsonpath=20input=0A+LINE=20= 1:=20select=20'$.split_part("~@~",=20"hi")'::jsonpath;=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20^=0A+select=20'$.split_part("~@~",=202,=20= "extra")'::jsonpath;=0A+ERROR:=20=20syntax=20error=20at=20or=20near=20= ","=20of=20jsonpath=20input=0A+LINE=201:=20select=20'$.split_part("~@~",=20= 2,=20"extra")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ^=0A+select=20'$.lower("hi")'::jsonpath;=0A+ERROR:=20=20syntax=20error=20= at=20or=20near=20"""=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.lower("hi")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ^=0A+select=20'$.upper("hi")'::jsonpath;=0A+ERROR:=20=20syntax=20error=20= at=20or=20near=20"""=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.upper("hi")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ^=0A+select=20'$.initcap("hi")'::jsonpath;=0A+ERROR:=20=20syntax=20error=20= at=20or=20near=20"""=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.initcap("hi")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20^=0A+select=20'$.ltrim(42)'::jsonpath;=0A+ERROR:=20=20syntax=20error=20= at=20or=20near=20"42"=20of=20jsonpath=20input=0A+LINE=201:=20select=20= '$.ltrim(42)'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ^=0A+select=20'$.ltrim("x",=20"y")'::jsonpath;=0A+ERROR:=20=20syntax=20= error=20at=20or=20near=20","=20of=20jsonpath=20input=0A+LINE=201:=20= select=20'$.ltrim("x",=20"y")'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20^=0A+select=20'$.rtrim(42)'::jsonpath;=0A+ERROR:=20=20= syntax=20error=20at=20or=20near=20"42"=20of=20jsonpath=20input=0A+LINE=20= 1:=20select=20'$.rtrim(42)'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20^=0A+select=20'$.rtrim("x",=20"y")'::jsonpath;=0A+ERROR:=20=20= syntax=20error=20at=20or=20near=20","=20of=20jsonpath=20input=0A+LINE=20= 1:=20select=20'$.rtrim("x",=20"y")'::jsonpath;=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20^=0A+select=20'$.trim(42)'::jsonpath;=0A+ERROR:=20=20= syntax=20error=20at=20or=20near=20"("=20of=20jsonpath=20input=0A+LINE=20= 1:=20select=20'$.trim(42)'::jsonpath;=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20^=0A+select=20'$.trim("x",=20"y")'::jsonpath;=0A+ERROR:=20=20= syntax=20error=20at=20or=20near=20"("=20of=20jsonpath=20input=0A+LINE=20= 1:=20select=20'$.trim("x",=20"y")'::jsonpath;=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20^=0A=20select=20'$.time()'::jsonpath;=0A=20=20= jsonpath=20=0A=20----------=0Adiff=20--git=20= a/src/test/regress/sql/jsonb_jsonpath.sql=20= b/src/test/regress/sql/jsonb_jsonpath.sql=0Aindex=20= 3e8929a5269..8169719343e=20100644=0A---=20= a/src/test/regress/sql/jsonb_jsonpath.sql=0A+++=20= b/src/test/regress/sql/jsonb_jsonpath.sql=0A@@=20-623,6=20+623,115=20@@=20= select=20jsonb_path_query('"2023-08-15=2012:34:56=20+5:30"',=20= '$.timestamp_tz().string(=0A=20select=20jsonb_path_query('"2023-08-15=20= 12:34:56"',=20'$.timestamp().string()');=0A=20rollback;=0A=20=0A+--=20= test=20.ltrim()=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20= "',=20'$.ltrim("=20")');=0A+select=20jsonb_path_query('"=20=20=20hello=20= =20=20"',=20'$.ltrim("=20")');=0A+select=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.ltrim()');=0A+select=20= jsonb_path_query('"zzzytest"',=20'$.ltrim("xyz")');=0A+select=20= jsonb_path_query('null',=20'$.ltrim()');=0A+select=20= jsonb_path_query('null',=20'$.ltrim()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('[]',=20'$.ltrim()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.ltrim()');=0A+select=20= jsonb_path_query('{}',=20'$.ltrim()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.ltrim()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('{}',=20'$.ltrim()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('1.23',=20'$.ltrim()');=0A+select=20= jsonb_path_query('"1.23"',=20'$.ltrim()');=0A+select=20= jsonb_path_query('"1.23aaa"',=20'$.ltrim()');=0A+select=20= jsonb_path_query('1234',=20'$.ltrim()');=0A+select=20= jsonb_path_query('true',=20'$.ltrim()');=0A+select=20= jsonb_path_query('1234',=20'$.ltrim().type()');=0A+select=20= jsonb_path_query('[2,=20true]',=20'$.ltrim()');=0A+select=20= jsonb_path_query_array('["=20=20maybe=20=20",=20"=20=20yes",=20"=20=20= no"]',=20'$[*].ltrim()');=0A+select=20jsonb_path_query_array('["=20=20= maybe=20=20",=20"=20=20yes",=20"=20=20no"]',=20'$[*].ltrim().type()');=0A= +=0A+--=20test=20.rtrim()=0A+select=20jsonb_path_query('"=20=20=20hello=20= =20=20"',=20'$.rtrim("=20")');=0A+select=20= jsonb_path_query('"testxxzx"',=20'$.rtrim("xyz")');=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.rtrim()');=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.rtrim()');=0A+=0A+--=20= test=20.btrim()=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20= "',=20'$.btrim("=20")');=0A+select=20jsonb_path_query('"xyxtrimyyx"',=20= '$.btrim("xyz")');=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20= "',=20'$.btrim()');=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20= "',=20'$.btrim()');=0A+=0A+--=20test=20.lower()=0A+select=20= jsonb_path_query('null',=20'$.lower()');=0A+select=20= jsonb_path_query('null',=20'$.lower()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('[]',=20'$.lower()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.lower()');=0A+select=20= jsonb_path_query('{}',=20'$.lower()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.lower()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('{}',=20'$.lower()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('1.23',=20'$.lower()');=0A+select=20= jsonb_path_query('"1.23"',=20'$.lower()');=0A+select=20= jsonb_path_query('"1.23aaa"',=20'$.lower()');=0A+select=20= jsonb_path_query('1234',=20'$.lower()');=0A+select=20= jsonb_path_query('true',=20'$.lower()');=0A+select=20= jsonb_path_query('1234',=20'$.lower().type()');=0A+select=20= jsonb_path_query('[2,=20true]',=20'$.lower()');=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20'$[*].lower()');=0A= +select=20jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20= '$[*].lower().type()');=0A+=0A+--=20test=20.upper()=0A+select=20= jsonb_path_query('null',=20'$.upper()');=0A+select=20= jsonb_path_query('null',=20'$.upper()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('[]',=20'$.upper()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.upper()');=0A+select=20= jsonb_path_query('{}',=20'$.upper()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.upper()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('{}',=20'$.upper()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('1.23',=20'$.upper()');=0A+select=20= jsonb_path_query('"1.23"',=20'$.upper()');=0A+select=20= jsonb_path_query('"1.23aaa"',=20'$.upper()');=0A+select=20= jsonb_path_query('1234',=20'$.upper()');=0A+select=20= jsonb_path_query('true',=20'$.upper()');=0A+select=20= jsonb_path_query('1234',=20'$.upper().type()');=0A+select=20= jsonb_path_query('[2,=20true]',=20'$.upper()');=0A+select=20= jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20'$[*].upper()');=0A= +select=20jsonb_path_query_array('["maybe",=20"yes",=20"no"]',=20= '$[*].upper().type()');=0A+=0A+--=20test=20.initcap()=0A+select=20= jsonb_path_query('null',=20'$.initcap()');=0A+select=20= jsonb_path_query('null',=20'$.initcap()',=20silent=20=3D>=20true);=0A= +select=20jsonb_path_query('[]',=20'$.initcap()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.initcap()');=0A+select=20= jsonb_path_query('{}',=20'$.initcap()');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.initcap()',=20silent=20=3D>=20= true);=0A+select=20jsonb_path_query('{}',=20'$.initcap()',=20silent=20=3D>= =20true);=0A+select=20jsonb_path_query('1.23',=20'$.initcap()');=0A= +select=20jsonb_path_query('"1.23"',=20'$.initcap()');=0A+select=20= jsonb_path_query('"1.23aaa"',=20'$.initcap()');=0A+select=20= jsonb_path_query('1234',=20'$.initcap()');=0A+select=20= jsonb_path_query('true',=20'$.initcap()');=0A+select=20= jsonb_path_query('1234',=20'$.initcap().type()');=0A+select=20= jsonb_path_query('[2,=20true]',=20'$.initcap()');=0A+select=20= jsonb_path_query('["maybe=20yes",=20"probably=20no"]',=20'$.initcap()');=0A= +=0A+--=20Test=20.replace()=0A+select=20jsonb_path_query('null',=20= '$.replace("x",=20"bye")');=0A+select=20jsonb_path_query('null',=20= '$.replace("x",=20"bye")',=20silent=20=3D>=20true);=0A+select=20= jsonb_path_query('["x",=20"y",=20"z"]',=20'$.replace("x",=20"bye")');=0A= +select=20jsonb_path_query('{}',=20'$.replace("x",=20"bye")');=0A+select=20= jsonb_path_query('[]',=20'strict=20$.replace("x",=20"bye")',=20silent=20= =3D>=20true);=0A+select=20jsonb_path_query('{}',=20'$.replace("x",=20= "bye")',=20silent=20=3D>=20true);=0A+select=20jsonb_path_query('1.23',=20= '$.replace("x",=20"bye")');=0A+select=20jsonb_path_query('"hello=20= world"',=20'$.replace("hello","bye")');=0A+select=20= jsonb_path_query('"hello=20world"',=20'$.replace("hello","bye")=20starts=20= with=20"bye"');=0A+=0A+--=20Test=20.split_part()=0A+select=20= jsonb_path_query('"abc~@~def~@~ghi"',=20'$.split_part("~@~",=202)');=0A= +select=20jsonb_path_query('"abc,def,ghi,jkl"',=20'$.split_part(",",=20= -2)');=0A+=0A+--=20Test=20string=20methods=20play=20nicely=20together=0A= +select=20jsonb_path_query('"hello=20world"',=20= '$.replace("hello","bye").upper()');=0A+select=20= jsonb_path_query('"hElLo=20WorlD"',=20= '$.lower().upper().lower().replace("hello","bye")');=0A+select=20= jsonb_path_query('"hElLo=20WorlD"',=20= '$.upper().lower().upper().replace("HELLO",=20"BYE")');=0A+select=20= jsonb_path_query('"hElLo=20WorlD"',=20= '$.lower().upper().lower().replace("hello","bye")=20starts=20with=20= "bye"');=0A+select=20jsonb_path_query('"=20=20=20hElLo=20WorlD=20"',=20= '$.btrim().lower().upper().lower().replace("hello","bye")=20starts=20= with=20"bye"');=0A+=0A=20--=20Test=20.time()=0A=20select=20= jsonb_path_query('null',=20'$.time()');=0A=20select=20= jsonb_path_query('true',=20'$.time()');=0Adiff=20--git=20= a/src/test/regress/sql/jsonpath.sql=20= b/src/test/regress/sql/jsonpath.sql=0Aindex=2061a5270d4e8..7dd2e57e7a6=20= 100644=0A---=20a/src/test/regress/sql/jsonpath.sql=0A+++=20= b/src/test/regress/sql/jsonpath.sql=0A@@=20-78,6=20+78,37=20@@=20select=20= '$.boolean()'::jsonpath;=0A=20select=20'$.date()'::jsonpath;=0A=20select=20= '$.decimal(4,2)'::jsonpath;=0A=20select=20'$.string()'::jsonpath;=0A= +select=20'$.replace("hello","bye")'::jsonpath;=0A+select=20= '$.lower()'::jsonpath;=0A+select=20'$.upper()'::jsonpath;=0A+select=20= '$.lower().upper().lower().replace("hello","bye")'::jsonpath;=0A+select=20= '$.ltrim()'::jsonpath;=0A+select=20'$.ltrim("xyz")'::jsonpath;=0A+select=20= '$.rtrim()'::jsonpath;=0A+select=20'$.rtrim("xyz")'::jsonpath;=0A+select=20= '$.btrim()'::jsonpath;=0A+select=20'$.btrim("xyz")'::jsonpath;=0A+select=20= '$.initcap()'::jsonpath;=0A+select=20'$.split_part("~@~",=20= 2)'::jsonpath;=0A+=0A+--=20Parse=20errors=0A+select=20= '$.replace("hello")'::jsonpath;=0A+select=20'$.replace()'::jsonpath;=0A= +select=20'$.replace("hello","bye","extra")'::jsonpath;=0A+select=20= '$.split_part("~@~")'::jsonpath;=0A+select=20'$.split_part()'::jsonpath;=0A= +select=20'$.split_part("~@~",=20"hi")'::jsonpath;=0A+select=20= '$.split_part("~@~",=202,=20"extra")'::jsonpath;=0A+select=20= '$.lower("hi")'::jsonpath;=0A+select=20'$.upper("hi")'::jsonpath;=0A= +select=20'$.initcap("hi")'::jsonpath;=0A+select=20= '$.ltrim(42)'::jsonpath;=0A+select=20'$.ltrim("x",=20"y")'::jsonpath;=0A= +select=20'$.rtrim(42)'::jsonpath;=0A+select=20'$.rtrim("x",=20= "y")'::jsonpath;=0A+select=20'$.trim(42)'::jsonpath;=0A+select=20= '$.trim("x",=20"y")'::jsonpath;=0A+=0A=20select=20'$.time()'::jsonpath;=0A= =20select=20'$.time(6)'::jsonpath;=0A=20select=20= '$.time_tz()'::jsonpath;=0A--=20=0A2.51.0=0A=0A= --Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii --Apple-Mail=_91B4342F-77ED-46F0-B39D-6E7FECEBD79B-- --Apple-Mail=_4A68DAED-BAF2-44DD-A14C-6875A89E054F Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=signature.asc Content-Type: application/pgp-signature; name=signature.asc Content-Description: Message signed with OpenPGP -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEd+KfmbOQis6ZycGGkt9idPjIgfEFAmkBG8cACgkQkt9idPjI gfGCZA//fzgQRu4X6wIkVmRoZI+NCHVwh7UoacWCRMqoxkluJR8Pq9zDiKQR7ELN SNVSUnRZOzCB1ZJQ2wfaQMQMs6evyn8+RDost47kpeN+NsA0s8hTY5vZswKT3jwK 1diX6SgJqcJUx3MHiz0y1Ecj8uF4Q5y7lMo/akrjPjuG6iji4KJi5+QFKP6AbYXR 00407rlqdWR6sBEjjI+LchzynO8APUI0DbkiLvSyJmqm+0Kt/krBTL5nIs65yM7L 0nDiG6vq58fCu4NF4pgsZS3aQaslmpW1sUv4GXYqU5Crp9tdVxbxIjEGh8rckapE TubPzgUiBYsqPwvZSfaJf1hKoxAeei9h9cdMziAufyb/EsxnMPXYXHIZTrvBCROJ WuO0KwRDax/zzF32oK4h7REDbL2P0yfqtpIi92Cb/QHgu+27k7l4+tCgpGFh59VC +DFGRZN2CHF8tRcGztbz6oy+5as0qFu+9kbvG8BmsWgDoVTc8k9CNFxOl+9poiza l9KNaf3xxW8LFYkE+CE6lxA+Z+ucJ2hd9MzX34JSIJvIsNiT0BJPz+0nyao6HeE/ qph2KDYEqkU2EPJbp4h4ett8PA9kub/pe/I6HgbaUFV3QyDrYSVjDo+9N9pg6X7o AYBnk9wP9ggdwJNNYBh+GwNJL7IsNl7q1rZlIpMMpLXpiKcAa3o= =PFsn -----END PGP SIGNATURE----- --Apple-Mail=_4A68DAED-BAF2-44DD-A14C-6875A89E054F--