[sqlalchemy] Mapper and Relation Question

2007-02-25 Thread robert . bagley

Hello,

I have a question regarding using a mapper to add a relation to a
mapped class using instance  attributes (not contained in the mapped
classes table def) on the mapped class control the select statement
for the join.

For example:
my Calendar class has a relation to CalendarEvent

Calendar.map_table(calendar_table,
properties={'events':relation(CalendarEvent,backref='calendar',collection_class
= CalendarEventList)})

I would like to be able to control the where clause of the join the
mapper uses when the property is accessed with data from my Calendar
class that is not in the table definition, such as the time slice the
Calendar represents.

So something like:

Calendar.map_table(calendar_table,
properties={'events':relation(CalendarEvent,primaryjoin=and_(Calendar.c.id==CalendarEvent.c.calendar_id,
calendar.CalendarEvent.c.starttime >= ???{need
help}???)),backref='calendar',collection_class = CalendarEventList)})

so in a use case:
c = Calendar() [Assume fill from db]
c.event_list_start = datetime.now()
c.event_list_end = datetime.now() + timedelta(days=1)

and the mapper would have:

Calendar.map_table(calendar_table,properties={'events':relation(CalendarEvent,
  primaryjoin=and_(
 
Calendar.c.space_id==calendar.CalendarEvent.c.calendar_id,
  CalendarEvent.c.starttime >= Calendar.event_list_start,
  CalendarEvent.c.endtime <=  Calendar.event_list_end,
)),backref='calendar',collection_class = CalendarEventList)})


I am not sure if SQLalchemy supports this or if I am looking at this
the wrong way.

Thanks in advance,

Rob


--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Complicated Mapper with Count Function

2007-02-25 Thread Koen Bok

Dear all.

I have to make a complicated mapper, and I need a little help.

We have a list of products. These products have stock, each individual
stock item has an entry in the stockproduct table. So to get the total
stock we need to count the items in the stock database. We can filter
them by a particular stock.

So I made a function to create a mapper to do just that. But there are
two problems:

- It's not working well, because if the count function equals 0 (no
stock) the product does not appear in the results.
- I have the feeling this can be better optimized, but I can't see it
(maybe put it in a join or subquery?)

The function

def productStockMapper(stockList):

or_list = or_()
for stock in stockList:
or_list.append(stockproduct_table.c.stock_id==stock.id)

s = select([product_table,
func.count(stockproduct_table.c.id).label('stock')],
and_(
stockproduct_table.c.product_id==product_table.c.id,
or_list),
group_by=[c for c in product_table.c]).alias('count_select')

return mapper(Product, s, non_primary=True)

The tables:

product_table = Table('products', metadata,
Column('id', Integer, primary_key=True),
Column('name', Unicode(255), nullable=False)
Column('code', Unicode(255), unique=True, nullable=False))

stockproduct_table = Table('stockproducts', metadata,
Column('id', Integer, primary_key=True),
Column('stock_id', Integer, ForeignKey("stocks.id"), nullable=False),
Column('product_id', Integer, ForeignKey("products.id"),
nullable=False))

stock_table = Table('stocks', metadata,
Column('id', Integer, primary_key=True),
Column('name', Unicode(255), nullable=False))


--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Spatial data (PostGIS/OGC) with SqlAlchemy

2007-02-25 Thread Allen Bierbaum

[snip]
 > When I use this with my table and datamapper code, it looks like
> everything is working fine but the generated SQL insert statement
> fails with a exception:
>
> sqlalchemy.exceptions.SQLError: (ProgrammingError) parse error -
> invalid geometry
>   'INSERT INTO gis_entity (id, name, pos) VALUES (%(mId)s, %(mName)s,
> %(mPos)s)' {'mName': 'New entity', 'mId': 1L, 'mPos':
> "GeomFromText('POINT(100 100)',-1)"}
>
> I know from using sql directly in pgadmin3 that this line works correctly:
>
> insert into gis_entity (id, name, pos) values (2, 'New entity',
> GeomFromText('POINT(100 100)', -1));
>
> Does anyone see how this varies from the sql statement issued by SA?

