summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorGary Kotton <gkotton@redhat.com>2013-04-22 07:50:31 +0000
committerGary Kotton <gkotton@redhat.com>2013-04-22 17:35:20 +0000
commitd733c8a0563a8866ec3a83824f8c34f8cc24ec44 (patch)
tree71381c3b9c682399e1689a35a486eeeae53d36e4 /openstack
parentda901232e9bbcf32ac6a86dc62fdd5fbf9bfb9c9 (diff)
downloadoslo-d733c8a0563a8866ec3a83824f8c34f8cc24ec44.tar.gz
oslo-d733c8a0563a8866ec3a83824f8c34f8cc24ec44.tar.xz
oslo-d733c8a0563a8866ec3a83824f8c34f8cc24ec44.zip
Add enforcement for foreign key contraints with sqlite
Fixes bug 1171732 When creating an engine the called can indicate whether or not to enforce the constraints for sqlite. Change-Id: I1d5820376f60388c084afea500f807cd25541800
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/db/sqlalchemy/session.py27
1 files changed, 22 insertions, 5 deletions
diff --git a/openstack/common/db/sqlalchemy/session.py b/openstack/common/db/sqlalchemy/session.py
index c719063..99439f4 100644
--- a/openstack/common/db/sqlalchemy/session.py
+++ b/openstack/common/db/sqlalchemy/session.py
@@ -248,6 +248,7 @@ from eventlet import greenthread
from oslo.config import cfg
from sqlalchemy import exc as sqla_exc
import sqlalchemy.interfaces
+from sqlalchemy.interfaces import PoolListener
import sqlalchemy.orm
from sqlalchemy.pool import NullPool, StaticPool
from sqlalchemy.sql.expression import literal_column
@@ -317,12 +318,25 @@ def set_defaults(sql_connection, sqlite_db):
sqlite_db=sqlite_db)
-def get_session(autocommit=True, expire_on_commit=False):
+class SqliteForeignKeysListener(PoolListener):
+ """
+ Ensures that the foreign key constraints are enforced in SQLite.
+
+ The foreign key constraints are disabled by default in SQLite,
+ so the foreign key constraints will be enabled here for every
+ database connection
+ """
+ def connect(self, dbapi_con, con_record):
+ dbapi_con.execute('pragma foreign_keys=ON')
+
+
+def get_session(autocommit=True, expire_on_commit=False,
+ sqlite_fk=False):
"""Return a SQLAlchemy session."""
global _MAKER
if _MAKER is None:
- engine = get_engine()
+ engine = get_engine(sqlite_fk=sqlite_fk)
_MAKER = get_maker(engine, autocommit, expire_on_commit)
session = _MAKER()
@@ -439,11 +453,12 @@ def _wrap_db_error(f):
return _wrap
-def get_engine():
+def get_engine(sqlite_fk=False):
"""Return a SQLAlchemy engine."""
global _ENGINE
if _ENGINE is None:
- _ENGINE = create_engine(CONF.sql_connection)
+ _ENGINE = create_engine(CONF.sql_connection,
+ sqlite_fk=sqlite_fk)
return _ENGINE
@@ -500,7 +515,7 @@ def _is_db_connection_error(args):
return False
-def create_engine(sql_connection):
+def create_engine(sql_connection, sqlite_fk=False):
"""Return a new SQLAlchemy engine."""
connection_dict = sqlalchemy.engine.url.make_url(sql_connection)
@@ -517,6 +532,8 @@ def create_engine(sql_connection):
engine_args['echo'] = True
if "sqlite" in connection_dict.drivername:
+ if sqlite_fk:
+ engine_args["listeners"] = [SqliteForeignKeysListener()]
engine_args["poolclass"] = NullPool
if CONF.sql_connection == "sqlite://":