Skip to content

Refuse an array shape pljs cannot represent, instead of changing the value - #43

Open
sfc-gh-okalaci wants to merge 1 commit into
up/11-jsonb-array-returnfrom
up/12-array-shape
Open

Refuse an array shape pljs cannot represent, instead of changing the value#43
sfc-gh-okalaci wants to merge 1 commit into
up/11-jsonb-array-returnfrom
up/12-array-shape

Conversation

@sfc-gh-okalaci

Copy link
Copy Markdown
Collaborator

Stacked on #42.

pljs represents a SQL array as a flat JavaScript array. Both directions handled an array
that does not fit that model by quietly producing something else.

Readingdeconstruct_array() flattens, so a multidimensional array arrived in
JavaScript one-dimensional. {{1,2},{3,4}} became [1,2,3,4], and writing it back gave a
different value than was read.

Writing — a nested JavaScript array aimed at a scalar element type went into the array
conversion anyway, because the dispatch condition asked only whether the target was
json/jsonb, which is false for every scalar. The element loop then converted each inner
array
to the element type:

CREATE FUNCTION f() RETURNS int[] AS $$ return [[1,2],[3,4]]; $$ LANGUAGE pljs;
SELECT f();
 {-1629977232,-1629977184}

Those are the inner arrays' ArrayType pointers reinterpreted as int4. No error, and
nothing about the output says it isn't data.

Reading now raises ERRCODE_FEATURE_NOT_SUPPORTED for a multidimensional array; writing
raises ERRCODE_DATATYPE_MISMATCH naming the target type. One-dimensional arrays are
unaffected in both directions, and a nested array remains valid for json/jsonb — the
targets that can actually represent one.

Test plan

sql/pg_array_shape.sql covers both directions, both error paths, a scalar target
(int, text), that one-dimensional arrays still round-trip, and that nested arrays
still work for jsonb and jsonb[].

It discriminates: reverted, the read silently returns [1,2,3,4] and the write returns
{-1629977232,-1629977184}. Full suite green on PostgreSQL 17 (55 tests); builds clean on
16, 18 and 19beta3.

…value

pljs represents a SQL array as a flat JavaScript array. Both directions handled an
array that does not fit that model by producing something else, quietly.

Reading: deconstruct_array() flattens, so a multidimensional array arrived in
JavaScript one-dimensional -- {{1,2},{3,4}} as [1,2,3,4] -- and writing it back
gave a different value than was read.

Writing: a nested JavaScript array aimed at a scalar element type went into the
array conversion anyway, because the dispatch condition asked only whether the
target was json/jsonb, which is false for every scalar. The element loop then
converted each inner array to the element type:

    CREATE FUNCTION f() RETURNS int[] AS $$ return [[1,2],[3,4]]; $$ LANGUAGE pljs;
    SELECT f();
     {-1629977232,-1629977184}

Those are the inner arrays' ArrayType pointers reinterpreted as int4. Not an
error, and not distinguishable from data by looking at it.

Reading now raises ERRCODE_FEATURE_NOT_SUPPORTED for a multidimensional array, and
writing raises ERRCODE_DATATYPE_MISMATCH naming the target type when a JavaScript
array is aimed at something that cannot hold one. One-dimensional arrays are
unaffected, and a nested array is still valid for json and jsonb, which are the
targets that can represent it.

Adds sql/pg_array_shape.sql, covering both directions, both error paths, that
one-dimensional arrays still round-trip, and that nested arrays still work for
jsonb and jsonb[].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant