mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Rename plpython to plpythonu, and update documentation to reflect its
now-untrusted status.
This commit is contained in:
@ -1,39 +0,0 @@
|
||||
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.
|
@ -1,5 +1,8 @@
|
||||
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
|
||||
@ -10,7 +13,7 @@ In no particular order...
|
||||
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;
|
||||
|
@ -16,24 +16,15 @@ SELECT valid_type('rick');
|
||||
|
||||
(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)
|
||||
|
||||
|
@ -29,7 +29,7 @@ SELECT global_test_two();
|
||||
(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
|
||||
|
@ -7,5 +7,5 @@ DROP TRIGGER users_update_trig on users ;
|
||||
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() ;
|
||||
|
@ -7,7 +7,7 @@ CREATE FUNCTION global_test_one() returns text
|
||||
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
|
||||
@ -16,7 +16,7 @@ CREATE FUNCTION global_test_two() returns text
|
||||
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
|
||||
@ -27,7 +27,7 @@ else:
|
||||
SD["call"] = 1
|
||||
return SD["call"]
|
||||
'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
-- import python modules
|
||||
|
||||
@ -39,7 +39,7 @@ except Exception, ex:
|
||||
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
|
||||
@ -63,14 +63,14 @@ except Exception, ex:
|
||||
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
|
||||
@ -78,7 +78,7 @@ CREATE FUNCTION import_test_two(users) RETURNS text
|
||||
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
|
||||
@ -89,7 +89,7 @@ for key in keys:
|
||||
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
|
||||
@ -110,7 +110,7 @@ if TD["new"]["fname"] == "william":
|
||||
TD["new"]["fname"] = TD["args"][0]
|
||||
rv = "MODIFY"
|
||||
return rv'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
|
||||
CREATE FUNCTION users_update() returns trigger
|
||||
@ -119,7 +119,7 @@ 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
|
||||
@ -127,7 +127,7 @@ 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
|
||||
@ -148,19 +148,19 @@ CREATE FUNCTION nested_call_one(text) RETURNS text
|
||||
'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
|
||||
|
||||
@ -176,7 +176,7 @@ except Exception, ex:
|
||||
plpy.error(str(ex))
|
||||
return None
|
||||
'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
CREATE FUNCTION spi_prepared_plan_test_nested(text) RETURNS text
|
||||
AS
|
||||
@ -191,12 +191,12 @@ except Exception, ex:
|
||||
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
|
||||
*/
|
||||
@ -210,7 +210,7 @@ if len(rv):
|
||||
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
|
||||
@ -229,7 +229,7 @@ if len(rv):
|
||||
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
|
||||
@ -247,7 +247,7 @@ if len(rv):
|
||||
return rv[0]["fname"]
|
||||
return None
|
||||
'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
|
||||
/* no typo no messing about
|
||||
@ -261,20 +261,20 @@ if len(rv):
|
||||
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
|
||||
*/
|
||||
@ -282,7 +282,7 @@ CREATE FUNCTION exception_index_invalid_nested() RETURNS text
|
||||
AS
|
||||
'rv = plpy.execute("SELECT test5(''foo'')")
|
||||
return rv[0]'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
|
||||
CREATE FUNCTION join_sequences(sequences) RETURNS text
|
||||
@ -296,13 +296,13 @@ for r in rv:
|
||||
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;
|
||||
|
@ -8,4 +8,4 @@ CREATE FUNCTION test_setof() returns setof text
|
||||
else:
|
||||
GD["calls"] = 1
|
||||
return str(GD["calls"])'
|
||||
LANGUAGE 'plpython';
|
||||
LANGUAGE plpythonu;
|
||||
|
@ -11,7 +11,7 @@ createdb $DBNAME >> test.log 2>&1
|
||||
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"
|
||||
|
Reference in New Issue
Block a user