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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ regression.out
.depend
docs/html
docs/latex
docs/xml
pljs--*.sql
compile_commands.json
6 changes: 3 additions & 3 deletions META.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "pljs",
"abstract": "PLJS trusted procedural language",
"description": "PLJS is a QuickJS-based Javascript Language Extension for \"modern\" PostgreSQL. It is compact, lightweight, and decently fast.",
"version": "1.0.3",
"version": "1.0.4",
"maintainer": ["Jerry Sievert <code@legitimatesounding.com>"],
"license": {
"PostgreSQL": "http://www.postgresql.org/about/licence"
Expand All @@ -17,9 +17,9 @@
},
"provides": {
"pljs": {
"file": "pljs--1.0.3.sql",
"file": "pljs--1.0.4.sql",
"docfile": "README.md",
"version": "1.0.3",
"version": "1.0.4",
"abstract": "PLJS trusted procedural language"
}
},
Expand Down
5 changes: 1 addition & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: lintcheck format cleansql docs clean test all

PLJS_VERSION = 1.0.3
PLJS_VERSION = 1.0.4

PG_CONFIG ?= pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
Expand All @@ -21,9 +21,6 @@ SHLIB_LINK = -Ldeps/quickjs -lquickjs
ifeq ($(DEBUG), 1)
PG_CFLAGS += -g
SHLIB_LINK += -g
else
PG_CFLAGS += -O3
SHLIB_LINK += -O3
endif

ifeq ($(DEBUG_MEMORY), 1)
Expand Down
14 changes: 14 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,17 @@ Released _August 20, 2025_.
Released _August 20, 2025_.

- PGXN release went out with an incorrect control file

### 1.0.4

Released _January 11, 2026_.

- Up memory default limit to 512MB
- Remove unnecessary include from modules.c
- Remove extra running of GC after each execution
- Better handling of SRF's, including freeing resources
- Increased test timeouts to accommodate slower CI machines
- Alter memory limit minimum to 64MB to facilitate testing
- Alter some tests for s390x testing
- Clean up parameter orders for function calls
- Fixed potential memory leak in `pljs_jsvalue_to_datums`
14 changes: 3 additions & 11 deletions expected/array_spread.out
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
-- ten seconds should be enough to show this doesn't destroy memory
set statement_timeout = '5s';
set pljs.memory_limit = '256';
do $$ Object.prototype [Symbol.iterator] = function() { return { next:() => this } };
[...({})];
$$ language pljs;
ERROR: execution error
DETAIL: InternalError: out of memory
at <anonymous> (<function>:2:1)
at <eval> (<function>:3:3)

-- we set the timeout to as high as we can, since some platforms may have slower CI machines
set pljs.statement_timeout = '65536s';
set pljs.memory_limit = '64';
do $$ Object.prototype [Symbol.iterator] = function() { return { next:() => this } };
[...({})];
$$ language pljs;
Expand Down
16 changes: 8 additions & 8 deletions expected/bytea.out
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ AS $$

return arr;
$$;
SELECT filled_int16array_bytea() = '\x0100020003000400'::bytea;
?column?
----------
t
SELECT filled_int16array_bytea();
filled_int16array_bytea
-------------------------
\x0100020003000400
(1 row)

CREATE FUNCTION filled_int32array_bytea() RETURNS bytea
Expand All @@ -81,10 +81,10 @@ AS $$

return arr;
$$;
SELECT filled_int32array_bytea() = '\x01000000020000000300000004000000'::bytea;
?column?
----------
t
SELECT filled_int32array_bytea();
filled_int32array_bytea
------------------------------------
\x01000000020000000300000004000000
(1 row)

DO $$
Expand Down
101 changes: 101 additions & 0 deletions expected/bytea_1.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
CREATE FUNCTION valid_arraybuffer_bytea(len integer) RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
arr = new ArrayBuffer(len);
for(i = 0; i < len; i++) {
arr[i] = i;
}

