Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postgres/src/pl/plpython/expected/   (The Python Language ©)  Datei vom 11.4.2026 mit Größe 14 kB image not shown  

Quelle  plpython_composite.out   Sprache: unbekannt

 
Spracherkennung für: .out vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$
return (12)
$$ LANGUAGE plpython3u;
SELECT multiout_simple();
 multiout_simple 
-----------------
 (1,2)
(1 row)

SELECT * FROM multiout_simple();
 i | j 
---+---
 1 | 2
(1 row)

SELECT i, j + 2 FROM multiout_simple();
 i | ?column? 
---+----------
 1 |        4
(1 row)

SELECT (multiout_simple()).j + 3;
 ?column? 
----------
        5
(1 row)

CREATE FUNCTION multiout_simple_setof(n integer = 1, OUT integer, OUT integer) RETURNS SETOF record AS $$
return [(12)] * n
$$ LANGUAGE plpython3u;
SELECT multiout_simple_setof();
 multiout_simple_setof 
-----------------------
 (1,2)
(1 row)

SELECT * FROM multiout_simple_setof();
 column1 | column2 
---------+---------
       1 |       2
(1 row)

SELECT * FROM multiout_simple_setof(3);
 column1 | column2 
---------+---------
       1 |       2
       1 |       2
       1 |       2
(3 rows)

CREATE FUNCTION multiout_record_as(typ text,
                                   first text, OUT first text,
                                   second integer, OUT second integer,
                                   retnull boolean) RETURNS record AS $$
if retnull:
    return None
if typ == 'dict':
    return { 'first': first, 'second': second, 'additionalfield': 'must not cause trouble' }
elif typ == 'tuple':
    return ( first, second )
elif typ == 'list':
    return [ first, second ]
elif typ == 'obj':
    class type_record: pass
    type_record.first = first
    type_record.second = second
    return type_record
elif typ == 'str':
    return "('%s',%r)" % (first, second)
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_record_as('dict', 'foo', 1, 'f');
 first | second 
-------+--------
 foo   |      1
(1 row)

SELECT multiout_record_as('dict', 'foo', 1, 'f');
 multiout_record_as 
--------------------
 (foo,1)
(1 row)

SELECT * FROM multiout_record_as('dict', null, null, false);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('dict', 'one', null, false);
 first | second 
-------+--------
 one   |       
(1 row)

SELECT * FROM multiout_record_as('dict', null, 2, false);
 first | second 
-------+--------
       |      2
(1 row)

SELECT * FROM multiout_record_as('dict', 'three', 3, false);
 first | second 
-------+--------
 three |      3
(1 row)

SELECT * FROM multiout_record_as('dict', null, null, true);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('tuple', null, null, false);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('tuple', 'one', null, false);
 first | second 
-------+--------
 one   |       
(1 row)

SELECT * FROM multiout_record_as('tuple', null, 2, false);
 first | second 
-------+--------
       |      2
(1 row)

SELECT * FROM multiout_record_as('tuple', 'three', 3, false);
 first | second 
-------+--------
 three |      3
(1 row)

SELECT * FROM multiout_record_as('tuple', null, null, true);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('list', null, null, false);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('list', 'one', null, false);
 first | second 
-------+--------
 one   |       
(1 row)

SELECT * FROM multiout_record_as('list', null, 2, false);
 first | second 
-------+--------
       |      2
(1 row)

SELECT * FROM multiout_record_as('list', 'three', 3, false);
 first | second 
-------+--------
 three |      3
(1 row)

SELECT * FROM multiout_record_as('list', null, null, true);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('obj', null, null, false);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('obj', 'one', null, false);
 first | second 
-------+--------
 one   |       
(1 row)

SELECT * FROM multiout_record_as('obj', null, 2, false);
 first | second 
-------+--------
       |      2
(1 row)

SELECT * FROM multiout_record_as('obj', 'three', 3, false);
 first | second 
-------+--------
 three |      3
(1 row)

SELECT * FROM multiout_record_as('obj', null, null, true);
 first | second 
-------+--------
       |       
(1 row)

SELECT * FROM multiout_record_as('str', 'one', 1, false);
 first | second 
-------+--------
 'one' |      1
(1 row)

