Commit 66f50386 authored by Tom Lane's avatar Tom Lane

Make plpython cope with funny characters in function names.

A function name that's double-quoted in SQL can contain almost any
characters, but we were using that name directly as part of the name
generated for the Python-level function, and Python doesn't like
anything that isn't pretty much a standard identifier.  To fix,
replace anything that isn't an ASCII letter or digit with an underscore
in the generated name.  This doesn't create any risk of duplicate Python
function names because we were already appending the function OID to
the generated name to ensure uniqueness.  Per bug #13960 from Jim Nasby.

Patch by Jim Nasby, modified a bit by me.  Back-patch to all
supported branches.
parent a65313f2
...@@ -16,8 +16,8 @@ select stupidn(); ...@@ -16,8 +16,8 @@ select stupidn();
zarkon zarkon
(1 row) (1 row)
-- test multiple arguments -- test multiple arguments and odd characters in function name
CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text CREATE FUNCTION "Argument test #1"(u users, a1 text, a2 text) RETURNS text
AS AS
'keys = list(u.keys()) 'keys = list(u.keys())
keys.sort() keys.sort()
...@@ -27,8 +27,8 @@ for key in keys: ...@@ -27,8 +27,8 @@ for key in keys:
words = a1 + " " + a2 + " => {" + ", ".join(out) + "}" words = a1 + " " + a2 + " => {" + ", ".join(out) + "}"
return words' return words'
LANGUAGE plpythonu; LANGUAGE plpythonu;
select argument_test_one(users, fname, lname) from users where lname = 'doe' order by 1; select "Argument test #1"(users, fname, lname) from users where lname = 'doe' order by 1;
argument_test_one Argument test #1
----------------------------------------------------------------------- -----------------------------------------------------------------------
jane doe => {fname: jane, lname: doe, userid: 1, username: j_doe} jane doe => {fname: jane, lname: doe, userid: 1, username: j_doe}
john doe => {fname: john, lname: doe, userid: 2, username: johnd} john doe => {fname: john, lname: doe, userid: 2, username: johnd}
......
...@@ -146,6 +146,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -146,6 +146,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
MemoryContext cxt; MemoryContext cxt;
MemoryContext oldcxt; MemoryContext oldcxt;
int rv; int rv;
char *ptr;
procStruct = (Form_pg_proc) GETSTRUCT(procTup); procStruct = (Form_pg_proc) GETSTRUCT(procTup);
rv = snprintf(procName, sizeof(procName), rv = snprintf(procName, sizeof(procName),
...@@ -155,6 +156,15 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -155,6 +156,15 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
if (rv >= sizeof(procName) || rv < 0) if (rv >= sizeof(procName) || rv < 0)
elog(ERROR, "procedure name would overrun buffer"); 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, cxt = AllocSetContextCreate(TopMemoryContext,
procName, procName,
ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_MINSIZE,
......
...@@ -11,8 +11,8 @@ CREATE FUNCTION stupidn() RETURNS text AS 'return "zarkon"' LANGUAGE plpython2u; ...@@ -11,8 +11,8 @@ CREATE FUNCTION stupidn() RETURNS text AS 'return "zarkon"' LANGUAGE plpython2u;
select stupidn(); select stupidn();
-- test multiple arguments -- test multiple arguments and odd characters in function name
CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text CREATE FUNCTION "Argument test #1"(u users, a1 text, a2 text) RETURNS text
AS AS
'keys = list(u.keys()) 'keys = list(u.keys())
keys.sort() keys.sort()
...@@ -23,7 +23,7 @@ words = a1 + " " + a2 + " => {" + ", ".join(out) + "}" ...@@ -23,7 +23,7 @@ words = a1 + " " + a2 + " => {" + ", ".join(out) + "}"
return words' return words'
LANGUAGE plpythonu; LANGUAGE plpythonu;
select argument_test_one(users, fname, lname) from users where lname = 'doe' order by 1; select "Argument test #1"(users, fname, lname) from users where lname = 'doe' order by 1;
-- check module contents -- check module contents
......
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