-
+
PL/Python - Python Procedural Language
To install PL/Python in a particular database, use
- createlang plpython dbname>.
+ createlang plpythonu dbname>.
+
+ PL/Python is only available as an untrusted> language
+ (meaning it does not offer any way of restricting what users
+ can do in it). It has therefore been renamed to plpythonu>.
+ The trusted variant plpython> may become available again in
+ future, if a new secure execution mechanism is developed by the Python
+ community.
+
+
+
If a language is installed into template1>, all subsequently
CREATE FUNCTION myfunc(text) RETURNS text
AS 'return args[0]'
- LANGUAGE plpython;
+ LANGUAGE plpythonu;
gets transformed into
available to all Python functions within a session. Use with care.
+
+
plan = plpy.prepare("SELECT 1")
SD["plan"] = plan
# rest of function
-' LANGUAGE plpython;
+' LANGUAGE plpythonu;
+
+
worries about funny characters.
-->
+PL/Python is now an untrusted language, and is renamed to 'plpythonu'
Dollar sign ($) is no longer allowed in operator names
Dollar sign ($) can be a non-first character in identifiers
Precision in FLOAT(p) is now interpreted as bits, not decimal digits
for languages that do not allow access to database server
internals or the file system. The languages
-
PL/Python are known to be trusted;
- the languages
PL/TclU and
-
PL/PerlU are designed to provide
- unlimited functionality and should not be
- marked trusted.
+ are considered trusted; the languages
+ are designed to provide unlimited functionality and should
+ not be marked trusted.
directory. If
Tcl/Tk> support is configured in, the handlers for
PL/Tcl> and PL/TclU> are also built and installed in the same
location. Likewise, the
PL/Perl> and PL/PerlU> handlers are built
- and installed if Perl support is configured, and
PL/Python> is
+ and installed if Perl support is configured, and
PL/PythonU> is
installed if Python support is configured.
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/bin/scripts/createlang.c,v 1.3 2003/06/11 05:13:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/scripts/createlang.c,v 1.4 2003/06/30 18:31:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
handler = "plperl_call_handler";
object = "plperl";
}
- else if (strcmp(langname, "plpython")==0)
+ else if (strcmp(langname, "plpythonu")==0)
{
- trusted = true;
+ trusted = false;
handler = "plpython_call_handler";
object = "plpython";
}
else
{
fprintf(stderr, _("%s: unsupported language \"%s\"\n"), progname, langname);
- fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and plpython.\n"));
+ fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and plpythonu.\n"));
exit(1);
}
+++ /dev/null
-PL/Python - Python Procedural Language for PostgreSQL
------------------------------------------------------
-$Id: README,v 1.2 2001/05/14 22:06:50 petere Exp $
-
-Installation:
-
-configure --with-python
-cd src/pl/plpython
-gmake
-gmake install
-
-Test:
-
-# have postmaster running...
-gmake installcheck
-
-Enable language:
-
-createlang plpython dbname
-
-
-Note that PL/Python is currently not built automatically because the
-code is new and there are some portability issues.
-
-A default Python installation does not provide a shared libpython
-library. This is not a problem on many platforms (although it makes
-things less efficient), but on some platforms (especially HP-UX) the
-link will fail outright.
-
-To create a shared libpython, see this web page for hints:
-
-http://www.python.org/cgi-bin/faqw.py?req=show&file=faq03.030.htp
-
-Place the resulting library in the same directory as the existing
-static libpythonX.Y.a and relink plpython.
-
-
-Further documentation is available in the PostgreSQL Programmer's
-Guide.
In no particular order...
+* Develop a trusted variant of PL/Python. Now that RExec has been shown
+ to be full of holes, this may take a while :-(
+
* Allow arrays as function arguments and return values. (almost done)
* Create a new restricted execution class that will allow me to pass
so the following will make PostgreSQL unhappy:
create table users (first_name text, last_name text);
- create function user_name(user) returns text as 'mycode' language 'plpython';
+ create function user_name(user) returns text as 'mycode' language plpython;
select user_name(user) from users;
alter table add column user_id integer;
select user_name(user) from users;
(1 row)
-SELECT read_file('/etc/passwd');
-ERROR: plpython: Call of function `read_file' failed.
-exceptions.IOError: can't open files in restricted mode
-SELECT write_file('/tmp/plpython','This is very bad');
-ERROR: plpython: Call of function `write_file' failed.
-exceptions.IOError: can't open files in restricted mode
-SELECT getpid();
-ERROR: plpython: Call of function `getpid' failed.
-exceptions.AttributeError: 'module' object has no attribute 'getpid'
-SELECT uname();
-ERROR: plpython: Call of function `uname' failed.
-exceptions.AttributeError: 'module' object has no attribute 'uname'
-SELECT sys_exit();
-ERROR: plpython: Call of function `sys_exit' failed.
-exceptions.AttributeError: 'module' object has no attribute 'exit'
-SELECT sys_argv();
- sys_argv
-----------------
- ['RESTRICTED']
+SELECT write_file('/tmp/plpython','Only trusted users should be able to do this!');
+ write_file
+------------------------------
+ Wrote to file: /tmp/plpython
+(1 row)
+
+SELECT read_file('/tmp/plpython');
+ read_file
+-----------------------------------------------
+ Only trusted users should be able to do this!
(1 row)
(1 row)
SELECT import_fail();
-NOTICE: ('import socket failed -- untrusted dynamic module: _socket',)
+NOTICE: ('import socket failed -- No module named foosocket',)
import_fail
--------------------
failed as expected
DROP FUNCTION users_update() ;
DROP TRIGGER users_delete_trig on users ;
DROP FUNCTION users_delete() ;
-DROP PROCEDURAL LANGUAGE 'plpython' ;
+DROP PROCEDURAL LANGUAGE plpythonu ;
DROP FUNCTION plpython_call_handler() ;
if not GD.has_key("global_test"):
GD["global_test"] = "set by global_test_one"
return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION global_test_two() returns text
AS
if not GD.has_key("global_test"):
GD["global_test"] = "set by global_test_two"
return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION static_test() returns int4
SD["call"] = 1
return SD["call"]
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
-- import python modules
plpy.notice("import socket failed -- %s" % str(ex))
return "failed as expected"
return "succeeded, that wasn''t supposed to happen"'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION import_succeed() returns text
plpy.notice("import failed -- %s" % str(ex))
return "failed, that wasn''t supposed to happen"
return "succeeded, as expected"'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION import_test_one(text) RETURNS text
AS
'import sha
digest = sha.new(args[0])
return digest.hexdigest()'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION import_test_two(users) RETURNS text
AS
plain = args[0]["fname"] + args[0]["lname"]
digest = sha.new(plain);
return "sha hash of " + plain + " is " + digest.hexdigest()'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION argument_test_one(users, text, text) RETURNS text
AS
out.append("%s: %s" % (key, args[0][key]))
words = args[1] + " " + args[2] + " => {" + ", ".join(out) + "}"
return words'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
-- these triggers are dedicated to HPHC of RI who
TD["new"]["fname"] = TD["args"][0]
rv = "MODIFY"
return rv'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION users_update() returns trigger
if TD["old"]["fname"] != TD["new"]["fname"] and TD["old"]["fname"] == TD["args"][0]:
return "SKIP"
return None'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION users_delete() RETURNS trigger
'if TD["old"]["fname"] == TD["args"][0]:
return "SKIP"
return None'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE TRIGGER users_insert_trig BEFORE INSERT ON users FOR EACH ROW
'q = "SELECT nested_call_two(''%s'')" % args[0]
r = plpy.execute(q)
return r[0]'
- LANGUAGE 'plpython' ;
+ LANGUAGE plpythonu ;
CREATE FUNCTION nested_call_two(text) RETURNS text
AS
'q = "SELECT nested_call_three(''%s'')" % args[0]
r = plpy.execute(q)
return r[0]'
- LANGUAGE 'plpython' ;
+ LANGUAGE plpythonu ;
CREATE FUNCTION nested_call_three(text) RETURNS text
AS
'return args[0]'
- LANGUAGE 'plpython' ;
+ LANGUAGE plpythonu ;
-- some spi stuff
plpy.error(str(ex))
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION spi_prepared_plan_test_nested(text) RETURNS text
AS
plpy.error(str(ex))
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* really stupid function just to get the module loaded
*/
-CREATE FUNCTION stupid() RETURNS text AS 'return "zarkon"' LANGUAGE 'plpython';
+CREATE FUNCTION stupid() RETURNS text AS 'return "zarkon"' LANGUAGE plpythonu;
/* a typo
*/
return rv[0]["fname"]
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* for what it's worth catch the exception generated by
* the typo, and return None
return rv[0]["fname"]
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* for what it's worth catch the exception generated by
* the typo, and reraise it as a plain error
return rv[0]["fname"]
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* no typo no messing about
return rv[0]["fname"]
return None
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* Flat out syntax error
*/
CREATE FUNCTION sql_syntax_error() RETURNS text
AS
'plpy.execute("syntax error")'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* check the handling of uncaught python exceptions
*/
CREATE FUNCTION exception_index_invalid(text) RETURNS text
AS
'return args[1]'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
/* check handling of nested exceptions
*/
AS
'rv = plpy.execute("SELECT test5(''foo'')")
return rv[0]'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE FUNCTION join_sequences(sequences) RETURNS text
seq = seq + r["sequence"]
return seq
'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION read_file(text) RETURNS text AS '
return open(args[0]).read()
-' LANGUAGE 'plpython';
+' LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION write_file(text,text) RETURNS text AS '
open(args[0],"w").write(args[1])
return "Wrote to file: %s" % args[0]
-' LANGUAGE 'plpython';
+' LANGUAGE plpythonu;
else:
GD["calls"] = 1
return str(GD["calls"])'
- LANGUAGE 'plpython';
+ LANGUAGE plpythonu;
echo " Done. ***"
echo -n "*** Create plpython."
-createlang plpython $DBNAME >> test.log 2>&1
+createlang plpythonu $DBNAME >> test.log 2>&1
echo " Done. ***"
echo -n "*** Create tables"