return arr;
$$;
SELECT length(valid_arraybuffer_bytea(20));
length
--------
20
(1 row)

CREATE FUNCTION valid_int8array_bytea(len integer) RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
return new Int8Array(len);
$$;
SELECT length(valid_int8array_bytea(20));
length
--------
20
(1 row)

CREATE FUNCTION valid_int16array_bytea(len integer) RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
return new Int16Array(len);
$$;
SELECT length(valid_int16array_bytea(20));
length
--------
40
(1 row)

CREATE FUNCTION filled_int8array_bytea() RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
arr = new Int8Array(4);
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;

return arr;
$$;
SELECT filled_int8array_bytea() = '\x01020304'::bytea;
?column?
----------
t
(1 row)

CREATE FUNCTION filled_int16array_bytea() RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
arr = new Int16Array(4);
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;

return arr;
$$;
SELECT filled_int16array_bytea();
filled_int16array_bytea
-------------------------
\x0001000200030004
(1 row)

CREATE FUNCTION filled_int32array_bytea() RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
AS $$
arr = new Int32Array(4);
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;

return arr;
$$;
SELECT filled_int32array_bytea();
filled_int32array_bytea
------------------------------------
\x00000001000000020000000300000004
(1 row)

DO $$
const test = 'string test';
const res = pljs.execute(`select $1::bytea`, [test]);
const result = res[0].bytea;

if (result === test) {
pljs.elog(INFO, 'OK');
} else {
pljs.elog(WARNING, 'FAIL');
}
$$ language pljs;
INFO: OK
1 change: 1 addition & 0 deletions expected/memory_limits.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
set pljs.memory_limit = 64;
do $$
const limit = pljs.execute(`select setting from pg_settings where name = $1`, ['pljs.memory_limit'])[0].setting;
const a = new ArrayBuffer(limit*1024*1024/2);
Expand Down
2 changes: 1 addition & 1 deletion pljs.control
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
comment = 'PL/JS trusted procedural language'

default_version = '1.0.3'
default_version = '1.0.4'
module_pathname = '$libdir/pljs'
relocatable = false
schema = pg_catalog
Expand Down
9 changes: 3 additions & 6 deletions sql/array_spread.sql
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
-- ten seconds should be enough to show this doesn't destroy memory
set statement_timeout = '5s';
set pljs.memory_limit = '256';
-- we set the timeout to as high as we can, since some platforms may have slower CI machines
set pljs.statement_timeout = '65536s';
set pljs.memory_limit = '64';

do $$ Object.prototype [Symbol.iterator] = function() { return { next:() => this } };
[...({})];
$$ language pljs;

do $$ Object.prototype [Symbol.iterator] = function() { return { next:() => this } };
[...({})];
$$ language pljs;
4 changes: 2 additions & 2 deletions sql/bytea.sql
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ AS $$
return arr;
$$;

SELECT filled_int16array_bytea() = '\x0100020003000400'::bytea;
SELECT filled_int16array_bytea();

CREATE FUNCTION filled_int32array_bytea() RETURNS bytea
LANGUAGE pljs IMMUTABLE STRICT
Expand All @@ -67,7 +67,7 @@ AS $$
return arr;
$$;

SELECT filled_int32array_bytea() = '\x01000000020000000300000004000000'::bytea;
SELECT filled_int32array_bytea();

DO $$
const test = 'string test';
Expand Down
2 changes: 2 additions & 0 deletions sql/memory_limits.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
set pljs.memory_limit = 64;

