[sqlalchemy] Re: New instance ExtraStat with identity key (...) conflicts with persistent instance ExtraStat

2008-12-02 Thread Doug Farrell
Michael,

 

Thanks for the pointer, that makes great sense, and once again points
how my generally small database design skills. I'll update my code to
try this out.

 

Again,

Thanks!

Doug

 

From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED]
On Behalf Of Michael Bayer
Sent: Saturday, November 29, 2008 9:28 PM
To: sqlalchemy@googlegroups.com
Subject: [sqlalchemy] Re: New instance ExtraStat with identity key (...)
conflicts with persistent instance ExtraStat

 

Simon's suggestion about the duplicate name still holds.  Your
relation from Stat-ExtraStat currently needs to be one-to-one since you
cannot have more than one ExtraStat referencing a single Stat, due to
the PK constraint on ExtraStat.name.  The error is raising at the point
of query() since autoflush is kicking in - use session.flush() to
isolate the error.

 

On Nov 29, 2008, at 12:18 PM, Doug Farrell wrote:





Hi all,

 

I'm having a problem with a new instance of a relation conflicting with

an existing instance. I'm using SA 0.5rc with Sqlite3. Here are my

simplified classes:

 

class Stat(sqladb.Base):

 __tablename__ = stats

 name = Column(String(32), primary_key=True)

 total= Column(Integer)

 created  = Column(DateTime, default=datetime.datetime.now())

 updated  = Column(DateTime)

 states   = Column(PickleType, default={})

 extraStats   = relation(ExtraStat, backref=stat)

 

class ExtraStat(sqladb.Base):

 __tablename__ = extrastats

 name = Column(String(32), ForeignKey(stats.name),
primary_key=True)

 total= Column(Integer)

 created  = Column(DateTime, default=datetime.datetime.now())

 updated  = Column(DateTime)

 states   = Column(PickleType, default={})

 

The above Stat class has a one-to-many relationship with the ExtraStat

class (which I think I've implemented correctly). Later in the

program I create an in memory data model that has as part of it's

components two

dictionaries that contain Stat instances. Those Stat instances have

relationships to ExtraStat instances. My problem comes in the

following when I'm trying to update the data in those instances/tables.

Here is a section of code that throws the exception:

 

 

 

pressName = press%s % pressNum

# add new ExtraStat instances as relations

self._addProductStatsPress(productType, pressName)

self._addPressStatsProduct(pressName, productType)

try:

   extraStat = session.query(Stat). \

   filter(Stat.name==productType). \

   join(extraStats). \

   filter(ExtraStat.name==pressName).one()

except:

   extraStat = ExtraStat(pressName, ExtraStat.PRESS_TYPE)

   self.productStats[productType].extraStats.append(extraStat)

   extraStat.states.setdefault(sstate, 0)

   extraStat.states[sstate] += 1

   extraStat.updated = now

   extraStat = session.merge(extraStat)

try:

   extraStat = session.query(Stat). \

   filter(Stat.name==pressName). \

   join(extraStats). \

   filter(ExtraStat.name==productType).one()    throws
exception right here

except:

   extraStat = ExtraStat(productType, ExtraStat.PRODUCT_TYPE)

   self.pressStats[pressName].extraStats.append(extraStat)

   extraStat.states.setdefault(sstate, 0)

   extraStat.states[sstate] += 1

   extraStat.updated = now

 

The marked area is wear it throws the exception. I'm not sure what to

do here to get past this, any help or ideas would be greatly

appreciated.

 

The exact exception is as follows:

Sqlalchemy.orm.exc.FlushError: New instance [EMAIL PROTECTED] With identity

key (class '__main__.ExtraStat',(u'C',)) conflicts with persistent

instance [EMAIL PROTECTED]

 

Thanks!

Doug





 



 


--~--~-~--~~~---~--~~
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: New instance ExtraStat with identity key (...) conflicts with persistent instance ExtraStat

2008-12-02 Thread Bob

I keep thinking one of my relatives has emailed me when you post here
and I get all excited. Any chance you can change your name ? :-)

