diff --git a/trytond/backend/database.py b/trytond/backend/database.py index fba6231c3d..44fc1481b8 100644 --- a/trytond/backend/database.py +++ b/trytond/backend/database.py @@ -138,3 +138,41 @@ class CursorInterface(object): Test if it is a Tryton database. ''' raise + + def nextid(self, table): + ''' + Return the next sequenced id for a table. + + :param table: the table name + :return: an integer + ''' + + def setnextid(self, table, value): + ''' + Set the current sequenced id for a table. + + :param table: the table name + ''' + + def currid(self, table): + ''' + Return the current sequenced id for a table. + + :param table: the table name + :return: an integer + ''' + + def lastid(self): + ''' + Return the last id inserted. + + :return: an integer + ''' + + def has_lock(self): + ''' + Return True if database handle lock table. + + :return: a boolean + ''' + raise diff --git a/trytond/backend/postgresql/database.py b/trytond/backend/postgresql/database.py index f2b06237d0..0cc4dc56e4 100644 --- a/trytond/backend/postgresql/database.py +++ b/trytond/backend/postgresql/database.py @@ -357,5 +357,19 @@ class Cursor(CursorInterface): ")") return len(self.cursor.fetchall()) != 0 + def nextid(self, table): + self.cursor.execute("SELECT NEXTVAL('" + table + "_id_seq')") + return self.cursor.fetchone()[0] + + def setnextid(self, table, value): + self.cursor.execute("SELECT SETVAL('" + table + "_id_seq', %d)" % value) + + def currid(self, table): + self.cursor.execute('SELECT last_value FROM "' + table + '_id_seq"') + return self.cursor.fetchone()[0] + + def has_lock(self): + return True + register_type(UNICODE) register_adapter(Session, AsIs) diff --git a/trytond/backend/table.py b/trytond/backend/table.py index 4f7ba8f586..114357e2dc 100644 --- a/trytond/backend/table.py +++ b/trytond/backend/table.py @@ -24,7 +24,7 @@ class TableHandlerInterface(object): if history: self.sequence_name = self.table_name + '___id_seq' else: - self.sequence_name = model._sequence + self.sequence_name = self.table_name + '_id_seq' self.module_name = module_name self.history = history diff --git a/trytond/ir/action.py b/trytond/ir/action.py index b5e64060eb..cc33edc77c 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -204,7 +204,6 @@ ActionKeyword() class ActionReport(ModelSQL, ModelView): "Action report" _name = 'ir.action.report' - _sequence = 'ir_action_id_seq' _description = __doc__ _inherits = {'ir.action': 'action'} model = fields.Char('Model') @@ -327,6 +326,16 @@ class ActionReport(ModelSQL, ModelView): return new_ids[0] return new_ids + def create(self, cursor, user, vals, context=None): + if cursor.nextid(self._table): + cursor.setnextid(self._table, cursor.currid('ir_action')) + new_id = super(ActionReport, self).create(cursor, user, vals, + context=context) + report = self.browse(cursor, user, new_id, context=context) + cursor.execute('UPDATE "' + self._table + '" SET id = %s ' \ + 'WHERE id = %s', (report.action.id, report.id)) + return report.action.id + def write(self, cursor, user, ids, vals, context=None): if context is None: context = {} @@ -357,7 +366,6 @@ ActionReport() class ActionActWindow(ModelSQL, ModelView): "Action act window" _name = 'ir.action.act_window' - _sequence = 'ir_action_id_seq' _description = __doc__ _inherits = {'ir.action': 'action'} domain = fields.Char('Domain Value') @@ -411,6 +419,16 @@ class ActionActWindow(ModelSQL, ModelView): for view in act.act_window_views] return res + def create(self, cursor, user, vals, context=None): + if cursor.nextid(self._table): + cursor.setnextid(self._table, cursor.currid('ir_action')) + new_id = super(ActionActWindow, self).create(cursor, user, vals, + context=context) + act_window = self.browse(cursor, user, new_id, context=context) + cursor.execute('UPDATE "' + self._table + '" SET id = %s ' \ + 'WHERE id = %s', (act_window.action.id, act_window.id)) + return act_window.action.id + def delete(self, cursor, user, ids, context=None): action_obj = self.pool.get('ir.action') @@ -455,7 +473,6 @@ ActionActWindowView() class ActionWizard(ModelSQL, ModelView): "Action wizard" _name = 'ir.action.wizard' - _sequence = 'ir_action_id_seq' _description = __doc__ _inherits = {'ir.action': 'action'} wiz_name = fields.Char('Wizard name', required=True) @@ -467,6 +484,16 @@ class ActionWizard(ModelSQL, ModelView): def default_type(self, cursor, user, context=None): return 'ir.action.wizard' + def create(self, cursor, user, vals, context=None): + if cursor.nextid(self._table): + cursor.setnextid(self._table, cursor.currid('ir_action')) + new_id = super(ActionWizard, self).create(cursor, user, vals, + context=context) + wizard = self.browse(cursor, user, new_id, context=context) + cursor.execute('UPDATE "' + self._table + '" SET id = %s ' \ + 'WHERE id = %s', (wizard.action.id, wizard.id)) + return wizard.action.id + def delete(self, cursor, user, ids, context=None): action_obj = self.pool.get('ir.action') @@ -580,7 +607,6 @@ ActionWizardSize() class ActionURL(ModelSQL, ModelView): "Action URL" _name = 'ir.action.url' - _sequence = 'ir_action_id_seq' _description = __doc__ _inherits = {'ir.action': 'action'} url = fields.Char('Action Url', required=True) @@ -593,6 +619,16 @@ class ActionURL(ModelSQL, ModelView): def default_target(self, cursor, user, context=None): return 'new' + def create(self, cursor, user, vals, context=None): + if cursor.nextid(self._table): + cursor.setnextid(self._table, cursor.currid('ir_action')) + new_id = super(ActionURL, self).create(cursor, user, vals, + context=context) + url = self.browse(cursor, user, new_id, context=context) + cursor.execute('UPDATE "' + self._table + '" SET id = %s ' \ + 'WHERE id = %s', (url.action.id, url.id)) + return url.action.id + def delete(self, cursor, user, ids, context=None): action_obj = self.pool.get('ir.action') diff --git a/trytond/ir/cron.py b/trytond/ir/cron.py index 3d561a10a1..8555972ae9 100644 --- a/trytond/ir/cron.py +++ b/trytond/ir/cron.py @@ -154,7 +154,8 @@ class Cron(ModelSQL, ModelView): return try: try: - cursor.execute('LOCK TABLE ir_cron') + if cursor.has_lock(): + cursor.execute('LOCK TABLE ir_cron') cursor.execute('SELECT * FROM ir_cron ' \ 'WHERE numbercall <> 0 ' \ 'AND active ' \ diff --git a/trytond/ir/sequence.py b/trytond/ir/sequence.py index c9b0cead08..9999078661 100644 --- a/trytond/ir/sequence.py +++ b/trytond/ir/sequence.py @@ -144,7 +144,8 @@ class SequenceStrict(Sequence): _description = __doc__ def get_id(self, cursor, user, clause, context=None): - cursor.execute('LOCK TABLE "' + self._table + '"') + if cursor.has_lock(): + cursor.execute('LOCK TABLE "' + self._table + '"') return super(SequenceStrict, self).get_id(cursor, user, clause, context=context) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index e58447d692..69ed9ec4a8 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -21,8 +21,6 @@ class ModelSQL(ModelStorage): ``[('name', 'ASC'), 'age', 'DESC']`` :_order_name: The name of the field (or an SQL statement) on which the records must be sorted when sorting on this model from an other one. - :_sequence: The name of the sequence in the database that increments the - ``id`` field. :_history: A boolean to historize record change. :_sql_constraints: A list of constraints that are added on the table. E.g.: @@ -35,7 +33,6 @@ class ModelSQL(ModelStorage): _table = None # The name of the table in database _order = None _order_name = None # Use to force order field when sorting on Many2One - _sequence = None _history = False def __init__(self): @@ -50,9 +47,6 @@ class ModelSQL(ModelStorage): assert self._table[-9:] != '__history', \ 'Model _table %s cannot end with "__history"' % self._table - if not self._sequence: - self._sequence = self._table+'_id_seq' - def init(self, cursor, module_name): super(ModelSQL, self).init(cursor, module_name) @@ -254,10 +248,6 @@ class ModelSQL(ModelStorage): del defaults[field] values.update(self._clean_defaults(defaults)) - # Get new id - cursor.execute("SELECT NEXTVAL('" + self._sequence + "')") - (id_new,) = cursor.fetchone() - (upd0, upd1, upd2) = ('', '', []) upd_todo = [] @@ -318,9 +308,16 @@ class ModelSQL(ModelStorage): upd1 += ', %s, now()' upd2.append(user) try: - cursor.execute('INSERT INTO "' + self._table + '" ' \ - '(id' + upd0 + ') ' \ - 'VALUES (' + str(id_new) + upd1 + ')', tuple(upd2)) + id_new = cursor.nextid(self._table) + if id_new: + cursor.execute('INSERT INTO "' + self._table + '" ' \ + '(id' + upd0 + ') ' \ + 'VALUES (' + str(id_new) + upd1 + ')', tuple(upd2)) + else: + cursor.execute('INSERT INTO "' + self._table + '" ' \ + '(' + upd0[1:] + ') ' \ + 'VALUES (' + upd1[1:] + ')', tuple(upd2)) + id_new = cursor.lastid() except DatabaseIntegrityError, exception: database = Database(cursor.database_name).connect() cursor2 = database.cursor() diff --git a/trytond/res/ir.py b/trytond/res/ir.py index a4e5326f3e..8bf29753a3 100644 --- a/trytond/res/ir.py +++ b/trytond/res/ir.py @@ -17,7 +17,7 @@ class UIMenuGroup(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'ir_ui_menu_group_rel', self._table) TableHandler.sequence_rename(cursor, 'ir_ui_menu_group_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(UIMenuGroup, self).init(cursor, module_name) UIMenuGroup() @@ -36,7 +36,7 @@ class ActionGroup(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'ir_action_group_rel', self._table) TableHandler.sequence_rename(cursor, 'ir_action_group_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(ActionGroup, self).init(cursor, module_name) ActionGroup() @@ -55,7 +55,7 @@ class ModelFieldGroup(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'ir_model_field_group_rel', self._table) TableHandler.sequence_rename(cursor, 'ir_model_field_group_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(ModelFieldGroup, self).init(cursor, module_name) ModelFieldGroup() @@ -74,7 +74,7 @@ class RuleGroupGroup(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'group_rule_group_rel', self._table) TableHandler.sequence_rename(cursor, 'group_rule_group_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(RuleGroupGroup, self).init(cursor, module_name) RuleGroupGroup() @@ -93,7 +93,7 @@ class RuleGroupUser(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'user_rule_group_rel', self._table) TableHandler.sequence_rename(cursor, 'user_rule_group_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(RuleGroupUser, self).init(cursor, module_name) RuleGroupUser() diff --git a/trytond/res/user.py b/trytond/res/user.py index 124c62c5fc..bb761e5937 100644 --- a/trytond/res/user.py +++ b/trytond/res/user.py @@ -323,7 +323,7 @@ class UserGroup(ModelSQL): # Migration from 1.0 table name change TableHandler.table_rename(cursor, 'res_group_user_rel', self._table) TableHandler.sequence_rename(cursor, 'res_group_user_rel_id_seq', - self._sequence) + self._table + '_id_seq') super(UserGroup, self).init(cursor, module_name) UserGroup()