Skip to main content

Adjacency List Relationships helper (only using databases own implementations)

Project description

--------------
SQLA_Hierarchy
--------------

-----------
Description
-----------

Given a `Table`_ object and a `Select`_ expression, this class will return the information from these objects with some extra columns that will properly denote the hierarchical relation between the rows. The returned Hierarchy object could then be executed and it will return the same Select statement submitted plus the following columns:

- level: the relative level of the row related to its parent
- connect_path: a list with all the ids that compound this part of the hierarchy, from the root node to the current value (**IMPORTANT**: Oracle requires some extra post processing to generate the list)
- is_leaf: boolean indicating is the particular id is a leaf or not

The resultset will be returned properly ordered by the levels in the hierarchy

Special remarks:

- The selected table must have a self referential foreign key relation, otherwise it will raise MissingForeignKey
- Not every database is supported (at the moment). Check the global var supported_db for an up2date list. Trying to execute Hierarchy with an unsupported db will raise NotImplementedError or HierarchyLesserError (check the errors classes docstring for the exact meaning of each of them).
- To prevent the query from returning every node as a different starting node and, therefore, having duplicate values, you can provide the 'starting_node' parameter in the kwargs. The value you must provide is the parent id for the root node you want to start building the hierarchical tree. None has the same meaning as "0" since we perform a coalesce function in the query. By default the system will add a 'starting_node'="0". If you don't want a starting node, pass 'starting_node'=False and the clause will not be added to the query

*Supported databases*:

- PostgreSQL (>=8.4.0)
- Oracle (>=10g)

*Databases we might support on a next version*:

- SQL Server
- DB2

*Databases that we know we cannot support* (because they do not implement recursive):

- MySQL
- SQLite

-------------
Some examples
-------------

First of all, let's set up some imports and variables we will be using ::

>>> import ConfigParser
>>> from sqlalchemy import Table, Column, ForeignKey, MetaData, create_engine
>>> from sqlalchemy import Unicode, select, and_
>>> from sqlalchemy.orm import mapper, relationship, scoped_session, sessionmaker
>>> from sqla_hierarchy import *
>>> DBSession = scoped_session(sessionmaker())
>>> metadata = MetaData()
>>> config = ConfigParser.ConfigParser()
>>> config.read('setup.cfg')
['setup.cfg']
>>> engine = create_engine('postgresql://%s' % config.get('dburi', 'pg-db'))
>>> DBSession.configure(bind=engine)
>>> metadata.bind = engine

Let's build some simple table/class to hold boss/employee relation ::

>>> example_tb = Table('employee', metadata,
... Column('id', Unicode, primary_key=True),
... Column('boss', Unicode, ForeignKey('employee.id')))
>>> class Employee(object):
... def __init__(self, employee, boss=None):
... self.id = employee
... self.boss = boss
... def __repr__(self):
... return "<Employee %s, Boss %s>" % (self.id, self.boss)
...
>>> mapper(Employee, example_tb, properties={ #doctest: +ELLIPSIS
... 'parent': relationship(Employee, remote_side=[example_tb.c.id])})
<Mapper at 0x...; Employee>
>>> example_tb.drop(checkfirst=True)
>>> example_tb.create(checkfirst=True)

Add some data ::

>>> pl = [Employee(u'King Cold', None), Employee(u'Frieza', u'King Cold'),
... Employee(u'Zarbon', u'Frieza'), Employee(u'Dodoria', u'Frieza'),
... Employee(u'Captain Ginyu', u'Frieza'),
... Employee(u'Jeice', u'Captain Ginyu'),
... Employee(u'Burter', u'Captain Ginyu'),
... Employee(u'Recoome', u'Captain Ginyu'),
... Employee(u'Guldo', u'Captain Ginyu'),
... Employee(u'Dr Gero', None), Employee(u'A-16', u'Dr Gero'),
... Employee(u'A-17', u'Dr Gero'), Employee(u'A-18', u'Dr Gero'),
... Employee(u'Cell', u'Dr Gero'), Employee(u'Cell Junior', u'Cell')]
>>> DBSession.add_all(pl)
>>> DBSession.commit()

Now let's query some basic relations. First we want a list of bosses and employees using some indentation to visually understand who depends on who ::

>>> qry = Hierarchy(DBSession, example_tb, select([example_tb]))
>>> rs = DBSession.execute(qry).fetchall()
>>> for ev in rs:
... if ev.level == 1:
... print(ev.id)
... else:
... print(" "*2*ev.level+ev.id)
Dr Gero
A-16
A-17
A-18
Cell
Cell Junior
King Cold
Frieza
Captain Ginyu
Burter
Guldo
Jeice
Recoome
Dodoria
Zarbon

