[sqlalchemy] Re: Thread issue?

2006-11-05 Thread François Wautier

Thanks for your reply,

> OK, i had the impression you were switching the mapper inside of a
> relation() somehow, but it seems all youre doing is sticking a mapper
> on a property (i dont quite understand how youd use it ?  )
>

I want to use it like this

fixRace(dbPeople, myrace)

listofgreeks=session.query(dbPeople.inRace).select_by(Nationality="Greece")

listofresident=session.query(dbPeople.inRace).select_by(Country="Germany")

So I need to have the "inRace" mapper  an attribute of the class itself. 

I'll stick to what I have right now, it seems to work fine.

Cheers,
François


> if i understand properly, id just do it this way:
>
> class dbPeople(object):
> def fixRace(self, race):
> self._race_id = race.id
> def _in_race(self):
> return object_session(self).query(dbRace).select(
> and_(tblRaceParticipant.c.Race_id==self._race_id,tblPeople.c.id==tblRacePar
>ticipant.c.Racer_id)) inRace = property(_in_race)
>
> François Wautier wrote:
> > Hi Michael,
> >
> > Thanks for your reply.
> >
> > First an apology, my program is now working It was a silly mistake...
> >
> > Second, I agree that what I am doing is not the most elegant thing I've
> > ever done... .to put it mildly... Yet, in most cases, the "fixRace"
> > function will only be run once at startup . In all but one case you
> > only deal with one race.  So that's not as bad as it sounds... Still the
> > application that input data into the database does need to deal with
> > multiple races. In that case I only keep one secondary mapper attached to
> > the class and only create a new one when needed (i.e. when the race
> > changes) (I probably need to "delete" the old mapper if present)
> >
> > At the bottom you will see the actual definition/mapping I use.
> >
> > I guess that I may be able to map the various attributes of dbPeople and
> > dbRace to attributes of dbRaceParticipant and deal with that object when
> > needed,   but I still see no elegant way of "fixing" the race, either I
> > create a secondary mapper (same as now essentially) or I need to pass the
> > race as an argument to all my queries... which is exactly what I am
> > trying to avoid.
> >
> > Cheers,
> > François
> >
> > Here is an excerpt of my definitions draft in progress
> >
> > =+%<%<
> > tblPeople=Table("People",
> > Column("id", Integer, primary_key = True),
> > Column("Nickname",Unicode(32),nullable=False,index=True),
> > Column("Firstname",Unicode(32),nullable=False),
> > Column("Lastname",Unicode(32),nullable=False,index=True),
> > Column("Email",VARCHAR(64),index=True),
> > Column("Birthdate",Date),
> > Column("Gender",Enum(["Male","Female"]),nullable=False),
> > Column("Nationality",Country,nullable=False),
> > Column("Address",Unicode(256)),
> > Column("Zip",Unicode(32)),
> > Column("Country",Country),
> > Column("Tel",String(16)),
> > Column("Tel_Ext",String(4)),
> > Column("Mobile",String(16)),
> > Column("Picture_id",Integer,ForeignKey("ADM_Files.id"),
> > nullable=True), Column("Tag",String(32)),
> > Column("Active",Boolean,default=True))
> >
> > tbbPeopleidx=Index('OnlyOne', tblPeople.c.Nickname,tblPeople.c.Firstname,
> > tblPeople.c.Lastname, unique=True)
> >
> > class dbPeople(object):
> >
> > def __str__(self):
> > return self.Fullname()
> >
> > def Fullname(self):
> > return unicode(self.Firstname)+u" "+unicode(self.Lastname)
> >
> > def age(self,adate=None):
> > """Compute the age of a person. If adate is set the age is
> > computed at the given date"""
> > if adate is None:
> > adate=datetime.date.today()
> > myage=adate.year-self.Birthdate.year
> > if adate.month > myage -=1
> > elif adate.month==self.Birthdate.month:
> > if adate.day > myage -=1
> > return myage
> >
> >
> > # Mapping a Racer with a Race
> > tblRaceParticipant=Table("Race_Participant",
> > Column("id", Integer, primary_key = True),
&g

[sqlalchemy] Re: Thread issue?

2006-11-04 Thread François Wautier

Hi Michael,

Thanks for your reply.

First an apology, my program is now working It was a silly mistake...

Second, I agree that what I am doing is not the most elegant thing I've ever 
done...
.to put it mildly... Yet, in most cases, the "fixRace" function will only be 
run once at startup . 
In all but one case you only deal with one race.  So that's not as bad as it 
sounds...  
Still the application that input data into the database does need to deal with 
multiple races.  
In that case I only keep one secondary mapper attached to the class and only 
create a new 
one when needed (i.e. when the race changes) (I probably need to "delete" the 
old mapper if present)

At the bottom you will see the actual definition/mapping I use. 

I guess that I may be able to map the various attributes of dbPeople and dbRace 
to attributes of dbRaceParticipant 
and deal with that object when needed,   but I still see no elegant way of 
"fixing" the race, either I 
create a secondary mapper (same as now essentially) or I need to pass the race 
as an argument 
to all my queries... which is exactly what I am trying to avoid.

Cheers,
François

Here is an excerpt of my definitions draft in progress

=+%<%<
tblPeople=Table("People",
Column("id", Integer, primary_key = True),
Column("Nickname",Unicode(32),nullable=False,index=True),
Column("Firstname",Unicode(32),nullable=False),
Column("Lastname",Unicode(32),nullable=False,index=True),
Column("Email",VARCHAR(64),index=True),
Column("Birthdate",Date),
Column("Gender",Enum(["Male","Female"]),nullable=False),
Column("Nationality",Country,nullable=False),
Column("Address",Unicode(256)),
Column("Zip",Unicode(32)),
Column("Country",Country),
Column("Tel",String(16)),
Column("Tel_Ext",String(4)),
Column("Mobile",String(16)),
Column("Picture_id",Integer,ForeignKey("ADM_Files.id"), nullable=True),
Column("Tag",String(32)),
Column("Active",Boolean,default=True))

tbbPeopleidx=Index('OnlyOne', tblPeople.c.Nickname,tblPeople.c.Firstname, 
tblPeople.c.Lastname, unique=True)

class dbPeople(object):

def __str__(self):
return self.Fullname()

def Fullname(self):
return unicode(self.Firstname)+u" "+unicode(self.Lastname)

def age(self,adate=None):
"""Compute the age of a person. If adate is set the age is computed
at the given date"""
if adate is None:
adate=datetime.date.today()
myage=adate.year-self.Birthdate.year
if adate.month Michael Bayer wrote:
> if you are creating mappers within functions on a per-request basis,
> that is a Very Bad Idea.  dont create ad-hoc mappers just to create
> queries.  you should only have one mapper per class, corresponding to
> the scope of the class itself.  i am beginning to consider if the
> "non_primary" keyword argument to mapper can even be deprecated since i
> am hypothesizing that it doesn't provide any unique functionality, and
> only leads to problems.
>
> if you want a particualr query to occur, you should create the query
> you want yourself.  without seeing anything that you are doing, if you
> are having issues, things like that would be the biggest reason.
>
>

--~--~-~--~~~---~--~~
 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] Thread issue?

