[sqlalchemy] problem with backref

2006-12-20 Thread Manlio Perillo


Hi, I have a strange (for me) problem with backref.

SQLAlchemy version is 0.3.1-1 on Debian Etch.


Here is the code:

from sqlalchemy import *


db = create_engine('postgres://manlio:[EMAIL PROTECTED]/test')

metadata = BoundMetaData(db)
a = Table(
'a', metadata,
Column('x', String),
Column('y', String),
PrimaryKeyConstraint('x', 'y')
)

b = Table(
'b', metadata,
Column('x', String),
Column('y', String),
Column('z', String),
PrimaryKeyConstraint('x', 'y'),
ForeignKeyConstraint(['x', 'y'], ['a.x', 'a.y'])
)

metadata.create_all()


class A(object):
def __init__(self, x, y):
self.x = x
self.y = y

class B(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z


mapper(A, a)
mapper(
B, b,
properties={
'a': relation(
A, backref=backref('b', lazy=False, uselist=False,
   cascade='all, delete-orphan'),
uselist=False, cascade='all, delete-orphan'
)
}
)


try:
conn = db.connect()
trans = conn.begin()
sess = create_session()

o = A('1', '2')
o.b = B(o.x, o.y, '3')
sess.save(o)

sess.flush()
sess.close()
trans.commit()


trans = conn.begin()
sess = create_session()

sess.update(o)
print o.b.z
del o.b

sess.flush()
sess.close()
trans.commit()

print o.b
s = a.select()
print conn.execute(s).fetchall()
finally:
metadata.drop_all()



The problem here is that when I delete o.b, SQLAlchemy deletes the rows
from 'a' table, too.

Moreover the programs blocks at metadata.drop_all().


Now:
1) when I remove the cascade rule from backref I obtain:
sqlalchemy.exceptions.AssertionError: Dependency rule tried to
blank-out primary key column 'b.x' on instance '[EMAIL PROTECTED]'

2) when I remove the cascade rule from relation I obtain:
sqlalchemy.exceptions.InvalidRequestError: Parent instance class
'__main__.A' is not bound to a Session, and no contextual session is
established; lazy load operation of attribute 'b' cannot proceed

3) when I remove the cascade rule from both backref and relation, I
   obtain:
sqlalchemy.exceptions.InvalidRequestError: Parent instance class
'__main__.A' is not bound to a Session, and no contextual session is
established; lazy load operation of attribute 'b' cannot proceed

4) if I set the cascade rule to all I obtain:
sqlalchemy.exceptions.InvalidRequestError: Instance '__main__.B object
at 0xb794068c' is not attached or pending within this session


What's the problem?



Thanks  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: problem with backref

2006-12-20 Thread Manlio Perillo



Manlio Perillo ha scritto:


Hi, I have a strange (for me) problem with backref.

SQLAlchemy version is 0.3.1-1 on Debian Etch.


Here is the code:

[...]

from sqlalchemy import *  trans = conn.begin()
 sess = create_session()

 sess.update(o)
 print o.b.z
 del o.b



A simple workaround is to remove cascade rules from the mapper and to
do:
   sess.delete(o.b)

However this require the explicit use of the session.


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: problem with backref

2006-12-20 Thread Alan Franzoni

[italian mode]
Come va Manlio? Ci sente anche qui alla fine :-) io per la fine dell'anno
dovrei riuscire a finire il progetto su cui sto lavorando e potrĂ² riprendere
finalmente il mio lavoro anche con python.it!
[/italian mode]

1st:
In order to use a transaction with a pre-existent connection, you should
bind the session to the connection. This can be done by creating the session
this way:

sess = create_session(bind_to=conn)

This is useful if you want to work both with the SQL layer and with the ORM
layer of SA. If you just want to use the ORM layer (like you appear to do),
forget the 'conn' and 'trans' in your code, and just do

sess = create_session()
trans = sess.create_transaction()

