EB.
EB.

Reputation: 3555

In OpenERP, how can I force SQL to run when a module is installed?

I have a module built in OpenERP that adds some fields to existing models.

The definition is roughly as follows:

class res_partner(osv.osv):
    _name = _inherit = 'res.partner'
    _columns = {
        'my_special_id': fields.integer('Special ID', required=False, readonly=True),
    }
    _defaults = {
        'my_special_id': lambda *a: None
    }

    _sql_constraints = [
        ('special_id_uniq', 'UNIQUE (my_special_id)', 'Must be unique.'),
    }

    _sql = """CREATE UNIQUE INDEX special_id_limited_uniq
            ON res_partner (my_special_id)
            WHERE my_special_id != 0
    """
res_partner()

My goal is to have a field (special_id_uniq) that:

  1. Defaults to NULL
  2. Is an integer
  3. Is unique, across all values, except for NULL

My first instinct was to create the _sql_constraint definition above, but this caused issues: apparently OpenERP doesn't have nullable integer fields, so 'None' is treated as 0. This breaks the SQL constraint, as now multiple values of 0 must be allowed.

To get around this, I removed the _sql_constraints option on the model and added the _sql code which creates a PostgreSQL partial index. To verify that it works, I ran the SQL myself on PostgreSQL and it acheives my desired effect. However, when I create a new DB via OpenERP and install my custom module, this SQL is not run. That is because the model is not being created:

def _auto_init(self, cr, context=None):
    #...
    create = not self._table_exist(cr)
    #...
    #Line 3046 of openerp/osv/orm.py version 6.1 function _auto_init
    if create:
        self._execute_sql(cr)
    #...

So, how can I run some custom SQL at the point of module installation?

Upvotes: 4

Views: 2304

Answers (2)

Daniel Reis
Daniel Reis

Reputation: 13342

You can achieve this by adding a function entry in a data xml file of the module.

<openerp>
  <data>
    <!-- ... your init data records ...-->
    <function model="res.partner" name="_my_init_mehod"/>
  </data>
</openerp>

You can see a working example of this in the standard module document: document_data.xml declares a call to the function _attach_parent_id to migrate all attachments to the new DMS structure at the end of the installation.

Upvotes: 3

EB.
EB.

Reputation: 3555

Actually, I might have just answered my own question: override _auto_init.

Edit:

Yes, the following works to run the SQL during install / upgrade:

def _auto_init(self, cr, context=None):
    ret = super(res_partner, self)._auto_init(cr, context)
    self._execute_sql(cr)
    return ret

Upvotes: 4

Related Questions