From 05b5c7a569c0ca964bf032995334a32f716dce9c Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 12 Feb 2014 11:05:38 +0100 Subject: [PATCH] [RFR] Group models per table when detecting columns to purge to prevent problems with models sharing the same table --- database_cleanup/model/purge_columns.py | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/database_cleanup/model/purge_columns.py b/database_cleanup/model/purge_columns.py index e46a8f0da..2d4f270ef 100644 --- a/database_cleanup/model/purge_columns.py +++ b/database_cleanup/model/purge_columns.py @@ -85,18 +85,21 @@ class CleanupPurgeWizardColumn(orm.TransientModel): res['name'] = _('Purge columns') return res - def get_orphaned_columns(self, cr, uid, model_pool, context=None): + def get_orphaned_columns(self, cr, uid, model_pools, context=None): """ From openobject-server/openerp/osv/orm.py Iterate on the database columns to identify columns of fields which have been removed """ - columns = [ - c for c in model_pool._columns - if not (isinstance(model_pool._columns[c], fields.function) - and not model_pool._columns[c].store)] + + columns = list(set([ + column for model_pool in model_pools + for column in model_pool._columns + if not (isinstance(model_pool._columns[column], fields.function) + and not model_pool._columns[column].store) + ])) columns += orm.MAGIC_COLUMNS - columns += self.blacklist.get(model_pool._table, []) + columns += self.blacklist.get(model_pools[0]._table, []) cr.execute("SELECT a.attname" " FROM pg_class c, pg_attribute a" @@ -106,26 +109,37 @@ class CleanupPurgeWizardColumn(orm.TransientModel): " AND pg_catalog.format_type(a.atttypid, a.atttypmod)" " NOT IN ('cid', 'tid', 'oid', 'xid')" " AND a.attname NOT IN %s", - (model_pool._table, False, tuple(columns))), + (model_pools[0]._table, False, tuple(columns))), return [column[0] for column in cr.fetchall()] def find(self, cr, uid, context=None): """ Search for columns that are not in the corresponding model. + + Group models by table to prevent false positives for columns + that are only in some of the models sharing the same table. + Example of this is 'sale_id' not being a field of stock.picking.in """ res = [] model_pool = self.pool['ir.model'] model_ids = model_pool.search(cr, uid, [], context=context) line_pool = self.pool['cleanup.purge.line.column'] + + # mapping of tables to tuples (model id, [pool1, pool2, ...]) + table2model = {} + for model in model_pool.browse(cr, uid, model_ids, context=context): model_pool = self.pool.get(model.model) if not model_pool or not model_pool._auto: continue + table2model.setdefault(model_pool._table, (model.id, []))[1].append(model_pool) + + for table, model_spec in table2model.iteritems(): for column in self.get_orphaned_columns( - cr, uid, model_pool, context=context): + cr, uid, model_spec[1], context=context): res.append((0, 0, { 'name': column, - 'model_id': model.id})) + 'model_id': model_spec[0]})) if not res: raise orm.except_orm( _('Nothing to do'),