Let's take a look at the special attributes sqla_hierachy added ::

>>> print(rs[0])
(u'Dr Gero', None, 1, ['Dr Gero'], False)

*Level*: The relative position of this record in the tree. '1' means he/she is the root. The higher the number, the bigger the distance is between the root and the current record ::

>>> print(rs[0].level)
1

*Connect Path*: Print the full list of members of this relation: from the root up to the current record::

>> print(rs[0].connect_path)
['Dr Gero']

*Is Leaf*: If is_leaf is True, this record has no more dependents. If False, there are more records that depend on him/her::

>>> print(rs[0].is_leaf)
False

Now an example with a record that is a leaf ::

>>> print(rs[9].level, rs[9].is_leaf)
(4, True)
>>> print(rs[9].connect_path)
['King Cold', 'Frieza', 'Captain Ginyu', 'Burter']

.. _Table: http://www.sqlalchemy.org/docs/core/schema.html#sqlalchemy.schema.Table
.. _Select: http://www.sqlalchemy.org/docs/core/expression_api.html#sqlalchemy.sql.expression.Select _

Project details


Release history Release notifications | RSS feed

This version

0.1

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqla_hierarchy-0.1.tar.gz (6.7 kB view details)

Uploaded Source

Built Distributions

sqla_hierarchy-0.1-py2.7.egg (12.1 kB view details)

Uploaded Source

sqla_hierarchy-0.1-py2.6.egg (12.1 kB view details)

Uploaded Source

sqla_hierarchy-0.1-py2.5.egg (12.1 kB view details)

Uploaded Source

sqla_hierarchy-0.1-py2.4.egg (12.1 kB view details)

Uploaded Source

File details

Details for the file sqla_hierarchy-0.1.tar.gz.

File metadata

File hashes

Hashes for sqla_hierarchy-0.1.tar.gz
Algorithm Hash digest
SHA256 ed16c49d137421d92673da233274d075ee9b13b8a270ca7c6f6d4e8b4f76544f
MD5 4b3c80e0af02a801d36dd60f7bdea406
BLAKE2b-256 06a3a8456cd0a488bc04ae9caec068937e5ba8e7a4827df631bede56d0b665b7

See more details on using hashes here.

File details

Details for the file sqla_hierarchy-0.1-py2.7.egg.

File metadata

File hashes

Hashes for sqla_hierarchy-0.1-py2.7.egg
Algorithm Hash digest
SHA256 7db814c1ac23d4dcbdc59c2e75c95c32aa2b833f98c929cc0e1b06a246c9361b
MD5 fe2ff8a1c253875beff2ad375659319b
BLAKE2b-256 168c1a2d19b5cef1309e84e680453e92b736d7dba5cad9b81f9b98014f2c7c9f

See more details on using hashes here.

File details

Details for the file sqla_hierarchy-0.1-py2.6.egg.

File metadata

File hashes

Hashes for sqla_hierarchy-0.1-py2.6.egg
Algorithm Hash digest
SHA256 4cf9309048c77cd775ae9b57df28bd2c2baba82e1d78c66b30950e071c92d081
MD5 5b7332788b9bc03387d29fde50e25e56
BLAKE2b-256 0bc70bf50c4cb9288cc81598bb594c6c014455d440f95a6e7b413d0927053848

See more details on using hashes here.

File details

Details for the file sqla_hierarchy-0.1-py2.5.egg.

File metadata

File hashes

Hashes for sqla_hierarchy-0.1-py2.5.egg
Algorithm Hash digest
SHA256 cff568762eb28f9b9f03055c137f5e329ed763dd7dbc4caee9066d47d486ef51
MD5 ce9192b07300652a68b8edd57ca2838e
BLAKE2b-256 7d7268fc0ca850d3b6d633034cabc91a8f9164bcc25d4b9a8c954517a7ce7484

See more details on using hashes here.

File details

Details for the file sqla_hierarchy-0.1-py2.4.egg.

File metadata

File hashes

Hashes for sqla_hierarchy-0.1-py2.4.egg
Algorithm Hash digest
SHA256 21e81997cf342f9fc6039ed3f0b8a085e49d741cf848a37b0d0800bdb9825dd3
MD5 c64eabab0e487556cbfa38a4346c6990
BLAKE2b-256 48cd3adb3b7a61cdbf21bcb9ea1c8be7af9e6f0524b498f03ea486addd9cc5b6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page