[MERGE] orm: Don't call the sequence when we create a new record. Use the

returning keyword of the INSERT statement.

bzr revid: stw@openerp.com-20140113153359-3a9w0thdpxp2aqb2
This commit is contained in:
Stephane Wirtel
2014-01-13 16:33:59 +01:00
+42 -23
View File
@@ -4412,7 +4412,15 @@ class BaseModel(object):
tocreate[v] = {}
else:
tocreate[v] = {'id': vals[self._inherits[v]]}
(upd0, upd1, upd2) = ('', '', [])
columns = [
# columns will contain a list of field defined as a tuple
# tuple(field_name, format_string, field_value)
# the tuple will be used by the string formatting for the INSERT
# statement.
('id', "nextval('%s')" % self._sequence),
]
upd_todo = []
unknown_fields = []
for v in vals.keys():
@@ -4429,15 +4437,12 @@ class BaseModel(object):
'No such field(s) in model %s: %s.',
self._name, ', '.join(unknown_fields))
# Try-except added to filter the creation of those records whose filds are readonly.
# Example : any dashboard which has all the fields readonly.(due to Views(database views))
try:
cr.execute("SELECT nextval('"+self._sequence+"')")
except:
raise except_orm(_('UserError'),
_('You cannot perform this operation. New Record Creation is not allowed for this object as this object is for reporting purpose.'))
if not self._sequence:
raise except_orm(
_('UserError'),
_('You cannot perform this operation. New Record Creation is not allowed for this object as this object is for reporting purpose.')
)
id_new = cr.fetchone()[0]
for table in tocreate:
if self._inherits[table] in vals:
del vals[self._inherits[table]]
@@ -4454,9 +4459,7 @@ class BaseModel(object):
else:
self.pool[table].write(cr, user, [record_id], tocreate[table], context=parent_context)
upd0 += ',' + self._inherits[table]
upd1 += ',%s'
upd2.append(record_id)
columns.append((self._inherits[table], '%s', record_id))
#Start : Set bool fields to be False if they are not touched(to make search more powerful)
bool_fields = [x for x in self._columns.keys() if self._columns[x]._type=='boolean']
@@ -4493,13 +4496,13 @@ class BaseModel(object):
if not edit:
vals.pop(field)
for field in vals:
if self._columns[field]._classic_write:
upd0 = upd0 + ',"' + field + '"'
upd1 = upd1 + ',' + self._columns[field]._symbol_set[0]
upd2.append(self._columns[field]._symbol_set[1](vals[field]))
current_field = self._columns[field]
if current_field._classic_write:
columns.append((field, '%s', current_field._symbol_set[1](vals[field])))
#for the function fields that receive a value, we set them directly in the database
#(they may be required), but we also need to trigger the _fct_inv()
if (hasattr(self._columns[field], '_fnct_inv')) and not isinstance(self._columns[field], fields.related):
if (hasattr(current_field, '_fnct_inv')) and not isinstance(current_field, fields.related):
#TODO: this way to special case the related fields is really creepy but it shouldn't be changed at
#one week of the release candidate. It seems the only good way to handle correctly this is to add an
#attribute to make a field `really readonly´ and thus totally ignored by the create()... otherwise
@@ -4511,17 +4514,33 @@ class BaseModel(object):
else:
#TODO: this `if´ statement should be removed because there is no good reason to special case the fields
#related. See the above TODO comment for further explanations.
if not isinstance(self._columns[field], fields.related):
if not isinstance(current_field, fields.related):
upd_todo.append(field)
if field in self._columns \
and hasattr(self._columns[field], 'selection') \
and hasattr(current_field, 'selection') \
and vals[field]:
self._check_selection_field_value(cr, user, field, vals[field], context=context)
if self._log_access:
upd0 += ',create_uid,create_date,write_uid,write_date'
upd1 += ",%s,(now() at time zone 'UTC'),%s,(now() at time zone 'UTC')"
upd2.extend((user, user))
cr.execute('insert into "'+self._table+'" (id'+upd0+") values ("+str(id_new)+upd1+')', tuple(upd2))
columns.append(('create_uid', '%s', user))
columns.append(('write_uid', '%s', user))
columns.append(('create_date', "(now() at time zone 'UTC')"))
columns.append(('write_date', "(now() at time zone 'UTC')"))
# the list of tuples used in this formatting corresponds to
# tuple(field_name, format, value)
# In some case, for example (id, create_date, write_date) we does not
# need to read the third value of the tuple, because the real value is
# encoded in the second value (the format).
cr.execute(
"""INSERT INTO "%s" (%s) VALUES(%s) RETURNING id""" % (
self._table,
', '.join('"%s"' % f[0] for f in columns),
', '.join(f[1] for f in columns)
),
tuple([f[2] for f in columns if len(f) > 2])
)
id_new, = cr.fetchone()
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
if self._parent_store and not context.get('defer_parent_store_computation'):