and just use trans.rollback() or trans.commit() in your code.

2nd:
If I got what you want: you want to be able to remove the 'B' instance from
the 'A' instance without removing the 'A' object from the db, right?
session.delete() is the way to go, because that's the way you remove objects
using the SA ORM. And you must pull out the 'cascade='all'' from the 'a'
relation, because if you instruct SA to do this, it will try to remove its
related object (the 'A' instance), which is not what you wont.

Look at this and tell me if it produces the result you would expect:

mapper(A, a)
mapper(
   B, b,
   properties={
   'a': relation(
   A, backref=backref('b', lazy=False, uselist=False,
  cascade='all'),
   uselist=False  )
   }
   )



sess = create_session()
o = A('1', '2')
o.b = B(o.x, o.y, '3')

sess.save(o)
sess.flush()
sess.expunge(o)
sess.clear()
del o

o = sess.query(A).get_by(x=1, y=2)
print o.b.z
sess.delete(o.b)
sess.flush()
sess.close()

print o.b
s = a.select()
print s.execute().fetchall()



--
Alan Franzoni [EMAIL PROTECTED]
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E

--~--~-~--~~~---~--~~
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] scalar subqueries

2006-12-20 Thread Manlio Perillo


Hi.

Is it possible to write something like:

SELECT name,
  (SELECT max(pop)
   FROM cities WHERE cities.state = states.name)
  FROM states


The problem is how to setup up the where condition in the subquery: is 
this possible?




Thanks  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] MySQL Functions

2006-12-20 Thread saxon75


Hi there,

I'm looking for a little help using MySQL functions in a WHERE clause
with SQLAlchemy.

The query I'd like to do is something like SELECT * FROM x WHERE
YEAR(FROM_UNIXTIME(timestamp)) == '2006';

Here's how I've tried to implement it:

metadata = MetaData()

articles_table = Table('blog_articles', metadata,
   Column('id', Integer, primary_key = True),
   Column('timestamp', Integer),
   Column('section_id', Integer, ForeignKey('blog_sections.id')),
   Column('title', String(255)),
   Column('text', TEXT)
)

class Article(object):
 def __init__(self, timestamp, title, text):
   self.article_timestamp = timestamp
   self.article_title = title
   self.article_text = text

mapper(Article, articles_table)

db = create_engine(settings.db_string)
session = create_session(bind_to=db)

result =
session.query(Article).select(func.year(func.from_unixtime(Article.c.timestamp))=='2006')

This throws the following error:
(ProgrammingError) function from_unixtime(integer) does not exist
HINT:   No function matches the given name and argument types. You may
need to add explicit type casts.

I tried a few things to explicitly cast the row type, but nothing
seemed to work.

This:
session.query(Article).select(func.year(func.from_unixtime(cast(Article.c.timestamp,
DateTime)))=='2006')

threw the following error:
(ProgrammingError) cannot cast type integer to timestamp with time
zone)

Any suggestions?

Thanks.


--~--~-~--~~~---~--~~
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: problem with backref

2006-12-20 Thread Manlio Perillo


Alan Franzoni ha scritto:

[italian mode]
Come va Manlio? Ci sente anche qui alla fine :-) io per la fine 
dell'anno dovrei riuscire a finire il progetto su cui sto lavorando e 
potrĂ² riprendere finalmente il mio lavoro anche con python.it 
http://python.it!

[/italian mode]



Hi Alan!


1st:
In order to use a transaction with a pre-existent connection, you should 
bind the session to the connection. This can be done by creating the 
session this way:


sess = create_session(bind_to=conn)

This is useful if you want to work both with the SQL layer and with the 
ORM layer of SA. If you just want to use the ORM layer (like you appear 
to do), forget the 'conn' and 'trans' in your code, and just do


sess = create_session()
trans = sess.create_transaction()

and just use trans.rollback() or trans.commit() in your code.




