Re: Couple of questions...

Sebastien Bigaret <[email protected]> 20 Apr 2004 20:54:50 +0200
Newsgroups gmane.comp.python.modeling
Message-ID <[email protected]>
        Hi Aaron,

"Aaron Freeman" <[email protected]> wrote:
> (1) Is there a debug flag somewhere that dump all SQL queries to the
> console?

Absolutely: set the environment variable MDL_ENABLE_DATABASE_LOGGING to
any true value. For details, see:
  http://modeling.sourceforge.net/UserGuide/env-vars-core.html


> (2) How are nested joins accomplished?
> For example, in the AuthorBooks schema, lets assume there is another table
> called publisher that has a 1-M relationship with books, like so (sorry
> about the formatting):
> 
[...
  Writer <-author----books->> Book <<-books----publisher-> Publisher
 ...]

> How would I get writers by publisher?
> 
> More specifically, is there an elegant way to do a nested join in a single
> query, or do I just have to do a single writer-book join and then iterate
> over the resultset for the second join?
> 

Yes, there is a dedicated way of doing this: use the dotted notation:

  >>> ec.fetch('Writer', 'books.publisher.bizName=="P1"')

returns every writer who published (at least) a book w/ publisher P1.

The generated SQL query is (postgresql here):

  SELECT DISTINCT t0.ID, t0.LAST_NAME, t0.FIRST_NAME, t0.AGE,
         t0.FK_WRITER_ID, t0.BIRTHDAY 
  FROM WRITER t0 
  INNER JOIN  ( BOOK t1
                INNER JOIN PUBLISHER t2 
                ON t1.FK_PUBLISHER=t2.ID )
  ON t0.ID=t1.FK_WRITER_ID
  WHERE t2.BIZ_NAME = 'P1';


> Code examples would be great!

  I'm including in the end of the message a PyModel named EAuthorBooks
  (E stands for Extended :) derived from the one used in the User's
  Guide, with sample data, demonstrating the approach.

        Regards,

        
-- Sébastien.



PS: you'll need to setup a database before running the example, e.g. w/
    postgresql:

   $ mdl_generate_DB_schema.py \
        --admin-dsn "localhost:template1:postgres:" \
        -v -C pymodel_extAutborBooks.py


------------------------------------------------------------------------
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-
"Extended AuthorBooks model, with a Publisher"

from Modeling.PyModel import *

##
# Defaults
AFloat.defaults['precision'] = 10
AFloat.defaults['scale'] = 2
AString.defaults['width'] = 40

Association.defaults['delete']=['nullify', 'nullify']

Entity.defaults['properties'] = [
  APrimaryKey('id', isClassProperty=0, isRequired=1, doc='PK')
]

##
# Adapt to fit your own configuration!!

_connDict = {'database': 'EAUTHOR_BOOKS', 'host':'localhost',
             'user':'postgres','password':''}

model = Model('EAuthorBooks',adaptorName='Postgresql',
                connDict=_connDict)

model.doc = ' ... '
model.version='0.1'
model.entities = [
  #
  Entity('Book',
         properties=[ AString('title', isRequired=1, columnName='title'),
                      AFloat('price'),
                       ],
         ),
  Entity('Writer',
         properties=[ AString('lastName',isRequired=1, width=30 ),
                      AString('firstName'),
                      AInteger('age', displayLabel='Age'),
                      ADateTime('birthday', usedForLocking=0),
                      ]
         ),
  Entity('Publisher',
         properties=[ AString('bizName',isRequired=1),
                      AString('location'),
                      ]
         ),
  ]
#---
model.associations=[
  Association('Book', 'Writer',
              relations=['author', 'books'],
              delete=['nullify', 'cascade'],
              keys=['FK_Writer_Id', 'id']),
  Association('Writer', 'Writer',
              relations=['pygmalion', None],
              delete=['nullify', None],
              keys=['FK_Writer_id', 'id']),
  Association('Book', 'Publisher', relations=['publisher', 'books'])
  ]

model.build()
model=model.component

if __name__=="__main__":
  #import pdb ; pdb.set_trace()
  
  from Modeling.dynamic import build
  build(model, define_properties=1)

  from Modeling.ModelSet import defaultModelSet
  defaultModelSet().addModel(model)

  from Modeling.EditingContext import EditingContext
  ec=EditingContext()

  from EAuthorBooks.Publisher import Publisher
  from EAuthorBooks.Writer import Writer
  from EAuthorBooks.Book import Book

  # Initialization
  p1=Publisher(); p1.bizName="P1"
  p2=Publisher(); p2.bizName="P2"

  w1=Writer(); w1.lastName="in p1"
  w2=Writer(); w2.lastName="in p2"
  w3=Writer(); w3.lastName="in p1 and p2"
  
  b1w1=Book(); b1w1.title="b1w1"
  b2w1=Book(); b2w1.title="b2w1"
  b1w2=Book(); b1w2.title="b1w2"
  b2w2=Book(); b2w2.title="b2w2"
  b1w3=Book(); b1w3.title="b1w3"
  b2w3=Book(); b2w3.title="b2w3"
  ec.insert(p1);
  ec.insert(p2); ec.insert(w1); ec.insert(w2); ec.insert(w3)
  ec.insert(b1w1); ec.insert(b2w1); ec.insert(b1w2); ec.insert(b2w2)
  ec.insert(b1w3); ec.insert(b2w3)

  w1.addToBooks(b1w1); b1w1.author=w1; w1.addToBooks(b2w1); b2w1.author=w1
  w2.addToBooks(b1w2); b1w2.author=w2; w2.addToBooks(b2w2); b2w2.author=w2
  w3.addToBooks(b1w3); b1w3.author=w3; w3.addToBooks(b2w3); b2w3.author=w3

  b1w1.publisher=p1; p1.addToBooks(b1w1)
  b2w1.publisher=p1; p1.addToBooks(b2w1);
  b1w2.publisher=p2; p2.addToBooks(b1w2)
  b2w2.publisher=p2; p2.addToBooks(b2w2);
  b1w3.publisher=p1; p1.addToBooks(b1w3)
  b2w3.publisher=p2; p2.addToBooks(b2w3);

  ec.saveChanges()

  # query
  ec=EditingContext()
  print [w.lastName
         for w in ec.fetch('Writer', 'books.publisher.bizName=="P1"')]
  # returns: w1 and w3
  ec=EditingContext()
  print [w.lastName
         for w in ec.fetch('Writer', 'books.publisher.bizName=="P2"')]
  # returns: w2 and w3
------------------------------------------------------------------------



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click