diff options
| author | Gary Kotton <gkotton@redhat.com> | 2013-04-22 07:50:31 +0000 |
|---|---|---|
| committer | Gary Kotton <gkotton@redhat.com> | 2013-04-22 17:35:20 +0000 |
| commit | d733c8a0563a8866ec3a83824f8c34f8cc24ec44 (patch) | |
| tree | 71381c3b9c682399e1689a35a486eeeae53d36e4 /openstack | |
| parent | da901232e9bbcf32ac6a86dc62fdd5fbf9bfb9c9 (diff) | |
| download | oslo-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.py | 27 |
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://": |