In my code I use:
trans = conn.begin()
sess = create_session(bind_to=conn)

The example posted was wrong, sorry.



2nd:
If I got what you want: you want to be able to remove the 'B' instance 
from the 'A' instance without removing the 'A' object from the db, 
right? 


Right.

session.delete() is the way to go, because that's the way you 
remove objects using the SA ORM. 


Yes, I just discovered this by myself.

The problem is that it requires the explicit use of the session.
In my case this means that I can not delete the object inside a method 
of my class.


class A(object):
   def enableB(enable=True):
  if enable:
 self.b = B(...)
  else:
 del self.b


Not a big problem, however.



Thanks and 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: problem with backref

2006-12-20 Thread Alan Franzoni



The problem is that it requires the explicit use of the session.
In my case this means that I can not delete the object inside a method
of my class.

class A(object):
def enableB(enable=True):
   if enable:
  self.b = B(...)
   else:
  del self.b


Not a big problem, however.



There's the 'threadlocal' that should let you work as you like, but I've
read its use is discouraged because it could lead to strange bugs.

BTW, couldn't you just pass your session to the methods requiring it?

class A(object):
   def enableB(enable=True, session):
  if enable:
 self.b = B(...)
  else:
 session.delete(self.b)




--
Alan Franzoni [EMAIL PROTECTED]
-
Togli .xyz dalla mia email per contattarmi.
Remove .xyz from my address in order to contact me.
-
GPG Key Fingerprint (Key ID = FE068F3E):
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E

--~--~-~--~~~---~--~~
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: MySQL Functions

2006-12-20 Thread Michael Bayer


i dont know much about FROM_TIMESTAMP but from the MySQL docs it seems
like it deals with a UNIX_TIMESTAMP value, which perhaps is different
from an integer (although it looks like an int from the examples.
maybe its a long?).

The steps to make this work are to get it to work from your MySQL
command line first.  then use echoing in SA to insure that its
producing the identical SQL to the working string.  as a last resort,
sometimes you have to make small test programs using straight DBAPI to
insure that theres no weirdness happening with MySQLdb.


--~--~-~--~~~---~--~~
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: problem with backref

2006-12-20 Thread Michael Bayer


the original mapping essentially expressed this relationship:

   A --  cascade=all, delete-orphan -- B

in both directions.  What that means is, there cannot be an A with no B
in the database, and there cannot be a B with no A in the database,
i.e. its either A-B or both will be deleted.  its like an oxygen
molecule, or something.

what you need to do is decide which of A and B can exist on its own
without a parent relationship.  since you want to delete rows from B
and not A, that would indicate that the mapping should be:

mapper(A, a)
mapper(
B, b,
properties={
'a': relation(
A, backref=backref('b', lazy=False, uselist=False,
   cascade='all, delete-orphan'),
uselist=False
)
}
)

i.e. the delete-orphan cascade is only in the direction from A-B.
the cascade from B-A is left at its default value of save-update, so
delete operations dont propigate from B's to A's.


--~--~-~--~~~---~--~~
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: MySQL Functions

2006-12-20 Thread saxon75


The initial query I posted definitely works--I've been using something
very much like it for a long time in my existing application.  I've
only recently discovered SA, though, and I'm trying to incorporate it
into my design.  FROM_TIMESTAMP can definitely take an integer input.

Anyway, thanks.


--~--~-~--~~~---~--~~
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: MySQL Functions

2006-12-20 Thread Michael Bayer


i just tried out your example and it executes fine using mysql 5, query
output is:

SELECT blog_articles.timestamp AS blog_articles_timestamp,
blog_articles.text AS blog_articles_text, blog_articles.id AS
blog_articles_id, blog_articles.title AS blog_articles_title
FROM blog_articles
WHERE year(from_unixtime(blog_articles.timestamp)) = %s ORDER BY
blog_articles.id

params: ['2006']


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