]> granicus.if.org Git - postgresql/commitdiff
Fix jsonb_plperl to convert Perl UV values correctly.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 21:39:57 +0000 (17:39 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 21:39:57 +0000 (17:39 -0400)
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

contrib/jsonb_plperl/expected/jsonb_plperl.out
contrib/jsonb_plperl/expected/jsonb_plperlu.out
contrib/jsonb_plperl/jsonb_plperl.c
contrib/jsonb_plperl/sql/jsonb_plperl.sql
contrib/jsonb_plperl/sql/jsonb_plperlu.sql

index d2d90eb4837f0610a0b700f0e036a7e7c3e36020..6dc090a87f72299afdf95f54c1360ace1382ba64 100644 (file)
@@ -39,6 +39,20 @@ SELECT testSVToJsonb();
  1
 (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
 CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
 LANGUAGE plperl
@@ -216,4 +230,4 @@ SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH');
 
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperl CASCADE;
-NOTICE:  drop cascades to 6 other objects
+NOTICE:  drop cascades to 7 other objects
index fe8ca19a719dcff0686c414bff3745adf7b02548..434327bea02907b818d08dddfec8aeafb3dc9803 100644 (file)
@@ -39,6 +39,20 @@ SELECT testSVToJsonb();
  1
 (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
 CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
 LANGUAGE plperlu
@@ -243,4 +257,4 @@ INFO:  $VAR1 = {'1' => {'2' => ['3','4','5']},'2' => '3'};
 
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperlu CASCADE;
-NOTICE:  drop cascades to 6 other objects
+NOTICE:  drop cascades to 7 other objects
index 1b63fc4b307b8ea8743014eabe6906cfb63ab2c7..e847ae53699d1390c07d9e342da15db4fbfe91b0 100644 (file)
@@ -198,7 +198,24 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
                        break;
 
                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);
 
index 642a71deb76b1a6df0bb99d475da692b2b70b086..8b062dfc6bb4a32db3b813ae90dd357f9b2c8590 100644 (file)
@@ -34,6 +34,18 @@ $$;
 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
 CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
 LANGUAGE plperl
index 907dd4f73c8f989c53f6d43be07d6eb9cafdc954..8d8e841540570089d9d3aac4efe0282bd1efe9f2 100644 (file)
@@ -34,6 +34,18 @@ $$;
 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
 CREATE FUNCTION testRegexpResultToJsonb() RETURNS jsonb
 LANGUAGE plperlu