robert -

this is not a backref issue at all. this is, remarkably, an eager loading bug that has been there completely from day one ! the invoice->company->address relationship is: invoice is many-to-one on company, company is one-to-many on addresses. an eager load chain all the way through will not get all the addresses ! nobody came across this one until now...sheesh.

will see if i can patch something today/tomorrow....

- mike


On Mar 5, 2006, at 7:28 PM, Robert Leftwich wrote:

This is the original backref problem, which appears to be related to the select_by, etc problem in my previous mail. Basically the company data returned is incomplete if accessed through a backref.

Robert
import datetime
from sqlalchemy import *

db = engine.create_engine('sqlite', {'filename':':memory:'}, echo=True)

companies_table = Table('companies', db,
Column('company_id', Integer, Sequence('company_id_seq', optional=True), primary_key = True),
    Column('company_name', String(40)),

)

addresses_table = Table('addresses', db,
Column('address_id', Integer, Sequence ('address_id_seq', optional=True), primary_key = True), Column('company_id', Integer, ForeignKey ("companies.company_id")),
                        Column('address', String(40)),
                        )

phones_table = Table('phone_numbers', db,
Column('phone_id', Integer, Sequence ('phone_id_seq', optional=True), primary_key = True), Column('address_id', Integer, ForeignKey ('addresses.address_id')),
                        Column('type', String(20)),
                        Column('number', String(10)),
                        )

invoice_table = Table('invoices', db,
Column('invoice_id', Integer, Sequence ('invoice_id_seq', optional=True), primary_key = True), Column('company_id', Integer, ForeignKey ("companies.company_id")),
                      Column('date', DateTime),
                      )

items_table = Table('items', db,
Column('item_id', Integer, Sequence ('item_id_seq', optional=True), primary_key = True), Column('invoice_id', Integer, ForeignKey ('invoices.invoice_id')),
                    Column('code', String(20)),
                    Column('qty', Integer),
                    )


companies_table.create()
addresses_table.create()
phones_table.create()
invoice_table.create()
items_table.create()

class Company(object):
    def __init__(self):
        self.company_id = None
    def __repr__(self):
return "Company:" + repr(getattr(self, 'company_id', None)) + " " + repr(getattr(self, 'company_name', None)) + " " + str([repr (addr) for addr in self.addresses])

class Address(object):
    def __repr__(self):
return "Address: " + repr(getattr(self, 'address_id', None)) + " " + repr(getattr(self, 'company_id', None)) + " " + repr (self.address) + str([repr(ph) for ph in self.phones])

class Phone(object):
    def __repr__(self):
return "Phone: " + repr(getattr(self, 'phone_id', None)) + " " + repr(getattr(self, 'address_id', None)) + " " + repr (self.type) + " " + repr(self.number)

class Invoice(object):
    def __init__(self):
        self.invoice_id = None
    def __repr__(self):
return "Invoice:" + repr(getattr(self, 'invoice_id', None)) + " " + repr(getattr(self, 'date', None)) + " " + repr (self.company) + " " + str([repr(item) for item in self.items])

class Item(object):
    def __repr__(self):
return "Item: " + repr(getattr(self, 'item_id', None)) + " " + repr(getattr(self, 'invoice_id', None)) + " " + repr(self.code) + " " + repr(self.qty)

Phone.mapper = mapper(Phone, phones_table, is_primary=True)

Address.mapper = mapper(Address, addresses_table, properties={
    'phones': relation(Phone.mapper, lazy=False, backref='address')
    })

Company.mapper = mapper(Company, companies_table, properties={
'addresses' : relation(Address.mapper, lazy=False, backref='company'),
    })

Item.mapper = mapper(Item, items_table, is_primary=True)

Invoice.mapper = mapper(Invoice, invoice_table, properties={
    'items': relation(Item.mapper, lazy=False, backref='invoice'),
'company': relation(Company.mapper, lazy=False, backref='invoices')
    })

objectstore.clear()
c1 = Company()
c1.company_name = 'company 1'

a1 = Address()
a1.address = 'a1 address'

p1 = Phone()
p1.type = 'home'
p1.number = '1111'

a1.phones.append(p1)

p2 = Phone()
p2.type = 'work'
p2.number = '22222'
a1.phones.append(p2)

c1.addresses.append(a1)

a2 = Address()
a2.address = 'a2 address'

p3 = Phone()
p3.type = 'home'
p3.number = '3333'
a2.phones.append(p3)

p4 = Phone()
p4.type = 'work'
p4.number = '44444'
a2.phones.append(p4)

c1.addresses.append(a2)

objectstore.commit()
objectstore.clear()

a = Company.mapper.get(1)
print a

# set up an invoice
i1 = Invoice()
i1.date = datetime.datetime.now()
i1.company = c1

item1 = Item()
item1.code = 'aaaa'
item1.qty = 1
item1.invoice = i1

item2 = Item()
item2.code = 'bbbb'
item2.qty = 2
item2.invoice = i1

item3 = Item()
item3.code = 'cccc'
item3.qty = 3
item3.invoice = i1

objectstore.commit()
objectstore.clear()

c = Company.mapper.get(1)
print c

objectstore.clear()

i = Invoice.mapper.get(1)
print i

assert repr(i.company) == repr(c)



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to