By looking at the postgres log I figured out what was causing the
error, but I still don't know how to fix it.

The problem is that SA considers "GeomFromText('POINT(100 100)', -1)"
to be a string so it puts it in single quotes when creating the SQL
command to execute. This causes problems because them postgres doesn't
know it could be calling a method instead.  I have tried returning an
sqlalchemy.func object but this doesn't work either.

Any ideas?

-Allen

--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Spatial data (PostGIS/OGC) with SqlAlchemy

2007-02-25 Thread Allen Bierbaum

I tried your idea but it doesn't seem to be valid code.  Here is the
code I tried:

   print "Trying with a transaction."
   conn = db.connect()
   trans = conn.begin()
   
conn.execute(sa.func.AddGeometryColumn('','gis_entity','fpos',-1,'LINESTRING',2))
   trans.commit()
   conn.close()

and here is the exception I get on the execute line:

Try with a transaction.
INFO:sqlalchemy.engine.base.Engine.0x..d0:BEGIN
Traceback (most recent call last):
  File "gis_type_test.py", line 73, in ?

conn.execute(sa.func.AddGeometryColumn('','gis_entity','fpos',-1,'LINESTRING',2,
engine=db))
  File "/usr/lib/python2.4/site-packages/sqlalchemy/engine/base.py",
line 258, in execute
return Connection.executors[type(object).__mro__[-2]](self,
object, *multiparams, **params)
KeyError: 

I am now running into a new problem as well though.  I can use my
previous hack to insert the column but I can't add data to it because
I have been unable to call "GeomFromText(..)" on the insert.

I tried to get this working by defining my own type:
class GeometryType(sa.types.TypeEngine):

   def __init__(self, SRID, typeName, dimension):
  super(GeometryType, self).__init__()
  self.mSrid = SRID
  self.mType = typeName.upper()
  self.mDim  = dimension

   def __repr__(self):
  return "%s:%s-%s(%s)" % (self.__class__.__name__, self.mType,
self.mDim, self.mSrid)

   def get_col_spec(self):
  return "GEOMETRY"

   def convert_bind_param(self, value, engine):
  return 'GeomFromText(\'%s\',%s)'%(value, self.mSrid)

   def convert_result_value(self, value, engine):
  # Not used yet
  return value

When I use this with my table and datamapper code, it looks like
everything is working fine but the generated SQL insert statement
fails with a exception:

sqlalchemy.exceptions.SQLError: (ProgrammingError) parse error -
invalid geometry
  'INSERT INTO gis_entity (id, name, pos) VALUES (%(mId)s, %(mName)s,
%(mPos)s)' {'mName': 'New entity', 'mId': 1L, 'mPos':
"GeomFromText('POINT(100 100)',-1)"}

I know from using sql directly in pgadmin3 that this line works correctly:

insert into gis_entity (id, name, pos) values (2, 'New entity',
GeomFromText('POINT(100 100)', -1));

Does anyone see how this varies from the sql statement issued by SA?
I have stared at it for 20 minutes and I don't see a difference.
Is there any way to see the raw SQL statement sent by SA to postgres?
I have turned up the debug output level to full but I still only can
see the format string and parameters used for making the sql
statement:

INFO:sqlalchemy.engine.base.Engine.0x..50:INSERT INTO gis_entity (id,
name, pos) VALUES (%(mId)s, %(mName)s, %(mPos)s)
INFO:sqlalchemy.engine.base.Engine.0x..50:{'mName': 'New entity',
'mId': 1L, 'mPos': "GeomFromText('POINT(100 100)',-1)"}

Does anyone see what I am doing wrong here?

Once I get this working, then I have to figure out how to get the data
back out from postgis. What I want to end up with here is an SQL
statement like this:

