Re: BUG #13960: plpython fails with certain function names - Mailing list pgsql-bugs

From Tom Lane
Subject Re: BUG #13960: plpython fails with certain function names
Date
Msg-id 25529.1455673778@sss.pgh.pa.us
Whole thread Raw
In response to Re: BUG #13960: plpython fails with certain function names  (Jim Nasby <Jim.Nasby@BlueTreble.com>)
Responses Re: BUG #13960: plpython fails with certain function names
Re: BUG #13960: plpython fails with certain function names
List pgsql-bugs
Jim Nasby <Jim.Nasby@bluetreble.com> writes:
> On 2/14/16 7:09 PM, Tom Lane wrote:
>> Yeah, that's what I was thinking about.  But yes, if we append the OID
>> anyway then we might as well just strip all non-alphanumeric chars
>> from the name.  Safe and you still get some debuggability.

> Attached. I opted not to modify the name in-place. If it's safe to
> modify in place, might want to just replace invalid characters with '_'
> instead of making a copy.

I like the idea of replacing invalid characters with '_'.  It's definitely
not safe to scribble on the pg_proc tuple, but we could get the same
result with a few wasted cycles by rescanning the procName string after
building it, as per attached.

            regards, tom lane

diff --git a/src/pl/plpython/expected/plpython_test.out b/src/pl/plpython/expected/plpython_test.out
index 7b76faf..f8270a7 100644
*** a/src/pl/plpython/expected/plpython_test.out
--- b/src/pl/plpython/expected/plpython_test.out
*************** select stupidn();
*** 16,23 ****
   zarkon
  (1 row)

! -- test multiple arguments
! CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text
      AS
  'keys = list(u.keys())
  keys.sort()
--- 16,23 ----
   zarkon
  (1 row)

! -- test multiple arguments and odd characters in function name
! CREATE FUNCTION "Argument test #1"(u users, a1 text, a2 text) RETURNS text
      AS
  'keys = list(u.keys())
  keys.sort()
*************** for key in keys:
*** 27,34 ****
  words = a1 + " " + a2 + " => {" + ", ".join(out) + "}"
  return words'
      LANGUAGE plpythonu;
! select argument_test_one(users, fname, lname) from users where lname = 'doe' order by 1;
!                            argument_test_one
  -----------------------------------------------------------------------
   jane doe => {fname: jane, lname: doe, userid: 1, username: j_doe}
   john doe => {fname: john, lname: doe, userid: 2, username: johnd}
--- 27,34 ----
  words = a1 + " " + a2 + " => {" + ", ".join(out) + "}"
  return words'
      LANGUAGE plpythonu;
! select "Argument test #1"(users, fname, lname) from users where lname = 'doe' order by 1;
!                            Argument test #1
  -----------------------------------------------------------------------
   jane doe => {fname: jane, lname: doe, userid: 1, username: j_doe}
   john doe => {fname: john, lname: doe, userid: 2, username: johnd}
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index e1f5620..a0d0792 100644
*** a/src/pl/plpython/plpy_procedure.c
--- b/src/pl/plpython/plpy_procedure.c
*************** PLy_procedure_create(HeapTuple procTup,
*** 146,151 ****
--- 146,152 ----
      MemoryContext cxt;
      MemoryContext oldcxt;
      int            rv;
+     char       *ptr;

      procStruct = (Form_pg_proc) GETSTRUCT(procTup);
      rv = snprintf(procName, sizeof(procName),
*************** PLy_procedure_create(HeapTuple procTup,
*** 155,160 ****
--- 156,170 ----
      if (rv >= sizeof(procName) || rv < 0)
          elog(ERROR, "procedure name would overrun buffer");

+     /* Replace any not-legal-in-Python-names characters with '_' */
+     for (ptr = procName; *ptr; ptr++)
+     {
+         if (!((*ptr >= 'A' && *ptr <= 'Z') ||
+               (*ptr >= 'a' && *ptr <= 'z') ||
+               (*ptr >= '0' && *ptr <= '9')))
+             *ptr = '_';
+     }
+
      cxt = AllocSetContextCreate(TopMemoryContext,
                                  procName,
                                  ALLOCSET_DEFAULT_MINSIZE,
diff --git a/src/pl/plpython/sql/plpython_test.sql b/src/pl/plpython/sql/plpython_test.sql
index c8d5ef5..3a76104 100644
*** a/src/pl/plpython/sql/plpython_test.sql
--- b/src/pl/plpython/sql/plpython_test.sql
*************** CREATE FUNCTION stupidn() RETURNS text A
*** 11,18 ****

  select stupidn();

! -- test multiple arguments
! CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text
      AS
  'keys = list(u.keys())
  keys.sort()
--- 11,18 ----

  select stupidn();

! -- test multiple arguments and odd characters in function name
! CREATE FUNCTION "Argument test #1"(u users, a1 text, a2 text) RETURNS text
      AS
  'keys = list(u.keys())
  keys.sort()
*************** words = a1 + " " + a2 + " => {" + ", ".j
*** 23,29 ****
  return words'
      LANGUAGE plpythonu;

! select argument_test_one(users, fname, lname) from users where lname = 'doe' order by 1;


  -- check module contents
--- 23,29 ----
  return words'
      LANGUAGE plpythonu;

! select "Argument test #1"(users, fname, lname) from users where lname = 'doe' order by 1;


  -- check module contents

pgsql-bugs by date:

Previous
From: Jim Nasby
Date:
Subject: Re: BUG #13960: plpython fails with certain function names
Next
From: Jim Nasby
Date:
Subject: Re: BUG #13960: plpython fails with certain function names