From 4228cabb72bb57e1df4c9d92613f1fcd4baadd5a Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Mon, 7 Mar 2022 18:30:57 -0800 Subject: [PATCH] plpython: Adjust docs after removal of Python 2 support. Reviewed-By: Tom Lane Discussion: https://postgr.es/m/20211031184548.g4sxfe47n2kyi55r@alap3.anarazel.de --- doc/src/sgml/hstore.sgml | 8 +- doc/src/sgml/json.sgml | 9 +- doc/src/sgml/ltree.sgml | 10 +- doc/src/sgml/plpython.sgml | 289 +++++-------------------- doc/src/sgml/ref/comment.sgml | 2 +- doc/src/sgml/ref/create_transform.sgml | 6 +- doc/src/sgml/ref/drop_transform.sgml | 4 +- 7 files changed, 71 insertions(+), 257 deletions(-) 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;