Skip to content

Commit

Permalink
[#3428] trigger exceptions raise ValidationErrors
Browse files Browse the repository at this point in the history
  • Loading branch information
wardi committed Feb 28, 2017
1 parent 40ece88 commit 916f515
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ckanext/datastore/db.py
Expand Up @@ -715,6 +715,9 @@ def upsert_data(context, data_dict):
toolkit._("The data was invalid (for example: a numeric value "
"is out of range or was inserted into a text field)."
))
except sqlalchemy.exc.InternalError as err:
message = err.args[0].split('\n')[0].decode('utf8')
raise ValidationError({u'records': [message.split(u') ', 1)[-1]]})

elif method in [_UPDATE, _UPSERT]:
unique_keys = _get_unique_key(context, data_dict)
Expand Down Expand Up @@ -1453,6 +1456,8 @@ def drop_function(name, if_exists):

def _write_engine_execute(sql):
connection = get_write_engine().connect()
# No special meaning for '%' in sql parameter:
connection = connection.execution_options(no_parameters=True)
trans = connection.begin()
try:
connection.execute(sql)
Expand Down
70 changes: 68 additions & 2 deletions ckanext/datastore/tests/test_create.py
Expand Up @@ -1000,7 +1000,9 @@ def test_create_trigger_applies_to_records(self):
u'datastore_search',
fields=[u'spam'],
resource_id=res['resource_id'])['records'],
[{u'spam': u'spam spam SPAM spam'}, {u'spam': u'spam spam EGGS spam'}])
[
{u'spam': u'spam spam SPAM spam'},
{u'spam': u'spam spam EGGS spam'}])

def test_upsert_trigger_applies_to_records(self):
ds = factories.Dataset()
Expand Down Expand Up @@ -1029,4 +1031,68 @@ def test_upsert_trigger_applies_to_records(self):
u'datastore_search',
fields=[u'spam'],
resource_id=res['resource_id'])['records'],
[{u'spam': u'spam spam BEANS spam'}, {u'spam': u'spam spam SPAM spam'}])
[
{u'spam': u'spam spam BEANS spam'},
{u'spam': u'spam spam SPAM spam'}])

def test_create_trigger_exception(self):
ds = factories.Dataset()

helpers.call_action(
u'datastore_function_create',
name=u'spamexception_trigger',
rettype=u'trigger',
definition=u'''
BEGIN
IF NEW.spam != 'spam' THEN
RAISE EXCEPTION '"%"? Yeeeeccch!', NEW.spam;
END IF;
RETURN NEW;
END;''')
try:
res = helpers.call_action(
u'datastore_create',
resource={u'package_id': ds['id']},
fields=[{u'id': u'spam', u'type': u'text'}],
records=[{u'spam': u'spam'}, {u'spam': u'EGGS'}],
triggers=[{u'function': u'spamexception_trigger'}])
except ValidationError as ve:
assert_equal(
ve.error_dict,
{u'records':[
u'"EGGS"? Yeeeeccch!']})
else:
assert 0, u'no validation error'

def test_upsert_trigger_exception(self):
ds = factories.Dataset()

helpers.call_action(
u'datastore_function_create',
name=u'spamonly_trigger',
rettype=u'trigger',
definition=u'''
BEGIN
IF NEW.spam != 'spam' THEN
RAISE EXCEPTION '"%"? Yeeeeccch!', NEW.spam;
END IF;
RETURN NEW;
END;''')
res = helpers.call_action(
u'datastore_create',
resource={u'package_id': ds['id']},
fields=[{u'id': u'spam', u'type': u'text'}],
triggers=[{u'function': u'spamonly_trigger'}])
try:
helpers.call_action(
u'datastore_upsert',
method=u'insert',
resource_id=res['resource_id'],
records=[{u'spam': u'spam'}, {u'spam': u'BEANS'}])
except ValidationError as ve:
assert_equal(
ve.error_dict,
{u'records':[
u'"BEANS"? Yeeeeccch!']})
else:
assert 0, u'no validation error'

0 comments on commit 916f515

Please sign in to comment.