Hey All, I'm running into an interesting problem. There's a quick obvious solution, but I think it's a placebo, so I want to run this by everyone else first.
In this case (attached .sql creates the necessary schema) I have three interconnected tables that I'm viewing using reflection. This is my normal setup which functions without any problems. However, I recently created a mapper sourcing from a subselect, and discovered an interesting problem crop up. At one point, the foreign key is being retrieved from the database as unicode, but is not being converted to a Python string. This causes an 'if type(...) == str' check to fail, at which point it's expected to be an object and things fail. If I set convert_unicode=False, I don't have this problem (but, of course, other things elsewhere fail...) As an interesting complication, I was unable to reproduce this effect in the attached test case (pg_mapper_select_working.py) which, as far as I can determine, almost exactly reproduces the schema generated by pg_audit_pub.sql. Attached is my system information, but in short I'm running 1368 with the DISCRETE ON() patch and modula support for PostgreSQL 8.x. Reproduce this by loading the pg_audit_pub.sql schema into your 'test' database and executing the pg_audit_pub.py with appropriate credentials. Hopefully this helps! Cheers, -G
pg_audit_pub.sql
Description: Binary data
pg_audit_pub.log
Description: Binary data
import sys from sqlalchemy import * # For verbose logging, change the echo and LOG booleans to True engine = create_engine('postgres', {'database':'test', 'host':'localhost', 'user':'xxx', 'password':'xxx'}, echo=True, echo_uow=True, convert_unicode=True) objectstore.LOG = True class AuditItem(object): pass audit_trail = Table('audit_trail', engine, autoload = True, schema = 'equipment') items_table = Table('items', engine, autoload = True, schema = 'equipment') audit_item = select([audit_trail.c.ts, audit_trail.c.event_type, audit_trail.c.user_id, audit_trail.c.new_state_id, audit_trail.c.owner_id, items_table.c.item_id, items_table.c.state_id], from_obj=[outerjoin(items_table, audit_trail)], order_by=[items_table.c.item_id, desc(audit_trail.c.ts)]).alias('audit_items') AuditItem = mapper(AuditItem, audit_item) a_items = AuditItem.select() for i in a_items: print i.item_id, i.state_id, i.ts, i.event_type, i.user_id, i.new_state_id, i.owner_id
import sys from sqlalchemy import * def CreateTables(): engine = create_engine('postgres', {'database':'test', 'host':'localhost', 'user':'postgres', 'password':'abcabc'}, echo=True, echo_uow=True, convert_unicode=True) objectstore.LOG = True states_table = Table('states', engine, Column('state_id', Integer, primary_key=True), Column('state_name', String), schema='public') items_table = Table('items', engine, Column('item_id', Integer, primary_key=True), Column('state_id', Integer, ForeignKey(states_table.c.state_id)), Column('details', Integer), schema='public') events_table = Table('events', engine, Column('event_id', Integer, primary_key=True), Column('item_id', Integer, ForeignKey(items_table.c.item_id)), Column('new_state_id', Integer, ForeignKey(states_table.c.state_id)), Column('ts', Integer), schema='public') states_table.create() items_table.create() events_table.create() states_table.insert().execute( {'state_id':10000, 'state_name':'Purple 10k'}, {'state_id':20000, 'state_name':'Orange 20k'}, {'state_id':30000, 'state_name':'Violet 30k'}, {'state_id':40000, 'state_name':'Yellow 40k'}) items_table.insert().execute( {'item_id':1, 'state_id':10000, 'details':100}, {'item_id':2, 'state_id':10000, 'details':200}, {'item_id':3, 'state_id':30000, 'details':300}, {'item_id':4, 'state_id':30000, 'details':400}, {'item_id':5, 'state_id':30000, 'details':500}) events_table.insert().execute( {'event_id':5000, 'new_state_id':20000, 'item_id':2, 'ts':'5522'}, {'event_id':6000, 'new_state_id':20000, 'item_id':3, 'ts':'6633'}, {'event_id':7000, 'new_state_id':20000, 'item_id':5, 'ts':'7755'}, {'event_id':8000, 'new_state_id':20000, 'item_id':1, 'ts':'8811'}, {'event_id':9000, 'new_state_id':40000, 'item_id':3, 'ts':'9933'}) engine = None def TestMappedSelect(convert_unicode): try: engine = create_engine('postgres', {'database':'test', 'host':'localhost', 'user':'postgres', 'password':'abcabc'}, echo=True, echo_uow=True, convert_unicode=convert_unicode) objectstore.LOG = True class State(object): pass class Item(object): pass class Event(object): pass class EventItem(object): pass states_table = Table('states', engine, autoload=True, schema='public') items_table = Table('items', engine, autoload=True, schema='public') events_table = Table('events', engine, autoload=True, schema='public') event_items_view = select([events_table.c.new_state_id, events_table.c.ts, items_table.c.item_id, items_table.c.state_id, items_table.c.details], from_obj=[outerjoin(items_table, events_table)], distinct=[items_table.c.item_id], order_by=[items_table.c.item_id, desc(events_table.c.ts)]).alias('event_items_view') assign_mapper(State, states_table) assign_mapper(Item, items_table) assign_mapper(Event, events_table) assign_mapper(EventItem, event_items_view) foo = EventItem.select() print 'ID', 'TS ', 'Details' for i in foo: print i.item_id, '', i.ts, i.details finally: events_table.drop() items_table.drop() states_table.drop() CreateTables() TestMappedSelect(False) CreateTables() TestMappedSelect(True)
Windows XP SP2 Cygwin SQLAlchemy 1368 modified with MOD patch and DISCRETE ON() patch. PostgreSQL 8.x