select id, name, AsText(pos) as pos from gis_entity;

Note that pos is retrieved through a server side function ('AsText')
that unpacks the binary representation from the database into a string
representation.  Is there any way to do this with SA so the system
will always create queries in this form whenever it tries to retrieve
the value of pos?

I don't know if this makes a solution easier, but I am using mappers
for all my tables.  What I would really like to have is a mapper that
would just automatically know to wrap all references to "pos" in
INSERT calls with a call to the server-side function 'GeomFromText'
and correspondingly wrap all references to "pos" in SELECT calls with
a call to the server-side function 'AsText'.  Is it possible to do
this at the mapper level?  If it is, then that could greatly simplify
everything I am trying to do here.

Thanks for you help.

-Allen

On 2/25/07, Michael Bayer <[EMAIL PROTECTED]> wrote:
>
>   if the function youre calling needs a transaction commit, why dont
> you call an explicit transaction ?
>
> conn = engine.connect()
> trans = conn.begin()
> conn.execute(func.AddGeometryColumn
> ('','gis_entity','fpos',-1,'LINESTRING',2))
> trans.commit()
>
>
> On Feb 25, 2007, at 11:02 AM, Allen Bierbaum wrote:
>
> >
> > I have been pursuing this further on my own and one of the issues I
> > have run into is how to cleanly add a geometry column to a database.
> > The posting referenced in the first e-mail [2] talks about doing this
> > directly with psycopg2 cursor because the poster could not get it
> > working with SA.  I gave it another try to see if I could get it
> > working and I think I have narrowed down the problem.  That said, I
> > still don't fully understand how to fix it with SA only.
> >
> > Here is my code example:
> >
> > 
> > db = sa.create_engine(dsn_str)
> >
> > # Option 1: Try using a function on the database  (doesn't work)
> > print "Run with func"
> > db.func.AddGeometryColumn(

[sqlalchemy] Re: how to force a clean refresh of a lazy loaded attribute

2007-02-25 Thread Michael Bayer


On Feb 25, 2007, at 9:03 AM, Manlio Perillo wrote:

>
> Michael Bayer ha scritto:
>>
>> On Feb 23, 2007, at 1:56 PM, Manlio Perillo wrote:
>>
>>> Hi again.
>>>
>>> I have an object attribute loaded via lazy loader.
>>> This object is loaded in a transaction.
>>>
>>> Then, in another transaction, I ussue an update statement (via  
>>> the sql
>>> module, not using the orm), that updates the table of the main
>>> object's
>>> attribute.
>>>
>>> The problem, now, is that I want to reload this attribute.
>>>
>>> I have tried, in a separate transaction:
>>> sess.update(obj)
>>> sess.expire(obj)
>>>
>>> One problem here is that the entire object is reloaded, and I do not
>>> want this.
>>
>> i think if you say delattr(obj, attributename), it will do a lazyload
>> on the next run.
>>
>
> Sorry, I have tested only sess.expire(obj).
>
> delattr(obj, attributename) does not works.
>

OK, again, if you want the actual object that is *in* the lazy loaded  
collection to be reloaded, you have to issue an expire() or refresh()  
on at least that object.  if the object is already in the session,  
the lazy load may still fire off but will only reload the instance  
that is already in the session.

so you might want do instead do this (assuming its a lazy load  
collection - modify accordingly for a scalar attribute):

for o in myinstance.somecollection:
 sess.expire(o)



--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Spatial data (PostGIS/OGC) with SqlAlchemy

2007-02-25 Thread Michael Bayer

  if the function youre calling needs a transaction commit, why dont  
you call an explicit transaction ?

conn = engine.connect()
trans = conn.begin()
conn.execute(func.AddGeometryColumn 
('','gis_entity','fpos',-1,'LINESTRING',2))
trans.commit()


On Feb 25, 2007, at 11:02 AM, Allen Bierbaum wrote:

>
> I have been pursuing this further on my own and one of the issues I
> have run into is how to cleanly add a geometry column to a database.
> The posting referenced in the first e-mail [2] talks about doing this
> directly with psycopg2 cursor because the poster could not get it
> working with SA.  I gave it another try to see if I could get it
> working and I think I have narrowed down the problem.  That said, I
> still don't fully understand how to fix it with SA only.
>
> Here is my code example:
>
> 
> db = sa.create_engine(dsn_str)
>
> # Option 1: Try using a function on the database  (doesn't work)
> print "Run with func"
> db.func.AddGeometryColumn('','gis_entity','fpos',-1,'LINESTRING', 
> 2).execute()
>
> # Option 2: Try directly with database statement execution (doesn't  
> work)
> print "Run on db"
> r = db.execute("select
> AddGeometryColumn('','gis_entity','cpos',-1,'LINESTRING',2)")
> r.close()
>
> # Option 3: use psycopg to execute directly without autocomit? (works)
> print "Run with psycopg isolation level"
> con = db.connect()
> con.connection.connection.set_isolation_level 
> (psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
> con.execute("select
> AddGeometryColumn('','gis_entity','p_pos',-1,'LINESTRING',2)")
> con.close()
> 
>
>
> So option 3 works, but I don't fully understand why it works and why I
> can't use one of the other options.  Option 1 is definitely my
> preferred way to do this because it will make the calls look like
> normal SA calls to a DB function.
>
> Can anyone tell my whey option 3 is working and if there is a way to
> do this directly with SA only?
>
> Thanks,
> Allen
>
>
> On 2/23/07, Allen <[EMAIL PROTECTED]> wrote:
>>
>> I would like to use SqlAlchemy with PostGIS to create, read, update,
>> and query spatial data.  I have search around a bit and found a few
>> ideas of doing this [1][2] but I haven't seen a definitive best
>> practice by any means.  It looks like all the solutions I can find
>> have a least some limitations.
>>
>> Is anyone here using SqlAlchemy with spatial databases and if so how
>> are you doing it right now?
>>
>> Specifically:
>> - How do you handle table specification with geometry types?
>> [1] tries to do this but it is incomplete
>>
>> - Do you use custom types and if so how are you doing this?
>> [2] has some custom type code but it seems to be tied to binary
>> formats and I don't see how to create/retrieve the geometry in text
>> format.
>>
>> - How are you handling the object mapping?
>> For example is there a way to map a "POINT" geometry to a python  
>> Point
>> class or tuple?
>>
>> - Do you have any general recommendations for how to use spatial data
>> successfully with SqlAlchemy?
>>
>>
>> Thanks,
>> Allen
>>
>> [1] http://www.mail-archive.com/sqlalchemy- 
>> [EMAIL PROTECTED]/msg03371.html
>> [2] http://bycycle.org/2007/01/29/using-postgis-with-sqlalchemy/
>>
>>
>>>
>>
>
> >


--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Spatial data (PostGIS/OGC) with SqlAlchemy

2007-02-25 Thread Allen Bierbaum

I have been pursuing this further on my own and one of the issues I
have run into is how to cleanly add a geometry column to a database.
The posting referenced in the first e-mail [2] talks about doing this
directly with psycopg2 cursor because the poster could not get it
working with SA.  I gave it another try to see if I could get it
working and I think I have narrowed down the problem.  That said, I
still don't fully understand how to fix it with SA only.

Here is my code example:


db = sa.create_engine(dsn_str)

# Option 1: Try using a function on the database  (doesn't work)
print "Run with func"
db.func.AddGeometryColumn('','gis_entity','fpos',-1,'LINESTRING',2).execute()

# Option 2: Try directly with database statement execution (doesn't work)
print "Run on db"
r = db.execute("select
AddGeometryColumn('','gis_entity','cpos',-1,'LINESTRING',2)")
r.close()

# Option 3: use psycopg to execute directly without autocomit? (works)
print "Run with psycopg isolation level"
con = db.connect()
con.connection.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
con.execute("select
AddGeometryColumn('','gis_entity','p_pos',-1,'LINESTRING',2)")
con.close()



So option 3 works, but I don't fully understand why it works and why I
can't use one of the other options.  Option 1 is definitely my
preferred way to do this because it will make the calls look like
normal SA calls to a DB function.

Can anyone tell my whey option 3 is working and if there is a way to
do this directly with SA only?

Thanks,
Allen


On 2/23/07, Allen <[EMAIL PROTECTED]> wrote:
>
> I would like to use SqlAlchemy with PostGIS to create, read, update,
> and query spatial data.  I have search around a bit and found a few
> ideas of doing this [1][2] but I haven't seen a definitive best
> practice by any means.  It looks like all the solutions I can find
> have a least some limitations.
>
> Is anyone here using SqlAlchemy with spatial databases and if so how
> are you doing it right now?
>
> Specifically:
> - How do you handle table specification with geometry types?
> [1] tries to do this but it is incomplete
>
> - Do you use custom types and if so how are you doing this?
> [2] has some custom type code but it seems to be tied to binary
> formats and I don't see how to create/retrieve the geometry in text
> format.
>
> - How are you handling the object mapping?
> For example is there a way to map a "POINT" geometry to a python Point
> class or tuple?
>
> - Do you have any general recommendations for how to use spatial data
> successfully with SqlAlchemy?
>
>
> Thanks,
> Allen
>
> [1] 
> http://www.mail-archive.com/sqlalchemy-users@lists.sourceforge.net/msg03371.html
> [2] http://bycycle.org/2007/01/29/using-postgis-with-sqlalchemy/
>
>
> >
>

--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: how to force a clean refresh of a lazy loaded attribute

2007-02-25 Thread Manlio Perillo

Michael Bayer ha scritto:
> 
> On Feb 23, 2007, at 1:56 PM, Manlio Perillo wrote:
> 
>> Hi again.
>>
>> I have an object attribute loaded via lazy loader.
>> This object is loaded in a transaction.
>>
>> Then, in another transaction, I ussue an update statement (via the sql
>> module, not using the orm), that updates the table of the main  
>> object's
>> attribute.
>>
>> The problem, now, is that I want to reload this attribute.
>>
>> I have tried, in a separate transaction:
>> sess.update(obj)
>> sess.expire(obj)
>>
>> One problem here is that the entire object is reloaded, and I do not
>> want this.
> 
> i think if you say delattr(obj, attributename), it will do a lazyload  
> on the next run.
> 

Sorry, I have tested only sess.expire(obj).

delattr(obj, attributename) does not works.



Regards  Manlio Perillo

--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: how to force a clean refresh of a lazy loaded attribute

2007-02-25 Thread Manlio Perillo

Michael Bayer ha scritto:
> 
> On Feb 23, 2007, at 1:56 PM, Manlio Perillo wrote:
> 
>> Hi again.
>>
>> I have an object attribute loaded via lazy loader.
>> This object is loaded in a transaction.
>>
>> Then, in another transaction, I ussue an update statement (via the sql
>> module, not using the orm), that updates the table of the main  
>> object's
>> attribute.
>>
>> The problem, now, is that I want to reload this attribute.
>>
>> I have tried, in a separate transaction:
>> sess.update(obj)
>> sess.expire(obj)
>>
>> One problem here is that the entire object is reloaded, and I do not
>> want this.
> 
> i think if you say delattr(obj, attributename), it will do a lazyload  
> on the next run.
> 

Ok, it needs the latest version in trunk but now works.

>> The other problem (maybe a bug?) is that the orm issue another  
>> query to
>> reload the data from the database, but in the object I still find the
>> old values!
>>
>> I have submitted a ticket for the last problem (#492).
> 
> "refresh-expire" cascade had not yet been implemented, just added it  
> in the trunk.
> 


Thanks!


Regards  Manlio Perillo

--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---