Commit 93b6e03a authored by Tom Lane's avatar Tom Lane

Fix jsonb_plperl to convert Perl UV values correctly.

Values greater than IV_MAX were incorrectly converted to SQL,
for instance ~0 would become -1 rather than 18446744073709551615
(on a 64-bit machine).

Dagfinn Ilmari Mannsåker, adjusted a bit by me

Discussion: https://postgr.es/m/d8jtvskjzzs.fsf@dalvik.ping.uio.no
parent e3b7f7cc
...@@ -39,6 +39,20 @@ SELECT testSVToJsonb(); ...@@ -39,6 +39,20 @@ SELECT testSVToJsonb();
1 1
(1 row) (1 row)
CREATE FUNCTION testUVToJsonb() RETURNS jsonb
LANGUAGE plperl
TRANSFORM FOR TYPE jsonb
as $$
$val = ~0;
return $val;
$$;
-- this might produce either 18446744073709551615 or 4294967295
SELECT testUVToJsonb() IN ('18446744073709551615'::jsonb, '4294967295'::jsonb);
?column?
----------
t
(1 row)
-- this revealed a bug in the original implementation -- this revealed a bug in the original implementation
CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
LANGUAGE plperl LANGUAGE plperl
...@@ -216,4 +230,4 @@ SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH'); ...@@ -216,4 +230,4 @@ SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH');
\set VERBOSITY terse \\ -- suppress cascade details \set VERBOSITY terse \\ -- suppress cascade details
DROP EXTENSION plperl CASCADE; DROP EXTENSION plperl CASCADE;
NOTICE: drop cascades to 6 other objects NOTICE: drop cascades to 7 other objects
...@@ -39,6 +39,20 @@ SELECT testSVToJsonb(); ...@@ -39,6 +39,20 @@ SELECT testSVToJsonb();
1 1
(1 row) (1 row)
CREATE FUNCTION testUVToJsonb() RETURNS jsonb
LANGUAGE plperlu
TRANSFORM FOR TYPE jsonb
as $$
$val = ~0;
return $val;
$$;
-- this might produce either 18446744073709551615 or 4294967295
SELECT testUVToJsonb() IN ('18446744073709551615'::jsonb, '4294967295'::jsonb);
?column?
----------
t
(1 row)
-- this revealed a bug in the original implementation -- this revealed a bug in the original implementation
CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
LANGUAGE plperlu LANGUAGE plperlu
...@@ -243,4 +257,4 @@ INFO: $VAR1 = {'1' => {'2' => ['3','4','5']},'2' => '3'}; ...@@ -243,4 +257,4 @@ INFO: $VAR1 = {'1' => {'2' => ['3','4','5']},'2' => '3'};
\set VERBOSITY terse \\ -- suppress cascade details \set VERBOSITY terse \\ -- suppress cascade details
DROP EXTENSION plperlu CASCADE; DROP EXTENSION plperlu CASCADE;
NOTICE: drop cascades to 6 other objects NOTICE: drop cascades to 7 other objects
...@@ -198,7 +198,24 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem) ...@@ -198,7 +198,24 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
break; break;
default: default:
if (SvIOK(in)) if (SvUOK(in))
{
/*
* If UV is >=64 bits, we have no better way to make this
* happen than converting to text and back. Given the low
* usage of UV in Perl code, it's not clear it's worth working
* hard to provide alternate code paths.
*/
const char *strval = SvPV_nolen(in);
out.type = jbvNumeric;
out.val.numeric =
DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum(strval),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1)));
}
else if (SvIOK(in))
{ {
IV ival = SvIV(in); IV ival = SvIV(in);
......
...@@ -34,6 +34,18 @@ $$; ...@@ -34,6 +34,18 @@ $$;
SELECT testSVToJsonb(); SELECT testSVToJsonb();
CREATE FUNCTION testUVToJsonb() RETURNS jsonb
LANGUAGE plperl
TRANSFORM FOR TYPE jsonb
as $$
$val = ~0;
return $val;
$$;
-- this might produce either 18446744073709551615 or 4294967295
SELECT testUVToJsonb() IN ('18446744073709551615'::jsonb, '4294967295'::jsonb);
-- this revealed a bug in the original implementation -- this revealed a bug in the original implementation
CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
LANGUAGE plperl LANGUAGE plperl
......
...@@ -34,6 +34,18 @@ $$; ...@@ -34,6 +34,18 @@ $$;
SELECT testSVToJsonb(); SELECT testSVToJsonb();
CREATE FUNCTION testUVToJsonb() RETURNS jsonb
LANGUAGE plperlu
TRANSFORM FOR TYPE jsonb
as $$
$val = ~0;
return $val;
$$;
-- this might produce either 18446744073709551615 or 4294967295
SELECT testUVToJsonb() IN ('18446744073709551615'::jsonb, '4294967295'::jsonb);
-- this revealed a bug in the original implementation -- this revealed a bug in the original implementation
CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
LANGUAGE plperlu LANGUAGE plperlu
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment