在使用PL/Python中编写的布尔存储过程的PostgreSQL CHECK约束中,可以更新错误消息的详细信息吗?
In a PostgreSQL CHECK constraint using a boolean stored procedure written in PL/Python, can the detail of the error message be updated?
问题在(虽然很长)标题中。我有这种方式的代码:
-- create the tables for models
CREATE TABLE invoice(
id SERIAL PRIMARY KEY,
value VARCHAR(8)
CONSTRAINT valid_money CHECK(validate_invoice_money(value))
);
使用此程序:
CREATE OR REPLACE FUNCTION validate_invoice_money(test VARCHAR) RETURNS BOOLEAN AS $$
import plpy
import re
if (re.match("^[0-9]+\.[0-9]{2}$", test) == None):
return False
return True
$$ LANGUAGE plpython3u IMMUTABLE;
(这个例子的细节并不重要,我知道有比这更好的方法来验证一个值,比如使用 MONEY
类型。)
当尝试插入未通过此检查时,我收到以下错误:
ERROR : new row for relation "invoice" violates check constraint "valid_model"
DETAIL : Failing row contains (1, "notvalid").
(error/detail 描述符是我自己的代码,但是PostgreSQL错误有一个error和一个detail字段提供。)
我有什么方法可以从我的 Python 程序中更改此错误的 "detail" 部分吗?
您不需要其他语言;您可以对值约束使用普通正则表达式:
-- create the tables for models
CREATE TABLE invoice(
id SERIAL PRIMARY KEY,
val VARCHAR(8)
-- CONSTRAINT valid_money CHECK(validate_invoice_money(value))
CONSTRAINT valid_money CHECK(val ~ '^[0-9]+\.[0-9]{2}$' )
);
INSERT INTO invoice (val) VALUES ('0123.98' ); -- success
INSERT INTO invoice (val) VALUES ('a123.98' ); -- failure
SELECT * FROM invoice;
结果:
CREATE TABLE
INSERT 0 1
ERROR: new row for relation "invoice" violates check constraint "valid_money"
DETAIL: Failing row contains (2, a123.98).
id | val
----+---------
1 | 0123.98
(1 row)
然后回答这个问题:我认为您无法获得有关违反约束的更多信息。
在 Postgres 9.6+ 中,您可以使用 utility functions, 的 plpython 函数通过详细消息引发错误,例如:
CREATE OR REPLACE FUNCTION validate_invoice_money(test VARCHAR)
RETURNS BOOLEAN AS $$
import re
if (re.match("^[0-9]+\.[0-9]{2}$", test) == None):
plpy.error("custom exception message",
detail="some info about exception",
hint="hint for users")
return False
return True
$$ LANGUAGE plpython3u IMMUTABLE;
insert into invoice
values (default, 'notvalid');
ERROR: plpy.Error: custom exception message
DETAIL: some info about exception
HINT: hint for users
CONTEXT: Traceback (most recent call last):
PL/Python function "validate_invoice_money", line 8, in <module>
hint="hint for users")
PL/Python function "validate_invoice_money"
问题在(虽然很长)标题中。我有这种方式的代码:
-- create the tables for models
CREATE TABLE invoice(
id SERIAL PRIMARY KEY,
value VARCHAR(8)
CONSTRAINT valid_money CHECK(validate_invoice_money(value))
);
使用此程序:
CREATE OR REPLACE FUNCTION validate_invoice_money(test VARCHAR) RETURNS BOOLEAN AS $$
import plpy
import re
if (re.match("^[0-9]+\.[0-9]{2}$", test) == None):
return False
return True
$$ LANGUAGE plpython3u IMMUTABLE;
(这个例子的细节并不重要,我知道有比这更好的方法来验证一个值,比如使用 MONEY
类型。)
当尝试插入未通过此检查时,我收到以下错误:
ERROR : new row for relation "invoice" violates check constraint "valid_model"
DETAIL : Failing row contains (1, "notvalid").
(error/detail 描述符是我自己的代码,但是PostgreSQL错误有一个error和一个detail字段提供。)
我有什么方法可以从我的 Python 程序中更改此错误的 "detail" 部分吗?
您不需要其他语言;您可以对值约束使用普通正则表达式:
-- create the tables for models
CREATE TABLE invoice(
id SERIAL PRIMARY KEY,
val VARCHAR(8)
-- CONSTRAINT valid_money CHECK(validate_invoice_money(value))
CONSTRAINT valid_money CHECK(val ~ '^[0-9]+\.[0-9]{2}$' )
);
INSERT INTO invoice (val) VALUES ('0123.98' ); -- success
INSERT INTO invoice (val) VALUES ('a123.98' ); -- failure
SELECT * FROM invoice;
结果:
CREATE TABLE
INSERT 0 1
ERROR: new row for relation "invoice" violates check constraint "valid_money"
DETAIL: Failing row contains (2, a123.98).
id | val
----+---------
1 | 0123.98
(1 row)
然后回答这个问题:我认为您无法获得有关违反约束的更多信息。
在 Postgres 9.6+ 中,您可以使用 utility functions, 的 plpython 函数通过详细消息引发错误,例如:
CREATE OR REPLACE FUNCTION validate_invoice_money(test VARCHAR)
RETURNS BOOLEAN AS $$
import re
if (re.match("^[0-9]+\.[0-9]{2}$", test) == None):
plpy.error("custom exception message",
detail="some info about exception",
hint="hint for users")
return False
return True
$$ LANGUAGE plpython3u IMMUTABLE;
insert into invoice
values (default, 'notvalid');
ERROR: plpy.Error: custom exception message
DETAIL: some info about exception
HINT: hint for users
CONTEXT: Traceback (most recent call last):
PL/Python function "validate_invoice_money", line 8, in <module>
hint="hint for users")
PL/Python function "validate_invoice_money"