do $$
const limit = pljs.execute(`select setting from pg_settings where name = $1`, ['pljs.memory_limit'])[0].setting;
const a = new ArrayBuffer(limit*1024*1024/2);
Expand Down
42 changes: 24 additions & 18 deletions src/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,8 @@ static int pljs_execute_params(const char *sql, JSValue params,
JSValue param = JS_GetPropertyUint32(ctx, params, i);
bool is_null;

values[i] = pljs_jsvalue_to_datum(param, parstate.param_types[i], ctx, NULL,
&is_null);
values[i] = pljs_jsvalue_to_datum(parstate.param_types[i], param, &is_null,
ctx, NULL);

JS_FreeValue(ctx, param);
}
Expand Down Expand Up @@ -441,8 +441,8 @@ static JSValue pljs_plan_execute(JSContext *ctx, JSValueConst this_val,
bool is_null;

values[i] = pljs_jsvalue_to_datum(
param, plan->parstate ? plan->parstate->param_types[i] : 0, ctx, NULL,
&is_null);
plan->parstate ? plan->parstate->param_types[i] : 0, param, &is_null,
ctx, NULL);

JS_FreeValue(ctx, param);
}
Expand Down Expand Up @@ -739,8 +739,8 @@ static JSValue pljs_plan_cursor(JSContext *ctx, JSValueConst this_val, int argc,
bool is_null;

values[i] = pljs_jsvalue_to_datum(
param, plan->parstate ? plan->parstate->param_types[i] : 0, ctx, NULL,
&is_null);
plan->parstate ? plan->parstate->param_types[i] : 0, param, &is_null,
ctx, NULL);
}

PG_TRY();
Expand Down Expand Up @@ -1069,14 +1069,20 @@ static JSValue pljs_return_next(JSContext *ctx, JSValueConst this_val, int argc,
return js_throw("field name / property name mismatch", ctx);
}

bool is_null = false;
pljs_jsvalue_to_record(argv[0], NULL, ctx, &is_null, retstate->tuple_desc,
retstate->tuple_store_state);
bool *nulls = (bool *)palloc0(sizeof(bool) * retstate->tuple_desc->natts);
Datum *values = pljs_jsvalue_to_datums(NULL, argv[0], &nulls,
retstate->tuple_desc, ctx);

tuplestore_putvalues(retstate->tuple_store_state, retstate->tuple_desc,
values, nulls);

pfree(nulls);
pfree(values);
} else {
bool is_null = false;
Datum result = pljs_jsvalue_to_datum(
argv[0], TupleDescAttr(retstate->tuple_desc, 0)->atttypid, ctx, NULL,
&is_null);
Datum result =
pljs_jsvalue_to_datum(TupleDescAttr(retstate->tuple_desc, 0)->atttypid,
argv[0], &is_null, ctx, NULL);
tuplestore_putvalues(retstate->tuple_store_state, retstate->tuple_desc,
&result, &is_null);
}
Expand Down Expand Up @@ -1372,8 +1378,8 @@ static JSValue pljs_window_get_func_arg_in_partition(JSContext *ctx,
return JS_UNDEFINED;
}

return pljs_datum_to_jsvalue(res, storage->function->argtypes[argno], ctx,
false);
return pljs_datum_to_jsvalue(storage->function->argtypes[argno], res, isnull,
true, ctx);
}

static JSValue pljs_window_get_func_arg_in_frame(JSContext *ctx,
Expand Down Expand Up @@ -1418,8 +1424,8 @@ static JSValue pljs_window_get_func_arg_in_frame(JSContext *ctx,
if (isout) {
return JS_UNDEFINED;
}
return pljs_datum_to_jsvalue(res, storage->function->argtypes[argno], ctx,
false);
return pljs_datum_to_jsvalue(storage->function->argtypes[argno], res, isnull,
true, ctx);
}

static JSValue pljs_window_get_func_arg_current(JSContext *ctx,
Expand Down Expand Up @@ -1450,8 +1456,8 @@ static JSValue pljs_window_get_func_arg_current(JSContext *ctx,
}
PG_END_TRY();

return pljs_datum_to_jsvalue(res, storage->function->argtypes[argno], ctx,
false);
return pljs_datum_to_jsvalue(storage->function->argtypes[argno], res, isnull,
true, ctx);
}

static JSValue pljs_window_object_to_string(JSContext *ctx,
Expand Down
Loading