[sqlalchemy] get_col_spec behavior has changed from 0.5.8 to 0.6.X

2010-08-13 Thread robert rottermann

hi there,
up to now I did use something like:

c = tblCompany.__table__.columns
COMPANY_FIELDS = [(k, c[k].type.get_col_spec()) for k in c.keys() if not 
k=='id']


to build some dynamic forms for a web application.

now this breaks with an error:
 AttributeError: 'VARCHAR' object has no attribute 'get_col_spec'

it seems to work still with MySQL but not with postgres. (maybe MySQL 
uses a slightly older version out of the 6.xx serie)


what is the correct way to build a list of fields a table provides ?

thanks
robert

--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Custom type does not seem to honour is_mutable

2010-08-13 Thread Dan
I have created a custom type in order to store denormalized PKs in a
TEXT field. The idea is that the text is converted back and forth from
a set of integers:

http://paste.pocoo.org/show/249784/

This seems to work OK, however if you make a change to the set it's
not picked up by SQLAlchemy on commit.

For example, given the following model:

class Post(DeclarativeBase):
__tablename__ = posts
id = Column(Integer, primary_key=True)
votes = Column(DenormalizedText)

def __init__(self, *args, **kwargs):
super(Post, self).__init__(*args, **kwargs)
self.votes = self.votes or set()

If I do this:

post = Post()
post.votes.add(3)

session.add(post)
session.commit()

The value '3' is committed to the 'votes' column as expected.

However if I then try to modify:

post.votes.add(5)
session.commit()

The change to the set is not saved to the DB, i.e. it's still 3.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] MySQL INSERT ... ON DUPLICATE KEY UPDATE

2010-08-13 Thread brian
http://github.com/bedwards/sqlalchemy_mysql_ext

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] get_col_spec behavior has changed from 0.5.8 to 0.6.X

2010-08-13 Thread Michael Bayer

On Aug 13, 2010, at 8:19 AM, robert rottermann wrote:

 hi there,
 up to now I did use something like:
 
 c = tblCompany.__table__.columns
 COMPANY_FIELDS = [(k, c[k].type.get_col_spec()) for k in c.keys() if not 
 k=='id']
 
 to build some dynamic forms for a web application.
 
 now this breaks with an error:
 AttributeError: 'VARCHAR' object has no attribute 'get_col_spec'
 
 it seems to work still with MySQL but not with postgres. (maybe MySQL uses a 
 slightly older version out of the 6.xx serie)
 
 what is the correct way to build a list of fields a table provides ?

get_col_spec() was removed in 0.6 and replaced with the compiler structure.

the string form of a type is available if you compile it against a dialect, 
like type.compile(dialect=engine.dialect).

its not a great idea to rely upon the string form of a type for anything other 
than issuing SQL since it changes based on dialect involved and arguments.   if 
you're needing a hash key or some kind of discriminator, use the type object or 
its class by itself.


-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Custom type does not seem to honour is_mutable

2010-08-13 Thread Michael Bayer

On Aug 13, 2010, at 10:01 AM, Dan wrote:

 I have created a custom type in order to store denormalized PKs in a
 TEXT field. The idea is that the text is converted back and forth from
 a set of integers:
 
 http://paste.pocoo.org/show/249784/

this is unrelated, but the code is incorrect there, should be

def process(value):
if value is not None:
items = [str(item).strip() for item in value]
value = self.separator.join(item for item in items if item)

otherwise, you must implement copy_value() on your type.   Here, the value 
isn't being copied so there's nothing to compare to.

Usually you're supposed to mixin MutableType which will raise notimplemented 
for copy_value().   I guess still more docs are needed since you were misled by 
the is_mutable() method.






 
 This seems to work OK, however if you make a change to the set it's
 not picked up by SQLAlchemy on commit.
 
 For example, given the following model:
 
 class Post(DeclarativeBase):
