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

Attachment: pg_audit_pub.sql
Description: Binary data

Attachment: 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

Reply via email to