Temporary fix for SQLite compatibility

There is a long standing issue (see partial-bug reference to
launchpad, currently a bug with the most "heat" of the high priority
ones) that Tuskar is not compatible with recent versions of
SQLite. Currently this breaks Tuskar on distros shipping recent SQLite
(e.g. Fedora 20) and if we upgrade the CI environment, it will break
CI too.

There is already updated code in oslo-incubator that fixes this, but
updating the whole module is not entirely straightforward (it breaks
stuff and requires amending Tuskar code). Petr Blaho is already
working on this.

I know updating oslo-incubator code directly is dirty, but it's the
only option to make Tuskar work on newer SQLite until the full module
updates land (aside from compiling older SQLite or manually applying
this patch each time).

Change-Id: Ie9e0c26f2cc701fce0ec8baaa18bd22a5b6e7568
Partial-Bug: #1290849
This commit is contained in:
Jiri Stransky 2014-05-21 17:03:25 +02:00
parent 514f63eca8
commit cb0a63de6c

View File

@ -398,13 +398,19 @@ def get_session(autocommit=True, expire_on_commit=False,
# 'c1'")
# N columns - (IntegrityError) (1062, "Duplicate entry 'values joined
# with -' for key 'name_of_our_constraint'")
# FIXME(jistr): manually updated to work around this bug:
# https://bugs.launchpad.net/tuskar/+bug/1290849
_DUP_KEY_RE_DB = {
"sqlite": re.compile(r"^.*columns?([^)]+)(is|are)\s+not\s+unique$"),
"postgresql": re.compile(r"^.*duplicate\s+key.*\"([^\"]+)\"\s*\n.*$"),
"mysql": re.compile(r"^.*\(1062,.*'([^\']+)'\"\)$")
"sqlite": (re.compile(r"^.*columns?([^)]+)(is|are)\s+not\s+unique$"),
re.compile(r"^.*UNIQUE\s+constraint\s+failed:\s+(.+)$")),
"postgresql": (re.compile(r"^.*duplicate\s+key.*\"([^\"]+)\"\s*\n.*$"),),
"mysql": (re.compile(r"^.*\(1062,.*'([^\']+)'\"\)$"),),
}
# FIXME(jistr): manually updated to work around this bug:
# https://bugs.launchpad.net/tuskar/+bug/1290849
def _raise_if_duplicate_entry_error(integrity_error, engine_name):
"""
In this function will be raised DBDuplicateEntry exception if integrity
@ -424,13 +430,16 @@ def _raise_if_duplicate_entry_error(integrity_error, engine_name):
if engine_name not in ["mysql", "sqlite", "postgresql"]:
return
m = _DUP_KEY_RE_DB[engine_name].match(integrity_error.message)
if not m:
for pattern in _DUP_KEY_RE_DB[engine_name]:
m = pattern.match(integrity_error.message)
if m:
break
else:
return
columns = m.group(1)
if engine_name == "sqlite":
columns = columns.strip().split(", ")
columns = [c.split('.')[-1] for c in columns.strip().split(", ")]
else:
columns = get_columns_from_uniq_cons_or_name(columns)
raise exception.DBDuplicateEntry(columns, integrity_error)