> Tom Lane <t...@sss.pgh.pa.us>:
>
>=?UTF-8?B?SXZhbiBQYW5jaGVua28=?= < w...@mail.ru > writes:
>> I have found a bug in jsonb_plperl extension. A possible fix is proposed 
>> below.
>> ...
>> +                            /* SVt_PV without POK flag is also NULL */
>> +                            if(SvTYPE(in) == SVt_PV) 
>
>Ugh.  Doesn't Perl provide some saner way to determine the type of a SV?
>
>The core code seems to think that SvOK() is a sufficient test for an
>undef.  Should we be doing that before the switch, perhaps? 
Thank you, Tom. Yes, there is a solution with SvOK(), please see the attached 
patch.

SvOK() check before the switch seems too early, because in such case we would  
loose hashes and arrays which are not SvOK. So I put it inside the switch. May 
be, it's better to remove the switch at all, and rewrite the code with ifs?

>
>(My underlying concern here is mostly about whether we have other
>similar bugs.  There are a lot of places checking SvTYPE.) 
I looked through plperl.c, but found no similar cases of checking SvTYPE.

>regards, tom lane
Regards, Ivan

>



diff --git a/contrib/jsonb_plperl/expected/jsonb_plperl.out b/contrib/jsonb_plperl/expected/jsonb_plperl.out
index 6dc090a..b784ca1 100644
--- a/contrib/jsonb_plperl/expected/jsonb_plperl.out
+++ b/contrib/jsonb_plperl/expected/jsonb_plperl.out
@@ -228,6 +228,31 @@ SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH');
  {"1": {"2": [3, 4, 5]}, "2": 3}
 (1 row)
 
+CREATE FUNCTION text2jsonb (text) RETURNS jsonb
+LANGUAGE plperl
+TRANSFORM FOR TYPE jsonb
+AS $$
+    my $x = shift;
+    return {a=>$x};
+$$;
+SELECT text2jsonb(NULL);
+ text2jsonb  
+-------------
+ {"a": null}
+(1 row)
+
+SELECT text2jsonb('11');
+ text2jsonb  
+-------------
+ {"a": "11"}
+(1 row)
+
+SELECT text2jsonb(NULL);
+ text2jsonb  
+-------------
+ {"a": null}
+(1 row)
+
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperl CASCADE;
-NOTICE:  drop cascades to 7 other objects
+NOTICE:  drop cascades to 8 other objects
diff --git a/contrib/jsonb_plperl/expected/jsonb_plperlu.out b/contrib/jsonb_plperl/expected/jsonb_plperlu.out
index 434327b..7fe0721 100644
--- a/contrib/jsonb_plperl/expected/jsonb_plperlu.out
+++ b/contrib/jsonb_plperl/expected/jsonb_plperlu.out
@@ -255,6 +255,31 @@ INFO:  $VAR1 = {'1' => {'2' => ['3','4','5']},'2' => '3'};
  {"1": {"2": [3, 4, 5]}, "2": 3}
 (1 row)
 
+CREATE FUNCTION text2jsonb (text) RETURNS jsonb
+LANGUAGE plperlu
+TRANSFORM FOR TYPE jsonb
+AS $$
+    my $x = shift;
+    return {a=>$x};
+$$;
+SELECT text2jsonb(NULL);
+ text2jsonb  
+-------------
+ {"a": null}
+(1 row)
+
+SELECT text2jsonb('11');
+ text2jsonb  
+-------------
+ {"a": "11"}
+(1 row)
+
+SELECT text2jsonb(NULL);
+ text2jsonb  
+-------------
+ {"a": null}
+(1 row)
+
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperlu CASCADE;
-NOTICE:  drop cascades to 7 other objects
+NOTICE:  drop cascades to 8 other objects
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index 79c5f57..8cf5d93 100644
--- a/contrib/jsonb_plperl/jsonb_plperl.c
+++ b/contrib/jsonb_plperl/jsonb_plperl.c
@@ -192,12 +192,12 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
 		case SVt_PVHV:
 			return HV_to_JsonbValue((HV *) in, jsonb_state);
 
-		case SVt_NULL:
-			out.type = jbvNull;
-			break;
-
 		default:
-			if (SvUOK(in))
+			if (!SvOK(in)) 
+			{
+				out.type = jbvNull;
+			}
+			else if (SvUOK(in))
 			{
 				/*
 				 * If UV is >=64 bits, we have no better way to make this
diff --git a/contrib/jsonb_plperl/sql/jsonb_plperl.sql b/contrib/jsonb_plperl/sql/jsonb_plperl.sql
index 8b062df..622141b 100644
--- a/contrib/jsonb_plperl/sql/jsonb_plperl.sql
+++ b/contrib/jsonb_plperl/sql/jsonb_plperl.sql
@@ -99,6 +99,17 @@ SELECT roundtrip('{"1": "string1"}', 'HASH');
 
 SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH');
 
+CREATE FUNCTION text2jsonb (text) RETURNS jsonb
+LANGUAGE plperl
+TRANSFORM FOR TYPE jsonb
+AS $$
+    my $x = shift;
+    return {a=>$x};
+$$;
+
+SELECT text2jsonb(NULL);
+SELECT text2jsonb('11');
+SELECT text2jsonb(NULL);
 
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperl CASCADE;
diff --git a/contrib/jsonb_plperl/sql/jsonb_plperlu.sql b/contrib/jsonb_plperl/sql/jsonb_plperlu.sql
index 8d8e841..9981c37 100644
--- a/contrib/jsonb_plperl/sql/jsonb_plperlu.sql
+++ b/contrib/jsonb_plperl/sql/jsonb_plperlu.sql
@@ -103,6 +103,17 @@ SELECT roundtrip('{"1": "string1"}', 'HASH');
 
 SELECT roundtrip('{"1": {"2": [3, 4, 5]}, "2": 3}', 'HASH');
 
+CREATE FUNCTION text2jsonb (text) RETURNS jsonb
+LANGUAGE plperlu
+TRANSFORM FOR TYPE jsonb
+AS $$
+    my $x = shift;
+    return {a=>$x};
+$$;
+
+SELECT text2jsonb(NULL);
+SELECT text2jsonb('11');
+SELECT text2jsonb(NULL);
 
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP EXTENSION plperlu CASCADE;

Reply via email to