Skip to content

Commit

Permalink
Adds BigInt support and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JerrySievert committed Nov 12, 2024
1 parent 4a618be commit 84f5b41
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Current Release Version: `0.8`
- [ ] startup functions
- [x] procedures/transactions
- [x] find function
- [ ] `BigInt`
- [x] `BigInt`
- [ ] full PLV8 parity

# 1.1
Expand Down
39 changes: 39 additions & 0 deletions expected/types.out
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,42 @@ SELECT return_array();
{foo,bar}
(1 row)

-- BigInt
-- a BigInt that will work on any value
CREATE OR REPLACE FUNCTION bigint_working(val BIGINT)
RETURNS BIGINT AS $$
return val - 1n;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_working(9223372036854775807);
bigint_working
---------------------
9223372036854775806
(1 row)

SELECT bigint_working(32);
bigint_working
----------------
31
(1 row)

-- a BigInt that will fail on any value
CREATE OR REPLACE FUNCTION bigint_failing(val BIGINT)
RETURNS BIGINT AS $$
return val - 1;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_failing(9223372036854775807);
ERROR: execution error
DETAIL: TypeError: cannot convert to bigint
at bigint_failing (<function>:3)

-- BigInt as Numeric
CREATE OR REPLACE FUNCTION bigint_numeric(a INT8, b INT8)
RETURNS NUMERIC AS $$
return a ** b;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_numeric(20, 200);
bigint_numeric
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
160693804425899027554196209234116260252220299378279283530137600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(1 row)

24 changes: 24 additions & 0 deletions sql/types.sql
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,27 @@ SELECT text_to_int4('abc');
-- ARRAYS
CREATE FUNCTION return_array() RETURNS TEXT[] AS $$ return ["foo", "bar"]; $$LANGUAGE pljs;
SELECT return_array();

-- BigInt
-- a BigInt that will work on any value
CREATE OR REPLACE FUNCTION bigint_working(val BIGINT)
RETURNS BIGINT AS $$
return val - 1n;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_working(9223372036854775807);

SELECT bigint_working(32);

-- a BigInt that will fail on any value
CREATE OR REPLACE FUNCTION bigint_failing(val BIGINT)
RETURNS BIGINT AS $$
return val - 1;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_failing(9223372036854775807);

-- BigInt as Numeric
CREATE OR REPLACE FUNCTION bigint_numeric(a INT8, b INT8)
RETURNS NUMERIC AS $$
return a ** b;
$$ LANGUAGE pljs STABLE STRICT;
SELECT bigint_numeric(20, 200);
47 changes: 40 additions & 7 deletions src/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ JSValue pljs_datum_to_jsvalue(Datum arg, Oid argtype, JSContext *ctx) {
break;

case INT8OID:
return_result = JS_NewInt64(ctx, DatumGetInt64(arg));
return_result = JS_NewBigInt64(ctx, DatumGetInt64(arg));
break;

case FLOAT4OID:
Expand Down Expand Up @@ -464,23 +464,43 @@ Datum pljs_jsvalue_to_datum(JSValue val, Oid rettype, JSContext *ctx,

case INT2OID: {
int32_t in;
JS_ToInt32(ctx, &in, val);
if (JS_IsBigInt(ctx, val)) {
int64_t big_in;

JS_ToBigInt64(ctx, &big_in, val);

in = (int32_t)big_in;
} else {
JS_ToInt32(ctx, &in, val);
}

PG_RETURN_INT16((int16_t)in);
break;
}

case INT4OID: {
int32_t in;
JS_ToInt32(ctx, &in, val);
if (JS_IsBigInt(ctx, val)) {
int64_t big_in;

JS_ToBigInt64(ctx, &big_in, val);

in = (int32_t)big_in;
} else {
JS_ToInt32(ctx, &in, val);
}

PG_RETURN_INT32(in);
break;
}

case INT8OID: {
int64_t in;
JS_ToInt64(ctx, &in, val);
if (JS_IsBigInt(ctx, val)) {
JS_ToBigInt64(ctx, &in, val);
} else {
JS_ToInt64(ctx, &in, val);
}

PG_RETURN_INT64(in);
break;
Expand All @@ -503,10 +523,23 @@ Datum pljs_jsvalue_to_datum(JSValue val, Oid rettype, JSContext *ctx,
}

case NUMERICOID: {
double in;
JS_ToFloat64(ctx, &in, val);
if (JS_IsBigInt(ctx, val)) {
// Convert the value to a string then convert it to NUMERIC
JSValue str = JS_ToString(ctx, val);

const char *in = JS_ToCString(ctx, str);

return DirectFunctionCall3(numeric_in, (Datum)in,
ObjectIdGetDatum(InvalidOid),
Int32GetDatum((int32)-1));

return DirectFunctionCall1(float8_numeric, Float8GetDatum((float8)in));
} else {
double in;

JS_ToFloat64(ctx, &in, val);

return DirectFunctionCall1(float8_numeric, Float8GetDatum((float8)in));
}
break;
}

Expand Down

0 comments on commit 84f5b41

Please sign in to comment.