You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
4.2 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2014-2016 Therp BV <http://therp.nl>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from openerp import api, fields, models, _
  5. from openerp.exceptions import UserError
  6. from ..identifier_adapter import IdentifierAdapter
  7. class CleanupPurgeLineTable(models.TransientModel):
  8. _inherit = 'cleanup.purge.line'
  9. _name = 'cleanup.purge.line.table'
  10. wizard_id = fields.Many2one(
  11. 'cleanup.purge.wizard.table', 'Purge Wizard', readonly=True)
  12. @api.multi
  13. def purge(self):
  14. """
  15. Unlink tables upon manual confirmation.
  16. """
  17. tables = self.mapped('name')
  18. for line in self:
  19. if line.purged:
  20. continue
  21. # Retrieve constraints on the tables to be dropped
  22. # This query is referenced in numerous places
  23. # on the Internet but credits probably go to Tom Lane
  24. # in this post http://www.postgresql.org/\
  25. # message-id/22895.1226088573@sss.pgh.pa.us
  26. # Only using the constraint name and the source table,
  27. # but I'm leaving the rest in for easier debugging
  28. self.env.cr.execute(
  29. """
  30. SELECT conname, confrelid::regclass, af.attname AS fcol,
  31. conrelid::regclass, a.attname AS col
  32. FROM pg_attribute af, pg_attribute a,
  33. (SELECT conname, conrelid, confrelid,conkey[i] AS conkey,
  34. confkey[i] AS confkey
  35. FROM (select conname, conrelid, confrelid, conkey,
  36. confkey, generate_series(1,array_upper(conkey,1)) AS i
  37. FROM pg_constraint WHERE contype = 'f') ss) ss2
  38. WHERE af.attnum = confkey AND af.attrelid = confrelid AND
  39. a.attnum = conkey AND a.attrelid = conrelid
  40. AND confrelid::regclass = '%s'::regclass;
  41. """, (IdentifierAdapter(line.name, quote=False),))
  42. for constraint in self.env.cr.fetchall():
  43. if constraint[3] in tables:
  44. self.logger.info(
  45. 'Dropping constraint %s on table %s (to be dropped)',
  46. constraint[0], constraint[3])
  47. self.env.cr.execute(
  48. "ALTER TABLE %s DROP CONSTRAINT %s",
  49. (
  50. IdentifierAdapter(constraint[3]),
  51. IdentifierAdapter(constraint[0])
  52. ))
  53. self.logger.info(
  54. 'Dropping table %s', line.name)
  55. self.env.cr.execute(
  56. "DROP TABLE %s", (IdentifierAdapter(line.name),))
  57. line.write({'purged': True})
  58. return True
  59. class CleanupPurgeWizardTable(models.TransientModel):
  60. _inherit = 'cleanup.purge.wizard'
  61. _name = 'cleanup.purge.wizard.table'
  62. _description = 'Purge tables'
  63. @api.model
  64. def find(self):
  65. """
  66. Search for tables that cannot be instantiated.
  67. Ignore views for now.
  68. """
  69. # Start out with known tables with no model
  70. known_tables = ['wkf_witm_trans']
  71. for model in self.env['ir.model'].search([]):
  72. if model.model not in self.env:
  73. continue
  74. model_pool = self.env[model.model]
  75. known_tables.append(model_pool._table)
  76. known_tables += [
  77. column._sql_names(model_pool)[0]
  78. for column in model_pool._columns.values()
  79. if (column._type == 'many2many' and
  80. hasattr(column, '_rel')) # unstored function fields of
  81. # type m2m don't have _rel
  82. ]
  83. self.env.cr.execute(
  84. """
  85. SELECT table_name FROM information_schema.tables
  86. WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
  87. AND table_name NOT IN %s""", (tuple(known_tables),))
  88. res = [(0, 0, {'name': row[0]}) for row in self.env.cr.fetchall()]
  89. if not res:
  90. raise UserError(_('No orphaned tables found'))
  91. return res
  92. purge_line_ids = fields.One2many(
  93. 'cleanup.purge.line.table', 'wizard_id', 'Tables to purge')