[IMP] allow non integer for ID's
[odoo/odoo.git] / openerp / modules / db.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #    Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU Affero General Public License as
10 #    published by the Free Software Foundation, either version 3 of the
11 #    License, or (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU Affero General Public License for more details.
17 #
18 #    You should have received a copy of the GNU Affero General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 import openerp.modules
24 import logging
25
26 def is_initialized(cr):
27     """ Check if a database has been initialized for the ORM.
28
29     The database can be initialized with the 'initialize' function below.
30
31     """
32     cr.execute("SELECT relname FROM pg_class WHERE relkind='r' AND relname='ir_module_module'")
33     return len(cr.fetchall()) > 0
34
35 def initialize(cr):
36     """ Initialize a database with for the ORM.
37
38     This executes base/base.sql, creates the ir_module_categories (taken
39     from each module descriptor file), and creates the ir_module_module
40     and ir_model_data entries.
41
42     """
43     f = openerp.modules.get_module_resource('base', 'base.sql')
44     if not f:
45         m = "File not found: 'base.sql' (provided by module 'base')."
46         logging.getLogger('init').critical(m)
47         raise IOError(m)
48     base_sql_file = openerp.tools.misc.file_open(f)
49     try:
50         cr.execute(base_sql_file.read())
51         cr.commit()
52     finally:
53         base_sql_file.close()
54
55     for i in openerp.modules.get_modules():
56         mod_path = openerp.modules.get_module_path(i)
57         if not mod_path:
58             continue
59
60         # This will raise an exception if no/unreadable descriptor file.
61         info = openerp.modules.load_information_from_description_file(i)
62
63         if not info:
64             continue
65         categories = info['category'].split('/')
66         category_id = create_categories(cr, categories)
67
68         if info['installable']:
69             if info['active']:
70                 state = 'to install'
71             else:
72                 state = 'uninstalled'
73         else:
74             state = 'uninstallable'
75
76         cr.execute('INSERT INTO ir_module_module \
77                 (author, website, name, shortdesc, description, \
78                     category_id, state, certificate, web, license, complexity, application, icon) \
79                 VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING id', (
80             info['author'],
81             info['website'], i, info['name'],
82             info['description'], category_id, state, info['certificate'],
83             info['web'],
84             info['license'],
85             info['complexity'], info['application'], info['icon']))
86         id = cr.fetchone()[0]
87         cr.execute('INSERT INTO ir_model_data \
88             (name,model,module, res_id, noupdate) VALUES (%s,%s,%s,%s,%s)', (
89                 'module_'+i, 'ir.module.module', 'base', id, True))
90         dependencies = info['depends']
91         for d in dependencies:
92             cr.execute('INSERT INTO ir_module_module_dependency \
93                     (module_id,name) VALUES (%s, %s)', (id, d))
94         cr.commit()
95
96 def create_categories(cr, categories):
97     """ Create the ir_module_category entries for some categories.
98
99     categories is a list of strings forming a single category with its
100     parent categories, like ['Grand Parent', 'Parent', 'Child'].
101
102     Return the database id of the (last) category.
103
104     """
105     p_id = None
106     category = []
107     while categories:
108         category.append(categories[0])
109         if p_id is not None:
110             cr.execute('SELECT id \
111                        FROM ir_module_category \
112                        WHERE name=%s AND parent_id=%s', (categories[0], p_id))
113         else:
114             cr.execute('SELECT id \
115                        FROM ir_module_category \
116                        WHERE name=%s AND parent_id IS NULL', (categories[0],))
117         c_id = cr.fetchone()
118         if not c_id:
119             cr.execute('INSERT INTO ir_module_category \
120                     (name, parent_id) \
121                     VALUES (%s, %s) RETURNING id', (categories[0], p_id))
122             c_id = cr.fetchone()[0]
123             xml_id = 'module_category_' + ('_'.join(map(lambda x: x.lower(), category))).replace('&', 'and').replace(' ', '_')
124             cr.execute('INSERT INTO ir_model_data (module, name, res_id, model) \
125                        VALUES (%s, %s, %s, %s)', ('base', xml_id, c_id, 'ir.module.category'))
126         else:
127             c_id = c_id[0]
128         p_id = c_id
129         categories = categories[1:]
130     return p_id
131
132 def has_unaccent(cr):
133     """ Test if the database has an unaccent function.
134
135     The unaccent is supposed to be provided by the PostgreSQL unaccent contrib
136     module but any similar function will be picked by OpenERP.
137
138     """
139     cr.execute("SELECT proname FROM pg_proc WHERE proname='unaccent'")
140     return len(cr.fetchall()) > 0
141
142 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: