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 1uMX26-00EVSl-Fj for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Jun 2025 19:10:46 +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 1uMX24-003Z9L-6o for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Jun 2025 19:10:44 +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 1uMX23-003Z4b-OE for pgsql-hackers@lists.postgresql.org; Tue, 03 Jun 2025 19:10:44 +0000 Received: from fout-b6-smtp.messagingengine.com ([202.12.124.149]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uMX21-0003Dl-3B for pgsql-hackers@lists.postgresql.org; Tue, 03 Jun 2025 19:10:43 +0000 Received: from phl-compute-03.internal (phl-compute-03.phl.internal [10.202.2.43]) by mailfout.stl.internal (Postfix) with ESMTP id 062EB11400EA; Tue, 3 Jun 2025 15:10:39 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-03.internal (MEProxy); Tue, 03 Jun 2025 15:10:40 -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=fm1; t=1748977839; x= 1749064239; bh=jQ2vlTkrnOPRjXAMw/zDfHJsOTZtD0UIl1iNlzS0lfo=; b=n SvJD81P//WdFnrNIk+kyv0+IFcIk453FwKsl3RzxGuZwk6Zkac8n/TcHzuihajkH eKkCr4bF3K5cwapVJmEXvJeHo/cUQQAzOLhqk73rovQt1rRumD9mfetLnZAGWNsj lhhjDqhxhxJYijtb81cTZnbf2OBxMot/h0+q1lW/sO1nISKW8luw190wqvyIuD6r 3trawk34K+wRuuZ6CDhKoPCK9upNL3Qsd1M7heXxbCjxEUj8CU23EQaIs3TtLBEC 5NiKeJZf8x55EECoi7Bd6FX2Z5n+Ftogv9CB1+xgLErtdNeURfgGgVm6FgukrZOV IHEZip6semenBQQIXGzUQ== 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=fm1; t= 1748977839; x=1749064239; bh=jQ2vlTkrnOPRjXAMw/zDfHJsOTZtD0UIl1i NlzS0lfo=; b=L9dmM2o8tr0oa7yviXxwfZYFfh7NQfkIMtgDBidHZNYzZlWChnR VIVWETgZo3s0/yKbWyhFvAEBKSNKq7pog9tRyOhwHnY+DFoLfvkg3XDwJDaNqR8X mM1B/Y913tsu+HC1XC2qrnGlZOjbsvi7/KTFULr15dFOaSc84/EmP1ZQKy0lIlgo uPS5X3UeTn+edlij/UbuP1npKNRrEe6OApT3nmcU3BvIUfXjBa/yaHy+lFxxcCrL WR9evWbx8R4cfV3I3KX3ApgX4ugOwx2+601F0pnHg729olOAs2zjc+oZPT2dTU5u MQ20k7/nyaTNbNpMxTPJer4HkJO27IUM/zA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtddugddutddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnh htshculddquddttddmnecujfgurhephffktgggufffjgevvfhfofesghdtmherhhdtvden ucfhrhhomhepfdffrghvihguucfgrdcuhghhvggvlhgvrhdfuceouggrvhhiugesjhhush htrghthhgvohhrhidrtghomheqnecuggftrfgrthhtvghrnhepudegfeeftefgudeiudff geekieeutdefueejieffueevfefgudduleefffekgeetnecuffhomhgrihhnpehgihhthh husgdrtghomhenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhr ohhmpegurghvihgusehjuhhsthgrthhhvghorhihrdgtohhmpdhnsggprhgtphhtthhope ejpdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehflhhorhgvnhhtshdrthhsvghl rghisehgmhgrihhlrdgtohhmpdhrtghpthhtohepthhglhesshhsshdrphhghhdrphgrrd hushdprhgtphhtthhopehpvghtvghrsegvihhsvghnthhrrghuthdrohhrghdprhgtphht thhopehrohgsvghrthhmhhgrrghssehgmhgrihhlrdgtohhmpdhrtghpthhtoheprggvkh horhhothhkohhvsehgmhgrihhlrdgtohhmpdhrtghpthhtohepphhgshhqlhdqhhgrtghk vghrsheslhhishhtshdrphhoshhtghhrvghsqhhlrdhorhhgpdhrtghpthhtoheprghnug hrvgifseguuhhnshhlrghnvgdrnhgvth X-ME-Proxy: Feedback-ID: i7c334307:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 3 Jun 2025 15:10:39 -0400 (EDT) From: "David E. Wheeler" Message-Id: <2F58E05D-D319-4CD3-8805-E1A8A2482A1A@justatheory.com> Content-Type: multipart/signed; boundary="Apple-Mail=_5667B366-1612-4C49-B40B-BB8E86078B6C"; protocol="application/pgp-signature"; micalg=pgp-sha256 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.600.51.1.1\)) Subject: Re: PATCH: jsonpath string methods: lower, upper, initcap, l/r/btrim, replace, split_part Date: Tue, 3 Jun 2025 15:10:28 -0400 In-Reply-To: <06FA8975-2E21-46A5-B510-028B3B967EB2@justatheory.com> Cc: Tom Lane , Peter Eisentraut , Robert Haas , Alexander Korotkov , pgsql-hackers , Andrew Dunstan To: Florents Tselai References: <145894.1727298237@sss.pgh.pa.us> <7e9debe6-4e96-4b0d-a801-b531e962ef43@eisentraut.org> <01DC1C38-0692-461B-AA63-5394330356BE@gmail.com> <2568904.1748022721@sss.pgh.pa.us> <40912112-7FFE-400F-A38F-368827C4BDF1@gmail.com> <176C517D-2DEB-4CAB-9AE4-261079D313B9@justatheory.com> <8FD5F4CF-9059-40C1-9F0A-C3CBA8DFE17A@justatheory.com> <696ECBBC-3CBF-4522-AE66-E48225688E93@gmail.com> <59C63857-406D-4704-A1EB-9BF3AA639C86@justatheory.com> <06FA8975-2E21-46A5-B510-028B3B967EB2@justatheory.com> X-Mailer: Apple Mail (2.3826.600.51.1.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_5667B366-1612-4C49-B40B-BB8E86078B6C Content-Type: multipart/mixed; boundary="Apple-Mail=_3AF7407A-DB86-49B1-AD0A-9240A792C903" --Apple-Mail=_3AF7407A-DB86-49B1-AD0A-9240A792C903 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii On Jun 3, 2025, at 15:02, David E. Wheeler wrote: > Patches attached, GitHub PR here: > > https://github.com/theory/postgres/pull/12 Found a little more unnecessary code to remove. Updated patches attached. Best, David --Apple-Mail=_3AF7407A-DB86-49B1-AD0A-9240A792C903 Content-Disposition: attachment; filename=v7-0001-Rename-jsonpath-method-arg-tokens.patch Content-Type: application/octet-stream; name=v7-0001-Rename-jsonpath-method-arg-tokens.patch; x-unix-mode=0644 Content-Transfer-Encoding: quoted-printable =46rom=2086704d1c079b205ccdcb79da974a690d4dca2ad3=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=20v7=201/2]=20Rename=20jsonpath=20method=20arg=20= tokens=0A=0ARename=20the=20`csv_`=20tokens=20to=20`int_`,=20because=20= they=20represent=20signed=20or=0Aunsigned=20integers,=20as=20follows:=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=0A= Rename=20the=20`datetime_precision`=20tokens=20to=20`uint_arg`,=20as=20= they=20represent=0Aunsigned=20integers=20and=20will=20be=20useful=20for=20= other=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.49.0=0A=0A= --Apple-Mail=_3AF7407A-DB86-49B1-AD0A-9240A792C903 Content-Disposition: attachment; filename=v7-0002-Add-additional-jsonpath-string-methods.patch Content-Type: application/octet-stream; name=v7-0002-Add-additional-jsonpath-string-methods.patch; x-unix-mode=0644 Content-Transfer-Encoding: quoted-printable =46rom=201e80d72d20c466fc198043e059556d649adbaf5b=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Florents=20Tselai=20= =0ADate:=20Tue,=203=20Jun=202025=2015:09:38=20= -0400=0ASubject:=20[PATCH=20v7=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.sgml=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20|=20140=20+++++++=0A=20= src/backend/utils/adt/jsonpath.c=20=20=20=20=20=20=20=20=20=20=20=20=20|=20= 113=20+++++-=0A=20src/backend/utils/adt/jsonpath_exec.c=20=20=20=20=20=20= =20=20|=20200=20++++++++++=0A=20src/backend/utils/adt/jsonpath_gram.y=20=20= =20=20=20=20=20=20|=20=2028=20+-=0A=20= src/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= 1169=20insertions(+),=204=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/func.sgml=20b/doc/src/sgml/func.sgml=0Aindex=20= c67688cbf5f..674c22c78d8=20100644=0A---=20a/doc/src/sgml/func.sgml=0A+++=20= b/doc/src/sgml/func.sgml=0A@@=20-18627,6=20+18627,146=20@@=20ERROR:=20=20= jsonpath=20member=20accessor=20can=20only=20be=20applied=20to=20an=20= object=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":=20= 32}]=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=20string=20= .=20lower()=0A+=20=20=20=20=20=20=20= =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=20String=20converted=20to=20all=20lower=20case=20according=20to=20= the=20rules=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..0872b115697=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-1201,7=20= +1298,9=20@@=20jspGetRightArg(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.right);=0A=20}=0A@@=20-1501,6=20+1600,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= dbab24737ef..2095f2a9c21=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_exec.c=0A+++=20= b/src/backend/utils/adt/jsonpath_exec.c=0A@@=20-301,6=20+301,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=09JsonbValue=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-1659,6=20+1661,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{=0A+=09=09=09if=20(unwrap=20&&=20= JsonbType(jb)=20=3D=3D=20jbvArray)=0A+=09=09=09=09return=20= executeItemUnwrapTargetArray(cxt,=20jsp,=20jb,=20found,=20false);=0A+=0A= +=09=09=09return=20executeStringInternalMethod(cxt,=20jsp,=20jb,=20= found);=0A+=09=09}=0A+=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-2792,6=20+2811,187=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=20executeStringInternalMethod(JsonPathExecContext=20= *cxt,=20JsonPathItem=20*jsp,=0A+=09=09=09=09=09=09=09=09=09=09=09=09= JsonbValue=20*jb,=20JsonValueList=20*found)=20{=0A+=09Assert(=09= jsp->type=20=3D=3D=20jpiStrLower=20||=0A+=09=09=09jsp->type=20=3D=3D=20= jpiStrUpper=20||=0A+=09=09=09jsp->type=20=3D=3D=20jpiStrReplace=20||=0A+=09= =09=09jsp->type=20=3D=3D=20jpiStrLtrim=20||=0A+=09=09=09jsp->type=20=3D=3D= =20jpiStrRtrim=20||=0A+=09=09=09jsp->type=20=3D=3D=20jpiStrBtrim=20||=0A= +=09=09=09jsp->type=20=3D=3D=20jpiStrInitcap=20||=0A+=09=09=09jsp->type=20= =3D=3D=20jpiStrSplitPart);=0A+=09JsonbValue=09jbvbuf;=0A+=09bool=09=09= hasNext;=0A+=09JsonPathExecResult=20res=20=3D=20jperNotFound;=0A+=09= JsonPathItem=20elem;=0A+=09Datum=09=09str;=20/*=20Datum=20representation=20= for=20the=20current=20string=20value.=20The=20first=20argument=20to=20= internal=20functions=20*/=0A+=09char=09=09*tmp=20=3D=20NULL;=0A+=09char=09= =09*resStr=20=3D=20NULL;=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_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),=0A= +=09=09=09=09=09=09=09=20=20errmsg("jsonpath=20item=20method=20.%s()=20= can=20only=20be=20applied=20to=20a=20string",=0A+=09=09=09=09=09=09=09=09= =09=20jspOperationName(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{=0A+=09=09=09char=09=20=20=20*characters_str;=0A+=09= =09=09int=09=09=09characters_len;=0A+=09=09=09PGFunction=09func=20=3D=20= NULL;=0A+=0A+=09=09=09if=20(jsp->content.arg)=0A+=09=09=09{=0A+=09=09=09=09= switch=20(jsp->type)=0A+=09=09=09=09{=0A+=09=09=09=09=09case=20= jpiStrLtrim:=0A+=09=09=09=09=09=09func=20=3D=20ltrim;=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09case=20jpiStrRtrim:=0A+=09=09=09=09=09=09func=20= =3D=20rtrim;=0A+=09=09=09=09=09=09break;=0A+=09=09=09=09=09case=20= jpiStrBtrim:=0A+=09=09=09=09=09=09func=20=3D=20btrim;=0A+=09=09=09=09=09=09= break;=0A+=09=09=09=09=09default:=20;=0A+=09=09=09=09}=0A+=09=09=09=09= jspGetArg(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.%s()=20argument",=20jspOperationName(jsp->type));=0A+=0A+=09= =09=09=09characters_str=20=3D=20jspGetString(&elem,=20&characters_len);=0A= +=09=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall2Coll(func,=0A+=09=09=09=09=09= DEFAULT_COLLATION_OID,=20str,=0A+=09=09=09=09=09= CStringGetTextDatum(characters_str)));=0A+=09=09=09=09break;=0A+=09=09=09= }=0A+=0A+=09=09=09switch=20(jsp->type)=0A+=09=09=09{=0A+=09=09=09=09case=20= jpiStrLtrim:=0A+=09=09=09=09=09func=20=3D=20ltrim1;=0A+=09=09=09=09=09= break;=0A+=09=09=09=09case=20jpiStrRtrim:=0A+=09=09=09=09=09func=20=3D=20= rtrim1;=0A+=09=09=09=09=09break;=0A+=09=09=09=09case=20jpiStrBtrim:=0A+=09= =09=09=09=09func=20=3D=20btrim1;=0A+=09=09=09=09=09break;=0A+=09=09=09=09= default:=20;=0A+=09=09=09}=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(func,=0A+=09=09=09=09=09= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09= case=20jpiStrLower:=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(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{=0A+=09=09=09char=09=09*from_str,=20*to_str;=0A= +=09=09=09int=09=09=09from_len,=20to_len;=0A+=0A+=09=09=09= jspGetLeftArg(jsp,=20&elem);=0A+=09=09=09if=20(elem.type=20!=3D=20= jpiString)=0A+=09=09=09=09elog(ERROR,=20"invalid=20jsonpath=20item=20= type=20for=20.replace()=20from");=0A+=0A+=09=09=09from_str=20=3D=20= jspGetString(&elem,=20&from_len);=0A+=0A+=09=09=09jspGetRightArg(jsp,=20= &elem);=0A+=09=09=09if=20(elem.type=20!=3D=20jpiString)=0A+=09=09=09=09= elog(ERROR,=20"invalid=20jsonpath=20item=20type=20for=20.replace()=20= to");=0A+=0A+=09=09=09to_str=20=3D=20jspGetString(&elem,=20&to_len);=0A+=0A= +=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall3Coll(replace_text,=0A+=09=09=09=09= C_COLLATION_OID,=0A+=09=09=09=09CStringGetTextDatum(tmp),=0A+=09=09=09=09= CStringGetTextDatum(from_str),=0A+=09=09=09=09= CStringGetTextDatum(to_str)));=0A+=09=09=09break;=0A+=09=09}=0A+=09=09= case=20jpiStrSplitPart:=0A+=09=09{=0A+=09=09=09char=09=09*from_str;=0A+=09= =09=09Numeric=09=09n;=0A+=09=09=09int=09=09=09from_len;=0A+=0A+=09=09=09= jspGetLeftArg(jsp,=20&elem);=0A+=09=09=09if=20(elem.type=20!=3D=20= jpiString)=0A+=09=09=09=09elog(ERROR,=20"invalid=20jsonpath=20item=20= type=20for=20.split_part()");=0A+=0A+=09=09=09from_str=20=3D=20= jspGetString(&elem,=20&from_len);=0A+=0A+=09=09=09jspGetRightArg(jsp,=20= &elem);=0A+=09=09=09if=20(elem.type=20!=3D=20jpiNumeric)=0A+=09=09=09=09= elog(ERROR,=20"invalid=20jsonpath=20item=20type=20for=20.split_part()");=0A= +=0A+=09=09=09n=20=3D=20jspGetNumeric(&elem);=0A+=0A+=09=09=09resStr=20=3D= =20TextDatumGetCString(DirectFunctionCall3Coll(split_part,=0A+=09=09=09=09= C_COLLATION_OID,=0A+=09=09=09=09CStringGetTextDatum(tmp),=0A+=09=09=09=09= CStringGetTextDatum(from_str),=0A+=09=09=09=09= DirectFunctionCall1(numeric_int8,=20NumericGetDatum(n))));=0A+=09=09=09= break;=0A+=09=09}=0A+=09=09default:=0A+=09=09=09elog(ERROR,=20= "unsupported=20jsonpath=20item=20type:=20%d",=20jsp->type);=0A+=09}=0A+=0A= +=09if=20(resStr)=0A+=09=09res=20=3D=20jperOk;=0A+=0A+=09hasNext=20=3D=20= jspGetNext(jsp,=20&elem);=0A+=0A+=09if=20(!hasNext=20&&=20!found)=0A+=09=09= return=20res;=0A+=0A+=09jb=20=3D=20hasNext=20?=20&jbvbuf=20:=20= palloc(sizeof(*jb));=0A+=0A+=09/*=20Create=20the=20appropriate=20jb=20= value=20to=20return=20*/=0A+=09switch=20(jsp->type)=0A+=09{=0A+=09=09/*=20= Cases=20for=20functions=20that=20return=20text=20*/=0A+=09=09case=20= jpiStrLower:=0A+=09=09case=20jpiStrUpper:=0A+=09=09case=20jpiStrReplace:=0A= +=09=09case=20jpiStrLtrim:=0A+=09=09case=20jpiStrRtrim:=0A+=09=09case=20= jpiStrBtrim:=0A+=09=09case=20jpiStrInitcap:=0A+=09=09case=20= jpiStrSplitPart:=0A+=09=09=09jb->type=20=3D=20jbvString;=0A+=09=09=09= jb->val.string.val=20=3D=20resStr;=0A+=09=09=09jb->val.string.len=20=3D=20= strlen(jb->val.string.val);=0A+=09=09default:=0A+=09=09=09;=0A+=09=09=09= /*=20cant'=20happen=20*/=0A+=09}=0A+=0A+=09return=20executeNextItem(cxt,=20= jsp,=20&elem,=20jb,=20found,=20hasNext);=0A+}=0A+=0A=20/*=0A=20=20*=20= Implementation=20of=20.keyvalue()=20method.=0A=20=20*=0Adiff=20--git=20= a/src/backend/utils/adt/jsonpath_gram.y=20= b/src/backend/utils/adt/jsonpath_gram.y=0Aindex=20= 0b16cec18c4..d4bc3d6034b=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.49.0=0A=0A= --Apple-Mail=_3AF7407A-DB86-49B1-AD0A-9240A792C903-- --Apple-Mail=_5667B366-1612-4C49-B40B-BB8E86078B6C 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+KfmbOQis6ZycGGkt9idPjIgfEFAmg/SKQACgkQkt9idPjI gfEjVw/+J7I8n4ouFRjCzk/OECtcX+Onh5ebWyegrp791w2BtoRwNQv/A1Mwombn 79TOW1CmEX0A60CsJmSWYZbuLn8fcOCd/jUMc1j6Z/P/aahTM+WdWX6t010dVlgL 3ShfbSYj/ef/9i7wJa7CjfOJX3omTdGEfKCteMmpciTqdGzH/sOjtAZ85K2EwW2n QQXXloXlQKVaivSrLHbA0eYlouQENeEhSpUeM0mT7iTehRsODweER5LRoDJVvgu4 ffld6EcyF5MDGSNJ04lEuMgfIQ3ly4yWbvLUiSOCLB5JzxsrOqqCOcMrqnTph9WP i6d3yOylnwtqib6NIBlhNFIuB+5M7/wnCV0HQWqWcqLB6TWr6fV321a+nGz9DzEX XwwhVJMOLc3hWx3Scy4roADHxgQ2IZImfxbVLyuHzNoyamd2EX5Q2IwfnTpzVYNg mTf3X5KLBrun8PrZBwNQQMnLp5KrTJEwQ0ZqPOXWRSloCVAYieKFNPbV51awd3vR Gt0d9YtOnpr4nkUqGgOwspSHVeJAObpHrxj6bjqZNdXFbHeaSN6MRVTHcGfTTsiL e26C9zhtmaBt3Go5vMMXQQYlObQRvTM/+qoK83kMoCfD076UAnZ5ZZ+umaaSU+Fn K2l2AomYt76p0gJW1QHfk7jjmgSu502BvPYPPgKxsYl7tD+URWA= =Lc3f -----END PGP SIGNATURE----- --Apple-Mail=_5667B366-1612-4C49-B40B-BB8E86078B6C--