Only rebuild mptt tree if needed

The tree will be only rebuild if a record with the default value of left or right fields exists.

issue5118
review16921002
This commit is contained in:
Sergi Almacellas Abellana
2016-01-11 15:33:08 +01:00
parent 1bd76628c6
commit 2a723f2e52
3 changed files with 21 additions and 8 deletions
+1
View File
@@ -1,5 +1,6 @@
* Allow nested inherited view
* Add button on cron to run once
* Only rebuild mptt tree if left or right values have their default values
* Check all fields when writing a sequence of records, values (CVE-2015-0861)
* Add view_ids on tree view
* Add parent_of operator
+3
View File
@@ -485,6 +485,9 @@ A many-to-one relation field.
Tree Traversal`_.
It only works if the :attr:`model_name` is the same then the model.
.. warning:: The MPTT Tree will be rebuild on database update if one record
is found having left or right field value equals to the default or NULL.
.. _`Modified Preorder Tree Traversal`: http://en.wikipedia.org/wiki/Tree_traversal
.. attribute:: Many2One.right
+17 -8
View File
@@ -126,6 +126,8 @@ class ModelSQL(ModelStorage):
@classmethod
def __register__(cls, module_name):
sql_table = cls.__table__()
cursor = Transaction().cursor
TableHandler = backend.get('TableHandler')
super(ModelSQL, cls).__register__(module_name)
@@ -135,10 +137,10 @@ class ModelSQL(ModelStorage):
pool = Pool()
# create/update table in the database
table = TableHandler(Transaction().cursor, cls, module_name)
table = TableHandler(cursor, cls, module_name)
if cls._history:
history_table = TableHandler(Transaction().cursor, cls,
module_name, history=True)
history_table = TableHandler(
cursor, cls, module_name, history=True)
history_table.index_action('id', action='add')
for field_name, field in cls._fields.iteritems():
@@ -205,17 +207,24 @@ class ModelSQL(ModelStorage):
if isinstance(field, fields.Many2One) \
and field.model_name == cls.__name__ \
and field.left and field.right:
cls._rebuild_tree(field_name, None, 0)
left_default = cls._defaults.get(field.left, lambda: None)()
right_default = cls._defaults.get(field.right, lambda: None)()
cursor.execute(*sql_table.select(sql_table.id,
where=(Column(sql_table, field.left) == left_default)
| (Column(sql_table, field.left) == Null)
| (Column(sql_table, field.right) == right_default)
| (Column(sql_table, field.right) == Null),
limit=1))
if cursor.fetchone():
cls._rebuild_tree(field_name, None, 0)
for ident, constraint, _ in cls._sql_constraints:
table.add_constraint(ident, constraint)
if cls._history:
cls._update_history_table()
cursor = Transaction().cursor
table = cls.__table__()
history_table = cls.__table_history__()
cursor.execute(*table.select(table.id))
cursor.execute(*sql_table.select(sql_table.id))
if cursor.fetchone():
cursor.execute(*history_table.select(history_table.id))
if not cursor.fetchone():
@@ -223,7 +232,7 @@ class ModelSQL(ModelStorage):
if not hasattr(f, 'set')]
cursor.execute(*history_table.insert(
[Column(history_table, c) for c in columns],
table.select(*(Column(table, c)
sql_table.select(*(Column(sql_table, c)
for c in columns))))
cursor.execute(*history_table.update(
[history_table.write_date], [None]))