Quantcast
Viewing all articles
Browse latest Browse all 18

SQL ordered trees, an addendum

I am currently working on an application which needs to store ordered trees in a PostgreSQL database. The elements in a single tree may be re-ordered by the user. For the trees themselves, I'm using something very similar to what depesz's post describes. There is a catch, however.

In order to allow the user to change the ordering of the tree's elements, the easiest way is to set the "moved" element's ordering index to ( 1 + ordering index of the element it's being added after). However, if element B has been moved after element A, and element C is then moved to after element A as well, this would cause an unique index violation. This may also happen on insertion (if a new element D is inserted after element A). Because of that, the ordering of the tree's elements need to be reset whenever such an operation takes place.

For starters, it is necessary to start by moving the objects "out of the way" before actually re-ordering: for example, if 3 rows are present with ordering indexes 2, 3 and 4, the middle row would have its ordering index set to 4 and that would fail.

UPDATE objects SET object_ordering = object_ordering + (
     SELECT 1 + 2 * max( object_ordering ) FROM objects );

It is then possible to reset the ordering index; the "trick" I used to do that relies on window functions, so it will only work on PostgreSQL 8.4 or 9.x.

UPDATE objects o1 SET object_ordering = 2 * o2.rn
    FROM ( SELECT object_id , row_number() OVER(
                   ORDER BY object_ordering_path
               ) AS rn FROM objects ) o2
    WHERE o1.object_id = o2.object_id;

Viewing all articles
Browse latest Browse all 18

Trending Articles