It is sqlite3 example and it also uses db function...
I do not quite understand what confuses you

On Monday, November 26, 2018 at 3:47:29 PM UTC+3, Ben Duncan wrote:
>
> What database are you using ?
>
> In our e-file system, we have something similar with  court cases, but we 
> use db functions to do the heavy lifting
> for use, since in postgres they can be called with a select directly ...
>
>
> *Ben Duncan*
> DBA / Chief Software Architect 
> Mississippi State Supreme Court
> Electronic Filing Division
>
>
> On Sat, Nov 24, 2018 at 10:31 AM Val K <valq...@gmail.com <javascript:>> 
> wrote:
>
>>
>> running example: 
>>
>> # fake table in which result of recursive select will be temporary stored
>> # id-values will be inherited from parent_child table
>> db.define_table('entry_collector',
>>         Field('child', 'integer'),
>>         Field('xpath', 'json'), # array of ids,  xpath[0] == root, 
>> xpath[-1] == child
>>         Field('root', 'integer'),
>>         Field('xdepth', 'integer'),
>>         migrate_enabled = False,
>>         fake_migrate = True
>>     )
>>
>>
>> def with_recursive(parent, child, roots_select, q, *fields, 
>> **select_kwargs):
>>     """
>>     parent, child  - fields obj ( like  db.parent_child.parent, 
>> db.parent_child.child )
>>     roots_select - sql string (like 'select 123 as id' or 
>> db(db.person.id.belongs([11,22,33])._select(db.person.id))
>>     q, fields, select_kwargs  - args that will pass to dal: 
>> db(q).select(*fields, **select_kwargs)
>>     select_kwargs may include 'entry_collector' - name of fake table for 
>> recursive (default is 'entry_collector')
>>     returns a regular rows dal object (nothing new)
>>     """
>>
>>     entry_collector = select_kwargs.pop('entry_collector', 
>> 'entry_collector')
>>     args = Storage(
>>         entry = parent.table._tablename,
>>         parent = parent.name,
>>         child  = child.name,
>>         entry_collector = entry_collector,
>>         roots = roots_select
>>     )
>>
>>     rec_sql_s = \
>>     """
>>         WITH RECURSIVE
>>         %(entry_collector)s(id, child, xpath, root, xdepth) AS
>>             (SELECT NULL, id, "[" || id || "]", id, 0 FROM (%(roots)s)
>>              UNION
>>              SELECT  %(entry)s.id,
>>                      %(entry)s.%(child)s,
>>                      rtrim(xpath,"]") || "," || %(entry)s.%(child)s || 
>> "]",
>>                      %(entry_collector)s.root,
>>                      %(entry_collector)s.xdepth + 1
>>                  FROM %(entry_collector)s
>>                  JOIN %(entry)s ON
>>                      NOT instr(%(entry_collector)s.xpath, 
>>  %(entry)s.%(parent)s || "," )
>>                      AND %(entry)s.%(parent)s = %(entry_collector)s.child
>>                  ORDER BY 5 DESC /* means BY xdepth  */
>>
>>             )
>>     """ % args
>>
>>     q = db(q)
>>     dal_select = q._db._adapter._select_aux
>>     def patch_select(*args, **kwargs):
>>         if args:
>>             is_recursive = False
>>             for fld in args[1]:
>>                 if  fld.table._tablename == 'entry_collector':
>>                     is_recursive = True
>>                     break
>>             if is_recursive:
>>                 args = list(args)
>>                 args[0] = rec_sql_s + args[0]
>>                 print 'with rec: ', args[0]
>>         return dal_select(*args, **kwargs)
>>
>>     q._db._adapter._select_aux = patch_select
>>     try:
>>         ret = q.select(*(fields + (db[entry_collector].id,)), 
>>  **select_kwargs)
>>     finally:
>>         q._db._adapter._select_aux = dal_select
>>        return ret
>>
>>
>>
>>
>> On Thursday, November 22, 2018 at 2:41:23 AM UTC+3, BigBaaadBob wrote:
>>>
>>> The use case is manufacturing. Large complicated manufacturing with 
>>> special requirements. And SAP need not apply... :-)
>>>
>>> On Wednesday, November 21, 2018 at 1:26:56 PM UTC-8, Dave S wrote:
>>>>
>>>>
>>>>
>>>> On Wednesday, November 21, 2018 at 10:33:13 AM UTC-8, BigBaaadBob wrote:
>>>>>
>>>>> I'm just trying to find a good solid way of doing the BOM pattern 
>>>>> using the DAL, and pretty much all of the decent articles I've found say 
>>>>> the Closure Table method is the best trade-off, especially for large-ish 
>>>>> and deep-ish BOM structures. 
>>>>>
>>>>
>>>> It would be interesting to hear your use case.  Are you into a 
>>>> scheduling problem like the airport/flight example?  Or an organizational 
>>>> example where you need to quickly find the director in the hierarchy above 
>>>> one us grunts?
>>>>
>>>>
>>>>> But, I'm not dogmatic. How would you code up a version using "with 
>>>>> recursive" queries using the DAL? If you post a running example it would 
>>>>> be 
>>>>> great at informing the group!
>>>>>
>>>>> On Wednesday, November 21, 2018 at 9:56:48 AM UTC-8, Val K wrote:
>>>>>>
>>>>>> Why do you have to use this crutches (despite they are genius)? Now, 
>>>>>> even Sqlite3 supports 'with recursive' queries.
>>>>>> And what do you mean under BOM  and large tree? If we are talking 
>>>>>> about BOM of  real (physical) object like a car or even an aircraft 
>>>>>> carrier, I think  it is not large tree
>>>>>>  only if you don't want to have BOAOM (bill of atoms of materials) 
>>>>>>
>>>>>>
>>>> My BOM experience is more with circuit boards, and there would probably 
>>>> a dozen part numbers for resistors and and a dozen part numbers for 
>>>> capacitors, and more than a dozen ICs.  But there could be a dozen or a 
>>>> hundred boards using part X, and if you need to figure out which boards 
>>>> are 
>>>> affected when the manufacturer stops manuffing the part, it starts getting 
>>>> interesting.  If you also make boxes the boards go into, then the 
>>>> hierarchy 
>>>> gains another level (although not many entries at that level).
>>>>
>>>>  
>>>>
>>>>> On Wednesday, November 21, 2018 at 7:58:48 PM UTC+3, BigBaaadBob wrote:
>>>>>>>
>>>>>>> I went ahead and coded something up, inspired by Massimo's Preorder 
>>>>>>> Traversal example. I wouldn't be offended if people suggest how to make 
>>>>>>> it 
>>>>>>> better/faster, perhaps by combining stuff in the Link function into one 
>>>>>>> query instead of many.
>>>>>>>
>>>>>>> # Demonstrate closure tables. Deletion of nodes is left as an 
>>>>>>> exercise to the reader.
>>>>>>> # See: 
>>>>>>> http://dirtsimple.org/2010/11/simplest-way-to-do-tree-based-queries.html
>>>>>>>  
>>>>>>>
>>>>>>> from gluon import DAL, Field
>>>>>>>
>>>>>>> db=DAL('sqlite://closure.db') 
>>>>>>>
>>>>>>> db.define_table(
>>>>>>>     'thing',
>>>>>>>     db.Field('name')
>>>>>>> )
>>>>>>> db.thing.truncate()
>>>>>>>
>>>>>>> db.define_table(
>>>>>>>     'closure',
>>>>>>>     db.Field('parent', type='reference thing'),
>>>>>>>     db.Field('child', type='reference thing'),
>>>>>>>     db.Field('depth', type='integer')
>>>>>>> )
>>>>>>> db.closure.truncate()
>>>>>>>
>>>>>>> def link(parent_id,child_id):
>>>>>>>     """ link(1,3) """
>>>>>>>     p = db.closure.with_alias('p')
>>>>>>>     c = db.closure.with_alias('c')
>>>>>>>     rows = db((p.child==parent_id) & (c.parent==child_id)).select(
>>>>>>>             p.parent.with_alias('parent'),
>>>>>>>             c.child.with_alias('child'),
>>>>>>>             (p.depth+c.depth+1).with_alias('depth'))
>>>>>>>     for row in rows:
>>>>>>>         db.closure.insert(parent=row.parent, child=row.child, 
>>>>>>> depth=row.depth)
>>>>>>>     
>>>>>>> def add_node(name,parent_name): 
>>>>>>>     """ add_node('Fruit','Food') """
>>>>>>>     child_id=db.thing.insert(name=name)
>>>>>>>     db.closure.insert(parent=child_id, child=child_id, depth=0)
>>>>>>>     if parent_name is not None:
>>>>>>>         parent_id=db(db.thing.name==parent_name).select().first().id
>>>>>>>         link(parent_id, child_id)
>>>>>>>     
>>>>>>> def ancestors(name): 
>>>>>>>     """ print ancestors('Red')""" 
>>>>>>>     node=db(db.thing.name==name).select().first()
>>>>>>>     return db((db.closure.child==node.id) & (db.closure.parent != 
>>>>>>> node.id)).select(
>>>>>>>         db.thing.name, 
>>>>>>> left=db.thing.on(db.thing.id==db.closure.parent), 
>>>>>>> orderby=db.closure.depth)
>>>>>>>
>>>>>>> def descendants(name): 
>>>>>>>     """ print descendants('Fruit')""" 
>>>>>>>     node=db(db.thing.name==name).select().first()
>>>>>>>     return db((db.closure.parent==node.id) & (db.closure.child != 
>>>>>>> node.id)).select(
>>>>>>>         db.thing.name, left=db.thing.on(db.thing.id==db.closure.child), 
>>>>>>> orderby=db.closure.depth)
>>>>>>>
>>>>>>> def closure():
>>>>>>>     """ print closure() """
>>>>>>>     parent = db.thing.with_alias('parent')
>>>>>>>     child = db.thing.with_alias('child')
>>>>>>>     return db().select(db.closure.id, parent.name, child.name, 
>>>>>>> db.closure.depth,
>>>>>>>                        left=(parent.on(parent.id == 
>>>>>>> db.closure.parent),
>>>>>>>                              child.on(child.id == 
>>>>>>> db.closure.child)))
>>>>>>>
>>>>>>> def test(): 
>>>>>>>     add_node('Food',None) 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     add_node('Vehicle',None) 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     add_node('Fruit','Food') 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     add_node('Meat','Food') 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     add_node('Red','Fruit') 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     add_node('Chevy','Vehicle') 
>>>>>>>     db.commit()
>>>>>>>     print closure()
>>>>>>>
>>>>>>>     print "descendants of 'Food'"
>>>>>>>     print descendants('Food') 
>>>>>>>
>>>>>>>     print "ancestors of 'Red'"
>>>>>>>     print ancestors('Red')
>>>>>>>
>>>>>>> test() 
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Tuesday, November 20, 2018 at 5:02:33 PM UTC-8, BigBaaadBob wrote:
>>>>>>>>
>>>>>>>> Has anyone implemented a closure table with triggers 
>>>>>>>> <http://dirtsimple.org/2010/11/simplest-way-to-do-tree-based-queries.html>
>>>>>>>>  approach 
>>>>>>>> to hierarchy (specifically for a Bill of Materials (BOM) pattern) in 
>>>>>>>> Web2Py's DAL?
>>>>>>>>
>>>>>>>> I've seen Massimo's implementation of Preorder Traversal which 
>>>>>>>> doesn't work for BOM patterns where there are multiple roots. The 
>>>>>>>> Adjacency 
>>>>>>>> Table method is slow for large trees.
>>>>>>>>
>>>>>>>> In a Bill of Materials situation 
>>>>>>>> <http://www.vertabelo.com/blog/technical-articles/identifying-the-bill-of-materials-bom-structure-in-databases>,
>>>>>>>>  
>>>>>>>> there are multiple roots in the main table, like this:
>>>>>>>>
>>>>>>>> db.define_table('item',
>>>>>>>>     Field('name', type='string', length=128, label=T('Name')))
>>>>>>>>
>>>>>>>> db.define_table('bill_of_materials',
>>>>>>>>     Field('parent_item_id', type='reference item', notnull=True, 
>>>>>>>> label=T('Parent Item')),
>>>>>>>>     Field('child_item_id', type='reference item', notnull=True, 
>>>>>>>> label=T('Child Item')),
>>>>>>>>     Field('quantity', type='decimal(8,2)', default='1.0', 
>>>>>>>> label=T('Quantity')))
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>> Interesting reading.
>>>>
>>>> /dps
>>>>  
>>>>
>>> -- 
>> Resources:
>> - http://web2py.com
>> - http://web2py.com/book (Documentation)
>> - http://github.com/web2py/web2py (Source code)
>> - https://code.google.com/p/web2py/issues/list (Report Issues)
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "web2py-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to web2py+un...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to