Fix parsing of UC errors in sqlite 3.7.16+/3.8.2+
The new version of libsqlite changed the format of error messages. Code of oslo.db helpers must be updated appropriately. This was meant to be fixed by I86e9673ac409b3b3e881bea7cb8b3516f320388d, but that change doesn't cope well with the new format of column names. Closes-Bug: #1259915 Change-Id: Iec39c8804ea47307a98d1b79899ff74af9404bf6
This commit is contained in:
parent
9fd406bf9a
commit
3728fbf0ae
@ -473,9 +473,9 @@ def get_session(autocommit=True, expire_on_commit=False, sqlite_fk=False,
|
|||||||
# N columns - (IntegrityError) column c1, c2, ..., N are not unique
|
# N columns - (IntegrityError) column c1, c2, ..., N are not unique
|
||||||
#
|
#
|
||||||
# sqlite since 3.7.16:
|
# sqlite since 3.7.16:
|
||||||
# 1 column - (IntegrityError) UNIQUE constraint failed: k1
|
# 1 column - (IntegrityError) UNIQUE constraint failed: tbl.k1
|
||||||
#
|
#
|
||||||
# N columns - (IntegrityError) UNIQUE constraint failed: k1, k2
|
# N columns - (IntegrityError) UNIQUE constraint failed: tbl.k1, tbl.k2
|
||||||
#
|
#
|
||||||
# postgres:
|
# postgres:
|
||||||
# 1 column - (IntegrityError) duplicate key value violates unique
|
# 1 column - (IntegrityError) duplicate key value violates unique
|
||||||
@ -532,7 +532,7 @@ def _raise_if_duplicate_entry_error(integrity_error, engine_name):
|
|||||||
columns = match.group(1)
|
columns = match.group(1)
|
||||||
|
|
||||||
if engine_name == "sqlite":
|
if engine_name == "sqlite":
|
||||||
columns = columns.strip().split(", ")
|
columns = [c.split('.')[-1] for c in columns.strip().split(", ")]
|
||||||
else:
|
else:
|
||||||
columns = get_columns_from_uniq_cons_or_name(columns)
|
columns = get_columns_from_uniq_cons_or_name(columns)
|
||||||
raise exception.DBDuplicateEntry(columns, integrity_error)
|
raise exception.DBDuplicateEntry(columns, integrity_error)
|
||||||
|
@ -28,7 +28,9 @@ from sqlalchemy.sql import select
|
|||||||
from sqlalchemy.types import UserDefinedType, NullType
|
from sqlalchemy.types import UserDefinedType, NullType
|
||||||
from openstack.common.py3kcompat import urlutils
|
from openstack.common.py3kcompat import urlutils
|
||||||
|
|
||||||
|
from openstack.common.db import exception
|
||||||
from openstack.common.db.sqlalchemy import migration
|
from openstack.common.db.sqlalchemy import migration
|
||||||
|
from openstack.common.db.sqlalchemy import session
|
||||||
from openstack.common.db.sqlalchemy import test_migrations
|
from openstack.common.db.sqlalchemy import test_migrations
|
||||||
from openstack.common.db.sqlalchemy import utils
|
from openstack.common.db.sqlalchemy import utils
|
||||||
from openstack.common.fixture import moxstubout
|
from openstack.common.fixture import moxstubout
|
||||||
@ -593,3 +595,47 @@ class TestConnectionUtils(test_utils.BaseTestCase):
|
|||||||
conn_pieces = urlutils.urlparse(self.connect_string)
|
conn_pieces = urlutils.urlparse(self.connect_string)
|
||||||
self.assertEqual(utils.get_db_connection_info(conn_pieces),
|
self.assertEqual(utils.get_db_connection_info(conn_pieces),
|
||||||
('dude', 'pass', 'test', 'localhost'))
|
('dude', 'pass', 'test', 'localhost'))
|
||||||
|
|
||||||
|
|
||||||
|
class TestRaiseDuplicateEntryError(test.BaseTestCase):
|
||||||
|
def _test_impl(self, engine_name, error_msg):
|
||||||
|
try:
|
||||||
|
error = sqlalchemy.exc.IntegrityError('test', 'test', error_msg)
|
||||||
|
session._raise_if_duplicate_entry_error(error, engine_name)
|
||||||
|
except exception.DBDuplicateEntry as e:
|
||||||
|
self.assertEqual(e.columns, ['a', 'b'])
|
||||||
|
else:
|
||||||
|
self.fail('DBDuplicateEntry was not raised')
|
||||||
|
|
||||||
|
def test_sqlite(self):
|
||||||
|
self._test_impl(
|
||||||
|
'sqlite',
|
||||||
|
'(IntegrityError) column a, b are not unique'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_sqlite_3_7_16_or_3_8_2_and_higher(self):
|
||||||
|
self._test_impl(
|
||||||
|
'sqlite',
|
||||||
|
'(IntegrityError) UNIQUE constraint failed: tbl.a, tbl.b'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_mysql(self):
|
||||||
|
self._test_impl(
|
||||||
|
'mysql',
|
||||||
|
'(IntegrityError) (1062, "Duplicate entry '
|
||||||
|
'\'2-3\' for key \'uniq_tbl0a0b\'")'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_postgresql(self):
|
||||||
|
self._test_impl(
|
||||||
|
'postgresql',
|
||||||
|
'(IntegrityError) duplicate key value violates unique constraint'
|
||||||
|
'"uniq_tbl0a0b"'
|
||||||
|
'\nDETAIL: Key (a, b)=(2, 3) already exists.\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_unsupported_backend_returns_none(self):
|
||||||
|
error = sqlalchemy.exc.IntegrityError('test', 'test', 'test')
|
||||||
|
rv = session._raise_if_duplicate_entry_error('oracle', error)
|
||||||
|
|
||||||
|
self.assertIsNone(rv)
|
||||||
|
Loading…
Reference in New Issue
Block a user