SELECT * FROM multiout_record_as('str', 'one', 2, false);
 first | second 
-------+--------
 'one' |      2
(1 row)

SELECT *, s IS NULL AS snull FROM multiout_record_as('tuple', 'xxx', NULL, 'f') AS f(f, s);
  f  | s | snull 
-----+---+-------
 xxx |   | t
(1 row)

SELECT *, f IS NULL AS fnull, s IS NULL AS snull FROM multiout_record_as('tuple', 'xxx', 1, 't') AS f(f, s);
 f | s | fnull | snull 
---+---+-------+-------
   |   | t     | t
(1 row)

SELECT * FROM multiout_record_as('obj', NULL, 10, 'f');
 first | second 
-------+--------
       |     10
(1 row)

CREATE FUNCTION multiout_setof(n integer,
                               OUT power_of_2 integer,
                               OUT length integer) RETURNS SETOF record AS $$
for i in range(n):
    power = 2 ** i
    length = plpy.execute("select length('%d')" % power)[0]['length']
    yield power, length
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_setof(3);
 power_of_2 | length 
------------+--------
          1 |      1
          2 |      1
          4 |      1
(3 rows)

SELECT multiout_setof(5);
 multiout_setof 
----------------
 (1,1)
 (2,1)
 (4,1)
 (8,1)
 (16,2)
(5 rows)

CREATE FUNCTION multiout_return_table() RETURNS TABLE (x integer, y text) AS $$
return [{'x': 4, 'y' :'four'},
        {'x': 7, 'y' :'seven'},
        {'x': 0, 'y' :'zero'}]
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_return_table();
 x |   y   
---+-------
 4 | four
 7 | seven
 0 | zero
(3 rows)

CREATE FUNCTION multiout_array(OUT integer[], OUT text) RETURNS SETOF record AS $$
yield [[1], 'a']
yield [[1,2], 'b']
yield [[1,2,3], None]
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_array();
 column1 | column2 
---------+---------
 {1}     | a
 {1,2}   | b
 {1,2,3} | 
(3 rows)

CREATE FUNCTION singleout_composite(OUT type_record) AS $$
return {'first': 1, 'second': 2}
$$ LANGUAGE plpython3u;
CREATE FUNCTION multiout_composite(OUT type_record) RETURNS SETOF type_record AS $$
return [{'first': 1, 'second': 2},
       {'first': 3, 'second': 4 }]
$$ LANGUAGE plpython3u;
SELECT * FROM singleout_composite();
 first | second 
-------+--------
 1     |      2
(1 row)

SELECT * FROM multiout_composite();
 first | second 
-------+--------
 1     |      2
 3     |      4
(2 rows)

-- composite OUT parameters in functions returning RECORD not supported yet
CREATE FUNCTION multiout_composite(INOUT n integer, OUT type_record) AS $$
return (n, (n * 2, n * 3))
$$ LANGUAGE plpython3u;
CREATE FUNCTION multiout_table_type_setof(typ text, returnnull boolean, INOUT n integer, OUT table_record) RETURNS SETOF record AS $$
if returnnull:
    d = None
elif typ == 'dict':
    d = {'first': n * 2, 'second': n * 3, 'extra': 'not important'}
elif typ == 'tuple':
    d = (n * 2, n * 3)
elif typ == 'list':
    d = [ n * 2, n * 3 ]
elif typ == 'obj':
    class d: pass
    d.first = n * 2
    d.second = n * 3
elif typ == 'str':
    d = "(%r,%r)" % (n * 2, n * 3)
for i in range(n):
    yield (i, d)
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_composite(2);
 n | column2 
---+---------
 2 | (4,6)
(1 row)

SELECT * FROM multiout_table_type_setof('dict', 'f', 3);
 n | column2 
---+---------
 0 | (6,9)
 1 | (6,9)
 2 | (6,9)
(3 rows)

SELECT * FROM multiout_table_type_setof('dict', 'f', 7);
 n | column2 
---+---------
 0 | (14,21)
 1 | (14,21)
 2 | (14,21)
 3 | (14,21)
 4 | (14,21)
 5 | (14,21)
 6 | (14,21)
(7 rows)