2008/12/2 Doug Farrell [EMAIL PROTECTED]:
 Michael,



 Thanks for the pointer, that makes great sense, and once again points how my
 generally small database design skills. I'll update my code to try this out.



 Again,

 Thanks!

 Doug



 From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED] On
 Behalf Of Michael Bayer
 Sent: Saturday, November 29, 2008 9:28 PM
 To: sqlalchemy@googlegroups.com
 Subject: [sqlalchemy] Re: New instance ExtraStat with identity key (...)
 conflicts with persistent instance ExtraStat



 Simon's suggestion about the duplicate name still holds.  Your relation
 from Stat-ExtraStat currently needs to be one-to-one since you cannot have
 more than one ExtraStat referencing a single Stat, due to the PK constraint
 on ExtraStat.name.  The error is raising at the point of query() since
 autoflush is kicking in - use session.flush() to isolate the error.



 On Nov 29, 2008, at 12:18 PM, Doug Farrell wrote:

 Hi all,



 I'm having a problem with a new instance of a relation conflicting with

 an existing instance. I'm using SA 0.5rc with Sqlite3. Here are my

 simplified classes:



 class Stat(sqladb.Base):

  __tablename__ = stats

  name = Column(String(32), primary_key=True)

  total= Column(Integer)

  created  = Column(DateTime, default=datetime.datetime.now())

  updated  = Column(DateTime)

  states   = Column(PickleType, default={})

  extraStats   = relation(ExtraStat, backref=stat)



 class ExtraStat(sqladb.Base):

  __tablename__ = extrastats

  name = Column(String(32), ForeignKey(stats.name),
 primary_key=True)

  total= Column(Integer)

  created  = Column(DateTime, default=datetime.datetime.now())

  updated  = Column(DateTime)

  states   = Column(PickleType, default={})



 The above Stat class has a one-to-many relationship with the ExtraStat

 class (which I think I've implemented correctly). Later in the

 program I create an in memory data model that has as part of it's

 components two

 dictionaries that contain Stat instances. Those Stat instances have

 relationships to ExtraStat instances. My problem comes in the

 following when I'm trying to update the data in those instances/tables.

 Here is a section of code that throws the exception:







 pressName = press%s % pressNum

 # add new ExtraStat instances as relations

 self._addProductStatsPress(productType, pressName)

 self._addPressStatsProduct(pressName, productType)

 try:

extraStat = session.query(Stat). \

filter(Stat.name==productType). \

join(extraStats). \

filter(ExtraStat.name==pressName).one()

 except:

extraStat = ExtraStat(pressName, ExtraStat.PRESS_TYPE)

self.productStats[productType].extraStats.append(extraStat)

extraStat.states.setdefault(sstate, 0)

extraStat.states[sstate] += 1

extraStat.updated = now

extraStat = session.merge(extraStat)

 try:

extraStat = session.query(Stat). \

filter(Stat.name==pressName). \

join(extraStats). \

filter(ExtraStat.name==productType).one()    throws
 exception right here

 except:

extraStat = ExtraStat(productType, ExtraStat.PRODUCT_TYPE)

self.pressStats[pressName].extraStats.append(extraStat)

extraStat.states.setdefault(sstate, 0)

extraStat.states[sstate] += 1

extraStat.updated = now



 The marked area is wear it throws the exception. I'm not sure what to

 do here to get past this, any help or ideas would be greatly

 appreciated.



 The exact exception is as follows:

 Sqlalchemy.orm.exc.FlushError: New instance [EMAIL PROTECTED] With identity

 key (class '__main__.ExtraStat',(u'C',)) conflicts with persistent

 instance [EMAIL PROTECTED]



 Thanks!

 Doug





 


--~--~-~--~~~---~--~~
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] inferring object class/table directly

2008-12-02 Thread Faheem Mitha


Hi,

If I have an ORM object, it is sometimes convenient to be able to infer 
the class directly. Eg. consider this function.

def add_patient_obj(session, patient_obj):
  Check if object primary key exists in db. If so,exit, else
 add.
 pid = patient_obj.id
 #print session.query(Patient).filter_by(id=pid).count()
 if session.query(Patient).filter_by(id=pid).count()  0:
 print Patient object with id %s is already in db.%pid
 exit
 else:
 session.save(patient_obj)
 session.commit()

But I want a generic version. Since patient_obj knows what class is 
belongs to, it should be possible not to have to state the class directly, 
which here is Patient.

