Greetings!

I have a situation where I would like to be able to switch between an
implicit eager load and an explicit no load of a series of related
objects. I've set up a couple of  mappers for the object in question
(Entry in the code below), the primary mapper keeps uses a lazy load
(lazy = True)  and the alternate uses no load (lazy = None). However,
I discovered that an object retrieved with the no load mapper,
performs a lazy load when attempting to explicitly add elements to the
relation list. I've included test code and the relevant log statements
below:

test code:


import sqlalchemy.ext.sessioncontext as sqlsessioncontext
import sqlalchemy as sql
import logging

#logging
file = logging.FileHandler(__name__+'.log')
file.setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logging.getLogger("sqlalchemy").addHandler(console)
logging.getLogger("sqlalchemy").addHandler(file)
logging.getLogger("sqlalchemy").setLevel(logging.DEBUG)

#create an in memory db
engine = sql.create_engine("sqlite:///:memory:")
metadata = sql.MetaData(engine=engine)
sessionContext =
sqlsessioncontext.SessionContext(lambda:sql.create_session(engine))


#class definitions
class Entry(object):
    def __init__(self, id = None, title = None):
        if id:
            self.id = id
        self.title = title
    table = sql.Table('entry', metadata,
        sql.Column('id', sql.Integer(), primary_key=True),
        sql.Column('title', sql.String(), primary_key=True)
    )

class TagAssoc(object):

    def __init__(self, entry = None, tag = None):
        self.entry = entry
        self.tag = tag

    table = sql.Table('entry_to_tag', metadata,
        sql.Column('tag_id', sql.Integer(),
sql.ForeignKey('tag.id',onupdate='CASCADE',ondelete='CASCADE'),
nullable=False),
        sql.Column('entry_id',sql.Integer(),
sql.ForeignKey('entry.id',onupdate='CASCADE',ondelete='CASCADE'),
nullable=False)
    )

class Tag(object):
    def __init__(self, id = None, name = None):
        if id:
            self.id = id
        self.name = name
    table = sql.Table('tag', metadata,
        sql.Column('id', sql.Integer(), primary_key=True),
        sql.Column('name', sql.String(), primary_key=True)
    )

metadata.create_all()

#entry mappers
loading_entry_mapper = sql.mapper(
    Entry,
    Entry.table,
    properties = {
        'tagAssocs' : sql.relation(TagAssoc, lazy = True,
cascade="all, delete-orphan")
    }
)
non_loading_entry_mapper = sql.mapper(
    Entry,
    Entry.table,
    properties = {
        'tagAssocs' : sql.relation(TagAssoc, lazy = None,
cascade="all, delete-orphan")
    },
    non_primary = True
)

tag_assoc_mapper = sql.mapper(
    TagAssoc,
    TagAssoc.table,
    primary_key=[TagAssoc.table.c.entry_id, TagAssoc.table.c.tag_id],
[EMAIL PROTECTED]
    properties = {
        'tag' : sql.relation(Tag, lazy=False, uselist=False),
        'entry' : sql.relation(Entry,lazy=False, uselist=False)
    }
)

tag_mapper = sql.mapper(
    Tag,
    Tag.table
)

#save test data
session = sessionContext.current
entry1 = Entry(id = 1, title="entry1")
session.save(entry1)
session.flush()
tag1 = Tag(id = 1, name="tag1")
session.save(tag1)
session.flush()
assoc1 = TagAssoc(entry1, tag1)
entry1.tagAssocs.append(assoc1)
session.save(assoc1)
session.flush()
session.close()


#retrieve the entry using the non-loading mapper
session = sessionContext.current

statement = sql.select([Entry.table])
entries = session.query(non_loading_entry_mapper).select(statement)

#use a simple case: set tagAssocs to a blank list. This shouldn't
cause an eager load, should it?
entries[0].tagAssocs = []


The relevant log section:

SELECT entry.id AS entry_id, entry.title AS entry_title
FROM entry
[]
instances()
Row (1, u'entry1')
Connection <pysqlite2.dbapi2.Connection object at 0x00DECDA0> being
returned to pool
(Entry|entry|non-primary) _instance(): identity key (<class
'__main__.Entry'>, (1, u'entry1'), None) not in session[]
(Entry|entry|non-primary) _instance(): created new instance
[EMAIL PROTECTED] identity (<class '__main__.Entry'>, (1, u'entry1'),
None)
populating [EMAIL PROTECTED] with RowProxy/id
populating [EMAIL PROTECTED] with RowProxy/title

#############not expected behavior for an attribute with no
load.###############
Executing lazy callable on [EMAIL PROTECTED]
lazy load attribute tagAssocs on instance [EMAIL PROTECTED]

Connection <pysqlite2.dbapi2.Connection object at 0x00DECDA0> checked
out from pool
SELECT anon_f75b.id AS anon_f75b_id, anon_f75b.title AS
anon_f75b_title, anon_d876.id AS anon_d876_id, anon_d876.name AS
anon_d876_name, entry_to_tag.entry_id AS entry_to_tag_entry_id,
entry_to_tag.tag_id AS entry_to_tag_tag_id
FROM entry_to_tag LEFT OUTER JOIN entry AS anon_f75b ON anon_f75b.id =
entry_to_tag.entry_id LEFT OUTER JOIN tag AS anon_d876 ON anon_d876.id
= entry_to_tag.tag_id
WHERE ? = entry_to_tag.entry_id ORDER BY entry_to_tag.oid,
anon_f75b.oid, anon_d876.oid
[1]
instances()
Row (1, u'entry1', 1, u'tag1', 1, 1)

Sooooo, what am I doing wrong?

Thanks,

Cory


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to