| From: | Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com> |
|---|---|
| To: | Jim Jones <jim(dot)jones(at)uni-muenster(dot)de> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: POC: PLpgSQL FOREACH IN JSON ARRAY |
| Date: | 2026-03-03 13:45:07 |
| Message-ID: | CAFj8pRDi-7S7cWgtsvdHm8vvhvd8xHQ7tdXymBfBQQgpYangPQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi
út 3. 3. 2026 v 8:43 odesílatel Jim Jones <jim(dot)jones(at)uni-muenster(dot)de>
napsal:
> Hi Pavel,
>
> I quickly tested the patch, and I also could observe a ~3x performance
> improvement!
>
> A few first impressions:
>
> ## in exec_stmt_foreach_json_a the boolean variable found is declared as
> false, bit its value is never set to true until exec_set_found() is called:
>
> /*
> * Set the FOUND variable to indicate the result of executing the loop
> * (namely, whether we looped one or more times). This must be set here so
> * that it does not interfere with the value of the FOUND variable inside
> * the loop processing itself.
> */
> exec_set_found(estate, found);
>
>
> Test:
>
>
> DO $$
> DECLARE
> x int;
> BEGIN
> FOREACH x IN JSON ARRAY '[1,2,3]'
> LOOP
> RAISE NOTICE 'x: %', x;
> END LOOP;
>
> IF FOUND THEN
> RAISE NOTICE 'FOUND is true';
> ELSE
> RAISE NOTICE 'FOUND is false';
> END IF;
> END;
> $$;
> NOTICE: x: 1
> NOTICE: x: 2
> NOTICE: x: 3
> NOTICE: FOUND is false
>
>
fixed + regress tests
>
> ## Suggestion in the plpgsql.sgml
>
> The <literal>FOREACH</literal> loop is much like a
> <literal>FOREACH</literal> loop,
>
> to
>
> "much like a regular <literal>FOREACH</literal> loop over arrays"
>
done
>
> ## Typo in comment
>
> /*
> * We cannot to use fieldnames for tupdescentry, because
> * these names can be suffixed by name of row variable.
> ...
>
> We cannot to use > We cannot use
>
fixed
>
>
> ## Nit pick
>
> These error messages are not wrong, but IMO a errhint/errdetail could
> add some value here:
>
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> errmsg("cannot extract elements from a scalar")));
>
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> errmsg("cannot extract elements from an object")));
>
> Something like this perhaps?
>
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> errmsg("cannot extract elements from a scalar"),
> errhint("FOREACH IN JSON ARRAY requires an array value.")));
>
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> errmsg("FOREACH expression must evaluate to a JSON array"),
> errdetail("Cannot iterate over a scalar value.")));
>
>
I rewrote it to
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("FOREACH expression must evaluate to a JSON array"),
errhint("Cannot iterate over a scalar value.")));
else if (JB_ROOT_IS_OBJECT(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("FOREACH expression must evaluate to a JSON array"),
errdetail("Cannot iterate over a object value.")));
Assert(JB_ROOT_IS_ARRAY(jb));
+ regress tests
>
> Thanks for the patch!
>
Thank you for check
Regards
Pavel
>
> Best, Jim
>
| Attachment | Content-Type | Size |
|---|---|---|
| v20260303-4-0001-FOREACH-scalar-IN-JSON-ARRAY.patch | text/x-patch | 30.7 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Anthonin Bonnefoy | 2026-03-03 14:13:37 | Re: Don't keep closed WAL segment in page cache after replay |
| Previous Message | Zhijie Hou (Fujitsu) | 2026-03-03 12:24:33 | RE: Fix slotsync worker busy loop causing repeated log messages |