2006-11-04 Thread François Wautier

Hi List,

I have a table of people,  one of Races and a RaceParticipant table that 
relate "people" to "races" and add a few extra info (e.g. Team, Weight, ...)

All this is working fine and thanks to the power of the ORM, I can do things 
like
race.Racers
people.Races

and get the right list.

Now I am trying to "fix" the race and try to retrieve only the people 
participating to the race.

What I have done is a create a function "fixRace". It takes a "race" as 
parameter and what it does is create a secondary mapper that is based on a 
query where the join is set properly. The mapper is then put in the "inRace" 
attribute of the "people" object.  My intention being to do things like

session.query(people.inRace).select_by("Nationality"="Sweden")  

I did a test using the shell and it seemed to work... but in my Qt 
application... It does not... 

my questions are

Event though my session is not flushed and only one thread at a time 
will 
access the session, could this be a threading problem?

Is there a better  way to do what I am trying to do?

Cheers,
François 

--~--~-~--~~~---~--~~
 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] compiled select

2006-10-30 Thread François Wautier


Hi list,

I think I came across a little problem I am still using 0.2.8 (+ flush 
patch), so this may have been solved already... 
in which case I apologise 

When I do

s=tblRace.select(and_(dbRace.c.id==dbRaceLeg.c.id,dbRaceLeg.c.Date>=bindparam("Race_Date")))
lor=conn.execute((s,Race_Date=datetime.date.today())

I get the expected result...

But when I do

s=tblRace.select(and_(dbRace.c.id==dbRaceLeg.c.id,dbRaceLeg.c.Date>=bindparam("Race_Date"))).compile()
lor=conn.execute((s,Race_Date=datetime.date.today())

I get an exception

  File "/usr/lib/python2.4/site-packages/sqlalchemy/engine/base.py", line 246, 
in execute
return Connection.executors[type(object).__mro__[-2]](self, object, 
*multiparams, **params)
  KeyError: 


Is this a known/solved problem or am I doing something wrong?

Cheers,
François

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



[sqlalchemy] Re: session.flush() closing connection

2006-10-30 Thread François Wautier

Hi Michael,

Thanks... Indeed it works... As long as I am careful and close the session 
after every flush (Something that make sense in the little application I am 
writing) several non concurrent threads can access and use the session.

Cool

Cheers,
François

> François Wautier wrote:
> > I moved the "connect" to the method handling the data and the problem
> > disappeared.
>
> yeah "connect()" should generally be localized as much as possible.
>
> > It would be easy enough to make sure all the "flushes" are done in a
> > single thread of execution, but can you share a session across multiple
> > thread if you ensure that anything dealing with connection (most methods
> > of the session save maybe for "save") are executed by a single thread?
> > IOW if you modify an object belonging to a session in a different thread,
> > will the session notice?
>
> you sort of can, but you have to be careful, as any load operation also
> writes data into the session.  Load operations trigger not only when
> you run a Query against that session, but also when any relations on
> instances trigger a lazy load operation.   if two threads each load an
> instance with the same primary key identifier, they could compete for
> which one actually gets placed in the session and the other one gets
> knocked out.   also a flush() is modifying the state of the underlying
> unit of work which is also not going to well tolerate other instances
> being loaded into that session.
>
> you might want to look into SessionContext which can manage Sessions
> per thread, and also can be customized to manage Sessions based on
> other criterion, such as for a GUI app on a "per-widget" basis,for
> example.
>
>
>

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



[sqlalchemy] Re: session.flush() closing connection

2006-10-21 Thread François Wautier


Hi Michael,

Thanks for the answers.

> also, when you say you "triggered" the problem, can you do that
> predictably ?  can you send a small test program that does it every
> time ?  otherwise it sounds like a threading thing (if thats at all
> possible).
>

Very much so. Everytime I run my budding application I trigger the problem.

>is there any chance the Connection youre using is being shared  
>between threads ?  thats also not supported.

Hmm Interresting question As you can see from the code snippet I sent 
previously, I am using PyQt.  Hence that is multithreaded. I hadn't thought 
about it, but since the data processing is being run by some dynamically 
created widget, it is essentially run in a different thread.

I moved the "connect" to the method handling the data and the problem 
disappeared.

It would be easy enough to make sure all the "flushes" are done in a single 
thread of execution, but can you share a session across multiple thread if 
you ensure that anything dealing with connection (most methods of the session 
save maybe for "save") are executed by a single thread? IOW if you modify an 
object belonging to a session in a different thread, will the session notice?

Regards,
François





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



[sqlalchemy] Re: session.flush() closing connection

2006-10-21 Thread François Wautier

Hi Michael,

Nope! Nothing of that sort. I couldn't care less about transaction at this 
point.

All I do is 


self.dbEng=sqlalchemy.create_engine(myurl,strategy='threadlocal')
#debug
self.dbEng.echo=True
try:
self.dbConn=self.dbEng.connect()
self.dbSession=sqlalchemy.create_session(bind_to= self.dbConn)
except sqlalchemy.exceptions.DBAPIError,msg:
QMessageBox.critical(None,"Race Management","Problem with the 
  database: "+str(msg))
sys.exit(-1)

After that all I do is create "dbPeople", set the needed properties and issue 
a "flush" on the one session I have.  

I did trigger the problem I described at least twice And once more just now). 
The behaviour was exactly the same in all cases. 

I installed SQLAlchemy using the standard Gentoo command (emerge), a md5sum on 
the file used in the install gives

fd9898c75d2773d075db89c6a99d31d6  /usr/portage/distfiles/SQLAlchemy-0.2.8.tar.gz

Regards,
François




> hey François -
>
> are you using the SessionTransaction explicitly ?  or connection.begin
> () ?   Ive tried many combinations, and the only way I can reproduce
> the problem is by doing something incorrect:
>
>  c = engine.connect()
>  s = create_session(bind_to=c)
>
>  tran = c.begin()
>  session_tran = s.create_transaction()
>
>  s.save(User())
>  s.flush()
>  u = User()
>  s.save(u)
>  s.user_name = 'some user'
>
>  tran.commit()
>  session_tran.commit()
>
> the reason the above is incorrect is because the "Transaction" and
> "SessionTransaction" are not nested properly.
>
> The fix you have wouldnt be correct since the SessionTransaction is
> being closed (if not the underlying connection, which was the
> original bug), so it should remove its association from its host
> Session.
>
> On Oct 20, 2006, at 6:59 AM, François Wautier wrote:
> > Hi Michael,
> >
> > It seems I spoke too quickly.
> >
> > The problem is now when I try to flush a  second time with a new
> > object.
> > Something like this
> >
> > newguy=dbPeople()
> > session.save(newguy)
> > newguy.Lastname="Doe"
> > newguy.Firstname="John"
> > newguy.gender="Ambiguous"
> > session.flush()
> > newguy=dbPeople()
> > session.save(newguy)
> > newguy.Lastname="Doe"
> > newguy.Firstname="Jane"
> > newguy.gender="Sheila"
> > session.flush()
> >
> > The last session flush results in a new record being written to the
> > database,
> > but an exception is raised, with the error message
> >
> > This transaction is inactive
> >
> > If one were to try to add more dbPeople, the records won't be saved
> > into the
> > database for the session keeps on using the same key value (the
> > table uses
> > an "auto_increment")
> >
> >
> > I hacked the code a bit and I solved the problem but I am far
> > from sure
> > that I did the right thing for all cases
> >
> > In  lib/sqlalchemy/orm/session.py  around line 67 I changed
> >
> >  for t in self.connections.values():
> > if (t[2]):
> > t[0].close()
> > self.session.transaction = None
> >
> > into
> >  keeptransaction=False
> >  for t in self.connections.values():
> > if (t[2]):
> > t[0].close()
> > else:
> > keeptransaction=True
> > if not keeptransaction=False:
> > self.session.transaction = None
> >
> > I wonder if something like this would not be preferable (but I
> > again, I have
> > no clue as to what the consequences of my code is)
> >
> > closeall=False
> > for t in self.connections.values():
> > if (t[2]):
> > closeall=True
> > if closeall:
> > for t in self.connections.values():
> > t[0].close()
> > self.session.transaction = None
> >
> >
> > Regards,
> > François
>
>

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



[sqlalchemy] Re: session.flush() closing connection

2006-10-20 Thread François Wautier

Hi Michael,

It seems I spoke too quickly.

The problem is now when I try to flush a  second time with a new object.  
Something like this

newguy=dbPeople()
session.save(newguy)
newguy.Lastname="Doe"
newguy.Firstname="John"
newguy.gender="Ambiguous"
session.flush()
newguy=dbPeople()
session.save(newguy)
newguy.Lastname="Doe"
newguy.Firstname="Jane"
newguy.gender="Sheila"
session.flush()

The last session flush results in a new record being written to the database, 
but an exception is raised, with the error message

This transaction is inactive

If one were to try to add more dbPeople, the records won't be saved into the 
database for the session keeps on using the same key value (the table uses 
an "auto_increment")


I hacked the code a bit and I solved the problem but I am far from sure 
that I did the right thing for all cases

In  lib/sqlalchemy/orm/session.py  around line 67 I changed

 for t in self.connections.values():
if (t[2]):
t[0].close()
self.session.transaction = None

into
 keeptransaction=False
 for t in self.connections.values():
if (t[2]):
t[0].close()
else:
keeptransaction=True
if not keeptransaction=False:
self.session.transaction = None

I wonder if something like this would not be preferable (but I again, I have 
no clue as to what the consequences of my code is)

closeall=False
for t in self.connections.values():
if (t[2]):
closeall=True
if closeall:
for t in self.connections.values():
t[0].close()
self.session.transaction = None


Regards,
François



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



[sqlalchemy] Re: session.flush() closing connection

2006-10-19 Thread François Wautier

Thanks for the patch... it works... so far

And sorry for the double post... my original email was held for a very long 
time on some google host

Cheers,
François


> thats a bug.  its because the flush() is closing the "connection" you
> passed to your session.
>
> heres a patch that fixes it, which i will try to commit later today but
> i want to work up some test cases:
>
> Index: lib/sqlalchemy/orm/session.py
> ===
> --- lib/sqlalchemy/orm/session.py   (revision 1852)
> +++ lib/sqlalchemy/orm/session.py   (working copy)
> @@ -37,7 +37,7 @@
>  e = connectable.engine
>  c = connectable.contextual_connect()
>  if not self.connections.has_key(e):
> -self.connections[e] = (c, c.begin())
> +self.connections[e] = (c, c.begin(), c is not connectable)
>  return self.connections[e][0]
>  def commit(self):
>  if self.parent is not None:
> @@ -58,7 +58,8 @@
>  if self.parent is not None:
>  return
>  for t in self.connections.values():
> -t[0].close()
> +if (t[2]):
> +t[0].close()
>  self.session.transaction = None
>
>  class Session(object):
>
>
>

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



[sqlalchemy] session.flush() and closed connection + 1 other questions

2006-10-18 Thread François Wautier

Hi,

This is my first posting to this list as I am new to SQLAlchemy , so let me 
express 
my gratitude to those who develop SQLAlchemy... It's absolutely fabulous... The 
ORM in 
particular is fantastic!

I am using version 0.2.8 with Python 2.4.3 and MySQL 4.1.21 on an up-to-date  
Linux Gentoo box

Session Flush Problem
=
I am having a problem with session.flush(). It seems that every time I issue a 
session flush the 
DB connection is closed. If I do something like this

eng = create_engine('mysql://test:[EMAIL 
PROTECTED]/test',strategy='threadlocal')
conn=eng.connect()
session = create_session(bind_to=conn)
query=session.query(dbPeople)   #This step needed for "compiling" the 
class/mapper or something like that
query=query.select_by_Lastname
listofpeople=query("Doe")
oneguy=listofpeople[0]
oneguy.Country="Namibia"
session.flush()
listofpeople=query("Smith")

The flush works alright and the database is updated, but the last line result
in an error message:

sqlalchemy.exceptions.InvalidRequestError: This Connection is closed

Is that the normal behaviour? I would have expected the session to query the DB 
and return a new list 
of dbPeople adding them to its list of "persistent" object. Am I doing 
something wrong? Misunderstanding 
something?

Is this or something similar  possible?
===

Given a dbPeople class, here is what I'd like to do

wherep=dbPeople()
wherep.Lastname="Smith"
wherep.Country="United Kingdom"
listofsmith=session.query(dbPeople).select_by(wherep)
listofsmithbosses=session.query(dbPeople).select_by(Manager=wherep)

Given the right table, classes and mapper definition (omitted here, in the 
above example, Manager could be 
defined as a "backref") the first query would produce an SQL "WHERE" clause like

"WHERE Lastname="Smith" AND Country="United Kingdom"

The list of dbPeople named "Smith" in the UK

Whilst the second would produce a query like
SELECT  FROM People AS Employee, People 
AS Manager, ManagerRel 
  WHERE Employee.id=ManagerRel.Employee AND 
Manager.id=ManagerRel.Manager AND
  Manager.Lastname="Smith" AND Manager.Country="United Kingdom"

The list of dbPeople whose manager is a "Smith" in the UK

Essentially, the (transient) object would keep track of which  properties were 
set (including set to None) and use
those to construct the WHERE clause.   Probably easier said then done  The 
case of "Pending" instances should 
be quite complex ( and in some case would not make any sense)  


Best Regards,
François


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