Hmmm, it looks interesting also! I'm just using the postgres version of your previous solution, and modified / added some features, so pg type ARRAY could be used with labels and to specify a maximum recursion level (let's say, do not go more then 10 levels (not relative to start_node, still)). I'll see after this solution and see which can be best applied :-)

Probably I'll create an Oracle server here to test it too.


Thank you very much,
Richard.


On 04/29/2013 02:57 PM, Mariano Mara wrote:

On 04/25/2013 11:17 AM, Richard Gerd Kuesters wrote:
Well. I'm pretty interested :) I did find your solution very flexible, thou.

Thanks a lot,
Richard.



For completeness, here is a pure sqlalchemy version of the same recursive ideas:


    def _hierarchy():
        # TODO: check if object has self referential key
        sq1 = S.query(self.model)
sq1 = sq1.add_columns(*(label("level", literal(1, type_=Integer)), label("cycle", literal(False, type_=Boolean)),
                                label("connect_path",
literal_column("ARRAY[id]", ARRAY(Integer)
                                    ))))
        sq1 = sq1.filter(self.model.parent_id==None)
        sq1 = sq1.cte(name="sq1", recursive=True)
        sq1_alias = aliased(sq1, name="pr")
        sq2_alias = aliased(self.model, name="p")
        sq1 = sq1.union_all(
                S.query(sq2_alias,
                        label("level", sq1_alias.c.level+1),
label("cycle", Any(sq2_alias.id, sq1_alias.c.connect_path)),
                        label("connect_path",
func.array_append(sq1_alias.c.connect_path,
                                                  sq2_alias.id))
).filter(and_(sq2_alias.parent_id==sq1_alias.c.id,
                                  ~sq1_alias.c.cycle)))
        q = S.query(sq1)
        q = q.add_columns(*(label("is_leaf",
            case([(
            sq1.c.connect_path.contained_by(
                over(func.lead(
sq1.c.connect_path, 1),order_by=sq1.c.connect_path))==True,
                False)], else_=True)),))
        return q.all()


It could use some testing (something I am about to do) and you still need to cast to your object but all the ingredients are here. As usual the model needs a self referential key (in this case "id" and "parent_id"). I try not to use the textual "ARRAY[id]" to generate the first connect_path but I couldn't make it without errors (and the time was pressing): If you have a suggestion on how to do so, I will surely appreciate it.

Mariano

On 04/25/2013 11:08 AM, Mariano Mara wrote:
On 04/25/2013 10:22 AM, Richard Gerd Kuesters wrote:
Hi all,

I've been playing with "sqla_hierarchy" from
https://github.com/marplatense/sqla_hierarchy .


That code of that sqla_hierarchy was written to provide a limited
support for cte, from the time when sqalchemy didn't have cte.
Since sqlalchemy has cte now I would recommend to migrate to pure
sqlalchemy code which will open more possibilities for you to interact
with your objects and provide support in the long term.

I am currently trying to do so (and once I solve how to get *level*,
*is_leaf* and *connect_path* attributes as part of the results, I can
surely share it through the list for anyone who's interested).

Mariano



--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to