From ab07e63228351c3f791f4da5413671cb7da1552e Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Wed, 26 Jul 2017 20:52:32 -0400 Subject: [PATCH] [#3816] datastore_mv_create quick hack --- ckan/lib/dictization/model_save.py | 3 +++ ckanext/datastore/backend/postgres.py | 14 ++++++++++++++ ckanext/datastore/logic/action.py | 7 +++++++ ckanext/datastore/plugin.py | 7 +++++++ 4 files changed, 31 insertions(+) diff --git a/ckan/lib/dictization/model_save.py b/ckan/lib/dictization/model_save.py index 60476666682..6f79abc366f 100644 --- a/ckan/lib/dictization/model_save.py +++ b/ckan/lib/dictization/model_save.py @@ -47,6 +47,9 @@ def resource_dict_save(res_dict, context): obj.url_changed = True setattr(obj, key, value) else: + if key == 'query' and (new or obj.extras.get('query') != value): + obj.url_changed = True # XXX hack to notify datastore + obj.url_type = 'datastore' # resources save extras directly onto the object, instead # of in a separate extras field like packages and groups new_extras[key] = value diff --git a/ckanext/datastore/backend/postgres.py b/ckanext/datastore/backend/postgres.py index ce1191e6ab0..0badaf97d9d 100644 --- a/ckanext/datastore/backend/postgres.py +++ b/ckanext/datastore/backend/postgres.py @@ -1770,6 +1770,20 @@ def delete(self, context, data_dict): finally: context['connection'].close() + def mv_create(self, resource_id, query): + # XXX + # XXX not even pretending to be safe + # XXX + sql = u''' + DROP MATERIALIZED VIEW IF EXISTS {resource_id}; + '''.format(resource_id=identifier(resource_id)) + _write_engine_execute(sql) + sql = u''' + CREATE MATERIALIZED VIEW {resource_id} AS {query}; + '''.format(resource_id=identifier(resource_id), query=query) + _write_engine_execute(sql) + + def create(self, context, data_dict): ''' The first row will be used to guess types not in the fields and the diff --git a/ckanext/datastore/logic/action.py b/ckanext/datastore/logic/action.py index d40067bdbe0..dffc2e3b482 100644 --- a/ckanext/datastore/logic/action.py +++ b/ckanext/datastore/logic/action.py @@ -171,6 +171,13 @@ def datastore_create(context, data_dict): return result +def datastore_mv_create(context, data_dict): + backend = DatastoreBackend.get_active_backend() + resource_id = data_dict['resource_id'] + p.toolkit.check_access('datastore_create', context, data_dict) + backend.mv_create(resource_id, data_dict['query']) + + def datastore_run_triggers(context, data_dict): ''' update each record with trigger diff --git a/ckanext/datastore/plugin.py b/ckanext/datastore/plugin.py index f47cbbfd796..6bfc37179bb 100644 --- a/ckanext/datastore/plugin.py +++ b/ckanext/datastore/plugin.py @@ -92,6 +92,12 @@ def configure(self, config): # IResourceUrlChange def notify(self, entity, operation=None): + # XXX: hack + if isinstance(entity, model.Resource) and 'query' in entity.extras: + p.toolkit.get_action('datastore_mv_create')( + {'model': model, 'ignore_auth': True}, + {'resource_id': entity.id, 'query': entity.extras['query']}) + return if not isinstance(entity, model.Package) or self.legacy_mode: return # if a resource is new, it cannot have a datastore resource, yet @@ -121,6 +127,7 @@ def get_actions(self): 'datastore_function_create': action.datastore_function_create, 'datastore_function_delete': action.datastore_function_delete, 'datastore_run_triggers': action.datastore_run_triggers, + 'datastore_mv_create': action.datastore_mv_create, } if not self.legacy_mode: if getattr(self.backend, 'enable_sql_search', False):