SELECT * FROM multiout_table_type_setof('tuple', 'f', 2);
 n | column2 
---+---------
 0 | (4,6)
 1 | (4,6)
(2 rows)

SELECT * FROM multiout_table_type_setof('tuple', 'f', 3);
 n | column2 
---+---------
 0 | (6,9)
 1 | (6,9)
 2 | (6,9)
(3 rows)

SELECT * FROM multiout_table_type_setof('list', 'f', 2);
 n | column2 
---+---------
 0 | (4,6)
 1 | (4,6)
(2 rows)

SELECT * FROM multiout_table_type_setof('list', 'f', 3);
 n | column2 
---+---------
 0 | (6,9)
 1 | (6,9)
 2 | (6,9)
(3 rows)

SELECT * FROM multiout_table_type_setof('obj', 'f', 4);
 n | column2 
---+---------
 0 | (8,12)
 1 | (8,12)
 2 | (8,12)
 3 | (8,12)
(4 rows)

SELECT * FROM multiout_table_type_setof('obj', 'f', 5);
 n | column2 
---+---------
 0 | (10,15)
 1 | (10,15)
 2 | (10,15)
 3 | (10,15)
 4 | (10,15)
(5 rows)

SELECT * FROM multiout_table_type_setof('str', 'f', 6);
 n | column2 
---+---------
 0 | (12,18)
 1 | (12,18)
 2 | (12,18)
 3 | (12,18)
 4 | (12,18)
 5 | (12,18)
(6 rows)

SELECT * FROM multiout_table_type_setof('str', 'f', 7);
 n | column2 
---+---------
 0 | (14,21)
 1 | (14,21)
 2 | (14,21)
 3 | (14,21)
 4 | (14,21)
 5 | (14,21)
 6 | (14,21)
(7 rows)

SELECT * FROM multiout_table_type_setof('dict', 't', 3);
 n | column2 
---+---------
 0 | 
 1 | 
 2 | 
(3 rows)

-- check what happens if a type changes under us
CREATE TABLE changing (
    i integer,
    j integer
);
CREATE FUNCTION changing_test(OUT n integer, OUT changing) RETURNS SETOF record AS $$
return [(1, {'i': 1, 'j': 2}),
        (1, (34))]
$$ LANGUAGE plpython3u;
SELECT * FROM changing_test();
 n | column2 
---+---------
 1 | (1,2)
 1 | (3,4)
(2 rows)

ALTER TABLE changing DROP COLUMN j;
SELECT * FROM changing_test();
ERROR:  length of returned sequence did not match number of columns in row
CONTEXT:  while creating return value
PL/Python function "changing_test"
SELECT * FROM changing_test();
ERROR:  length of returned sequence did not match number of columns in row
CONTEXT:  while creating return value
PL/Python function "changing_test"
ALTER TABLE changing ADD COLUMN j integer;
SELECT * FROM changing_test();
 n | column2 
---+---------
 1 | (1,2)
 1 | (3,4)
(2 rows)

-- tables of composite types
CREATE FUNCTION composite_types_table(OUT tab table_record[], OUT typ type_record[] ) RETURNS SETOF record AS $$
yield {'tab': [('first', 1), ('second', 2)],
      'typ': [{'first': 'third', 'second': 3},
              {'first': 'fourth', 'second': 4}]}
yield {'tab': [('first', 1), ('second', 2)],
      'typ': [{'first': 'third', 'second': 3},
              {'first': 'fourth', 'second': 4}]}
yield {'tab': [('first', 1), ('second', 2)],
      'typ': [{'first': 'third', 'second': 3},
              {'first': 'fourth', 'second': 4}]}
$$ LANGUAGE plpython3u;
SELECT * FROM composite_types_table();
            tab             |            typ             
----------------------------+----------------------------
 {"(first,1)","(second,2)"} | {"(third,3)","(fourth,4)"}
 {"(first,1)","(second,2)"} | {"(third,3)","(fourth,4)"}
 {"(first,1)","(second,2)"} | {"(third,3)","(fourth,4)"}
(3 rows)

-- check what happens if the output record descriptor changes
CREATE FUNCTION return_record(t text) RETURNS record AS $$
return {'t': t, 'val': 10}
$$ LANGUAGE plpython3u;
SELECT * FROM return_record('abc') AS r(t text, val integer);
  t  | val 
