summaryrefslogtreecommitdiffstats
path: root/openstack/common/db/sqlalchemy
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/common/db/sqlalchemy
parentda901232e9bbcf32ac6a86dc62fdd5fbf9bfb9c9 (diff)
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/common/db/sqlalchemy')
-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://":