__tablename__ = posts
id = Column(Integer, primary_key=True)
votes = Column(DenormalizedText)
 
def __init__(self, *args, **kwargs):
super(Post, self).__init__(*args, **kwargs)
self.votes = self.votes or set()
 
 If I do this:
 
 post = Post()
 post.votes.add(3)
 
 session.add(post)
 session.commit()
 
 The value '3' is committed to the 'votes' column as expected.
 
 However if I then try to modify:
 
 post.votes.add(5)
 session.commit()
 
 The change to the set is not saved to the DB, i.e. it's still 3.
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Dan


On Aug 13, 3:17 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 13, 2010, at 10:01 AM, Dan wrote:

  I have created a custom type in order to store denormalized PKs in a
  TEXT field. The idea is that the text is converted back and forth from
  a set of integers:

 http://paste.pocoo.org/show/249784/

 this is unrelated, but the code is incorrect there, should be

         def process(value):
             if value is not None:
                 items = [str(item).strip() for item in value]
                 value = self.separator.join(item for item in items if item)

 otherwise, you must implement copy_value() on your type.   Here, the value 
 isn't being copied so there's nothing to compare to.


Yes, sorry for the typo. Realized myself once I'd posted.

 Usually you're supposed to mixin MutableType which will raise notimplemented 
 for copy_value().   I guess still more docs are needed since you were misled 
 by the is_mutable() method.


I've tried the same thing with the MutableType mixin with the same
result, i.e:

class DenormalizedText(types.TypeDecorator, types.MutableType):

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] MySQL INSERT ... ON DUPLICATE KEY UPDATE

2010-08-13 Thread Michael Bayer
nice job.   I didn't think MySQL supported RETURNING ?   that can all go away 
if so.   Also how do i specify an UPDATE clause distinct from the INSERT ?  The 
mysql docs seem to indicate this is possible (i.e. it would UPDATE c=c+1 
instead of inserting 5 columns).   Generative would be nice:

table.insert().values(a=1, b=2, c=3).on_duplicate_update(c=table.c.c + 1)

you'd be monkeypatching the Insert construct instead of Table with the 
above, adding on_duplicate_update() that would copy the original Insert into 
your construct.   A default for everything might be on_duplicate_update('*').

MySQL is confusing here...there's REPLACE also and I always thought that was 
their INSERT or UPDATE solution.   This one seems much more useful.




On Aug 13, 2010, at 12:37 AM, brian wrote:

 http://github.com/bedwards/sqlalchemy_mysql_ext
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Michael Bayer

On Aug 13, 2010, at 10:24 AM, Dan wrote:

 
 
 On Aug 13, 3:17 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 13, 2010, at 10:01 AM, Dan wrote:
 
 I have created a custom type in order to store denormalized PKs in a
 TEXT field. The idea is that the text is converted back and forth from
 a set of integers:
 
 http://paste.pocoo.org/show/249784/
 
 this is unrelated, but the code is incorrect there, should be
 
 def process(value):
 if value is not None:
 items = [str(item).strip() for item in value]
 value = self.separator.join(item for item in items if item)
 
 otherwise, you must implement copy_value() on your type.   Here, the value 
 isn't being copied so there's nothing to compare to.
 
 
 Yes, sorry for the typo. Realized myself once I'd posted.
 
 Usually you're supposed to mixin MutableType which will raise notimplemented 
 for copy_value().   I guess still more docs are needed since you were misled 
 by the is_mutable() method.
 
 
 I've tried the same thing with the MutableType mixin with the same
 result, i.e:
 
 class DenormalizedText(types.TypeDecorator, types.MutableType):

MutableType would be first.  But again this only just so the 
NotImplementedError lets you know copy_value() is needed.I could make the 
default copy_value() raise if is_mutable() is true...though it pains me to add 
more method calls...

from sqlalchemy import *

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *

Base = declarative_base()
metadata = Base.metadata
engine = create_engine('sqlite://', echo=True)

