On Feb 2, 2014, at 4:31 PM, Matt Phipps <[email protected]> wrote:
> def _trackable_truckload_details():
> text = db.text("EXEC ODSQuery.SelectBridgeLoadBoard")
> cols = [col for col in LoadBoard.__table__.c]
> cols = map((lambda x: label('ODSQuery_tblLoadBoard_' + x.name, x)), cols)
> mobile_cols = LoadMobileTracking.load_mobile_tracking_id.property.columns
> mobile_cols = map((lambda x: label('LoadMobileTracking_' + x.name, x)),
> cols)
> cols.extend(mobile_cols)
> taf = text.columns(*cols)
> return db.session.query(
> LoadBoard.load,
> LoadBoard.orgn_stop,
> LoadBoard.dest_stop,
> LoadMobileTracking.load_mobile_tracking_id).from_statement(taf).all()
>
>
> Actually, I'm pretty surprised it worked at all before, without the labeling.
> How did it figure out which result set columns went to which ORM object?
This is because what’s actually going on is more sophisticated than just
matching up the names. When the ORM looks for columns in a row, it uses the
actual Column object to target the column. If your class is mapped to a table
“users”, for example, it would look like this:
users = Table(‘users’, metadata, Column(‘id’, Integer), Column(‘name’, String))
# … later
for row in conn.execute(some_orm_statement):
user_id = row[users.c.id]
user_name = row[users.c.name]
that is, we aren’t using strings at all. When the Core select() object (or
TextAsFrom in this case) is compiled for the backend, all the Column objects it
SELECTs from are put into an internal collection called the “result_map”, which
keys the result columns in several ways, including their positional index (0,
1, 2, ..) as well as the string name the statement knows they’ll have in the
result set (e.g. the label name in this case) to all the objects that might be
used to look them up.
So using a label(), that adds another layer onto this. The label() you create
from an existing Column still refers to that Column, and we say the Label
object “proxies” the Column. if you look in mylabel.proxy_set() you’ll see
that Column.
So when we generate the result_map, we put as keys *all* of the things that
each label() is a “proxy” for, including the Column objects that are in our
mapping. its this large and awkward dictionary structure I’ve had to stare at
for many years as I often have to fix new issues that have arisen (such as this
one).
The result is generated, we link the columns in the cursor.description by
string name to the string names we know are rendered in the final compiled
construct, the result set now knows that all the Column/Label objects
corresponding to “id” are linked to that column and that’s how the lookup
proceeds.
>
> I’m committing 2932 in a moment and I’m super really hoping I can put out
> 0.9.2 today but it’s easy for me to run out of time, but 0.9.2 is definitely
> due.
>
> That would be awesome! Incidentally though, would this labeling still work
> once the fix is in?
all the existing mechanisms are maintained and I’ve just made some of the
matching logic a bit more liberal here, so should be fine. It’s all committed
if you want to try out the git master.
signature.asc
Description: Message signed with OpenPGP using GPGMail
