From ebf3bea1467d574bbf5ca7f90cfcee4fd83f098b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sun, 22 Nov 2015 16:40:21 +0100 Subject: [PATCH] sql: remove formdef references from global views after formdef removal (#8979) --- tests/test_sql.py | 27 +++++++++++++++++++++++++++ wcs/formdef.py | 12 ++++++++++++ wcs/sql.py | 19 +++++++++++++------ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/tests/test_sql.py b/tests/test_sql.py index 79af042..d6dfeda 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -1274,3 +1274,30 @@ def test_view_user_name(): cur.execute('''SELECT user_name FROM wcs_all_forms WHERE id = %s ''', (formdata2.id,)) assert bool(cur.fetchone()[0] == user.name) + +@postgresql +def test_select_formdata_after_formdef_removal(): + drop_formdef_tables() + conn, cur = sql.get_connection_and_cursor() + + now = datetime.datetime.now() + + for i in range(2): + formdef = FormDef() + formdef.name = 'test formdef removal' + formdef.fields = [] + formdef.store() + + data_class = formdef.data_class(mode='sql') + formdata = data_class() + formdata.just_created() + formdata.store() + + # test generic select + objects = sql.AnyFormData.select() + assert len(objects) == 2 + + formdef.remove_self() + + objects = sql.AnyFormData.select() + assert len(objects) == 1 diff --git a/wcs/formdef.py b/wcs/formdef.py index 51b2081..37c6c3c 100644 --- a/wcs/formdef.py +++ b/wcs/formdef.py @@ -197,6 +197,18 @@ class FormDef(StorableObject): if changed: self.store() + @classmethod + def remove_object(cls, id): + super(FormDef, cls).remove_object(id) + if get_publisher().is_using_postgresql(): + # recreate global views so they don't reference formdata from + # deleted formefs + import sql + conn, cur = sql.get_connection_and_cursor() + sql.do_global_views(conn, cur) + conn.commit() + cur.close() + def data_class(self, mode=None): if hasattr(sys.modules['formdef'], self.url_name.title()): data_class = getattr(sys.modules['formdef'], self.url_name.title()) diff --git a/wcs/sql.py b/wcs/sql.py index 0bfce05..e38da37 100644 --- a/wcs/sql.py +++ b/wcs/sql.py @@ -265,6 +265,10 @@ def get_formdef_table_name(formdef): formdef.store() return formdef.table_name +def get_formdef_view_name(formdef): + return 'wcs_view_%s_%s' % (formdef.id, + get_name_as_sql_identifier(formdef.url_name)[:40]) + def guard_postgres(func): def f(*args, **kwargs): try: @@ -565,9 +569,7 @@ def get_view_fields(formdef): def do_views(formdef, conn, cur, rebuild_global_views=True): # create new view table_name = get_formdef_table_name(formdef) - view_name = 'wcs_view_%s_%s' % (formdef.id, - get_name_as_sql_identifier(formdef.url_name)[:40]) - + view_name = get_formdef_view_name(formdef) view_fields = get_view_fields(formdef) column_names = {} @@ -648,19 +650,24 @@ def drop_global_views(conn, cur): def do_global_views(conn, cur): # recreate global views - view_names = [] + from wcs.formdef import FormDef + view_names = [get_formdef_view_name(x) for x in FormDef.select()] + cur.execute('''SELECT table_name FROM information_schema.views WHERE table_name LIKE %s''', ('wcs\_view\_%',)) + existing_views = set() while True: row = cur.fetchone() if row is None: break - view_names.append(row[0]) + existing_views.add(row[0]) + view_names = existing_views.intersection(view_names) if not view_names: return - from wcs.formdef import FormDef + cur.execute('''DROP VIEW IF EXISTS wcs_all_forms CASCADE''') + fake_formdef = FormDef() common_fields = get_view_fields(fake_formdef) common_fields.append(('concerned_roles_array', 'concerned_roles_array')) -- 2.6.2