# HG changeset patch # User Laurent Peuch # Date 1557974579 -7200 # Node ID 8ac9ac8d91433d6c915760fb55ce443929b64641 # Parent 703a263dd61832f713104a244c2c4adf149a4f22 [mod] make ViolatedConstraint actually display useful information Move from: (Pdb++) raise some_exception *** ViolatedConstraint: To: (Pdb++) raise some_exception *** ViolatedConstraint: constraint 'cstr56c2ab4b3154f21d08b067742ce5bd9d' is being violated by the query 'ALTER TABLE cw_Bibliography ADD CONSTRAINT cstr56c2ab4b3154f21d08b067742ce5bd9d CHECK(cw_item_type IN ('journalArticle', 'note', 'book', 'thesis', 'film', 'web page', 'manuscrit', 'tapuscrit'))'. You can run the inverted constraint on the database to list the problematic rows. And save hours of debugging to actually understand what is going on. diff -r 703a263dd618 -r 8ac9ac8d9143 cubicweb/_exceptions.py --- a/cubicweb/_exceptions.py Thu May 16 09:40:28 2019 +0200 +++ b/cubicweb/_exceptions.py Thu May 16 04:42:59 2019 +0200 @@ -107,9 +107,14 @@ class ViolatedConstraint(RepositoryError): - def __init__(self, cnx, cstrname): + def __init__(self, cnx, cstrname, query): self.cnx = cnx self.cstrname = cstrname + message = ( + "constraint '%s' is being violated by the query '%s'. " + "You can run the inverted constraint on the database to list the problematic rows." + ) % (cstrname, query) + super(ViolatedConstraint, self).__init__(message) # security exceptions ######################################################### diff -r 703a263dd618 -r 8ac9ac8d9143 cubicweb/server/sources/native.py --- a/cubicweb/server/sources/native.py Thu May 16 09:40:28 2019 +0200 +++ b/cubicweb/server/sources/native.py Thu May 16 04:42:59 2019 +0200 @@ -716,14 +716,17 @@ mo = re.search(r'\bcstr[a-f0-9]{32}\b', arg) if mo is not None: # postgresql - raise ViolatedConstraint(cnx, cstrname=mo.group(0)) + raise ViolatedConstraint(cnx, cstrname=mo.group(0), + query=query) if arg.startswith('CHECK constraint failed:'): # sqlite3 (new) - raise ViolatedConstraint(cnx, cstrname=arg.split(':', 1)[1].strip()) + raise ViolatedConstraint(cnx, cstrname=arg.split(':', 1)[1].strip(), + query=query) mo = re.match('^constraint (cstr.*) failed$', arg) if mo is not None: # sqlite3 (old) - raise ViolatedConstraint(cnx, cstrname=mo.group(1)) + raise ViolatedConstraint(cnx, cstrname=mo.group(1), + query=query) raise return cursor