diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml
index 870063c288..679878b3af 100644
--- a/doc/src/sgml/hstore.sgml
+++ b/doc/src/sgml/hstore.sgml
@@ -943,12 +943,8 @@ ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || '';
and hstore_plperlu, for trusted and untrusted PL/Perl.
If you install these transforms and specify them when creating a
function, hstore values are mapped to Perl hashes. The
- extensions for PL/Python are
- called hstore_plpythonu, hstore_plpython2u,
- and hstore_plpython3u
- (see for the PL/Python naming
- convention). If you use them, hstore values are mapped to
- Python dictionaries.
+ extension for PL/Python is called hstore_plpython3u.
+ If you use it, hstore values are mapped to Python dictionaries.
diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml
index 673c70c3bb..c4223fafb6 100644
--- a/doc/src/sgml/json.sgml
+++ b/doc/src/sgml/json.sgml
@@ -716,12 +716,9 @@ UPDATE table_name SET jsonb_field[1]['a'] = '1';
- The extensions for PL/Python are called jsonb_plpythonu,
- jsonb_plpython2u, and
- jsonb_plpython3u (see for the PL/Python naming convention). If you
- use them, jsonb values are mapped to Python dictionaries,
- lists, and scalars, as appropriate.
+ The extension for PL/Python is called jsonb_plpython3u.
+ If you use it, jsonb values are mapped to Python
+ dictionaries, lists, and scalars, as appropriate.
diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml
index 436be76bfa..508f404ae8 100644
--- a/doc/src/sgml/ltree.sgml
+++ b/doc/src/sgml/ltree.sgml
@@ -826,19 +826,15 @@ ltreetest=> SELECT ins_label(path,2,'Space') FROM test WHERE path <@ 'Top.
Transforms
- Additional extensions are available that implement transforms for
- the ltree type for PL/Python. The extensions are
- called ltree_plpythonu, ltree_plpython2u,
- and ltree_plpython3u
- (see for the PL/Python naming
- convention). If you install these transforms and specify them when
+ The ltree_plpython3u extension implements transforms for
+ the ltree type for PL/Python. If installed and specified when
creating a function, ltree values are mapped to Python lists.
(The reverse is currently not supported, however.)
- It is strongly recommended that the transform extensions be installed in
+ It is strongly recommended that the transform extension be installed in
the same schema as ltree. Otherwise there are
installation-time security hazards if a transform extension's schema
contains objects defined by a hostile user.
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index b67f8f4aae..54355effd7 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -14,8 +14,7 @@
To install PL/Python in a particular database, use
- CREATE EXTENSION plpythonu (but
- see also ).
+ CREATE EXTENSION plpython3u.
@@ -28,14 +27,14 @@
PL/Python is only available as an untrusted
language, meaning
it does not offer any way of restricting what users can do in it and
- is therefore named plpythonu. A trusted
+ is therefore named plpython3u. A trusted
variant plpython might become available in the future
if a secure execution mechanism is developed in Python. The
writer of a function in untrusted PL/Python must take care that the
function cannot be used to do anything unwanted, since it will be
able to do anything that could be done by a user logged in as the
database administrator. Only superusers can create functions in
- untrusted languages such as plpythonu.
+ untrusted languages such as plpython3u.
@@ -47,140 +46,6 @@
-
- Python 2 vs. Python 3
-
-
- PL/Python supports both the Python 2 and Python 3 language
- variants. (The PostgreSQL installation instructions might contain
- more precise information about the exact supported minor versions
- of Python.) Because the Python 2 and Python 3 language variants
- are incompatible in some important aspects, the following naming
- and transitioning scheme is used by PL/Python to avoid mixing them:
-
-
-
-
- The PostgreSQL language named plpython2u
- implements PL/Python based on the Python 2 language variant.
-
-
-
-
-
- The PostgreSQL language named plpython3u
- implements PL/Python based on the Python 3 language variant.
-
-
-
-
-
- The language named plpythonu implements
- PL/Python based on the default Python language variant, which is
- currently Python 2. (This default is independent of what any
- local Python installations might consider to be
- their default
, for example,
- what /usr/bin/python might be.) The
- default will probably be changed to Python 3 in a distant future
- release of PostgreSQL, depending on the progress of the
- migration to Python 3 in the Python community.
-
-
-
-
- This scheme is analogous to the recommendations in PEP 394 regarding the
- naming and transitioning of the python command.
-
-
-
- It depends on the build configuration or the installed packages
- whether PL/Python for Python 2 or Python 3 or both are available.
-
-
-
-
- The built variant depends on which Python version was found during
- the installation or which version was explicitly set using
- the PYTHON environment variable;
- see . To make both variants of
- PL/Python available in one installation, the source tree has to be
- configured and built twice.
-
-
-
-
- This results in the following usage and migration strategy:
-
-
-
-
- Existing users and users who are currently not interested in
- Python 3 use the language name plpythonu and
- don't have to change anything for the foreseeable future. It is
- recommended to gradually future-proof
the code
- via migration to Python 2.6/2.7 to simplify the eventual
- migration to Python 3.
-
-
-
- In practice, many PL/Python functions will migrate to Python 3
- with few or no changes.
-
-
-
-
-
- Users who know that they have heavily Python 2 dependent code
- and don't plan to ever change it can make use of
- the plpython2u language name. This will
- continue to work into the very distant future, until Python 2
- support might be completely dropped by PostgreSQL.
-
-
-
-
-
- Users who want to dive into Python 3 can use
- the plpython3u language name, which will keep
- working forever by today's standards. In the distant future,
- when Python 3 might become the default, they might like to
- remove the 3
for aesthetic reasons.
-
-
-
-
-
- Daredevils, who want to build a Python-3-only operating system
- environment, can change the contents of
- plpythonu's extension control and script files
- to make plpythonu be equivalent
- to plpython3u, keeping in mind that this
- would make their installation incompatible with most of the rest
- of the world.
-
-
-
-
-
-
- See also the
- document What's
- New In Python 3.0 for more information about porting to
- Python 3.
-
-
-
- It is not allowed to use PL/Python based on Python 2 and PL/Python
- based on Python 3 in the same session, because the symbols in the
- dynamic modules would clash, which could result in crashes of the
- PostgreSQL server process. There is a check that prevents mixing
- Python major versions in a session, which will abort the session if
- a mismatch is detected. It is possible, however, to use both
- PL/Python variants in the same database, from separate sessions.
-
-
-
PL/Python Functions
@@ -193,7 +58,7 @@ CREATE FUNCTION funcname (argument-list<
RETURNS return-type
AS $$
# PL/Python function body
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -225,7 +90,7 @@ AS $$
if a > b:
return a
return b
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
The Python code that is given as the body of the function definition
@@ -255,7 +120,7 @@ CREATE FUNCTION pystrip(x text)
AS $$
x = x.strip() # error
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
because assigning to x
makes x a local variable for the entire block,
@@ -271,7 +136,7 @@ AS $$
global x
x = x.strip() # ok now
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
But it is advisable not to rely on this implementation detail of
PL/Python. It is better to treat the function parameters as
@@ -303,11 +168,8 @@ $$ LANGUAGE plpythonu;
- PostgreSQL smallint and int are
- converted to Python int.
- PostgreSQL bigint and oid are converted
- to long in Python 2 and to int in
- Python 3.
+ PostgreSQL smallint, int, bigint
+ and oid are converted to Python int.
@@ -335,19 +197,15 @@ $$ LANGUAGE plpythonu;
- PostgreSQL bytea is converted to
- Python str in Python 2 and to bytes
- in Python 3. In Python 2, the string should be treated as a
- byte sequence without any character encoding.
+ PostgreSQL bytea is converted to Python bytes.
- All other data types, including the PostgreSQL character string
- types, are converted to a Python str. In Python
- 2, this string will be in the PostgreSQL server encoding; in
- Python 3, it will be a Unicode string like all strings.
+ All other data types, including the PostgreSQL character string types,
+ are converted to a Python str (in Unicode like all Python
+ strings).
@@ -375,10 +233,10 @@ $$ LANGUAGE plpythonu;
- When the PostgreSQL return type is bytea, the
- return value will be converted to a string (Python 2) or bytes
- (Python 3) using the respective Python built-ins, with the
- result being converted to bytea.
+ When the PostgreSQL return type is bytea, the return value
+ will be converted to Python bytes using the respective
+ Python built-ins, with the result being converted to
+ bytea.
@@ -393,14 +251,8 @@ $$ LANGUAGE plpythonu;
- Strings in Python 2 are required to be in the PostgreSQL server
- encoding when they are passed to PostgreSQL. Strings that are
- not valid in the current server encoding will raise an error,
- but not all encoding mismatches can be detected, so garbage
- data can still result when this is not done correctly. Unicode
- strings are converted to the correct encoding automatically, so
- it can be safer and more convenient to use those. In Python 3,
- all strings are Unicode strings.
+ Strings are automatically converted to the PostgreSQL server encoding
+ when they are passed to PostgreSQL.
@@ -440,7 +292,7 @@ AS $$
if a > b:
return a
return b
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
As shown above, to return an SQL null value from a PL/Python
@@ -461,10 +313,10 @@ CREATE FUNCTION return_arr()
RETURNS int[]
AS $$
return [1, 2, 3, 4, 5]
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT return_arr();
- return_arr
+ return_arr
-------------
{1,2,3,4,5}
(1 row)
@@ -479,11 +331,11 @@ SELECT return_arr();
CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_int4(ARRAY[[1,2,3],[4,5,6]]);
INFO: ([[1, 2, 3], [4, 5, 6]], <type 'list'>)
- test_type_conversion_array_int4
+ test_type_conversion_array_int4
---------------------------------
{{1,2,3},{4,5,6}}
(1 row)
@@ -506,7 +358,7 @@ CREATE FUNCTION return_str_arr()
RETURNS varchar[]
AS $$
return "hello"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT return_str_arr();
return_str_arr
@@ -540,7 +392,7 @@ AS $$
if (e["age"] < 30) and (e["salary"] > 100000):
return True
return False
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -574,7 +426,7 @@ CREATE FUNCTION make_pair (name text, value integer)
AS $$
return ( name, value )
# or alternatively, as list: return [ name, value ]
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
To return an SQL null for any column, insert None at
@@ -600,7 +452,7 @@ CREATE FUNCTION make_pair (name text, value integer)
RETURNS named_value
AS $$
return { "name": name, "value": value }
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
Any extra dictionary key/value pairs are ignored. Missing keys are
@@ -633,7 +485,7 @@ AS $$
nv.name = name
nv.value = value
return nv
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -646,7 +498,7 @@ $$ LANGUAGE plpythonu;
CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$
return (1, 2)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM multiout_simple();
@@ -657,7 +509,7 @@ SELECT * FROM multiout_simple();
CREATE PROCEDURE python_triple(INOUT a integer, INOUT b integer) AS $$
return (a * 3, b * 3)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
CALL python_triple(5, 10);
@@ -693,7 +545,7 @@ AS $$
# return tuple containing lists as composite types
# all other combinations work also
return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] )
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -724,7 +576,7 @@ AS $$
return ( self.how, self.who[self.ndx] )
return producer(how, [ "World", "PostgreSQL", "PL/Python" ])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -740,7 +592,7 @@ CREATE FUNCTION greet (how text)
AS $$
for who in [ "World", "PostgreSQL", "PL/Python" ]:
yield ( how, who )
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -756,7 +608,7 @@ $$ LANGUAGE plpythonu;
CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$
return [(1, 2)] * n
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM multiout_simple_setof(3);
@@ -794,7 +646,7 @@ SELECT * FROM multiout_simple_setof(3);
DO $$
# PL/Python code
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
An anonymous code block receives no arguments, and whatever value it
@@ -1089,7 +941,7 @@ CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
plan = plpy.prepare("SELECT 1")
SD["plan"] = plan
# rest of function
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -1132,7 +984,7 @@ for row in plpy.cursor("select num from largetable"):
if row['num'] % 2:
odd += 1
return odd
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$
odd = 0
@@ -1145,7 +997,7 @@ while True:
if row['num'] % 2:
odd += 1
return odd
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$
odd = 0
@@ -1153,7 +1005,7 @@ plan = plpy.prepare("select num from largetable where num % $1 <> 0", ["in
rows = list(plpy.cursor(plan, [2])) # or: = list(plan.cursor([2]))
return len(rows)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -1198,7 +1050,7 @@ CREATE FUNCTION try_adding_joe() RETURNS text AS $$
return "something went wrong"
else:
return "Joe added"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
@@ -1231,7 +1083,7 @@ except plpy.SPIError as e:
return "other error, SQLSTATE %s" % e.sqlstate
else:
return "fraction inserted"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
Note that because all exceptions from
the plpy.spiexceptions module inherit
@@ -1280,7 +1132,7 @@ else:
result = "funds transferred correctly"
plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
If the second UPDATE statement results in an
exception being raised, this function will report the error, but
@@ -1312,7 +1164,7 @@ else:
result = "funds transferred correctly"
plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
Note that the use of try/catch is still
required. Otherwise the exception would propagate to the top of
@@ -1329,44 +1181,6 @@ $$ LANGUAGE plpythonu;
to be rolled back.
-
-
- Older Python Versions
-
-
- Context managers syntax using the with keyword
- is available by default in Python 2.6. For compatibility with
- older Python versions, you can call the
- subtransaction manager's __enter__ and
- __exit__ functions using the
- enter and exit convenience
- aliases. The example function that transfers funds could be
- written as:
-
-CREATE FUNCTION transfer_funds_old() RETURNS void AS $$
-try:
- subxact = plpy.subtransaction()
- subxact.enter()
- try:
- plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
- plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
- except:
- import sys
- subxact.exit(*sys.exc_info())
- raise
- else:
- subxact.exit(None, None, None)
-except plpy.SPIError as e:
- result = "error transferring funds: %s" % e.args
-else:
- result = "funds transferred correctly"
-
-plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
-plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
-
-
-
@@ -1389,7 +1203,7 @@ $$ LANGUAGE plpythonu;
Here is an example:
CREATE PROCEDURE transaction_test1()
-LANGUAGE plpythonu
+LANGUAGE plpython3u
AS $$
for i in range(0, 10):
plpy.execute("INSERT INTO test1 (a) VALUES (%d)" % i)
@@ -1465,7 +1279,7 @@ CREATE FUNCTION raise_custom_exception() RETURNS void AS $$
plpy.error("custom exception message",
detail="some info about exception",
hint="hint for users")
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
=# SELECT raise_custom_exception();
ERROR: plpy.Error: custom exception message
@@ -1496,6 +1310,17 @@ plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % (
+
+ Python 2 vs. Python 3
+
+
+ PL/Python supports only Python 3. Past versions of
+ PostgreSQL supported Python 2, using the
+ plpythonu and plpython2u language
+ names.
+
+
+
Environment Variables
diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml
index b12796095f..23d9029af9 100644
--- a/doc/src/sgml/ref/comment.sgml
+++ b/doc/src/sgml/ref/comment.sgml
@@ -349,7 +349,7 @@ COMMENT ON TEXT SEARCH CONFIGURATION my_config IS 'Special word filtering';
COMMENT ON TEXT SEARCH DICTIONARY swedish IS 'Snowball stemmer for Swedish language';
COMMENT ON TEXT SEARCH PARSER my_parser IS 'Splits text into words';
COMMENT ON TEXT SEARCH TEMPLATE snowball IS 'Snowball stemmer';
-COMMENT ON TRANSFORM FOR hstore LANGUAGE plpythonu IS 'Transform between hstore and Python dict';
+COMMENT ON TRANSFORM FOR hstore LANGUAGE plpython3u IS 'Transform between hstore and Python dict';
COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for RI';
COMMENT ON TYPE complex IS 'Complex number data type';
COMMENT ON VIEW my_view IS 'View of departmental costs';
diff --git a/doc/src/sgml/ref/create_transform.sgml b/doc/src/sgml/ref/create_transform.sgml
index 3f81dc6bba..34bdc60e13 100644
--- a/doc/src/sgml/ref/create_transform.sgml
+++ b/doc/src/sgml/ref/create_transform.sgml
@@ -156,11 +156,11 @@ CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAG
To create a transform for type hstore and language
- plpythonu, first set up the type and the language:
+ plpython3u, first set up the type and the language:
CREATE TYPE hstore ...;
-CREATE EXTENSION plpythonu;
+CREATE EXTENSION plpython3u;
Then create the necessary functions:
@@ -174,7 +174,7 @@ AS ...;
And finally create the transform to connect them all together:
-CREATE TRANSFORM FOR hstore LANGUAGE plpythonu (
+CREATE TRANSFORM FOR hstore LANGUAGE plpython3u (
FROM SQL WITH FUNCTION hstore_to_plpython(internal),
TO SQL WITH FUNCTION plpython_to_hstore(internal)
);
diff --git a/doc/src/sgml/ref/drop_transform.sgml b/doc/src/sgml/ref/drop_transform.sgml
index d25cb51604..544a9663d7 100644
--- a/doc/src/sgml/ref/drop_transform.sgml
+++ b/doc/src/sgml/ref/drop_transform.sgml
@@ -101,9 +101,9 @@ DROP TRANSFORM [ IF EXISTS ] FOR type_name LANGUAGE <
To drop the transform for type hstore and language
- plpythonu:
+ plpython3u:
-DROP TRANSFORM FOR hstore LANGUAGE plpythonu;
+DROP TRANSFORM FOR hstore LANGUAGE plpython3u;