from sqlalchemy import types

class DenormalizedText(types.TypeDecorator):

Stores denormalized primary keys that can be 
accessed as a set. 

:param coerce: coercion function that ensures correct
   type is returned

:param separator: separator character


impl = types.Text

def __init__(self, coerce=int, separator= , **kwargs):

self.coerce = coerce
self.separator = separator

super(DenormalizedText, self).__init__(**kwargs)

def bind_processor(self, dialect):

def process(value):
if value is not None:
items = [str(item).strip() for item in value]
value = self.separator.join(item for item in items if item)
return value
return process

def result_processor(self, dialect, coltype):
def process(value):
if not value:
return set()
return set(self.coerce(item) \
   for item in value.split(self.separator))
return process

def copy_value(self, value):
return set(value)

def is_mutable(self):

return True


class Post(Base):
   __tablename__ = posts
   id = Column(Integer, primary_key=True)
   votes = Column(DenormalizedText)

   def __init__(self, *args, **kwargs):
   super(Post, self).__init__(*args, **kwargs)
   self.votes = self.votes or set()

Base.metadata.create_all(engine)

session = sessionmaker(engine)()

post = Post()
post.votes.add(3)

session.add(post)
session.commit()

print ---
post.votes.add(5)
session.commit()






 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Dan
Unfortunately still getting the same result:

http://paste.pocoo.org/show/249801/

The test snippet shows that the modified set is not actually saved to
the database.

On Aug 13, 3:29 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 13, 2010, at 10:24 AM, Dan wrote:





  On Aug 13, 3:17 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  On Aug 13, 2010, at 10:01 AM, Dan wrote:

  I have created a custom type in order to store denormalized PKs in a
  TEXT field. The idea is that the text is converted back and forth from
  a set of integers:

 http://paste.pocoo.org/show/249784/

  this is unrelated, but the code is incorrect there, should be

          def process(value):
              if value is not None:
                  items = [str(item).strip() for item in value]
                  value = self.separator.join(item for item in items if item)

  otherwise, you must implement copy_value() on your type.   Here, the value 
  isn't being copied so there's nothing to compare to.

  Yes, sorry for the typo. Realized myself once I'd posted.

  Usually you're supposed to mixin MutableType which will raise 
  notimplemented for copy_value().   I guess still more docs are needed 
  since you were misled by the is_mutable() method.

  I've tried the same thing with the MutableType mixin with the same
  result, i.e:

  class DenormalizedText(types.TypeDecorator, types.MutableType):

 MutableType would be first.  But again this only just so the 
 NotImplementedError lets you know copy_value() is needed.    I could make the 
 default copy_value() raise if is_mutable() is true...though it pains me to 
 add more method calls...

 from sqlalchemy import *

 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import *

 Base = declarative_base()
 metadata = Base.metadata
 engine = create_engine('sqlite://', echo=True)

 from sqlalchemy import types

 class DenormalizedText(types.TypeDecorator):
     
     Stores denormalized primary keys that can be
     accessed as a set.

     :param coerce: coercion function that ensures correct
                    type is returned

     :param separator: separator character
     

     impl = types.Text

     def __init__(self, coerce=int, separator= , **kwargs):

         self.coerce = coerce
         self.separator = separator

         super(DenormalizedText, self).__init__(**kwargs)

     def bind_processor(self, dialect):

         def process(value):
             if value is not None:
                 items = [str(item).strip() for item in value]
                 value = self.separator.join(item for item in items if item)
             return value
         return process

     def result_processor(self, dialect, coltype):
         def process(value):
             if not value:
                 return set()
             return set(self.coerce(item) \
                        for item in value.split(self.separator))
         return process

     def copy_value(self, value):
         return set(value)

     def is_mutable(self):

         return True

 class Post(Base):
    __tablename__ = posts
    id = Column(Integer, primary_key=True)
    votes = Column(DenormalizedText)

    def __init__(self, *args, **kwargs):
        super(Post, self).__init__(*args, **kwargs)
        self.votes = self.votes or set()

 Base.metadata.create_all(engine)

 session = sessionmaker(engine)()

 post = Post()
 post.votes.add(3)

 session.add(post)
 session.commit()

 print ---
 post.votes.add(5)
 session.commit()



  --
  You received this message because you are subscribed to the Google Groups 
  sqlalchemy group.
  To post to this group, send email to sqlalch...@googlegroups.com.
  To unsubscribe from this group, send email to 
  sqlalchemy+unsubscr...@googlegroups.com.
  For more options, visit this group 
  athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Michael Bayer

