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 1uIwqS-00E623-VA for pgsql-hackers@arkaria.postgresql.org; Sat, 24 May 2025 21:55:57 +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 1uIwqR-00DtAC-R2 for pgsql-hackers@arkaria.postgresql.org; Sat, 24 May 2025 21:55:55 +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 1uIwqR-00Dt9x-D0 for pgsql-hackers@lists.postgresql.org; Sat, 24 May 2025 21:55:55 +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 1uIwqL-000o5q-0N for pgsql-hackers@lists.postgresql.org; Sat, 24 May 2025 21:55:51 +0000 Received: from phl-compute-11.internal (phl-compute-11.phl.internal [10.202.2.51]) by mailfhigh.phl.internal (Postfix) with ESMTP id B6FC211400D8; Sat, 24 May 2025 17:55:47 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-11.internal (MEProxy); Sat, 24 May 2025 17:55:47 -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=fm3; t=1748123747; x= 1748210147; bh=cdGp7yalKtQ4JiBF0V6kw9Wav4XZkjY0sBwxyzgkh9I=; b=v T45qcyHv4/v11FEOwx2Q/fFhaE5o0j69dg/PTpzO3yvXtgVluHgS2Lt60vPJrplP PzCHY2mL2E2w/0jhuXGc6ZjT4JS9W3AUdQTCJnBYtXqA789A92zrZ96KHNDXPUsz N2lg2ub62SnnERP8/Fi/eXDZNJ9CQkoe70lNg2jfaKzYmJP/KOgkeN66PFSfRrfl WF3n+ln3IGk2UJyIFShMcwpYRkQKALYx4KRegiIXC2UwxcX+yk9hEthPgsWH4ad4 2fS0hfL61DUXwOxVIksh32MPjdLXv6eE2X/wRMEtippE1UM6nmMVq9tPNtVQcg7y 8Cg9N8BpwW3qAMRZApJ8g== 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= 1748123747; x=1748210147; bh=cdGp7yalKtQ4JiBF0V6kw9Wav4XZkjY0sBw xyzgkh9I=; b=w2c5cv9jBMLJ0SaYSJYxGbS0vbV3EGFRC8yLYMtY3sYt/wxftQn gdy4t6UlPMdpZGQ+HuymkGU6z3GT4AfBABWABvrfGCtOxWijWSyVocv1AJndyeNQ WXxieGYYoxbuE6/80A25ZokjqZtpJvqEAEzVEJSHHcJp7DuMQ098vUd44uNfmctw q6Wn91Lg/nF2a3tMSuIGCfzLoz8BANh+bhHtpoXTl9DKyZurhBZw5/IDD08O1zpi 4wCVrbkUrra8lmHF3Rsf1U+X5lKLeGtQuDzawQa3EZjm+qa761On6aSVFxwVCCGq uFXEZQo68zBWkKC7O3iYgbRe0t2kP28hy2w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtddtgdduvdekgeculddtuddrgeefvddrtd dtmdcutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggft fghnshhusghstghrihgsvgdpuffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftd dtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhkfgtggfuffgj vefvfhfosehgtdhmrehhtdejnecuhfhrohhmpedfffgrvhhiugcugfdrucghhhgvvghlvg hrfdcuoegurghvihgusehjuhhsthgrthhhvghorhihrdgtohhmqeenucggtffrrghtthgv rhhnpeeviedvhedtkeeuleeigeektedtgeehjeehhfeuuedvudeivedtgfdtvefhtdelke enucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegurghv ihgusehjuhhsthgrthhhvghorhihrdgtohhmpdhnsggprhgtphhtthhopeejpdhmohguvg epshhmthhpohhuthdprhgtphhtthhopehflhhorhgvnhhtshdrthhsvghlrghisehgmhgr ihhlrdgtohhmpdhrtghpthhtohepthhglhesshhsshdrphhghhdrphgrrdhushdprhgtph htthhopehpvghtvghrsegvihhsvghnthhrrghuthdrohhrghdprhgtphhtthhopehrohgs vghrthhmhhgrrghssehgmhgrihhlrdgtohhmpdhrtghpthhtoheprggvkhhorhhothhkoh hvsehgmhgrihhlrdgtohhmpdhrtghpthhtohepphhgshhqlhdqhhgrtghkvghrsheslhhi shhtshdrphhoshhtghhrvghsqhhlrdhorhhgpdhrtghpthhtoheprghnughrvgifseguuh hnshhlrghnvgdrnhgvth X-ME-Proxy: Feedback-ID: i7c334307:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 24 May 2025 17:55:46 -0400 (EDT) From: "David E. Wheeler" Message-Id: <8FD5F4CF-9059-40C1-9F0A-C3CBA8DFE17A@justatheory.com> Content-Type: multipart/signed; boundary="Apple-Mail=_AC9A478A-EAD9-4435-8417-F90B602FABD5"; 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: Sat, 24 May 2025 17:55:36 -0400 In-Reply-To: <176C517D-2DEB-4CAB-9AE4-261079D313B9@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> 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=_AC9A478A-EAD9-4435-8417-F90B602FABD5 Content-Type: multipart/mixed; boundary="Apple-Mail=_D3EB9222-2ABF-47BD-AF1A-0E48738E0328" --Apple-Mail=_D3EB9222-2ABF-47BD-AF1A-0E48738E0328 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 On May 24, 2025, at 17:46, David E. Wheeler = wrote: > Oh, and I forgot to mention, src/backend/utils/adt/jsonpath_scan.l = looks like it has a ton of duplication in it. Shouldn=E2=80=99t it just = add the new keywords, something like: And now I see my patch broke the grammar because I left some of my = fiddling in there. Apologies. Here=E2=80=99s an updated patch with the = updated keyword map, too. Best, David --Apple-Mail=_D3EB9222-2ABF-47BD-AF1A-0E48738E0328 Content-Disposition: attachment; filename=v4-0001-Add-additional-jsonpath-string-methods.patch Content-Type: application/octet-stream; name=v4-0001-Add-additional-jsonpath-string-methods.patch; x-unix-mode=0644 Content-Transfer-Encoding: quoted-printable =46rom=206a4705fd7cd79de9ad49e679fe15e5b2ca19fe10=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Florents=20Tselai=20= =0ADate:=20Sat,=2024=20May=202025=2017:55:08=20= -0400=0ASubject:=20[PATCH=20v4]=20Add=20additional=20jsonpath=20string=20= methods=0A=0AAdd=20the=20following=20jsonpath=20methods:=0A=0A*=20=20=20= l/r/btrim()=0A*=20=20=20lower(),=20upper()=0A*=20=20=20initcap()=0A*=20=20= =20replace()=0A*=20=20=20split_part()=0A=0AEach=20simply=20dispatches=20= to=20the=20standard=20string=20processing=20functions.=0AThese=20depend=20= on=20the=20locale,=20but=20since=20it's=20set=20at=20`initdb`,=20they=20= can=20be=0Aconsidered=20immutable=20and=20therefore=20allowed=20in=20any=20= jsonpath=20expression.=0A---=0A=20doc/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|=20171=20++++++++=0A=20= src/backend/utils/adt/jsonpath.c=20=20=20=20=20=20=20=20=20=20=20=20=20|=20= 176=20++++++++-=0A=20src/backend/utils/adt/jsonpath_exec.c=20=20=20=20=20= =20=20=20|=20189=20+++++++++=0A=20src/backend/utils/adt/jsonpath_gram.y=20= =20=20=20=20=20=20=20|=20=2071=20+++-=0A=20= src/backend/utils/adt/jsonpath_scan.l=20=20=20=20=20=20=20=20|=20=2041=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=2022=20++=0A=20= src/test/regress/expected/jsonb_jsonpath.out=20|=20393=20= +++++++++++++++++++=0A=20src/test/regress/expected/jsonpath.out=20=20=20=20= =20=20=20|=20=2072=20++++=0A=20src/test/regress/sql/jsonb_jsonpath.sql=20= =20=20=20=20=20|=20108=20+++++=0A=20src/test/regress/sql/jsonpath.sql=20=20= =20=20=20=20=20=20=20=20=20=20|=20=2013=20+=0A=2010=20files=20changed,=20= 1252=20insertions(+),=204=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/func.sgml=20b/doc/src/sgml/func.sgml=0Aindex=20= c67688cbf5f..25d0d920dbf=20100644=0A---=20a/doc/src/sgml/func.sgml=0A+++=20= b/doc/src/sgml/func.sgml=0A@@=20-18627,6=20+18627,177=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= .=20ltrim()=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=20with=20spaces=20removed=20from=20the=20start=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=20= jsonb_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=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= 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=20= characters=20in=0A+=20=20=20=20=20=20=20=20= characters=20removed=20from=20the=20start=20= of=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=20jsonb_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()=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=20spaces=20removed=20from=20the=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('"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=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(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=20= characters=20in=0A+=20=20=20=20=20=20=20=20= characters=20removed=20from=20the=20end=20of=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=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()=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=20spaces=20removed=20from=20the=20start=20and=20end=20= of=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=20jsonb_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=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(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=20= characters=20in=0A+=20=20=20=20=20=20=20=20= characters=20removed=20from=20the=20start=20= and=20end=0A+=20=20=20=20=20=20=20=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('"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..646c7b460a3=20= 100644=0A---=20a/src/backend/utils/adt/jsonpath.c=0A+++=20= b/src/backend/utils/adt/jsonpath.c=0A@@=20-326,6=20+326,38=20@@=20= flattenJsonPathParseItem(StringInfo=20buf,=20int=20*result,=20struct=20= Node=20*escontext,=0A=20=09=09=09=09*(int32=20*)=20(buf->data=20+=20= right)=20=3D=20chld=20-=20pos;=0A=20=09=09=09}=0A=20=09=09=09break;=0A+=09= =09case=20jpiReplaceFunc:=0A+=09=09case=20jpiStrSplitPartFunc:=0A+=09=09= {=0A+=09=09=09{=0A+=09=09=09=09/*=0A+=09=09=09=09=20*=20First,=20reserve=20= place=20for=20left/right=20arg's=20positions,=20then=0A+=09=09=09=09=20*=20= record=20both=20args=20and=20sets=20actual=20position=20in=20reserved=0A= +=09=09=09=09=20*=20places.=0A+=09=09=09=09=20*/=0A+=09=09=09=09int32=09=09= arg0=20=3D=20reserveSpaceForItemPointer(buf);=0A+=09=09=09=09int32=09=09= arg1=20=3D=20reserveSpaceForItemPointer(buf);=0A+=0A+=09=09=09=09if=20= (!item->value.method_args.arg0)=0A+=09=09=09=09=09chld=20=3D=20pos;=0A+=09= =09=09=09else=20if=20(!flattenJsonPathParseItem(buf,=20&chld,=20= escontext,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20=20=20= item->value.method_args.arg0,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=20=20= =20nestingLevel=20+=20argNestingLevel,=0A+=09=09=09=09=09=09=09=09=09=09=09= =09=20=20=20insideArraySubscript))=0A+=09=09=09=09=09return=20false;=0A+=09= =09=09=09*(int32=20*)=20(buf->data=20+=20arg0)=20=3D=20chld=20-=20pos;=0A= +=0A+=09=09=09=09if=20(!item->value.method_args.arg1)=0A+=09=09=09=09=09= chld=20=3D=20pos;=0A+=09=09=09=09else=20if=20= (!flattenJsonPathParseItem(buf,=20&chld,=20escontext,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=20=20=20item->value.method_args.arg1,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=20=20=20nestingLevel=20+=20argNestingLevel,=0A+=09=09= =09=09=09=09=09=09=09=09=09=09=20=20=20insideArraySubscript))=0A+=09=09=09= =09=09return=20false;=0A+=09=09=09=09*(int32=20*)=20(buf->data=20+=20= arg1)=20=3D=20chld=20-=20pos;=0A+=09=09=09}=0A+=09=09}=0A+=09=09break;=0A= =20=09=09case=20jpiLikeRegex:=0A=20=09=09=09{=0A=20=09=09=09=09int32=09=09= offs;=0A@@=20-362,6=20+394,9=20@@=20flattenJsonPathParseItem(StringInfo=20= buf,=20int=20*result,=20struct=20Node=20*escontext,=0A=20=09=09case=20= jpiTimeTz:=0A=20=09=09case=20jpiTimestamp:=0A=20=09=09case=20= jpiTimestampTz:=0A+=09=09case=20jpiStrLtrimFunc:=0A+=09=09case=20= jpiStrRtrimFunc:=0A+=09=09case=20jpiStrBtrimFunc:=0A=20=09=09=09{=0A=20=09= =09=09=09int32=09=09arg=20=3D=20reserveSpaceForItemPointer(buf);=0A=20=0A= @@=20-457,6=20+492,9=20@@=20flattenJsonPathParseItem(StringInfo=20buf,=20= int=20*result,=20struct=20Node=20*escontext,=0A=20=09=09case=20= jpiInteger:=0A=20=09=09case=20jpiNumber:=0A=20=09=09case=20= jpiStringFunc:=0A+=09=09case=20jpiStrLowerFunc:=0A+=09=09case=20= jpiStrUpperFunc:=0A+=09=09case=20jpiStrInitcapFunc:=0A=20=09=09=09break;=0A= =20=09=09default:=0A=20=09=09=09elog(ERROR,=20"unrecognized=20jsonpath=20= item=20type:=20%d",=20item->type);=0A@@=20-831,6=20+869,72=20@@=20= printJsonPathItem(StringInfo=20buf,=20JsonPathItem=20*v,=20bool=20inKey,=0A= =20=09=09=09}=0A=20=09=09=09appendStringInfoChar(buf,=20')');=0A=20=09=09= =09break;=0A+=09=09case=20jpiReplaceFunc:=0A+=09=09=09= appendStringInfoString(buf,=20".replace(");=0A+=09=09=09if=20= (v->content.method_args.arg0)=0A+=09=09=09{=0A+=09=09=09=09jspGetArg0(v,=20= &elem);=0A+=09=09=09=09printJsonPathItem(buf,=20&elem,=20false,=20= false);=0A+=09=09=09}=0A+=09=09=09if=20(v->content.method_args.arg1)=0A+=09= =09=09{=0A+=09=09=09=09appendStringInfoChar(buf,=20',');=0A+=09=09=09=09= jspGetArg1(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=20jpiStrSplitPartFunc:=0A+=09=09=09= appendStringInfoString(buf,=20".split_part(");=0A+=09=09=09if=20= (v->content.method_args.arg0)=0A+=09=09=09{=0A+=09=09=09=09jspGetArg0(v,=20= &elem);=0A+=09=09=09=09printJsonPathItem(buf,=20&elem,=20false,=20= false);=0A+=09=09=09}=0A+=09=09=09if=20(v->content.method_args.arg1)=0A+=09= =09=09{=0A+=09=09=09=09appendStringInfoChar(buf,=20',');=0A+=09=09=09=09= jspGetArg1(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=20jpiStrLowerFunc:=0A+=09=09=09= appendStringInfoString(buf,=20".lower()");=0A+=09=09=09break;=0A+=09=09= case=20jpiStrUpperFunc:=0A+=09=09=09appendStringInfoString(buf,=20= ".upper()");=0A+=09=09=09break;=0A+=09=09case=20jpiStrInitcapFunc:=0A+=09= =09=09appendStringInfoString(buf,=20".initcap()");=0A+=09=09=09break;=0A= +=09=09case=20jpiStrLtrimFunc:=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=20jpiStrRtrimFunc:=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=20jpiStrBtrimFunc:=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+1010,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=20jpiReplaceFunc:=0A+=09=09=09return=20= "replace";=0A+=09=09case=20jpiStrLowerFunc:=0A+=09=09=09return=20= "lower";=0A+=09=09case=20jpiStrUpperFunc:=0A+=09=09=09return=20"upper";=0A= =20=09=09case=20jpiTime:=0A=20=09=09=09return=20"time";=0A=20=09=09case=20= jpiTimeTz:=0A@@=20-914,6=20+1024,16=20@@=20= jspOperationName(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=20jpiStrLtrimFunc:=0A+=09=09=09return=20= "ltrim";=0A+=09=09case=20jpiStrRtrimFunc:=0A+=09=09=09return=20"rtrim";=0A= +=09=09case=20jpiStrBtrimFunc:=0A+=09=09=09return=20"btrim";=0A+=09=09= case=20jpiStrInitcapFunc:=0A+=09=09=09return=20"initcap";=0A+=09=09case=20= jpiStrSplitPartFunc:=0A+=09=09=09return=20"split_part";=0A=20=09=09= default:=0A=20=09=09=09elog(ERROR,=20"unrecognized=20jsonpath=20item=20= type:=20%d",=20type);=0A=20=09=09=09return=20NULL;=0A@@=20-1016,6=20= +1136,9=20@@=20jspInitByBuffer(JsonPathItem=20*v,=20char=20*base,=20= int32=20pos)=0A=20=09=09case=20jpiInteger:=0A=20=09=09case=20jpiNumber:=0A= =20=09=09case=20jpiStringFunc:=0A+=09=09case=20jpiStrLowerFunc:=0A+=09=09= case=20jpiStrUpperFunc:=0A+=09=09case=20jpiStrInitcapFunc:=0A=20=09=09=09= break;=0A=20=09=09case=20jpiString:=0A=20=09=09case=20jpiKey:=0A@@=20= -1044,6=20+1167,11=20@@=20jspInitByBuffer(JsonPathItem=20*v,=20char=20= *base,=20int32=20pos)=0A=20=09=09=09read_int32(v->content.args.left,=20= base,=20pos);=0A=20=09=09=09read_int32(v->content.args.right,=20base,=20= pos);=0A=20=09=09=09break;=0A+=09=09case=20jpiReplaceFunc:=0A+=09=09case=20= jpiStrSplitPartFunc:=0A+=09=09=09read_int32(v->content.method_args.arg0,=20= base,=20pos);=0A+=09=09=09read_int32(v->content.method_args.arg1,=20= base,=20pos);=0A+=09=09break;=0A=20=09=09case=20jpiNot:=0A=20=09=09case=20= jpiIsUnknown:=0A=20=09=09case=20jpiExists:=0A@@=20-1055,6=20+1183,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=20jpiStrLtrimFunc:=0A+=09=09case=20= jpiStrRtrimFunc:=0A+=09=09case=20jpiStrBtrimFunc:=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+1221,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= jpiStrLtrimFunc=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrRtrimFunc=20||=0A+=09=09=20=20=20v->type=20=3D=3D=20= jpiStrBtrimFunc);=0A=20=0A=20=09jspInitByBuffer(a,=20v->base,=20= v->content.arg);=0A=20}=0A@@=20-1149,10=20+1283,18=20@@=20= jspGetNext(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20=09=09=09=20=20=20= v->type=20=3D=3D=20jpiInteger=20||=0A=20=09=09=09=20=20=20v->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=20= jpiReplaceFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrLowerFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrUpperFunc=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=20jpiTimeTz=20||=0A=20=09=09=09= =20=20=20v->type=20=3D=3D=20jpiTimestamp=20||=0A-=09=09=09=20=20=20= v->type=20=3D=3D=20jpiTimestampTz);=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiTimestampTz=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrLtrimFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrRtrimFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrBtrimFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrInitcapFunc=20||=0A+=09=09=09=20=20=20v->type=20=3D=3D=20= jpiStrSplitPartFunc);=0A=20=0A=20=09=09if=20(a)=0A=20=09=09=09= jspInitByBuffer(a,=20v->base,=20v->nextPos);=0A@@=20-1184,6=20+1326,24=20= @@=20jspGetLeftArg(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20=09= jspInitByBuffer(a,=20v->base,=20v->content.args.left);=0A=20}=0A=20=0A= +void=0A+jspGetArg0(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A+{=0A+=09= Assert(v->type=20=3D=3D=20jpiReplaceFunc=20||=0A+=09=09=09v->type=20=3D=3D= =20jpiStrSplitPartFunc);=0A+=0A+=09jspInitByBuffer(a,=20v->base,=20= v->content.method_args.arg0);=0A+}=0A+=0A+void=0A= +jspGetArg1(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A+{=0A+=09= Assert(v->type=20=3D=3D=20jpiReplaceFunc=20||=0A+=09=09=09v->type=20=3D=3D= =20jpiStrSplitPartFunc);=0A+=0A+=09jspInitByBuffer(a,=20v->base,=20= v->content.method_args.arg1);=0A+}=0A+=0A=20void=0A=20= jspGetRightArg(JsonPathItem=20*v,=20JsonPathItem=20*a)=0A=20{=0A@@=20= -1206,6=20+1366,7=20@@=20jspGetRightArg(JsonPathItem=20*v,=20= JsonPathItem=20*a)=0A=20=09jspInitByBuffer(a,=20v->base,=20= v->content.args.right);=0A=20}=0A=20=0A+=0A=20bool=0A=20= jspGetBool(JsonPathItem=20*v)=0A=20{=0A@@=20-1227,7=20+1388,8=20@@=20= jspGetString(JsonPathItem=20*v,=20int32=20*len)=0A=20{=0A=20=09= Assert(v->type=20=3D=3D=20jpiKey=20||=0A=20=09=09=20=20=20v->type=20=3D=3D= =20jpiString=20||=0A-=09=09=20=20=20v->type=20=3D=3D=20jpiVariable);=0A+=09= =09=20=20=20v->type=20=3D=3D=20jpiVariable=20||=0A+=09=09=20=20=20= v->type=20=3D=3D=20jpiStringFunc);=0A=20=0A=20=09if=20(len)=0A=20=09=09= *len=20=3D=20v->content.value.datalen;=0A@@=20-1501,6=20+1663,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=20jpiReplaceFunc:=0A+=09=09=09case=20jpiStrLowerFunc:=0A+=09=09=09= case=20jpiStrUpperFunc:=0A+=09=09=09case=20jpiStrLtrimFunc:=0A+=09=09=09= case=20jpiStrRtrimFunc:=0A+=09=09=09case=20jpiStrBtrimFunc:=0A+=09=09=09= case=20jpiStrInitcapFunc:=0A+=09=09=09case=20jpiStrSplitPartFunc:=0A=20=09= =09=09=09status=20=3D=20jpdsNonDateTime;=0A=20=09=09=09=09break;=0A=20=0A= diff=20--git=20a/src/backend/utils/adt/jsonpath_exec.c=20= b/src/backend/utils/adt/jsonpath_exec.c=0Aindex=20= dbab24737ef..51239121f18=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=20jpiStrLtrimFunc:=0A+=09=09case=20jpiStrLowerFunc:=0A+=09=09case=20= jpiStrUpperFunc:=0A+=09=09case=20jpiReplaceFunc:=0A+=09=09case=20= jpiStrRtrimFunc:=0A+=09=09case=20jpiStrBtrimFunc:=0A+=09=09case=20= jpiStrInitcapFunc:=0A+=09=09case=20jpiStrSplitPartFunc:=0A+=09=09{=0A+=09= =09=09if=20(unwrap=20&&=20JsonbType(jb)=20=3D=3D=20jbvArray)=0A+=09=09=09= =09return=20executeItemUnwrapTargetArray(cxt,=20jsp,=20jb,=20found,=20= false);=0A+=0A+=09=09=09return=20executeStringInternalMethod(cxt,=20jsp,=20= jb,=20found);=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,176=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=20jpiStrLowerFunc=20||=0A+=09=09=09jsp->type=20=3D=3D=20= jpiStrUpperFunc=20||=0A+=09=09=09jsp->type=20=3D=3D=20jpiReplaceFunc=20= ||=0A+=09=09=09jsp->type=20=3D=3D=20jpiStrLtrimFunc=20||=0A+=09=09=09= jsp->type=20=3D=3D=20jpiStrRtrimFunc=20||=0A+=09=09=09jsp->type=20=3D=3D=20= jpiStrBtrimFunc=20||=0A+=09=09=09jsp->type=20=3D=3D=20jpiStrInitcapFunc=20= ||=0A+=09=09=09jsp->type=20=3D=3D=20jpiStrSplitPartFunc);=0A+=09= JsonbValue=09jbvbuf;=0A+=09bool=09=09hasNext;=0A+=09JsonPathExecResult=20= res=20=3D=20jperNotFound;=0A+=09JsonPathItem=20elem;=0A+=09Datum=09=09= str;=20/*=20Datum=20representation=20for=20the=20current=20string=20= value.=20The=20first=20argument=20to=20internal=20functions=20*/=0A+=09= char=09=09*tmp=20=3D=20NULL;=0A+=09char=09=09*resStr=20=3D=20NULL;=0A+=0A= +=09if=20(!(jb=20=3D=20getScalar(jb,=20jbvString)))=0A+=09=09= RETURN_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()=20can=20= only=20be=20applied=20to=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=20jpiStrLtrimFunc:=0A+=09=09case=20jpiStrRtrimFunc:=0A+=09=09= case=20jpiStrBtrimFunc:=0A+=09=09{=0A+=09=09=09char=09=20=20=20= *characters_str;=0A+=09=09=09int=09=09=09characters_len;=0A+=09=09=09= PGFunction=09func=20=3D=20NULL;=0A+=0A+=09=09=09switch=20(jsp->type)=0A+=09= =09=09{=0A+=09=09=09=09case=20jpiStrLtrimFunc:=0A+=09=09=09=09=09func=20= =3D=20ltrim1;=0A+=09=09=09=09=09break;=0A+=09=09=09=09case=20= jpiStrRtrimFunc:=0A+=09=09=09=09=09func=20=3D=20rtrim1;=0A+=09=09=09=09=09= break;=0A+=09=09=09=09case=20jpiStrBtrimFunc:=0A+=09=09=09=09=09func=20=3D= =20btrim1;=0A+=09=09=09=09=09break;=0A+=09=09=09=09default:=20;=0A+=09=09= =09}=0A+=0A+=09=09=09if=20(jsp->content.arg)=0A+=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=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall2Coll(func,=0A+=09=09=09=09=09= DEFAULT_COLLATION_OID,=20str,=0A+=09=09=09=09=09CStringGetTextDatum("=20= ")));=0A+=09=09=09break;=0A+=09=09}=0A+=0A+=09=09case=20jpiStrLowerFunc:=0A= +=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(lower,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiStrUpperFunc:=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(upper,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiStrInitcapFunc:=0A+=09=09=09resStr=20=3D=20= TextDatumGetCString(DirectFunctionCall1Coll(initcap,=20= DEFAULT_COLLATION_OID,=20str));=0A+=09=09=09break;=0A+=09=09case=20= jpiReplaceFunc:=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= jspGetArg0(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=09jspGetArg1(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=20jpiStrSplitPartFunc:=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= =09jspGetArg0(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=09jspGetArg1(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= jpiStrLowerFunc:=0A+=09=09case=20jpiStrUpperFunc:=0A+=09=09case=20= jpiReplaceFunc:=0A+=09=09case=20jpiStrLtrimFunc:=0A+=09=09case=20= jpiStrRtrimFunc:=0A+=09=09case=20jpiStrBtrimFunc:=0A+=09=09case=20= jpiStrInitcapFunc:=0A+=09=09case=20jpiStrSplitPartFunc:=0A+=09=09=09= jb->type=20=3D=20jbvString;=0A+=09=09=09jb->val.string.val=20=3D=20= resStr;=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= 499745a8fef..c998c40cfbd=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_gram.y=0A+++=20= b/src/backend/utils/adt/jsonpath_gram.y=0A@@=20-43,6=20+43,9=20@@=20= static=20bool=20makeItemLikeRegex(JsonPathParseItem=20*expr,=0A=20=09=09=09= =09=09=09=09=20=20JsonPathString=20*flags,=0A=20=09=09=09=09=09=09=09=20=20= JsonPathParseItem=20**=20result,=0A=20=09=09=09=09=09=09=09=20=20struct=20= Node=20*escontext);=0A+static=20JsonPathParseItem=20= *makeItemReplaceFunc(JsonPathParseItem=20*arg0,=20JsonPathParseItem=20= *arg1);=0A+static=20JsonPathParseItem=20= *makeItemStrSplitPartFunc(JsonPathParseItem=20*arg0,=20JsonPathParseItem=20= *arg1);=0A+=0A=20=0A=20/*=0A=20=20*=20Bison=20doesn't=20allocate=20= anything=20that=20needs=20to=20live=20across=20parser=20calls,=0A@@=20= -86,6=20+89,8=20@@=20static=20bool=20makeItemLikeRegex(JsonPathParseItem=20= *expr,=0A=20%token=09=09=09DATETIME_P=0A=20%token=09=09=09= BIGINT_P=20BOOLEAN_P=20DATE_P=20DECIMAL_P=20INTEGER_P=20NUMBER_P=0A=20= %token=09=09=09STRINGFUNC_P=20TIME_P=20TIME_TZ_P=20TIMESTAMP_P=20= TIMESTAMP_TZ_P=0A+%token=09=09=09STR_REPLACEFUNC_P=20STR_LOWER_P=20= STR_UPPER_P=20STR_LTRIM_P=20STR_RTRIM_P=20STR_BTRIM_P=0A+=09=09=09=09=09= STR_INITCAP_P=20STR_SPLIT_PART_P=0A=20=0A=20%type=09=09result=0A=20= =0A@@=20-94,8=20+99,9=20@@=20static=20bool=20= makeItemLikeRegex(JsonPathParseItem=20*expr,=0A=20=09=09=09=09=09= index_elem=20starts_with_initial=20expr_or_predicate=0A=20=09=09=09=09=09= datetime_template=20opt_datetime_template=20csv_elem=0A=20=09=09=09=09=09= datetime_precision=20opt_datetime_precision=0A+=09=09=09=09=09= str_method_arg_elem=0A=20=0A-%type=09=09=09accessor_expr=20= csv_list=20opt_csv_list=0A+%type=09=09=09accessor_expr=20csv_list=20= opt_csv_list=20str_method_arg_list=0A=20=0A=20%type=09=09= index_list=0A=20=0A@@=20-278,6=20+284,32=20@@=20accessor_op:=0A=20=09=09= {=20$$=20=3D=20makeItemUnary(jpiTimestamp,=20$4);=20}=0A=20=09|=20'.'=20= TIMESTAMP_TZ_P=20'('=20opt_datetime_precision=20')'=0A=20=09=09{=20$$=20= =3D=20makeItemUnary(jpiTimestampTz,=20$4);=20}=0A+=09|=20'.'=20= STR_REPLACEFUNC_P=20'('=20str_method_arg_list=20')'=0A+=09=09{=0A+=09=09=09= if=20(list_length($4)=20=3D=3D=202)=0A+=09=09=09=09$$=20=3D=20= makeItemReplaceFunc(linitial($4),=20lsecond($4));=0A+=09=09=09else=0A+=09= =09=09=09ereturn(escontext,=20false,=0A+=09=09=09=09=09=09= (errcode(ERRCODE_SYNTAX_ERROR),=0A+=09=09=09=09=09=09=20errmsg("invalid=20= input=20syntax=20for=20type=20%s",=20"jsonpath"),=0A+=09=09=09=09=09=09=20= errdetail(".replace()=20accepts=20two=20arguments.")));=0A+=09=09}=0A+=09= |=20'.'=20STR_SPLIT_PART_P=20'('=20str_method_arg_list=20')'=0A+=09=09{=0A= +=09=09=09if=20(list_length($4)=20=3D=3D=202)=0A+=09=09=09=09$$=20=3D=20= makeItemStrSplitPartFunc(linitial($4),=20lsecond($4));=0A+=09=09=09else=0A= +=09=09=09=09ereturn(escontext,=20false,=0A+=09=09=09=09=09=09= (errcode(ERRCODE_SYNTAX_ERROR),=0A+=09=09=09=09=09=09=20errmsg("invalid=20= input=20syntax=20for=20type=20%s",=20"jsonpath"),=0A+=09=09=09=09=09=09=20= errdetail(".split_part()=20accepts=20two=20arguments.")));=0A+=09=09}=0A= +=09|=20'.'=20STR_LTRIM_P=20'('=20opt_datetime_template=20')'=0A+=09=09{=20= $$=20=3D=20makeItemUnary(jpiStrLtrimFunc,=20$4);=20}=0A+=09|=20'.'=20= STR_RTRIM_P=20'('=20opt_datetime_template=20')'=0A+=09=09{=20$$=20=3D=20= makeItemUnary(jpiStrRtrimFunc,=20$4);=20}=0A+=09|=20'.'=20STR_BTRIM_P=20= '('=20opt_datetime_template=20')'=0A+=09=09{=20$$=20=3D=20= makeItemUnary(jpiStrBtrimFunc,=20$4);=20}=0A=20=09;=0A=20=0A=20csv_elem:=0A= @@=20-317,6=20+349,15=20@@=20opt_datetime_template:=0A=20=09|=20/*=20= EMPTY=20*/=09=09=09=09=09{=20$$=20=3D=20NULL;=20}=0A=20=09;=0A=20=0A= +str_method_arg_elem:=0A+=09STRING_P=09=09=09=09=09=09{=20$$=20=3D=20= makeItemString(&$1);=20}=0A+=09|=20INT_P=09=09=09=09=09=09=09{=20$$=20=3D=20= makeItemNumeric(&$1);=20}=0A+=09;=0A+=0A+str_method_arg_list:=0A+=09= str_method_arg_elem=09=09=09=09=09=09=09{=20$$=20=3D=20list_make1($1);=20= }=0A+=09|=20str_method_arg_list=20','=20str_method_arg_elem=09{=20$$=20=3D= =20lappend($1,=20$3);=20}=0A+=09;=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+398,9=20= @@=20key_name:=0A=20=09|=20TIME_TZ_P=0A=20=09|=20TIMESTAMP_P=0A=20=09|=20= TIMESTAMP_TZ_P=0A+=09|=20STR_LTRIM_P=0A+=09|=20STR_RTRIM_P=0A+=09|=20= STR_BTRIM_P=0A=20=09;=0A=20=0A=20method:=0A@@=20-373,6=20+417,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= jpiStrLowerFunc;=20}=0A+=09|=20STR_UPPER_P=09=09=09=09=09{=20$$=20=3D=20= jpiStrUpperFunc;=20}=0A+=09|=20STR_INITCAP_P=09=09=09=09=09{=20$$=20=3D=20= jpiStrInitcapFunc;=20}=0A=20=09;=0A=20%%=0A=20=0A@@=20-472,6=20+519,28=20= @@=20makeItemBinary(JsonPathItemType=20type,=20JsonPathParseItem=20*la,=20= JsonPathParseItem=20*=0A=20=09return=20v;=0A=20}=0A=20=0A+static=20= JsonPathParseItem=20*=0A+makeItemReplaceFunc(JsonPathParseItem=20*arg0,=20= JsonPathParseItem=20*arg1)=0A+{=0A+=09JsonPathParseItem=20*v=20=3D=20= makeItemType(jpiReplaceFunc);=0A+=0A+=09v->value.method_args.arg0=20=3D=20= arg0;=0A+=09v->value.method_args.arg1=20=3D=20arg1;=0A+=0A+=09return=20= v;=0A+}=0A+=0A+static=20JsonPathParseItem=20*=0A= +makeItemStrSplitPartFunc(JsonPathParseItem=20*arg0,=20JsonPathParseItem=20= *arg1)=0A+{=0A+=09JsonPathParseItem=20*v=20=3D=20= makeItemType(jpiStrSplitPartFunc);=0A+=0A+=09v->value.method_args.arg0=20= =3D=20arg0;=0A+=09v->value.method_args.arg1=20=3D=20arg1;=0A+=0A+=09= return=20v;=0A+}=0A+=0A=20static=20JsonPathParseItem=20*=0A=20= makeItemUnary(JsonPathItemType=20type,=20JsonPathParseItem=20*a)=0A=20{=0A= diff=20--git=20a/src/backend/utils/adt/jsonpath_scan.l=20= b/src/backend/utils/adt/jsonpath_scan.l=0Aindex=20= c7aab83eeb4..f20e9e5f1d3=20100644=0A---=20= a/src/backend/utils/adt/jsonpath_scan.l=0A+++=20= b/src/backend/utils/adt/jsonpath_scan.l=0A@@=20-433,6=20+433,47=20@@=20= static=20const=20JsonPathKeyword=20keywords[]=20=3D=20{=0A=20=09{9,=20= false,=20TIMESTAMP_P,=20"timestamp"},=0A=20=09{10,=20false,=20= LIKE_REGEX_P,=20"like_regex"},=0A=20=09{12,=20false,=20TIMESTAMP_TZ_P,=20= "timestamp_tz"},=0A+=09{=202,=20false,=09IS_P,=09=09"is"},=0A+=09{=202,=20= false,=09TO_P,=09=09"to"},=0A+=09{=203,=20false,=09ABS_P,=09=09"abs"},=0A= +=09{=203,=20false,=09LAX_P,=09=09"lax"},=0A+=09{=204,=20false,=09= DATE_P,=09=09"date"},=0A+=09{=204,=20false,=09FLAG_P,=09=09"flag"},=0A+=09= {=204,=20false,=09LAST_P,=09=09"last"},=0A+=09{=204,=20true,=09NULL_P,=09= =09"null"},=0A+=09{=204,=20false,=09SIZE_P,=09=09"size"},=0A+=09{=204,=20= false,=09TIME_P,=09=09"time"},=0A+=09{=204,=20true,=09TRUE_P,=09=09= "true"},=0A+=09{=204,=20false,=09TYPE_P,=09=09"type"},=0A+=09{=204,=20= false,=09WITH_P,=09=09"with"},=0A+=09{=205,=20false,=20STR_BTRIM_P,=20= "btrim"},=0A+=09{=205,=20true,=09FALSE_P,=09"false"},=0A+=09{=205,=20= false,=09FLOOR_P,=09"floor"},=0A+=09{=205,=20false,=20STR_LOWER_P,=20= "lower"},=0A+=09{=205,=20false,=20STR_LTRIM_P,=20"ltrim"},=0A+=09{=205,=20= false,=20STR_RTRIM_P,=20"rtrim"},=0A+=09{=205,=20false,=20STR_UPPER_P,=20= "upper"},=0A+=09{=206,=20false,=09BIGINT_P,=09"bigint"},=0A+=09{=206,=20= false,=09DOUBLE_P,=09"double"},=0A+=09{=206,=20false,=09EXISTS_P,=09= "exists"},=0A+=09{=206,=20false,=09NUMBER_P,=09"number"},=0A+=09{=206,=20= false,=09STARTS_P,=09"starts"},=0A+=09{=206,=20false,=09STRICT_P,=09= "strict"},=0A+=09{=206,=20false,=09STRINGFUNC_P,=20"string"},=0A+=09{=20= 7,=20false,=09BOOLEAN_P,=09"boolean"},=0A+=09{=207,=20false,=09= CEILING_P,=09"ceiling"},=0A+=09{=207,=20false,=09DECIMAL_P,=09= "decimal"},=0A+=09{=207,=20false,=20STR_INITCAP_P,=20"initcap"},=0A+=09{=20= 7,=20false,=09INTEGER_P,=09"integer"},=0A+=09{=207,=20false,=20= STR_REPLACEFUNC_P,=20"replace"},=0A+=09{=207,=20false,=09TIME_TZ_P,=09= "time_tz"},=0A+=09{=207,=20false,=09UNKNOWN_P,=09"unknown"},=0A+=09{=20= 8,=20false,=09DATETIME_P,=09"datetime"},=0A+=09{=208,=20false,=09= KEYVALUE_P,=09"keyvalue"},=0A+=09{=209,=20false,=09TIMESTAMP_P,=20= "timestamp"},=0A+=09{=2010,false,=20LIKE_REGEX_P,=20"like_regex"},=0A+=09= {=2010,false,=20STR_SPLIT_PART_P,=20"split_part"},=0A+=09{=2012,false,=20= TIMESTAMP_TZ_P,=20"timestamp_tz"},=0A=20};=0A=20=0A=20/*=0Adiff=20--git=20= a/src/include/utils/jsonpath.h=20b/src/include/utils/jsonpath.h=0Aindex=20= 23a76d233e9..4c60f9d1826=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+=09jpiReplaceFunc,=09=09=09=09/*=20= .replace()=20item=20method=20*/=0A+=09jpiStrLowerFunc,=09=09=09/*=20= .lower()=20item=20method=20*/=0A+=09jpiStrUpperFunc,=09=09=09/*=20= .upper()=20item=20method=20*/=0A+=09jpiStrLtrimFunc,=09=09=09/*=20= .ltrim()=20item=20method=20*/=0A+=09jpiStrRtrimFunc,=09=09=09/*=20= .rtrim()=20item=20method=20*/=0A+=09jpiStrBtrimFunc,=09=09=09/*=20= .btrim()=20item=20method=20*/=0A+=09jpiStrInitcapFunc,=09=09=09/*=20= .initcap()=20item=20method=20*/=0A+=09jpiStrSplitPartFunc,=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= @@=20-188,6=20+196,12=20@@=20typedef=20struct=20JsonPathItem=0A=20=09=09=09= int32=09=09patternlen;=0A=20=09=09=09uint32=09=09flags;=0A=20=09=09}=09=09= =09like_regex;=0A+=0A+=09=09struct=0A+=09=09{=0A+=09=09=09int32=09=09= arg0;=0A+=09=09=09int32=09=09arg1;=0A+=09=09}=09=09=09method_args;=0A=20=09= }=09=09=09content;=0A=20}=20JsonPathItem;=0A=20=0A@@=20-199,6=20+213,8=20= @@=20extern=20bool=20jspGetNext(JsonPathItem=20*v,=20JsonPathItem=20*a);=0A= =20extern=20void=20jspGetArg(JsonPathItem=20*v,=20JsonPathItem=20*a);=0A=20= extern=20void=20jspGetLeftArg(JsonPathItem=20*v,=20JsonPathItem=20*a);=0A= =20extern=20void=20jspGetRightArg(JsonPathItem=20*v,=20JsonPathItem=20= *a);=0A+extern=20void=20jspGetArg0(JsonPathItem=20*v,=20JsonPathItem=20= *a);=0A+extern=20void=20jspGetArg1(JsonPathItem=20*v,=20JsonPathItem=20= *a);=0A=20extern=20Numeric=20jspGetNumeric(JsonPathItem=20*v);=0A=20= extern=20bool=20jspGetBool(JsonPathItem=20*v);=0A=20extern=20char=20= *jspGetString(JsonPathItem=20*v,=20int32=20*len);=0A@@=20-266,6=20= +282,12=20@@=20struct=20JsonPathParseItem=0A=20=09=09=09uint32=09=09len;=0A= =20=09=09=09char=09=20=20=20*val;=09/*=20could=20not=20be=20not=20= null-terminated=20*/=0A=20=09=09}=09=09=09string;=0A+=0A+=09=09struct=0A= +=09=09{=0A+=09=09=09JsonPathParseItem=20*arg0;=0A+=09=09=09= JsonPathParseItem=20*arg1;=0A+=09=09}=09=09=09method_args;=0A=20=09}=09=09= =09value;=0A=20};=0A=20=0Adiff=20--git=20= a/src/test/regress/expected/jsonb_jsonpath.out=20= b/src/test/regress/expected/jsonb_jsonpath.out=0Aindex=20= 4bcd4e91a29..2dbaec92129=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,399=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('"=20=20=20hello=20=20=20"',=20= '$.ltrim()');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= "hello=20=20=20"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('null',=20= '$.ltrim()');=0A+ERROR:=20=20jsonpath=20item=20method=20.ltrim()=20can=20= only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query('null',=20'$.ltrim()',=20silent=20=3D>=20true);=0A+=20= jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A+select=20= jsonb_path_query('[]',=20'$.ltrim()');=0A+=20jsonb_path_query=20=0A= +------------------=0A+(0=20rows)=0A+=0A+select=20jsonb_path_query('[]',=20= 'strict=20$.ltrim()');=0A+ERROR:=20=20jsonpath=20item=20method=20= .ltrim()=20can=20only=20be=20applied=20to=20a=20string=0A+select=20= jsonb_path_query('{}',=20'$.ltrim()');=0A+ERROR:=20=20jsonpath=20item=20= method=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('"=20=20=20hello=20=20=20"',=20= '$.rtrim("=20")');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= "=20=20=20hello"=0A+(1=20row)=0A+=0A+select=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.rtrim()');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"=20=20=20hello"=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.rtrim()');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"=20=20=20hello"=0A+(1=20= row)=0A+=0A+--=20test=20.btrim()=0A+select=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.btrim("=20")');=0A+=20jsonb_path_query=20=0A= +------------------=0A+=20"hello"=0A+(1=20row)=0A+=0A+select=20= jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.btrim("=20")');=0A+=20= jsonb_path_query=20=0A+------------------=0A+=20"hello"=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=20hello=20=20=20"',=20= '$.btrim()');=0A+=20jsonb_path_query=20=0A+------------------=0A+=20= "hello"=0A+(1=20row)=0A+=0A+--=20test=20.lower()=0A+select=20= jsonb_path_query('null',=20'$.lower()');=0A+ERROR:=20=20jsonpath=20item=20= method=20.lower()=20can=20only=20be=20applied=20to=20a=20string=0A= +select=20jsonb_path_query('null',=20'$.lower()',=20silent=20=3D>=20= true);=0A+=20jsonb_path_query=20=0A+------------------=0A+(0=20rows)=0A+=0A= +select=20jsonb_path_query('[]',=20'$.lower()');=0A+=20jsonb_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= +--=20Test=20string=20methods=20play=20nicely=20together=0A+select=20= jsonb_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..1b122e877d5=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,78=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=20select=20= '$.time()'::jsonpath;=0A=20=20jsonpath=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..e229e0a0d04=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,114=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=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.ltrim()');=0A+select=20jsonb_path_query('null',=20= '$.ltrim()');=0A+select=20jsonb_path_query('null',=20'$.ltrim()',=20= silent=20=3D>=20true);=0A+select=20jsonb_path_query('[]',=20= '$.ltrim()');=0A+select=20jsonb_path_query('[]',=20'strict=20= $.ltrim()');=0A+select=20jsonb_path_query('{}',=20'$.ltrim()');=0A= +select=20jsonb_path_query('[]',=20'strict=20$.ltrim()',=20silent=20=3D>=20= true);=0A+select=20jsonb_path_query('{}',=20'$.ltrim()',=20silent=20=3D>=20= true);=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=20jsonb_path_query('"=20=20=20= hello=20=20=20"',=20'$.rtrim("=20")');=0A+select=20jsonb_path_query('"=20= =20=20hello=20=20=20"',=20'$.rtrim()');=0A+select=20jsonb_path_query('"=20= =20=20hello=20=20=20"',=20'$.rtrim()');=0A+=0A+--=20test=20.btrim()=0A= +select=20jsonb_path_query('"=20=20=20hello=20=20=20"',=20'$.btrim("=20= ")');=0A+select=20jsonb_path_query('"=20=20=20hello=20=20=20"',=20= '$.btrim("=20")');=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+=0A= +--=20Test=20string=20methods=20play=20nicely=20together=0A+select=20= jsonb_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..8752ffcf08c=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,19=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=20select=20'$.time()'::jsonpath;=0A=20select=20= '$.time(6)'::jsonpath;=0A=20select=20'$.time_tz()'::jsonpath;=0A--=20=0A= 2.49.0=0A=0A= --Apple-Mail=_D3EB9222-2ABF-47BD-AF1A-0E48738E0328-- --Apple-Mail=_AC9A478A-EAD9-4435-8417-F90B602FABD5 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+KfmbOQis6ZycGGkt9idPjIgfEFAmgyQFgACgkQkt9idPjI gfHRkxAAjSL9gLUgblgpBqtey2gadzUQUSy7nH5dNfM8TtXVue10hNxiGHe2/4Ta rJvyH6N9U54D/Fwk7WVVOzYbJeVaoIFEjhpe8Dr1ITAd+/0S2TXXpA4R13PuEzm3 w7Vj+HwdXT4t3FLyS5XZS4jfqiFBTIQqxCZLhII1XM5aAUI5JL67oixDNn3s3Uks EJT8XeB399AhvXA5KQUx9xZnGvoArt+0x3nKdDOiCvq501leKKDCTwco+98L6df6 JhIetMSdqMJ91RCh7t0b8Krtfchui9Cx3AFrMmyyzlLlF1ivA3sbS2cwWJ/w0153 IjqBoyIXOvRYcwxbGBTlLwrS5V/0QIGbPMvCfEnoCe0e/QKHa0mqeqWJVCUrAK9S roegikfiKskV1KQfSp2rry6DR6TM9swGGK+z9an36TghG8oijqfps1OZU85iBOtU z6klxcUClgbbAL11bsKax4/ctDq/JQL2AU+vpM6Sp1jLbsriTwJWylcj+EwwM8jJ NXum6DP4XU/7PLzGHoAktMSapwz0JZJHgpt/yPE5+bdiRWDGvymwACbDP6XaA3nl Fz4kui0tLGqBsaLtpJJv9kW8iMSyXwHJt6gFyM99X3i+2a+ldWgXkeoG9DsqIsIs +HMeDTUAICtACaSYzQDyPTmtT2KtBkSAKX2SA1swtyAEl9KraMI= =cbSx -----END PGP SIGNATURE----- --Apple-Mail=_AC9A478A-EAD9-4435-8417-F90B602FABD5--