mirror of
https://git.postgresql.org/git/postgresql.git
synced 2026-02-07 18:47:29 +08:00
PL/Python now accepts Unicode objects where it previously only accepted string objects (for example, as return value). Unicode objects are converted to the PostgreSQL server encoding as necessary. This change is also necessary for future Python 3 support, which treats all strings as Unicode objects. Since this removes the error conditions that the plpython_unicode test file tested for, the alternative result files are no longer necessary.
456 lines
16 KiB
Plaintext
456 lines
16 KiB
Plaintext
-- these triggers are dedicated to HPHC of RI who
|
|
-- decided that my kid's name was william not willem, and
|
|
-- vigorously resisted all efforts at correction. they have
|
|
-- since gone bankrupt...
|
|
CREATE FUNCTION users_insert() returns trigger
|
|
AS
|
|
'if TD["new"]["fname"] == None or TD["new"]["lname"] == None:
|
|
return "SKIP"
|
|
if TD["new"]["username"] == None:
|
|
TD["new"]["username"] = TD["new"]["fname"][:1] + "_" + TD["new"]["lname"]
|
|
rv = "MODIFY"
|
|
else:
|
|
rv = None
|
|
if TD["new"]["fname"] == "william":
|
|
TD["new"]["fname"] = TD["args"][0]
|
|
rv = "MODIFY"
|
|
return rv'
|
|
LANGUAGE plpythonu;
|
|
CREATE FUNCTION users_update() returns trigger
|
|
AS
|
|
'if TD["event"] == "UPDATE":
|
|
if TD["old"]["fname"] != TD["new"]["fname"] and TD["old"]["fname"] == TD["args"][0]:
|
|
return "SKIP"
|
|
return None'
|
|
LANGUAGE plpythonu;
|
|
CREATE FUNCTION users_delete() RETURNS trigger
|
|
AS
|
|
'if TD["old"]["fname"] == TD["args"][0]:
|
|
return "SKIP"
|
|
return None'
|
|
LANGUAGE plpythonu;
|
|
CREATE TRIGGER users_insert_trig BEFORE INSERT ON users FOR EACH ROW
|
|
EXECUTE PROCEDURE users_insert ('willem');
|
|
CREATE TRIGGER users_update_trig BEFORE UPDATE ON users FOR EACH ROW
|
|
EXECUTE PROCEDURE users_update ('willem');
|
|
CREATE TRIGGER users_delete_trig BEFORE DELETE ON users FOR EACH ROW
|
|
EXECUTE PROCEDURE users_delete ('willem');
|
|
-- quick peek at the table
|
|
--
|
|
SELECT * FROM users;
|
|
fname | lname | username | userid
|
|
--------+-------+----------+--------
|
|
jane | doe | j_doe | 1
|
|
john | doe | johnd | 2
|
|
willem | doe | w_doe | 3
|
|
rick | smith | slash | 4
|
|
(4 rows)
|
|
|
|
-- should fail
|
|
--
|
|
UPDATE users SET fname = 'william' WHERE fname = 'willem';
|
|
-- should modify william to willem and create username
|
|
--
|
|
INSERT INTO users (fname, lname) VALUES ('william', 'smith');
|
|
INSERT INTO users (fname, lname, username) VALUES ('charles', 'darwin', 'beagle');
|
|
SELECT * FROM users;
|
|
fname | lname | username | userid
|
|
---------+--------+----------+--------
|
|
jane | doe | j_doe | 1
|
|
john | doe | johnd | 2
|
|
willem | doe | w_doe | 3
|
|
rick | smith | slash | 4
|
|
willem | smith | w_smith | 5
|
|
charles | darwin | beagle | 6
|
|
(6 rows)
|
|
|
|
-- dump trigger data
|
|
CREATE TABLE trigger_test
|
|
(i int, v text );
|
|
CREATE FUNCTION trigger_data() returns trigger language plpythonu as $$
|
|
|
|
if 'relid' in TD:
|
|
TD['relid'] = "bogus:12345"
|
|
|
|
skeys = list(TD.keys())
|
|
skeys.sort()
|
|
for key in skeys:
|
|
val = TD[key]
|
|
plpy.notice("TD[" + key + "] => " + str(val))
|
|
|
|
return None
|
|
|
|
$$;
|
|
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_before',)
|
|
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] => 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_before',)
|
|
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] => 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_after',)
|
|
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] => 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 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;
|
|
-- Unicode variant
|
|
CREATE FUNCTION stupid3u() RETURNS trigger
|
|
AS $$
|
|
return u"foo"
|
|
$$ LANGUAGE plpythonu;
|
|
CREATE TRIGGER stupid_trigger3
|
|
BEFORE UPDATE ON trigger_test
|
|
FOR EACH ROW EXECUTE PROCEDURE stupid3u();
|
|
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 "stupid3u"
|
|
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: while modifying trigger row
|
|
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: while modifying trigger row
|
|
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: while modifying trigger row
|
|
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: while modifying trigger row
|
|
PL/Python function "stupid7"
|
|
DROP TRIGGER stupid_trigger7 ON trigger_test;
|
|
-- Unicode variant
|
|
CREATE FUNCTION stupid7u() RETURNS trigger
|
|
AS $$
|
|
TD["new"] = {u'a': 'foo', u'b': 'bar'}
|
|
return "MODIFY"
|
|
$$ LANGUAGE plpythonu;
|
|
CREATE TRIGGER stupid_trigger7
|
|
BEFORE UPDATE ON trigger_test
|
|
FOR EACH ROW EXECUTE PROCEDURE stupid7u();
|
|
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: while modifying trigger row
|
|
PL/Python function "stupid7u"
|
|
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)
|
|
|