Re: suspicious pointer/integer coersion - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: suspicious pointer/integer coersion
Date
Msg-id 42D274AD.4020408@dunslane.net
Whole thread Raw
In response to Re: suspicious pointer/integer coersion  (Andrew Dunstan <andrew@dunslane.net>)
Responses Re: suspicious pointer/integer coersion
List pgsql-hackers

Andrew Dunstan wrote:

>
>
> Andrew Dunstan wrote:
>
>>
>>
>>
>>
>> Looking further ... we already do this implicitly for prodesc in the
>> call handler - we would just need to do the same thing for per-call
>> structures and divorce them from prodesc, which can be repeated on
>> the implicit stack.
>>
>> I'll work on that - changes should be quite small.
>>
>
> Attached is a patch that fixes (I hope) both a recently introduced
> problem with recursion and a problem with array returns that became
> evident as a result of not throwing away non-fatal warnings (thanks to
> David Fetter for noticing this). Regression test updates to include
> both cases are included in the patch.
>
> I will start looking at putting the procedure descriptors in a dynahash.
>
>

and here's the patch this time.

cheers


andrew
Index: plperl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plperl/plperl.c,v
retrieving revision 1.84
diff -c -r1.84 plperl.c
*** plperl.c    10 Jul 2005 16:13:13 -0000    1.84
--- plperl.c    11 Jul 2005 13:08:26 -0000
***************
*** 90,98 ****
      FmgrInfo    arg_out_func[FUNC_MAX_ARGS];
      bool        arg_is_rowtype[FUNC_MAX_ARGS];
      SV           *reference;
-     FunctionCallInfo caller_info;
-     Tuplestorestate *tuple_store;
-     TupleDesc tuple_desc;
  } plperl_proc_desc;


--- 90,95 ----
***************
*** 106,113 ****

  static bool plperl_use_strict = false;

! /* this is saved and restored by plperl_call_handler */
  static plperl_proc_desc *plperl_current_prodesc = NULL;

  /**********************************************************************
   * Forward declarations
--- 103,113 ----

  static bool plperl_use_strict = false;

! /* these are saved and restored by plperl_call_handler */
  static plperl_proc_desc *plperl_current_prodesc = NULL;
+ static FunctionCallInfo plperl_current_caller_info;
+ static Tuplestorestate *plperl_current_tuple_store;
+ static TupleDesc plperl_current_tuple_desc;

  /**********************************************************************
   * Forward declarations
***************
*** 577,586 ****
--- 577,592 ----
  {
      Datum retval;
      plperl_proc_desc *save_prodesc;
+     FunctionCallInfo save_caller_info;
+     Tuplestorestate *save_tuple_store;
+     TupleDesc save_tuple_desc;

      plperl_init_all();

      save_prodesc = plperl_current_prodesc;
+     save_caller_info = plperl_current_caller_info;
+     save_tuple_store = plperl_current_tuple_store;
+     save_tuple_desc = plperl_current_tuple_desc;

      PG_TRY();
      {
***************
*** 592,602 ****
--- 598,614 ----
      PG_CATCH();
      {
          plperl_current_prodesc = save_prodesc;
+         plperl_current_caller_info = save_caller_info;
+         plperl_current_tuple_store = save_tuple_store;
+         plperl_current_tuple_desc = save_tuple_desc;
          PG_RE_THROW();
      }
      PG_END_TRY();

      plperl_current_prodesc = save_prodesc;
+     plperl_current_caller_info = save_caller_info;
+     plperl_current_tuple_store = save_tuple_store;
+     plperl_current_tuple_desc = save_tuple_desc;

      return retval;
  }
***************
*** 897,902 ****
--- 909,915 ----
      SV           *perlret;
      Datum        retval;
      ReturnSetInfo *rsi;
+         SV* array_ret = NULL;

      if (SPI_connect() != SPI_OK_CONNECT)
          elog(ERROR, "could not connect to SPI manager");
***************
*** 904,912 ****
      prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);

      plperl_current_prodesc = prodesc;
!     prodesc->caller_info = fcinfo;
!     prodesc->tuple_store = 0;
!     prodesc->tuple_desc = 0;

      perlret = plperl_call_perl_func(prodesc, fcinfo);

--- 917,925 ----
      prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);

      plperl_current_prodesc = prodesc;
!     plperl_current_caller_info = fcinfo;
!     plperl_current_tuple_store = 0;
!     plperl_current_tuple_desc = 0;

      perlret = plperl_call_perl_func(prodesc, fcinfo);

***************
*** 958,967 ****
          }

          rsi->returnMode = SFRM_Materialize;
!         if (prodesc->tuple_store)
          {
!             rsi->setResult = prodesc->tuple_store;
!             rsi->setDesc = prodesc->tuple_desc;
          }
          retval = (Datum)0;
      }
--- 971,980 ----
          }

          rsi->returnMode = SFRM_Materialize;
!         if (plperl_current_tuple_store)
          {
!             rsi->setResult = plperl_current_tuple_store;
!             rsi->setDesc = plperl_current_tuple_desc;
          }
          retval = (Datum)0;
      }
***************
*** 1006,1012 ****
      {
          /* Return a perl string converted to a Datum */
          char *val;
-         SV* array_ret;


          if (prodesc->fn_retisarray && SvTYPE(SvRV(perlret)) == SVt_PVAV)
--- 1019,1024 ----
***************
*** 1024,1030 ****
                                 Int32GetDatum(-1));
      }

