Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions expected/function.out
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,52 @@ SELECT * FROM set_of_unnamed_records() AS x(a int, b int);
1 | 2
(1 row)

-- RETURNS TABLE with array of objects (composite SRF array return)
CREATE FUNCTION returns_table_array() RETURNS TABLE(id int, name text) AS
$$
return [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
$$
LANGUAGE pljs;
SELECT * FROM returns_table_array();
id | name
----+---------
1 | Alice
2 | Bob
3 | Charlie
(3 rows)

-- RETURNS TABLE with single object
CREATE FUNCTION returns_table_single() RETURNS TABLE(x int, y text) AS
$$
return { x: 42, y: 'hello' };
$$
LANGUAGE pljs;
SELECT * FROM returns_table_single();
x | y
----+-------
42 | hello
(1 row)

-- RETURNS SETOF composite with array return
CREATE FUNCTION set_of_rec_array() RETURNS SETOF rec AS
$$
return [
{ i: 10, t: 'ten' },
{ i: 20, t: 'twenty' }
];
$$
LANGUAGE pljs;
SELECT * FROM set_of_rec_array();
i | t
----+--------
10 | ten
20 | twenty
(2 rows)

-- execute with an array of arguments
CREATE FUNCTION execute_with_array() RETURNS VOID AS
$$
Expand Down
31 changes: 31 additions & 0 deletions sql/function.sql
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,37 @@ SELECT * FROM set_of_unnamed_records() AS x(a int, c int);
-- name counts and values match
SELECT * FROM set_of_unnamed_records() AS x(a int, b int);

-- RETURNS TABLE with array of objects (composite SRF array return)
CREATE FUNCTION returns_table_array() RETURNS TABLE(id int, name text) AS
$$
return [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
$$
LANGUAGE pljs;
SELECT * FROM returns_table_array();

-- RETURNS TABLE with single object
CREATE FUNCTION returns_table_single() RETURNS TABLE(x int, y text) AS
$$
return { x: 42, y: 'hello' };
$$
LANGUAGE pljs;
SELECT * FROM returns_table_single();

-- RETURNS SETOF composite with array return
CREATE FUNCTION set_of_rec_array() RETURNS SETOF rec AS
$$
return [
{ i: 10, t: 'ten' },
{ i: 20, t: 'twenty' }
];
$$
LANGUAGE pljs;
SELECT * FROM set_of_rec_array();

-- execute with an array of arguments
CREATE FUNCTION execute_with_array() RETURNS VOID AS
$$
Expand Down
42 changes: 35 additions & 7 deletions src/pljs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,15 +1183,42 @@ static Datum call_srf_function(FunctionCallInfo fcinfo, pljs_context *context,
bool is_null = false;

if (state->is_composite) {
bool *nulls = (bool *)palloc0(sizeof(bool) * state->tuple_desc->natts);
// Handle composite (RETURNS TABLE / RETURNS SETOF record):
// JS can return a single object or an array of objects.
if (JS_IsArray(context->ctx, ret)) {
// Array of objects: iterate and put each as a row.
for (uint32_t i = 0; i < pljs_js_array_length(ret, context->ctx);
i++) {
JSValue val = JS_GetPropertyUint32(context->ctx, ret, i);
bool *nulls =
(bool *)palloc0(sizeof(bool) * state->tuple_desc->natts);

Datum *values = pljs_jsvalue_to_datums(
NULL, val, &nulls, state->tuple_desc, context->ctx);

if (values != NULL) {
tuplestore_putvalues(state->tuple_store_state,
state->tuple_desc, values, nulls);
pfree(values);
}
pfree(nulls);
JS_FreeValue(context->ctx, val);
}
} else {
// Single object: put as one row.
bool *nulls =
(bool *)palloc0(sizeof(bool) * state->tuple_desc->natts);

Datum *values = pljs_jsvalue_to_datums(NULL, argv[0], &nulls,
state->tuple_desc, context->ctx);
tuplestore_putvalues(state->tuple_store_state, state->tuple_desc,
values, nulls);
Datum *values = pljs_jsvalue_to_datums(
NULL, ret, &nulls, state->tuple_desc, context->ctx);

pfree(nulls);
pfree(values);
if (values != NULL) {
tuplestore_putvalues(state->tuple_store_state,
state->tuple_desc, values, nulls);
pfree(values);
}
pfree(nulls);
}
} else {
if (JS_IsArray(context->ctx, ret)) {
for (uint32_t i = 0; i < pljs_js_array_length(ret, context->ctx);
Expand All @@ -1203,6 +1230,7 @@ static Datum call_srf_function(FunctionCallInfo fcinfo, pljs_context *context,
context->ctx, NULL);
tuplestore_putvalues(state->tuple_store_state, state->tuple_desc,
&result, &is_null);
JS_FreeValue(context->ctx, val);
}
} else {
if (!JS_IsUndefined(ret)) {
Expand Down