I have done the following, which works, but is hideous, horrible, ugly, 
fragile hack. Can anyone suggest a better way of doing this?

Please CC me on any reply. Thanks in advance.

Regards, Faheem.

def add_obj(session, obj):
  Check if object primary key exists in db. If so,exit, else
 add.
 
 c = str(type(obj)).split(')[1].split(.)[1]
 s = q = session.query(+ c +)
 exec(s)
 pid = obj.id
 if q.filter_by(id=pid).count()  0:
 print Patient object with id %s is already in db.%pid
 exit
 else:
 session.save(obj)
 session.commit()

--~--~-~--~~~---~--~~
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] a-directional i.e. bi-directional m:m relations

2008-12-02 Thread Eric Ongerth

I could use some insightful suggestions here:
What do you think of this use case?

Let's say I have a class Foo mapped to a table 'foos',  and a
many:many relation between these objects, stored in the table
'foo_relations'.

columns on foos:
id (Integer)
data (Text)

columns on foo_relations:
this_foo_id (Integer)
that_foo_id (Integer)

But this implicitly creates a direction to the m:m relation,
something that I don't want.  I want this m:m relation to be bi-
directional (or you could call it adirectional).  The setup above
makes one foo into this and the other into that.  It's not, of
course, because of what I labeled them; it's because the columns have
to be labeled at all.  But I don't want a specific directionality
here.

Now when I want to find out whether a Foo has a relation to another
Foo, I have to check whether there exists any row in foo_relations
that has the given Foo as either as this OR that.  Also, what if I
need backrefs on the foo_relations mapper?  The backref from 'this'
and the backref from 'that' would both point to something called a
foo, but they would have to be given separate labels in order ot not
be conflicting property names -- when really, I would not want to know
if a foo was the 'that' or the 'this' of some foo relation.

So ideally in a case like this, I could set an option that says the
m:m relation is bidirectional, and that the backrefs for both foreign
keys in the m:m table should really point to the same place (or at
least be unioned together).

I have a feeling that would violate some part of the RDBMS standards,
and I'm perfectly willing to go without or work around.  This is more
of a philosophical point for learning's sake -- what do other people
do in such cases?

Thanks,
Eric

--~--~-~--~~~---~--~~
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: inferring object class/table directly

2008-12-02 Thread Eric Ongerth

def add_obj(session, obj):
  Check if object primary key exists in db. If so,exit, else
 add.
 
 pid = obj.id
if session.query(obj.__class__).filter_by(id=pid).count():
 print Patient object with id %s is already in db.%pid
 exit
 else:
 session.save(obj)
 session.commit()


Not too difficult.  You can also use type(obj) instead of
obj.__class__.

Furthermore, if you really need to determine the object's class's
mapped table,
obj_table = obj.__class__._sa_class_manager.mapper.mapped_table

Of course, being an underscored thing, _sa_class_manager is not
something you should count on from version to version of sqlalchemy,
so keep that in consideration and don't use it anywhere you don't plan
to maintain.

Eric