!     SvREFCNT_dec(perlret);
      return retval;
  }

--- 1036,1044 ----
                                 Int32GetDatum(-1));
      }

!     if (array_ret == NULL)
!       SvREFCNT_dec(perlret);
!
      return retval;
  }

***************
*** 1526,1532 ****
  plperl_return_next(SV *sv)
  {
      plperl_proc_desc *prodesc = plperl_current_prodesc;
!     FunctionCallInfo fcinfo = prodesc->caller_info;
      ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
      MemoryContext cxt;
      HeapTuple tuple;
--- 1540,1546 ----
  plperl_return_next(SV *sv)
  {
      plperl_proc_desc *prodesc = plperl_current_prodesc;
!     FunctionCallInfo fcinfo = plperl_current_caller_info;
      ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
      MemoryContext cxt;
      HeapTuple tuple;
***************
*** 1553,1560 ****

      cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);

!     if (!prodesc->tuple_store)
!         prodesc->tuple_store = tuplestore_begin_heap(true, false, work_mem);

      if (prodesc->fn_retistuple)
      {
--- 1567,1575 ----

      cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);

!     if (!plperl_current_tuple_store)
!         plperl_current_tuple_store =
!             tuplestore_begin_heap(true, false, work_mem);

      if (prodesc->fn_retistuple)
      {
***************
*** 1590,1599 ****
          tuple = heap_form_tuple(tupdesc, &ret, &isNull);
      }

!     if (!prodesc->tuple_desc)
!         prodesc->tuple_desc = tupdesc;

!     tuplestore_puttuple(prodesc->tuple_store, tuple);
      heap_freetuple(tuple);
      MemoryContextSwitchTo(cxt);
  }
--- 1605,1614 ----
          tuple = heap_form_tuple(tupdesc, &ret, &isNull);
      }

!     if (!plperl_current_tuple_desc)
!         plperl_current_tuple_desc = tupdesc;

!     tuplestore_puttuple(plperl_current_tuple_store, tuple);
      heap_freetuple(tuple);
      MemoryContextSwitchTo(cxt);
  }
Index: expected/plperl.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plperl/expected/plperl.out,v
retrieving revision 1.3
diff -c -r1.3 plperl.out
*** expected/plperl.out    10 Jul 2005 15:19:43 -0000    1.3
--- expected/plperl.out    11 Jul 2005 13:08:26 -0000
***************
*** 367,369 ****
--- 367,422 ----
               2
  (2 rows)

+ ---
+ --- Test recursion via SPI
+ ---
+ CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
+ AS $$
+
+   my $i = shift;
+   foreach my $x (1..$i)
+   {
+     return_next "hello $x";
+   }
+   if ($i > 2)
+   {
+     my $z = $i-1;
+     my $cursor = spi_query("select * from recurse($z)");
+     while (defined(my $row = spi_fetchrow($cursor)))
+     {
+       return_next "recurse $i: $row->{recurse}";
+     }
+   }
+   return undef;
+
+ $$;
+ SELECT * FROM recurse(2);
+  recurse
+ ---------
+  hello 1
+  hello 2
+ (2 rows)
+
+ SELECT * FROM recurse(3);
+       recurse
+ --------------------
+  hello 1
+  hello 2
+  hello 3
+  recurse 3: hello 1
+  recurse 3: hello 2
+ (5 rows)
+
+ ---
+ --- Test arrary return
+ ---
+ CREATE OR REPLACE FUNCTION  array_of_text() RETURNS TEXT[][]
+ LANGUAGE plperl as $$
+     return [['a"b','c,d'],['e\\f','g']];
+ $$;
+ SELECT array_of_text();
+         array_of_text
+ -----------------------------
+  {{"a\"b","c,d"},{"e\\f",g}}
+ (1 row)
+
Index: sql/plperl.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plperl/sql/plperl.sql,v
retrieving revision 1.3
diff -c -r1.3 plperl.sql
*** sql/plperl.sql    10 Jul 2005 15:19:43 -0000    1.3
--- sql/plperl.sql    11 Jul 2005 13:08:26 -0000
***************
*** 260,262 ****
--- 260,303 ----
  return;
  $$ LANGUAGE plperl;
  SELECT * from perl_spi_func();
+
+
+ ---
+ --- Test recursion via SPI
+ ---
+
+
+ CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
+ AS $$
+
+   my $i = shift;
+   foreach my $x (1..$i)
+   {
+     return_next "hello $x";
+   }
+   if ($i > 2)
+   {
+     my $z = $i-1;
+     my $cursor = spi_query("select * from recurse($z)");
+     while (defined(my $row = spi_fetchrow($cursor)))
+     {
+       return_next "recurse $i: $row->{recurse}";
+     }
+   }
+   return undef;
+
+ $$;
+
+ SELECT * FROM recurse(2);
+ SELECT * FROM recurse(3);
+
+
+ ---
+ --- Test arrary return
+ ---
+ CREATE OR REPLACE FUNCTION  array_of_text() RETURNS TEXT[][]
+ LANGUAGE plperl as $$
+     return [['a"b','c,d'],['e\\f','g']];
+ $$;
+
+ SELECT array_of_text();

pgsql-hackers by date:

Previous
From: Dennis Bjorklund
Date:
Subject: Re: [BUGS] BUG #1745: Unable to delete data from the
Next
From: Tom Lane
Date:
Subject: Re: 4 pgcrypto regressions failures - 1 unsolved