On Aug 13, 2010, at 10:45 AM, Dan wrote:

 Unfortunately still getting the same result:
 
 http://paste.pocoo.org/show/249801/
 
 The test snippet shows that the modified set is not actually saved to
 the database.

that code snippet is not complete (doesn't create a Session, doesn't add Post 
to it, doesn't commit() or flush() the session but then removes it so I guess 
maybe its a scoped_session, don't know) so I don't actually know what you're 
doing.   The test case below adds your assertion, uses the Session properly, 
and works fine.   The previous test I pasted also works (if I bothered to write 
out a full test for it, you can be sure I ran it).

from sqlalchemy import *

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *

Base = declarative_base()
metadata = Base.metadata
engine = create_engine('sqlite://', echo=True)

from sqlalchemy import types

class DenormalizedText(types.TypeDecorator):

Stores denormalized primary keys that can be 
accessed as a set. 

:param coerce: coercion function that ensures correct
   type is returned

:param separator: separator character


impl = types.Text

def __init__(self, coerce=int, separator= , **kwargs):

self.coerce = coerce
self.separator = separator

super(DenormalizedText, self).__init__(**kwargs)

def bind_processor(self, dialect):

def process(value):
if value is not None:
items = [str(item).strip() for item in value]
value = self.separator.join(item for item in items if item)
return value
return process

def result_processor(self, dialect, coltype):
def process(value):
if not value:
return set()
return set(self.coerce(item) \
   for item in value.split(self.separator))
return process

def copy_value(self, value):
return set(value)

def is_mutable(self):

return True


class Post(Base):
   __tablename__ = posts
   id = Column(Integer, primary_key=True)
   votes = Column(DenormalizedText)

   def __init__(self, *args, **kwargs):
   super(Post, self).__init__(*args, **kwargs)
   self.votes = self.votes or set()

Base.metadata.create_all(engine)

session = sessionmaker(engine)()


post = Post()
assert post.votes == set([])
session.add(post)
session.commit()

post.votes.add(1)

assert 1 in post.votes
session.commit()

post_id = post.id

# close out transaction, session entirely, even 
# though commit expires everything anyway
session.close()

post = session.query(Post).get(post_id)

assert 1 in post.votes





 
 On Aug 13, 3:29 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 13, 2010, at 10:24 AM, Dan wrote:
 
 
 
 
 
 On Aug 13, 3:17 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 13, 2010, at 10:01 AM, Dan wrote:
 
 I have created a custom type in order to store denormalized PKs in a
 TEXT field. The idea is that the text is converted back and forth from
 a set of integers:
 
 http://paste.pocoo.org/show/249784/
 
 this is unrelated, but the code is incorrect there, should be
 
 def process(value):
 if value is not None:
 items = [str(item).strip() for item in value]
 value = self.separator.join(item for item in items if item)
 
 otherwise, you must implement copy_value() on your type.   Here, the value 
 isn't being copied so there's nothing to compare to.
 
 Yes, sorry for the typo. Realized myself once I'd posted.
 
 Usually you're supposed to mixin MutableType which will raise 
 notimplemented for copy_value().   I guess still more docs are needed 
 since you were misled by the is_mutable() method.
 
 I've tried the same thing with the MutableType mixin with the same
 result, i.e:
 
 class DenormalizedText(types.TypeDecorator, types.MutableType):
 
 MutableType would be first.  But again this only just so the 
 NotImplementedError lets you know copy_value() is needed.I could make 
 the default copy_value() raise if is_mutable() is true...though it pains me 
 to add more method calls...
 
 from sqlalchemy import *
 
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import *
 
 Base = declarative_base()
 metadata = Base.metadata
 engine = create_engine('sqlite://', echo=True)
 
 from sqlalchemy import types
 
 class DenormalizedText(types.TypeDecorator):
 
 Stores denormalized primary keys that can be
 accessed as a set.
 
 :param coerce: coercion function that ensures correct
type is returned
 
 :param separator: separator character
 
 
 impl = types.Text
 
 def __init__(self, coerce=int, separator= , **kwargs):
 
 self.coerce = coerce
 self.separator = separator
 
 super(DenormalizedText, self).__init__(**kwargs)
 
 def bind_processor(self, dialect):
 
  

[sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Dan

 that code snippet is not complete (doesn't create a Session, doesn't add Post 
 to it, doesn't commit() or flush() the session but then removes it so I guess 
 maybe its a scoped_session, don't know) so I don't actually know what you're 
 doing.   The test case below adds your assertion, uses the Session properly, 
 and works fine.   The previous test I pasted also works (if I bothered to 
 write out a full test for it, you can be sure I ran it).

Sorry for lack of context - had to strip out test from a whole lot of
other code - not an excuse I know.

There must be some other issue here, I'll investigate further and let
you know.


-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Dan
The issue appeared to be removing the session instance
(session.remove()) - I was trying to get a clean session for testing.

Anyway, works fine now - thanks for your help and sorry for wasting
your time.

On Aug 13, 4:21 pm, Dan danjac...@gmail.com wrote:
  that code snippet is not complete (doesn't create a Session, doesn't add 
  Post to it, doesn't commit() or flush() the session but then removes it so 
  I guess maybe its a scoped_session, don't know) so I don't actually know 
  what you're doing.   The test case below adds your assertion, uses the 
  Session properly, and works fine.   The previous test I pasted also works 
  (if I bothered to write out a full test for it, you can be sure I ran it).

 Sorry for lack of context - had to strip out test from a whole lot of
 other code - not an excuse I know.

 There must be some other issue here, I'll investigate further and let
 you know.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Re: Custom type does not seem to honour is_mutable

2010-08-13 Thread Michael Bayer
hey no problem glad you're back in business.


On Aug 13, 2010, at 11:35 AM, Dan wrote:

 The issue appeared to be removing the session instance
 (session.remove()) - I was trying to get a clean session for testing.
 
 Anyway, works fine now - thanks for your help and sorry for wasting
 your time.
 
 On Aug 13, 4:21 pm, Dan danjac...@gmail.com wrote:
 that code snippet is not complete (doesn't create a Session, doesn't add 
 Post to it, doesn't commit() or flush() the session but then removes it so 
 I guess maybe its a scoped_session, don't know) so I don't actually know 
 what you're doing.   The test case below adds your assertion, uses the 
 Session properly, and works fine.   The previous test I pasted also works 
 (if I bothered to write out a full test for it, you can be sure I ran it).
 
 Sorry for lack of context - had to strip out test from a whole lot of
 other code - not an excuse I know.
 
 There must be some other issue here, I'll investigate further and let
 you know.
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: How to link one table to itself?

2010-08-13 Thread Alvaro Reinoso
I've tried many things and I always get similar errors. I'm sure all
the foreign keys are OK.

Could not determine relationship direction for primaryjoin condition
'users.id = user_channels.user_id', on relationship User.channels. Do
the columns in 'foreign_keys' represent only the 'foreign' columns in
this join condition ?.

This error came up from another table and all the tables are working
properly without this relation. Almost all the tables are related to
each other. Maybe, this relation affects the rest of them in some way.
Any idea of How I can solve this problem?

Thanks!

On Aug 12, 8:36 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Aug 12, 2010, at 5:43 PM, Alvaro Reinoso wrote:



  I'm trying that, but I got different error:

  Could not determine relationship direction for primaryjoin condition
  'users.id = :id_1', on relationship User.mediaGroups. Specify the
  'foreign_keys' argument to indicate which columns on the relationship
  are foreign.

  As I can see, the error is related to the users table which I don't
  use in this class. However, user table is related to media_groups.
  This is the user's table:

  class User(rdb.Model):
     Represents the user
     rdb.metadata(metadata)
     rdb.tablename(users)

     id = Column(id, Integer, primary_key=True)
     name = Column(name, String(50))
     email = Column(email, String(50))

     channels = relationship(Channel, secondary=user_channels,
  order_by=Channel.titleView, backref=users)
     mediaGroups = relationship(MediaGroup, secondary=user_media_groups,
  order_by=MediaGroup.title, backref=users)

  Do I need to add something else to that table?

 user_media_groups needs to have a ForeignKey that points to users.  



  Thanks!!!

  On Aug 12, 5:15 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  On Aug 12, 2010, at 5:09 PM, Michael Bayer wrote:

  On Aug 12, 2010, at 4:58 PM, Alvaro Reinoso wrote:

  I'm still working on the solution. I've found out some stuff in
  internet. I guess I'm close to, but I haven't got it yet. I'm using
  this for the relation:

         mediaGroups = relationship(MediaGroup,
  secondary=media_group_groups, order_by=MediaGroup.title,
  backref='media_groups', foreign_keys =
  [media_group_groups.groupA_id, media_group_groups.groupB_id],
                                         primaryjoin = MediaGroup.id == 
  media_group_groups.groupA_id,
  secondaryjoin = MediaGroup.id == media_group_groups.groupB_id)

  I'm playing with the parameters, but I usually get this error:

  ArgumentError: Could not determine relationship direction for
  primaryjoin condition 'users.id = :id_1', on relationship
  User.mediaGroups. Specify the 'foreign_keys' argument to indicate
  which columns on the relationship are foreign.

  media_group_groups is not available when primaryjoin is evaluated as 
  a string, nor within foreign_keys which is not necessary here since 
  your meta_group_groups already has ForeignKey objects on it, so use a 
  non-string format for primaryjoin.   i will add additional examples to 
  the declarative docs.

  scratch part of that, tablenames are available in the string eval as long 
  as they're from the same MetaData:

      mediaGroup = relationship(MediaGroup,

  secondary=media_group_groups, order_by=MediaGroup.title,
  backref=media_groups, 
  primaryjoin=MediaGroup.id==media_group_groups.c.groupA_id,
  secondaryjoin=MediaGroup.id==media_group_groups.c.groupB_id

  also the error for the exampe you have above should be 'Table' object has 
  no attribute 'groupA_id'.

  Thank you!

  On Aug 12, 1:08 pm, Alvaro Reinoso alvrein...@gmail.com wrote:
  Hello,

  I'm trying to link one table to itself. I have media groups which can
  contain more media group. I created a relation many to many:

     media_group_groups = Table(
                         media_group_groups,
                         metadata,
                         Column(groupA_id, Integer, 
  ForeignKey(media_groups.id)),
                         Column(groupB_id, Integer, 
  ForeignKey(media_groups.id))
                 )

     class MediaGroup(rdb.Model):
         Represents MediaGroup class. Conteins channels and other media
  groups
         rdb.metadata(metadata)
         rdb.tablename(media_groups)

         id = Column(id, Integer, primary_key=True)
         title = Column(title, String(100))
         parents = Column(parents, String(512))

         channels = relationship(Channel, secondary=media_group_channels,
  order_by=Channel.titleView, backref=media_groups)
         mediaGroup = relationship(MediaGroup,
  secondary=media_group_groups, order_by=MediaGroup.title,
  backref=media_groups)

  I got this error:

  ArgumentError: Could not determine join condition between parent/
  child tables on relationship MediaGroup.mediaGroup. Specify a
  'primaryjoin' expression. If this is a many-to-many relationship,
  'secondaryjoin' is needed as well.

  When I create the tables I don't get any error, it's just when 

Re: [sqlalchemy] How to link one table to itself?

2010-08-13 Thread Michael Bayer

On Aug 12, 2010, at 1:08 PM, Alvaro Reinoso wrote:

 Hello,
 
 I'm trying to link one table to itself. I have media groups which can
 contain more media group. I created a relation many to many:
 
media_group_groups = Table(
   media_group_groups,
   metadata,
   Column(groupA_id, Integer, 
 ForeignKey(media_groups.id)),
   Column(groupB_id, Integer, 
 ForeignKey(media_groups.id))
   )
 
class MediaGroup(rdb.Model):
   Represents MediaGroup class. Conteins channels and other media
 groups
   rdb.metadata(metadata)
   rdb.tablename(media_groups)
 
   id = Column(id, Integer, primary_key=True)
   title = Column(title, String(100))
   parents = Column(parents, String(512))
 
   channels = relationship(Channel, secondary=media_group_channels,
 order_by=Channel.titleView, backref=media_groups)
   mediaGroup = relationship(MediaGroup,
 secondary=media_group_groups, order_by=MediaGroup.title,
 backref=media_groups)
 
 I got this error:
 
 ArgumentError: Could not determine join condition between parent/
 child tables on relationship MediaGroup.mediaGroup. Specify a
 'primaryjoin' expression. If this is a many-to-many relationship,
 'secondaryjoin' is needed as well.
 
 When I create the tables I don't get any error, it's just when I add
 any element to it.
 Any idea???
 
 Thanks in advance!

because you're having a particularly large amount of difficulty here, I'd very 
much like to determine what about the documentation or behavior of 
relationships is continuously leading you down the wrong path - this becuase I 
myself am not familiar with that many ways to get an error without eventually 
hitting upon the right solution.   Ive taken the effort to reconstruct every 
table and relationship you've expressed in this thread. Below you will see 
an example of everything you've expressed, pretty much using code snippets 
you've already illustrated plus reconstructions, leading into a persistence 
scenario that inserts into all seven tables.  I did not come across any of the 
issues you describe except the initial one expressing that 
primary/secondaryjoin is needed for MediaGroup.mediaGroup.

Please start by running it as is, against the given sqlite database, so you can 
see how it works.   Then, I need you to determine what about your setup is 
different than this, which would pinpoint the source of the issue-  you do this 
by blending the code below with your app, changing one part at a time until the 
difference between emitting the error and working properly is localized.   
Then, I need to know how to detect the mistake you've been making and to raise 
a more informative error message.  The foreign_keys argument is virtually 
never needed and at the very least I think I am going to remove the mention of 
that argument from the message.   Let me know what you come up with.


from sqlalchemy import *

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *

Base = declarative_base()
metadata = Base.metadata

media_group_groups = Table(
media_group_groups,
metadata,
Column(groupA_id, Integer, ForeignKey(media_groups.id)),
Column(groupB_id, Integer, ForeignKey(media_groups.id))
)

user_media_groups = Table(
user_media_groups,
metadata,
Column(user_id, Integer, ForeignKey(users.id)),
Column(media_group_id, Integer, ForeignKey(media_groups.id)),
)

user_channels = Table(
user_channels,
metadata,
Column(user_id, Integer, ForeignKey(users.id)),
Column(channel_id, Integer, ForeignKey(channel.id))
)

media_group_channels = Table(
media_group_channels,
metadata,
Column(media_group_id, Integer, ForeignKey(media_groups.id)),
Column(channel_id, Integer, ForeignKey(channel.id))
)

class Channel(Base):
__tablename__ = 'channel'
id = Column(id, Integer, primary_key=True)
titleView = Column(title, String(100))

class MediaGroup(Base):
__tablename__ = media_groups

id = Column(id, Integer, primary_key=True)
title = Column(title, String(100))
parents = Column(parents, String(512))

channels = relationship(Channel, secondary=media_group_channels,
order_by=Channel.titleView, 
backref=media_groups)

mediaGroup = relationship(MediaGroup,
secondary=media_group_groups, 
order_by=MediaGroup.title,
primaryjoin=id==media_group_groups.c.groupA_id,
secondaryjoin=id==media_group_groups.c.groupB_id,
backref=media_groups)

class User(Base):
__tablename__ = users

id = Column(id, Integer, primary_key=True)
name = 

[sqlalchemy] Re: SQLite: Rolling back DDL requests

2010-08-13 Thread Peter Hansen
On Jun 24, 1:23 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Jun 24, 2010, at 12:35 PM, Torsten Landschoff wrote:
  That's what I thought but it does not cure my problem.
  e.raw_connect().isolation_levelis in fact None, but the rollback is not
  done anyway. :-(

 its passing it through.dont know what else we can do there

I ran into this myself today and after struggling for a few hours I
came across this thread.  I then ended up creating a test case to
reproduce the problem and it suggests the problem stems from some
behaviour of transactions or of the engine.base.Connection class.  I
don't quite know what to make of it yet, but I think it shows that the
effect of passing it through is being counteracted by something
else.  I ran this on Python 2.6.5 with SA 0.6.3 on Windows.

'''Test showing unexpected behaviour with sqlalchemy and sqlite3 and
isolation_level settings.  The test creates one table outside of
a transaction (to detect potential problems with the test not
executing
properly) then creates a second table inside a transaction which it
immediately rolls back.

test01() fails basically as expected, since the sqlite3 DBAPI layer
appears to need isolation_level==None to properly roll back DDL
statements.

test02() succeeds because isolation_level==None now.  This test and
test01()
both use a connection from engine.raw_connection(), which is a
sqlalchemy.pool._ConnectionFairy() object.

test03() tries again with isolation_level==None but using a
transaction
created from a connection returned by engine.connect(), which is a
sqlalchemy.engine.base.Connection() object.  This test fails in spite
of the isolation_level setting.
'''

import unittest
from sqlalchemy import create_engine

DBPATH = 'sqlite://'
DDL = 'create table %s (id integer primary key)'

class TestCase(unittest.TestCase):
def setup(self, **kwargs):
self.engine = create_engine(DBPATH, **kwargs)
self.engine.execute(DDL % 'foo')

def rollback_raw(self):
conn = self.engine.raw_connection()
try:
conn.execute('begin')
conn.execute(DDL % 'bar')
raise ValueError
except ValueError:
conn.rollback()

def rollback_txn(self):
conn = self.engine.connect()
try:
txn = conn.begin()
conn.execute(DDL % 'bar')
raise ValueError
except ValueError:
txn.rollback()

def get_table_names(self):
conn = self.engine.raw_connection()
return [x[0] for x in conn.execute('select name from
sqlite_master')]

def test01(self):
'''use engine with default isolation_level'''
self.setup()
self.rollback_raw()
self.assertEqual(['foo'], self.get_table_names())

def test02(self):
'''use raw_connection with isolation_level None'''
self.setup(connect_args={'isolation_level': None})
self.rollback_raw()
self.assertEqual(['foo'], self.get_table_names())

def test03(self):
'''use transaction with isolation_level None'''
self.setup(connect_args={'isolation_level': None})
self.rollback_txn()
self.assertEqual(['foo'], self.get_table_names())

if __name__ == '__main__':
unittest.main()


--
Peter Hansen
Engenuity Corporation

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.