Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
cfe380a6
Commit
cfe380a6
authored
Aug 13, 2009
by
Peter Eisentraut
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Augment test coverage in PL/Python, especially for error conditions.
parent
50125511
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
573 additions
and
34 deletions
+573
-34
src/pl/plpython/expected/plpython_params.out
src/pl/plpython/expected/plpython_params.out
+6
-0
src/pl/plpython/expected/plpython_record.out
src/pl/plpython/expected/plpython_record.out
+31
-0
src/pl/plpython/expected/plpython_schema.out
src/pl/plpython/expected/plpython_schema.out
+0
-8
src/pl/plpython/expected/plpython_setof.out
src/pl/plpython/expected/plpython_setof.out
+7
-0
src/pl/plpython/expected/plpython_test.out
src/pl/plpython/expected/plpython_test.out
+24
-0
src/pl/plpython/expected/plpython_trigger.out
src/pl/plpython/expected/plpython_trigger.out
+279
-8
src/pl/plpython/plpython.c
src/pl/plpython/plpython.c
+2
-2
src/pl/plpython/sql/plpython_params.sql
src/pl/plpython/sql/plpython_params.sql
+1
-0
src/pl/plpython/sql/plpython_record.sql
src/pl/plpython/sql/plpython_record.sql
+36
-0
src/pl/plpython/sql/plpython_schema.sql
src/pl/plpython/sql/plpython_schema.sql
+0
-10
src/pl/plpython/sql/plpython_setof.sql
src/pl/plpython/sql/plpython_setof.sql
+7
-0
src/pl/plpython/sql/plpython_spi.sql
src/pl/plpython/sql/plpython_spi.sql
+0
-1
src/pl/plpython/sql/plpython_test.sql
src/pl/plpython/sql/plpython_test.sql
+15
-0
src/pl/plpython/sql/plpython_trigger.sql
src/pl/plpython/sql/plpython_trigger.sql
+165
-5
No files found.
src/pl/plpython/expected/plpython_params.out
View file @
cfe380a6
...
...
@@ -43,6 +43,12 @@ SELECT test_param_names2(users) from users;
{'lname': 'smith', 'username': 'slash', 'userid': 4, 'fname': 'rick'}
(4 rows)
SELECT test_param_names2(NULL);
test_param_names2
-------------------
None
(1 row)
SELECT test_param_names3(1);
test_param_names3
-------------------
...
...
src/pl/plpython/expected/plpython_record.out
View file @
cfe380a6
--
-- Test returning tuples
--
CREATE TABLE table_record (
first text,
second int4
) ;
CREATE TYPE type_record AS (
first text,
second int4
) ;
CREATE FUNCTION test_table_record_as(typ text, first text, second integer, retnull boolean) RETURNS table_record AS $$
if retnull:
return None
...
...
@@ -298,3 +306,26 @@ SELECT * FROM test_inout_params('test_in');
test_in_inout
(1 row)
-- errors cases
CREATE FUNCTION test_type_record_error1() RETURNS type_record AS $$
return { 'first': 'first' }
$$ LANGUAGE plpythonu;
SELECT * FROM test_type_record_error1();
ERROR: key "second" 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: PL/Python function "test_type_record_error1"
CREATE FUNCTION test_type_record_error2() RETURNS type_record AS $$
return [ 'first' ]
$$ LANGUAGE plpythonu;
SELECT * FROM test_type_record_error2();
ERROR: length of returned sequence did not match number of columns in row
CONTEXT: PL/Python function "test_type_record_error2"
CREATE FUNCTION test_type_record_error3() RETURNS type_record AS $$
class type_record: pass
type_record.first = 'first'
return type_record
$$ LANGUAGE plpythonu;
SELECT * FROM test_type_record_error3();
ERROR: attribute "second" does not exist in Python object
HINT: To return null in a column, let the returned object have an attribute named after column with value None.
CONTEXT: PL/Python function "test_type_record_error3"
src/pl/plpython/expected/plpython_schema.out
View file @
cfe380a6
...
...
@@ -41,11 +41,3 @@ CREATE TABLE xsequences (
sequence text not null
) ;
CREATE INDEX xsequences_pid_idx ON xsequences(pid) ;
CREATE TABLE table_record (
first text,
second int4
) ;
CREATE TYPE type_record AS (
first text,
second int4
) ;
src/pl/plpython/expected/plpython_setof.out
View file @
cfe380a6
--
-- Test returning SETOF
--
CREATE FUNCTION test_setof_error() RETURNS SETOF text AS $$
return 37
$$ LANGUAGE plpythonu;
SELECT test_setof_error();
ERROR: returned object cannot be iterated
DETAIL: PL/Python set-returning functions must return an iterable object.
CONTEXT: PL/Python function "test_setof_error"
CREATE FUNCTION test_setof_as_list(count integer, content text) RETURNS SETOF text AS $$
return [ content ]*count
$$ LANGUAGE plpythonu;
...
...
src/pl/plpython/expected/plpython_test.out
View file @
cfe380a6
...
...
@@ -26,3 +26,27 @@ select argument_test_one(users, fname, lname) from users where lname = 'doe' ord
willem doe => {fname: willem, lname: doe, userid: 3, username: w_doe}
(3 rows)
CREATE FUNCTION elog_test() RETURNS void
AS $$
plpy.debug('debug')
plpy.log('log')
plpy.info('info')
plpy.info(37)
plpy.info('info', 37, [1, 2, 3])
plpy.notice('notice')
plpy.warning('warning')
plpy.error('error')
$$ LANGUAGE plpythonu;
SELECT elog_test();
INFO: ('info',)
CONTEXT: PL/Python function "elog_test"
INFO: (37,)
CONTEXT: PL/Python function "elog_test"
INFO: ('info', 37, [1, 2, 3])
CONTEXT: PL/Python function "elog_test"
NOTICE: ('notice',)
CONTEXT: PL/Python function "elog_test"
WARNING: ('warning',)
CONTEXT: PL/Python function "elog_test"
ERROR: ('error',)
CONTEXT: PL/Python function "elog_test"
src/pl/plpython/expected/plpython_trigger.out
View file @
cfe380a6
...
...
@@ -81,17 +81,43 @@ for key in skeys:
return None
$$;
CREATE TRIGGER show_trigger_data_trig
CREATE TRIGGER show_trigger_data_trig
_before
BEFORE INSERT OR UPDATE OR DELETE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
CREATE TRIGGER show_trigger_data_trig_after
AFTER INSERT OR UPDATE OR DELETE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
CREATE TRIGGER show_trigger_data_trig_stmt
BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE ON trigger_test
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_data(23,'skidoo');
insert into trigger_test values(1,'insert');
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => INSERT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => STATEMENT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_stmt',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => INSERT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
NOTICE: ('TD[name] => show_trigger_data_trig
_before
',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'insert'}",)
CONTEXT: PL/Python function "trigger_data"
...
...
@@ -105,14 +131,54 @@ NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => INSERT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_after',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'insert'}",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => AFTER',)
CONTEXT: PL/Python function "trigger_data"
update trigger_test set v = 'update' where i = 1;
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => UPDATE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => STATEMENT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_stmt',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => UPDATE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
NOTICE: ('TD[name] => show_trigger_data_trig
_before
',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'update'}",)
CONTEXT: PL/Python function "trigger_data"
...
...
@@ -126,14 +192,74 @@ NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => UPDATE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_after',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'update'}",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[old] => {'i': 1, 'v': 'insert'}",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => AFTER',)
CONTEXT: PL/Python function "trigger_data"
delete from trigger_test;
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => DELETE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => STATEMENT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_stmt',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => DELETE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_before',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[old] => {'i': 1, 'v': 'update'}",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => DELETE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
NOTICE: ('TD[name] => show_trigger_data_trig
_after
',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
...
...
@@ -145,9 +271,154 @@ NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => AFTER',)
CONTEXT: PL/Python function "trigger_data"
truncate table trigger_test;
NOTICE: ("TD[args] => ['23', 'skidoo']",)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => TRUNCATE',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => STATEMENT',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig_stmt',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
CONTEXT: PL/Python function "trigger_data"
DROP TRIGGER show_trigger_data_trig on trigger_test;
DROP FUNCTION trigger_data();
DROP FUNCTION trigger_data() CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to trigger show_trigger_data_trig_before on table trigger_test
drop cascades to trigger show_trigger_data_trig_after on table trigger_test
drop cascades to trigger show_trigger_data_trig_stmt on table trigger_test
--
-- trigger error handling
--
INSERT INTO trigger_test VALUES (0, 'zero');
-- returning non-string from trigger function
CREATE FUNCTION stupid1() RETURNS trigger
AS $$
return 37
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger1
BEFORE INSERT ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid1();
INSERT INTO trigger_test VALUES (1, 'one');
ERROR: unexpected return value from trigger procedure
DETAIL: Expected None or a string.
CONTEXT: PL/Python function "stupid1"
DROP TRIGGER stupid_trigger1 ON trigger_test;
-- returning MODIFY from DELETE trigger
CREATE FUNCTION stupid2() RETURNS trigger
AS $$
return "MODIFY"
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger2
BEFORE DELETE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid2();
DELETE FROM trigger_test WHERE i = 0;
WARNING: PL/Python trigger function returned "MODIFY" in a DELETE trigger -- ignored
CONTEXT: PL/Python function "stupid2"
DROP TRIGGER stupid_trigger2 ON trigger_test;
INSERT INTO trigger_test VALUES (0, 'zero');
-- returning unrecognized string from trigger function
CREATE FUNCTION stupid3() RETURNS trigger
AS $$
return "foo"
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger3
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid3();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
ERROR: unexpected return value from trigger procedure
DETAIL: Expected None, "OK", "SKIP", or "MODIFY".
CONTEXT: PL/Python function "stupid3"
DROP TRIGGER stupid_trigger3 ON trigger_test;
-- deleting the TD dictionary
CREATE FUNCTION stupid4() RETURNS trigger
AS $$
del TD["new"]
return "MODIFY";
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger4
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid4();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
ERROR: TD["new"] deleted, cannot modify row
CONTEXT: PL/Python function "stupid4"
DROP TRIGGER stupid_trigger4 ON trigger_test;
-- TD not a dictionary
CREATE FUNCTION stupid5() RETURNS trigger
AS $$
TD["new"] = ['foo', 'bar']
return "MODIFY";
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger5
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid5();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
ERROR: TD["new"] is not a dictionary
CONTEXT: PL/Python function "stupid5"
DROP TRIGGER stupid_trigger5 ON trigger_test;
-- TD not having string keys
CREATE FUNCTION stupid6() RETURNS trigger
AS $$
TD["new"] = {1: 'foo', 2: 'bar'}
return "MODIFY";
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger6
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid6();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
ERROR: TD["new"] dictionary key at ordinal position 0 is not a string
CONTEXT: PL/Python function "stupid6"
DROP TRIGGER stupid_trigger6 ON trigger_test;
-- TD keys not corresponding to row columns
CREATE FUNCTION stupid7() RETURNS trigger
AS $$
TD["new"] = {'a': 'foo', 'b': 'bar'}
return "MODIFY";
$$ LANGUAGE plpythonu;
CREATE TRIGGER stupid_trigger7
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE stupid7();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
ERROR: key "a" found in TD["new"] does not exist as a column in the triggering row
CONTEXT: PL/Python function "stupid7"
DROP TRIGGER stupid_trigger7 ON trigger_test;
-- calling a trigger function directly
SELECT stupid7();
ERROR: trigger functions can only be called as triggers
--
-- Null values
--
SELECT * FROM trigger_test;
i | v
---+------
0 | zero
(1 row)
CREATE FUNCTION test_null() RETURNS trigger
AS $$
TD["new"]['v'] = None
return "MODIFY"
$$ LANGUAGE plpythonu;
CREATE TRIGGER test_null_trigger
BEFORE UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE test_null();
UPDATE trigger_test SET v = 'null' WHERE i = 0;
DROP TRIGGER test_null_trigger ON trigger_test;
SELECT * FROM trigger_test;
i | v
---+---
0 |
(1 row)
src/pl/plpython/plpython.c
View file @
cfe380a6
/**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL
*
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.12
3 2009/07/20 08:01:06
petere Exp $
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.12
4 2009/08/13 20:50:05
petere Exp $
*
*********************************************************************
*/
...
...
@@ -538,7 +538,7 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
platt
=
PyList_GetItem
(
plkeys
,
i
);
if
(
!
PyString_Check
(
platt
))
ereport
(
ERROR
,
(
errmsg
(
"
name of TD[
\"
new
\"
] attribute
at ordinal position %d is not a string"
,
i
)));
(
errmsg
(
"
TD[
\"
new
\"
] dictionary key
at ordinal position %d is not a string"
,
i
)));
attn
=
SPI_fnumber
(
tupdesc
,
PyString_AsString
(
platt
));
if
(
attn
==
SPI_ERROR_NOATTRIBUTE
)
ereport
(
ERROR
,
...
...
src/pl/plpython/sql/plpython_params.sql
View file @
cfe380a6
...
...
@@ -31,4 +31,5 @@ $$ LANGUAGE plpythonu;
SELECT
test_param_names0
(
2
,
7
);
SELECT
test_param_names1
(
1
,
'text'
);
SELECT
test_param_names2
(
users
)
from
users
;
SELECT
test_param_names2
(
NULL
);
SELECT
test_param_names3
(
1
);
src/pl/plpython/sql/plpython_record.sql
View file @
cfe380a6
...
...
@@ -2,6 +2,17 @@
-- Test returning tuples
--
CREATE
TABLE
table_record
(
first
text
,
second
int4
)
;
CREATE
TYPE
type_record
AS
(
first
text
,
second
int4
)
;
CREATE
FUNCTION
test_table_record_as
(
typ
text
,
first
text
,
second
integer
,
retnull
boolean
)
RETURNS
table_record
AS
$$
if
retnull
:
return
None
...
...
@@ -102,3 +113,28 @@ SELECT * FROM test_in_out_params('test_in');
-- this doesn't work yet :-(
SELECT
*
FROM
test_in_out_params_multi
(
'test_in'
);
SELECT
*
FROM
test_inout_params
(
'test_in'
);
-- errors cases
CREATE
FUNCTION
test_type_record_error1
()
RETURNS
type_record
AS
$$
return
{
'first'
:
'first'
}
$$
LANGUAGE
plpythonu
;
SELECT
*
FROM
test_type_record_error1
();
CREATE
FUNCTION
test_type_record_error2
()
RETURNS
type_record
AS
$$
return
[
'first'
]
$$
LANGUAGE
plpythonu
;
SELECT
*
FROM
test_type_record_error2
();
CREATE
FUNCTION
test_type_record_error3
()
RETURNS
type_record
AS
$$
class
type_record
:
pass
type_record
.
first
=
'first'
return
type_record
$$
LANGUAGE
plpythonu
;
SELECT
*
FROM
test_type_record_error3
();
src/pl/plpython/sql/plpython_schema.sql
View file @
cfe380a6
...
...
@@ -38,13 +38,3 @@ CREATE TABLE xsequences (
sequence
text
not
null
)
;
CREATE
INDEX
xsequences_pid_idx
ON
xsequences
(
pid
)
;
CREATE
TABLE
table_record
(
first
text
,
second
int4
)
;
CREATE
TYPE
type_record
AS
(
first
text
,
second
int4
)
;
src/pl/plpython/sql/plpython_setof.sql
View file @
cfe380a6
...
...
@@ -2,6 +2,13 @@
-- Test returning SETOF
--
CREATE
FUNCTION
test_setof_error
()
RETURNS
SETOF
text
AS
$$
return
37
$$
LANGUAGE
plpythonu
;
SELECT
test_setof_error
();
CREATE
FUNCTION
test_setof_as_list
(
count
integer
,
content
text
)
RETURNS
SETOF
text
AS
$$
return
[
content
]
*
count
$$
LANGUAGE
plpythonu
;
...
...
src/pl/plpython/sql/plpython_spi.sql
View file @
cfe380a6
-- nested calls
--
...
...
src/pl/plpython/sql/plpython_test.sql
View file @
cfe380a6
...
...
@@ -19,3 +19,18 @@ return words'
LANGUAGE
plpythonu
;
select
argument_test_one
(
users
,
fname
,
lname
)
from
users
where
lname
=
'doe'
order
by
1
;
CREATE
FUNCTION
elog_test
()
RETURNS
void
AS
$$
plpy
.
debug
(
'debug'
)
plpy
.
log
(
'log'
)
plpy
.
info
(
'info'
)
plpy
.
info
(
37
)
plpy
.
info
(
'info'
,
37
,
[
1
,
2
,
3
])
plpy
.
notice
(
'notice'
)
plpy
.
warning
(
'warning'
)
plpy
.
error
(
'error'
)
$$
LANGUAGE
plpythonu
;
SELECT
elog_test
();
src/pl/plpython/sql/plpython_trigger.sql
View file @
cfe380a6
...
...
@@ -82,14 +82,174 @@ return None
$$
;
CREATE
TRIGGER
show_trigger_data_trig
CREATE
TRIGGER
show_trigger_data_trig
_before
BEFORE
INSERT
OR
UPDATE
OR
DELETE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
trigger_data
(
23
,
'skidoo'
);
CREATE
TRIGGER
show_trigger_data_trig_after
AFTER
INSERT
OR
UPDATE
OR
DELETE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
trigger_data
(
23
,
'skidoo'
);
CREATE
TRIGGER
show_trigger_data_trig_stmt
BEFORE
INSERT
OR
UPDATE
OR
DELETE
OR
TRUNCATE
ON
trigger_test
FOR
EACH
STATEMENT
EXECUTE
PROCEDURE
trigger_data
(
23
,
'skidoo'
);
insert
into
trigger_test
values
(
1
,
'insert'
);
update
trigger_test
set
v
=
'update'
where
i
=
1
;
delete
from
trigger_test
;
DROP
TRIGGER
show_trigger_data_trig
on
trigger_test
;
DROP
FUNCTION
trigger_data
();
truncate
table
trigger_test
;
DROP
FUNCTION
trigger_data
()
CASCADE
;
--
-- trigger error handling
--
INSERT
INTO
trigger_test
VALUES
(
0
,
'zero'
);
-- returning non-string from trigger function
CREATE
FUNCTION
stupid1
()
RETURNS
trigger
AS
$$
return
37
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger1
BEFORE
INSERT
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid1
();
INSERT
INTO
trigger_test
VALUES
(
1
,
'one'
);
DROP
TRIGGER
stupid_trigger1
ON
trigger_test
;
-- returning MODIFY from DELETE trigger
CREATE
FUNCTION
stupid2
()
RETURNS
trigger
AS
$$
return
"MODIFY"
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger2
BEFORE
DELETE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid2
();
DELETE
FROM
trigger_test
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger2
ON
trigger_test
;
INSERT
INTO
trigger_test
VALUES
(
0
,
'zero'
);
-- returning unrecognized string from trigger function
CREATE
FUNCTION
stupid3
()
RETURNS
trigger
AS
$$
return
"foo"
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger3
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid3
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger3
ON
trigger_test
;
-- deleting the TD dictionary
CREATE
FUNCTION
stupid4
()
RETURNS
trigger
AS
$$
del
TD
[
"new"
]
return
"MODIFY"
;
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger4
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid4
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger4
ON
trigger_test
;
-- TD not a dictionary
CREATE
FUNCTION
stupid5
()
RETURNS
trigger
AS
$$
TD
[
"new"
]
=
[
'foo'
,
'bar'
]
return
"MODIFY"
;
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger5
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid5
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger5
ON
trigger_test
;
-- TD not having string keys
CREATE
FUNCTION
stupid6
()
RETURNS
trigger
AS
$$
TD
[
"new"
]
=
{
1
:
'foo'
,
2
:
'bar'
}
return
"MODIFY"
;
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger6
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid6
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger6
ON
trigger_test
;
-- TD keys not corresponding to row columns
CREATE
FUNCTION
stupid7
()
RETURNS
trigger
AS
$$
TD
[
"new"
]
=
{
'a'
:
'foo'
,
'b'
:
'bar'
}
return
"MODIFY"
;
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
stupid_trigger7
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
stupid7
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
stupid_trigger7
ON
trigger_test
;
-- calling a trigger function directly
SELECT
stupid7
();
--
-- Null values
--
SELECT
*
FROM
trigger_test
;
CREATE
FUNCTION
test_null
()
RETURNS
trigger
AS
$$
TD
[
"new"
][
'v'
]
=
None
return
"MODIFY"
$$
LANGUAGE
plpythonu
;
CREATE
TRIGGER
test_null_trigger
BEFORE
UPDATE
ON
trigger_test
FOR
EACH
ROW
EXECUTE
PROCEDURE
test_null
();
UPDATE
trigger_test
SET
v
=
'null'
WHERE
i
=
0
;
DROP
TRIGGER
test_null_trigger
ON
trigger_test
;
SELECT
*
FROM
trigger_test
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment