diff --git a/database_cleanup/identifier_adapter.py b/database_cleanup/identifier_adapter.py new file mode 100644 index 000000000..280fcd920 --- /dev/null +++ b/database_cleanup/identifier_adapter.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# © 2016 Therp BV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from psycopg2.extensions import ISQLQuote + + +class IdentifierAdapter(ISQLQuote): + def __init__(self, identifier, quote=True): + self.quote = quote + self.identifier = identifier + + def __conform__(self, protocol): + if protocol == ISQLQuote: + return self + + def getquoted(self): + def is_identifier_char(c): + return c.isalnum() or c in ['_', '$'] + + format_string = '"%s"' + if not self.quote: + format_string = '%s' + return format_string % filter(is_identifier_char, self.identifier) diff --git a/database_cleanup/models/purge_columns.py b/database_cleanup/models/purge_columns.py index b8cc0d9ad..4eb7a2a0a 100644 --- a/database_cleanup/models/purge_columns.py +++ b/database_cleanup/models/purge_columns.py @@ -3,6 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import _, api, fields, models from openerp.exceptions import UserError +from ..identifier_adapter import IdentifierAdapter class CleanupPurgeLineColumn(models.TransientModel): @@ -39,9 +40,11 @@ class CleanupPurgeLineColumn(models.TransientModel): 'Dropping column %s from table %s', line.name, model_pool._table) self.env.cr.execute( - """ - ALTER TABLE "%s" DROP COLUMN "%s" - """ % (model_pool._table, line.name)) + 'ALTER TABLE %s DROP COLUMN %s', + ( + IdentifierAdapter(model_pool._table), + IdentifierAdapter(line.name) + )) line.write({'purged': True}) self.env.cr.commit() return True diff --git a/database_cleanup/models/purge_data.py b/database_cleanup/models/purge_data.py index 638a24ff7..9e1817ff8 100644 --- a/database_cleanup/models/purge_data.py +++ b/database_cleanup/models/purge_data.py @@ -3,6 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import _, api, fields, models from openerp.exceptions import UserError +from ..identifier_adapter import IdentifierAdapter class CleanupPurgeLineData(models.TransientModel): @@ -45,11 +46,11 @@ class CleanupPurgeWizardData(models.TransientModel): self.env.cr.execute( """ SELECT id FROM ir_model_data - WHERE model = %%s + WHERE model = %s AND res_id IS NOT NULL AND NOT EXISTS ( SELECT id FROM %s WHERE id=ir_model_data.res_id) - """ % self.env[model]._table, (model,)) + """, (model, IdentifierAdapter(self.env[model]._table))) data_ids.extend(data_row for data_row, in self.env.cr.fetchall()) data_ids += self.env['ir.model.data'].search([ ('model', 'in', unknown_models), diff --git a/database_cleanup/models/purge_tables.py b/database_cleanup/models/purge_tables.py index e8746c966..b37654c75 100644 --- a/database_cleanup/models/purge_tables.py +++ b/database_cleanup/models/purge_tables.py @@ -3,6 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import api, fields, models, _ from openerp.exceptions import UserError +from ..identifier_adapter import IdentifierAdapter class CleanupPurgeLineTable(models.TransientModel): @@ -42,7 +43,7 @@ class CleanupPurgeLineTable(models.TransientModel): WHERE af.attnum = confkey AND af.attrelid = confrelid AND a.attnum = conkey AND a.attrelid = conrelid AND confrelid::regclass = '%s'::regclass; - """ % line.name) + """, (IdentifierAdapter(line.name, quote=False),)) for constraint in self.env.cr.fetchall(): if constraint[3] in tables: @@ -50,12 +51,16 @@ class CleanupPurgeLineTable(models.TransientModel): 'Dropping constraint %s on table %s (to be dropped)', constraint[0], constraint[3]) self.env.cr.execute( - "ALTER TABLE %s DROP CONSTRAINT %s" % ( - constraint[3], constraint[0])) + "ALTER TABLE %s DROP CONSTRAINT %s", + ( + IdentifierAdapter(constraint[3]), + IdentifierAdapter(constraint[0]) + )) self.logger.info( 'Dropping table %s', line.name) - self.env.cr.execute("DROP TABLE \"%s\"" % (line.name,)) + self.env.cr.execute( + "DROP TABLE %s", (IdentifierAdapter(line.name),)) line.write({'purged': True}) self.env.cr.commit() return True