On Dec 2, 2:24 pm, Faheem Mitha [EMAIL PROTECTED] wrote:
 Hi,

 If I have an ORM object, it is sometimes convenient to be able to infer
 the class directly. Eg. consider this function.

 def add_patient_obj(session, patient_obj):
       Check if object primary key exists in db. If so,exit, else
      add.
      pid = patient_obj.id
      #print session.query(Patient).filter_by(id=pid).count()
      if session.query(Patient).filter_by(id=pid).count()  0:
          print Patient object with id %s is already in db.%pid
          exit
      else:
          session.save(patient_obj)
          session.commit()

 But I want a generic version. Since patient_obj knows what class is
 belongs to, it should be possible not to have to state the class directly,
 which here is Patient.

 I have done the following, which works, but is hideous, horrible, ugly,
 fragile hack. Can anyone suggest a better way of doing this?

 Please CC me on any reply. Thanks in advance.

                                                     Regards, Faheem.

 def add_obj(session, obj):
       Check if object primary key exists in db. If so,exit, else
      add.
      
      c = str(type(obj)).split(')[1].split(.)[1]
      s = q = session.query(+ c +)
      exec(s)
      pid = obj.id
      if q.filter_by(id=pid).count()  0:
          print Patient object with id %s is already in db.%pid
          exit
      else:
          session.save(obj)
          session.commit()
--~--~-~--~~~---~--~~
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: inferring object class/table directly

2008-12-02 Thread Michael Bayer


On Dec 2, 2008, at 6:04 PM, Eric Ongerth wrote:


 def add_obj(session, obj):
  Check if object primary key exists in db. If so,exit, else
 add.
 
 pid = obj.id
if session.query(obj.__class__).filter_by(id=pid).count():
 print Patient object with id %s is already in db.%pid
 exit
 else:
 session.save(obj)
 session.commit()


 Not too difficult.  You can also use type(obj) instead of
 obj.__class__.

 Furthermore, if you really need to determine the object's class's
 mapped table,
 obj_table = obj.__class__._sa_class_manager.mapper.mapped_table

here's the API way:

object_mapper(obj).mapped_table



--~--~-~--~~~---~--~~
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: a-directional i.e. bi-directional m:m relations

2008-12-02 Thread Michael Bayer


On Dec 2, 2008, at 5:54 PM, Eric Ongerth wrote:

 Now when I want to find out whether a Foo has a relation to another
 Foo, I have to check whether there exists any row in foo_relations
 that has the given Foo as either as this OR that.  Also, what if I
 need backrefs on the foo_relations mapper?  The backref from 'this'
 and the backref from 'that' would both point to something called a
 foo, but they would have to be given separate labels in order ot not
 be conflicting property names -- when really, I would not want to know
 if a foo was the 'that' or the 'this' of some foo relation.

 So ideally in a case like this, I could set an option that says the
 m:m relation is bidirectional, and that the backrefs for both foreign
 keys in the m:m table should really point to the same place (or at
 least be unioned together).

 I have a feeling that would violate some part of the RDBMS standards,
 and I'm perfectly willing to go without or work around.  This is more
 of a philosophical point for learning's sake -- what do other people
 do in such cases?

you can store two rows in the association table, one for each  
direction.   or provide an accessor which just unions together the  
forwards and backwards references between Foo objects.  or make a  
readonly relation() that does the appropriate OR logic.   I might  
even try combining both of those techniques somehow.


--~--~-~--~~~---~--~~
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: inferring object class/table directly

2008-12-02 Thread Faheem Mitha

[This message has also been posted.]
Hi Eric,

Thanks very much for the improvement.

On Tue, 2 Dec 2008 15:04:34 -0800 (PST), Eric Ongerth
[EMAIL PROTECTED] wrote:

 def add_obj(session, obj):
   Check if object primary key exists in db. If so,exit, else
  add.
  
  pid = obj.id
 if session.query(obj.__class__).filter_by(id=pid).count():
  print Patient object with id %s is already in db.%pid
  exit
  else:
  session.save(obj)
  session.commit()

Yes, I was looking for this, and printed out obj.__dict__ but didn't
see it there. A dictionary of attributes is very useful in theory, but
doesn't always seem to have all attributes. Is this documented
anywhere?

 Not too difficult.  You can also use type(obj) instead of
 obj.__class__.

I thought of trying this, but didn't. It didn't seem likely to work,
anyway. Is either of these preferred over the other in terms of API
stability, and if so, why?

 Furthermore, if you really need to determine the object's class's
 mapped table,
 obj_table = obj.__class__._sa_class_manager.mapper.mapped_table

 Of course, being an underscored thing, _sa_class_manager is not
 something you should count on from version to version of sqlalchemy,
 so keep that in consideration and don't use it anywhere you don't plan
 to maintain.

Not sure what the object class's mapped table is, but will look it up.

  Regards, Faheem.

--~--~-~--~~~---~--~~
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: inferring object class/table directly

2008-12-02 Thread Faheem Mitha

[This message has also been posted.]
On Tue, 2 Dec 2008 18:25:19 -0500, Michael Bayer
[EMAIL PROTECTED] wrote:

 On Dec 2, 2008, at 6:04 PM, Eric Ongerth wrote:

[snip]
 Furthermore, if you really need to determine the object's class's
 mapped table,
 obj_table = obj.__class__._sa_class_manager.mapper.mapped_table

 here's the API way:

 object_mapper(obj).mapped_table

Hi Michael,

Thanks for the clarification.

 Regards, Faheem.

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