-----+-----
 abc |  10
(1 row)

SELECT * FROM return_record('abc') AS r(t text, val bigint);
  t  | val 
-----+-----
 abc |  10
(1 row)

SELECT * FROM return_record('abc') AS r(t text, val integer);
  t  | val 
-----+-----
 abc |  10
(1 row)

SELECT * FROM return_record('abc') AS r(t varchar(30), val integer);
  t  | val 
-----+-----
 abc |  10
(1 row)

SELECT * FROM return_record('abc') AS r(t varchar(100), val integer);
  t  | val 
-----+-----
 abc |  10
(1 row)

SELECT * FROM return_record('999') AS r(val text, t integer);
 val |  t  
-----+-----
 10  | 999
(1 row)

CREATE FUNCTION return_record_2(t text) RETURNS record AS $$
return {'v1':1,'v2':2,t:3}
$$ LANGUAGE plpython3u;
SELECT * FROM return_record_2('v3') AS (v3 int, v2 int, v1 int);
 v3 | v2 | v1 
----+----+----
  3 |  2 |  1
(1 row)

SELECT * FROM return_record_2('v3') AS (v2 int, v3 int, v1 int);
 v2 | v3 | v1 
----+----+----
  2 |  3 |  1
(1 row)

SELECT * FROM return_record_2('v4') AS (v1 int, v4 int, v2 int);
 v1 | v4 | v2 
----+----+----
  1 |  3 |  2
(1 row)

SELECT * FROM return_record_2('v4') AS (v1 int, v4 int, v2 int);
 v1 | v4 | v2 
----+----+----
  1 |  3 |  2
(1 row)

-- error
SELECT * FROM return_record_2('v4') AS (v1 int, v3 int, v2 int);
ERROR:  key "v3" not found in mapping
HINT:  To return null in a column, add the value None to the mapping with the key named after the column.
CONTEXT:  while creating return value
PL/Python function "return_record_2"
-- works
SELECT * FROM return_record_2('v3') AS (v1 int, v3 int, v2 int);
 v1 | v3 | v2 
----+----+----
  1 |  3 |  2
(1 row)

SELECT * FROM return_record_2('v3') AS (v1 int, v2 int, v3 int);
 v1 | v2 | v3 
----+----+----
  1 |  2 |  3
(1 row)

-- recursion with a different inner result type didn't use to work
CREATE FUNCTION return_record_3(t text) RETURNS record AS $$
if t == "text":
     plpy.execute("SELECT * FROM return_record_3('int') AS (a int)");
     return { "a": "x" }
elif t == "int":
     return { "a": 1 }
$$ LANGUAGE plpython3u;
SELECT * FROM return_record_3('text') AS (a text);
 a 
---
 x
(1 row)

-- multi-dimensional array of composite types.
CREATE FUNCTION composite_type_as_list()  RETURNS type_record[] AS $$
  return [[('first', 1), ('second', 1)], [('first', 2), ('second', 2)], [('first', 3), ('second', 3)]];
$$ LANGUAGE plpython3u;
SELECT * FROM composite_type_as_list();
                               composite_type_as_list                               
------------------------------------------------------------------------------------
 {{"(first,1)","(second,1)"},{"(first,2)","(second,2)"},{"(first,3)","(second,3)"}}
(1 row)

-- Starting with PostgreSQL 10, a composite type in an array cannot be
-- represented as a Python list, because it's ambiguous with multi-dimensional
-- arrays. So this throws an error now. The error should contain a useful hint
-- on the issue.
CREATE FUNCTION composite_type_as_list_broken()  RETURNS type_record[] AS $$
  return [['first', 1]];
$$ LANGUAGE plpython3u;
SELECT * FROM composite_type_as_list_broken();
ERROR:  malformed record literal: "first"
DETAIL:  Missing left parenthesis.
HINT:  To return a composite type in an array, return the composite type as a Python tuple, e.g., "[('foo',)]".
CONTEXT:  while creating return value
PL/Python function "composite_type_as_list_broken"

[Dauer der Verarbeitung: 0.24 Sekunden, vorverarbeitet 2026-08-08]