[sqlalchemy] Re: UOW relation delete bug

2007-03-28 Thread Michael Bayer

it works for me, the bind params are in sqlite:

[[1], [3], [5]]

in postgres:

[{'id': 1}, {'id': 3}, {'id': 5}]

in both cases, thats a list of three sets of bind params, one  
positional and the other named, which correspond to executemany().
if this condition doesnt work with MS-SQL,  MS-SQL should get added  
to test/engine/execute.py, which test the various scenarios of  
*multiparams and **params that you can send to execute().  just pick  
the paramstyle that works with MS-SQL and add it to the supported  
list for that test.

On Mar 28, 2007, at 1:36 AM, Rick Morrison wrote:

 Surprised no one has hit this one yet.

 When issuing a series of deletes in a UOW, SA issues the bogus  
 delete statement

 DELETE child where id = [1,2,3]

 instead of using IN()

 Test case attached. Seems to work in Sqlite even while issuing the  
 bogus SQL (which is probably why a unit test didn't pick it up),  
 but MS-SQL doesn't like it; didn't check PG or others.


 
 from sqlalchemy import *
 import logging

 logging.basicConfig()
 logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

 #metadata = BoundMetaData('mssql://d:[EMAIL PROTECTED]/drvtest')
 metadata = BoundMetaData('sqlite:///:memory:')

 entity = Table('entity', metadata,
 Column('id',  INT,  primary_key=True, nullable=False),
 Column('typ', VARCHAR(12)),
 Column('lname',   VARCHAR(128))
 )

 entityattr = Table('entityattr', metadata,
   Column('id',  INT,  primary_key=True,  
 nullable=False),
   Column('ident',   INT, ForeignKey('entity.id'),  
 nullable=False),
   Column('typ', VARCHAR(12), nullable=False),
   Column('val', VARCHAR(128))
   )

 metadata.create_all()

 class O(object):
 def __init__(self,**kw):
 for k,v in kw.items():
 setattr(self,k,v)

 class Ent(O): pass
 class Entattr(O): pass

 mapper(Ent, entity, properties = {'props':relation(Entattr,  
 cascade=all, delete-orphan)})
 mapper(Entattr, entityattr)

 S = create_session()

 S.save(Ent(typ='A',lname='A',
props = [Entattr(typ='A1', val='1'),
 Entattr(typ='A2', val='2'),
 Entattr(typ='A3', val='3'),
 Entattr(typ='A4', val='4'),
 Entattr(typ='A5', val='5'),
 Entattr(typ='A6', val='6')
 ]))
 S.flush()
 S.clear()

 e = S.query(Ent).options(eagerload('props')).select()[0]

 # remove some attributes
 e.props = [p for p in e.props if 0 == int(p.val) % 2]

 # put some back
 e.props.append(Entattr(typ='A6', val='6'))
 e.props.append(Entattr(typ='A7', val='7'))
 e.props.append(Entattr(typ='A8', val='8'))

 S.flush()# -- Delete issued here
 S.clear()

 e = S.query(Ent).options(eagerload('props')).select()[0]
 assert 6 == len(e.props)

 metadata.drop_all()


--~--~-~--~~~---~--~~
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: Fix on ADODBAPI

2007-03-28 Thread Paul Johnston

Hi,

The bit applicable to adodbapi doesn't consider the port at all (at the 
moment...)

class MSSQLDialect_adodbapi(MSSQLDialect):
...
def make_connect_string(self, keys):
connectors = [Provider=SQLOLEDB]
connectors.append (Data Source=%s % keys.get(host))
connectors.append (Initial Catalog=%s % keys.get(database))
user = keys.get(user)
if user:
connectors.append(User Id=%s % user)
connectors.append(Password=%s % keys.get(password, ))
else:
connectors.append(Integrated Security=SSPI)
return [[;.join (connectors)], {}]

Paul


El Gringo wrote:





Ok I saw fixes in the current trunk:

class MSSQLDialect_pymssql(MSSQLDialect):
def make_connect_string(self, keys):
if keys.get('port'):
# pymssql expects port as host:port, not a separate arg
keys['host'] = ''.join([keys.get('host', ''), ':',
str(keys['port'])])
del keys['port']
return [[], keys]


I guess the right separator is not ':' but ','. G just a way from
MS to disagree from standarts.




  



--~--~-~--~~~---~--~~
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: Fix on ADODBAPI

2007-03-28 Thread El Gringo



On 28 mar, 12:30, Paul Johnston [EMAIL PROTECTED] wrote:
 Hi,

 The bit applicable toadodbapidoesn't consider the port at all (at the
 moment...)


Check the current trunk, if port is specified, the port key is deleted
and its value added to the key host with ''.join([keys.get('host',
''), ':',
str(keys['port'])]) .  The problem is the ':' wich must be a coma for
an adodb connection string.

check 
http://msdn2.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx.

 server=tcp:servername, portnumber


--~--~-~--~~~---~--~~
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: func() bug ?

2007-03-28 Thread Julien Cigar

Hello Mike,

This simple test illustrate the problem :

 from sqlalchemy import func
 print 'foo' == func.any('bar')
any(:any) = :a_1

it should be :a_1 = any(:any)

If you look at the PostgreSQL documentation,
http://www.postgresql.org/docs/8.2/static/functions-comparisons.html#AEN14105 
the syntax is: 
expression operator ANY (array expression)

and not :
ANY (array expression) expression operator

Note the ANY can also be used with subselect (so it's not specific to
the PostgreSQL array type) :
http://www.postgresql.org/docs/8.2/static/functions-subquery.html#AEN13959

expression operator ANY (subquery)

and in this case it's also incorrect :

 print 'foo' == func.any(select)
any(:any) = :a_1

(again it should be :a_1 = any(:any))

Regards,
Julien

On Tue, 2007-03-27 at 12:13 -0400, Michael Bayer wrote:
 also we dont really have any direct support for python array types,  
 which seemed to be an element of your test.  can you try a basic func  
 test without an array type being used ?
 
 
 
 On Mar 27, 2007, at 10:58 AM, Julien Cigar wrote:
 
 
  The query is rather complicated: http://rafb.net/p/qyx3vA47.html
  The problem is at line 95 (the FIXME)
 
  Thanks
 
  Michael Bayer wrote:
  On Mar 27, 2007, at 10:00 AM, Julien Cigar wrote:
 
 
  Hello,
 
  I'm using SQLAlchemy 0.3.5, and it seems that the func() output is
  broken with some functions.
  I use the ANY function of PostgreSQL with something like :
  func.any(q.c.habitats)==filter_habitat
 
  SQLAlchemy translates this in:
  WHERE any(habitats) = %(any)s, which is incorrect.
 
 
 
  For example:
 
  the result should be :
  iasdev= select true as result where 'abc' = ANY(array['abc',  
  'def']);
   result
  
   t
 
  where SQLAlchemy generates the query as :
 
  iasdev= select true as result where ANY(array['abc', 'def']) =  
  'abc';
  ERROR:  syntax error at or near ANY at character 29
  LINE 1: select true as result where ANY(array['abc', 'def']) =
  'abc'...
 
  Is this a bug ? (or maybe it's possible to keep the order...) ?
 
 
  can i have some complete code examples please ?  i dont understand
  how your snippet would produce a full SELECT statement.  the phrase
  youve shown me translates exactly as specified, assuming
  filter_habitat is ia non ClauseElement::
 
 func.any(q.c.habitats)==filter_habitat
 
 should be:
 
 any(habitats) = %(any)s
 
 
 
 
 
 
 
 
  -- 
  Julien Cigar
  Belgian Biodiversity Platform
  http://www.biodiversity.be
  Universit� Libre de Bruxelles (ULB)
  Campus de la Plaine CP 257
  B�timent NO, Bureau 4 N4 115C (Niveau 4)
  Boulevard du Triomphe, entr�e ULB 2
  B-1050 Bruxelles
  office: [EMAIL PROTECTED]
  home: [EMAIL PROTECTED]
  biobel reference: http://biobel.biodiversity.be/biobel/person/show/471
 
 
  
 
 
  
-- 
Julien Cigar
Belgian Biodiversity Platform
http://www.biodiversity.be
Universit� Libre de Bruxelles
Campus de la Plaine CP 257
B�timent NO, Bureau 4 N4 115C (Niveau 4)
Boulevard du Triomphe, entr�e ULB 2
B-1050 Bruxelles
mail: [EMAIL PROTECTED]


--~--~-~--~~~---~--~~
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: func() bug ?

2007-03-28 Thread Michael Bayer

a few things here.

first of all, if its an operator, you probably want to use op():

literal('foo').op('ANY')('bar')

secondly, when you say x == ClauseElement, the __eq__() method in  
Python that gets called on the clauseelement has no reversed  
version.  so its impossible for the ClauseElement on the right to  
know that it should be on the left.

you can work around this similarly to the previous example, by making  
both sides a ClauseElement and saying:

literal('foo') == func.any('bar')

On Mar 28, 2007, at 10:42 AM, Julien Cigar wrote:


 Hello Mike,

 This simple test illustrate the problem :

 from sqlalchemy import func
 print 'foo' == func.any('bar')
 any(:any) = :a_1

 it should be :a_1 = any(:any)

 If you look at the PostgreSQL documentation,
 http://www.postgresql.org/docs/8.2/static/functions- 
 comparisons.html#AEN14105 the syntax is:
 expression operator ANY (array expression)

 and not :
 ANY (array expression) expression operator

 Note the ANY can also be used with subselect (so it's not specific to
 the PostgreSQL array type) :
 http://www.postgresql.org/docs/8.2/static/functions- 
 subquery.html#AEN13959

 expression operator ANY (subquery)

 and in this case it's also incorrect :

 print 'foo' == func.any(select)
 any(:any) = :a_1

 (again it should be :a_1 = any(:any))

 Regards,
 Julien

 On Tue, 2007-03-27 at 12:13 -0400, Michael Bayer wrote:
 also we dont really have any direct support for python array types,
 which seemed to be an element of your test.  can you try a basic func
 test without an array type being used ?



 On Mar 27, 2007, at 10:58 AM, Julien Cigar wrote:


 The query is rather complicated: http://rafb.net/p/qyx3vA47.html
 The problem is at line 95 (the FIXME)

 Thanks

 Michael Bayer wrote:
 On Mar 27, 2007, at 10:00 AM, Julien Cigar wrote:


 Hello,

 I'm using SQLAlchemy 0.3.5, and it seems that the func() output is
 broken with some functions.
 I use the ANY function of PostgreSQL with something like :
 func.any(q.c.habitats)==filter_habitat

 SQLAlchemy translates this in:
 WHERE any(habitats) = %(any)s, which is incorrect.



 For example:

 the result should be :
 iasdev= select true as result where 'abc' = ANY(array['abc',
 'def']);
  result
 
  t

 where SQLAlchemy generates the query as :

 iasdev= select true as result where ANY(array['abc', 'def']) =
 'abc';
 ERROR:  syntax error at or near ANY at character 29
 LINE 1: select true as result where ANY(array['abc', 'def']) =
 'abc'...

 Is this a bug ? (or maybe it's possible to keep the order...) ?


 can i have some complete code examples please ?  i dont understand
 how your snippet would produce a full SELECT statement.  the phrase
 youve shown me translates exactly as specified, assuming
 filter_habitat is ia non ClauseElement::

func.any(q.c.habitats)==filter_habitat

should be:

any(habitats) = %(any)s








 -- 
 Julien Cigar
 Belgian Biodiversity Platform
 http://www.biodiversity.be
 Universit� Libre de Bruxelles (ULB)
 Campus de la Plaine CP 257
 B�timent NO, Bureau 4 N4 115C (Niveau 4)
 Boulevard du Triomphe, entr�e ULB 2
 B-1050 Bruxelles
 office: [EMAIL PROTECTED]
 home: [EMAIL PROTECTED]
 biobel reference: http://biobel.biodiversity.be/biobel/person/ 
 show/471






 -- 
 Julien Cigar
 Belgian Biodiversity Platform
 http://www.biodiversity.be
 Universit� Libre de Bruxelles
 Campus de la Plaine CP 257
 B�timent NO, Bureau 4 N4 115C (Niveau 4)
 Boulevard du Triomphe, entr�e ULB 2
 B-1050 Bruxelles
 mail: [EMAIL PROTECTED]


 


--~--~-~--~~~---~--~~
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: [PATCH] Using entry points to load database dialects

2007-03-28 Thread Monty Taylor

Michael Bayer wrote:
 dialects can be used on their own without the engine being present  
 (such as, to generate SQL), also you can construct an engine passing  
 in your own module object which might have been procured from  
 somewhere else (or could be a mock object,for example).

Ok, yes indeed. Those are good reasons. :)


 On Mar 26, 2007, at 11:45 PM, Monty Taylor wrote:
 
 Always one in every bunch. :)

 I hear what you're saying about the import errors. But does it really
 help to allow work to get done before throwing the error? I would  
 think
 you'd want to know right up front if you don't have a driver loaded
 rather then letting a program actually get started up and think you  
 can
 write data (think fat client app) only to get a connection exception.

 But I, of course, could be very wrong about this. I am about many  
 things...

 Monty

 Michael Bayer wrote:
 yeah i dont like setup.py develop either :)but anyway,  patch is
 good.  one thing i have to nail down though is ticket #480.   the
 main point of that ticket is to cleanly isolate ImportErrors of
 actual DBAPI modules apart from the containing dialect module
 itself.   the dialects are catching all the DBAPI-related
 ImportErrors though so its not necessarily blocking this patch (its
 just they cant report them nicely).


 On Mar 26, 2007, at 1:34 PM, Monty Taylor wrote:

 Michael Bayer wrote:
 i think using entry points to load in external database dialects  
 is a
 great idea.

 though the current six core dialects i think i still want to  
 load via
 __import__ though since im a big fan of running SA straight out of
 the source directory (and therefore thered be no entry points for
 those in that case).

 so probably a check via __import__('sqlalchemy.databases') first,
 then an entry point lookup.  does that work ?
 Here is a patch that implements use of entry points to load  
 dialects.
 The largest change is actually adding a get_dialect to replace the
 functionality of get_module, since entry points really want to  
 return
 classes, and we only ever use the dialect class from the returned
 module
 anyway...

 This does not break code that I have that loads the mysql  
 dialect, and
 it does work with my new code that adds a new dialect - although I
 suppose it's possible it could have broken something I didn't find.

 As a side note, I agree with Gaetan - you can run entry points and
 stuff
 out of the current directory, especially if you use setup.py
 develop ...
 but this code does the entry points second, after a check for the
 module
 the old way.

 Monty


 === modified file 'lib/sqlalchemy/engine/strategies.py'
 --- lib/sqlalchemy/engine/strategies.py2007-02-25 22:44:52 +
 +++ lib/sqlalchemy/engine/strategies.py2007-03-26 17:03:13 +
 @@ -42,16 +42,16 @@
  u = url.make_url(name_or_url)

  # get module from sqlalchemy.databases
 -module = u.get_module()
 +dialect_cls = u.get_dialect()

  dialect_args = {}
  # consume dialect arguments from kwargs
 -for k in util.get_cls_kwargs(module.dialect):
 +for k in util.get_cls_kwargs(dialect_cls):
  if k in kwargs:
  dialect_args[k] = kwargs.pop(k)

  # create dialect
 -dialect = module.dialect(**dialect_args)
 +dialect = dialect_cls(**dialect_args)

  # assemble connection arguments
  (cargs, cparams) = dialect.create_connect_args(u)
 @@ -71,7 +71,7 @@
  raise exceptions.DBAPIError(Connection
 failed, e)
  creator = kwargs.pop('creator', connect)

 -poolclass = kwargs.pop('poolclass', getattr(module,
 'poolclass', poollib.QueuePool))
 +poolclass = kwargs.pop('poolclass', getattr
 (dialect_cls, 'poolclass', poollib.QueuePool))
  pool_args = {}
  # consume pool arguments from kwargs, translating a
 few of the arguments
  for k in util.get_cls_kwargs(poolclass):

 === modified file 'lib/sqlalchemy/engine/url.py'
 --- lib/sqlalchemy/engine/url.py   2007-03-18 22:35:19 +
 +++ lib/sqlalchemy/engine/url.py   2007-03-26 16:47:01 +
 @@ -2,6 +2,7 @@
  import cgi
  import sys
  import urllib
 +import pkg_resources
  from sqlalchemy import exceptions

  Provide the URL object as well as the make_url parsing
 function.
 @@ -69,6 +70,23 @@
  s += '?' + .join([%s=%s % (k, self.query[k]) for
 k in keys])
  return s

 +def get_dialect(self):
 +Return the SQLAlchemy database dialect class
 corresponding to this URL's driver name.
 +dialect=None
 +try:
 +  module=getattr(__import__('sqlalchemy.databases.%s' %
 self.drivername).databases, self.drivername)
 +  dialect=module.dialect
 +except ImportError:
 +if sys.exc_info()[2].tb_next is None:
 +  for res in pkg_resources.iter_entry_points
 ('sqlalchemy.databases'):
 +if 

[sqlalchemy] Re: mssql using pymssql 0.8 and sqlalchemy 0.3.6

2007-03-28 Thread Lee Connell

the table I'm trying to grab is under 30 chars.  Is there a way to
change this limit?

On Mar 28, 12:23 pm, Rick Morrison [EMAIL PROTECTED] wrote:
 Pymssql uses DBlib under the covers, and
 there's a 30-character identifier limit in DBlib.

 That limit applies to any identifier, including table and column names,
 which might explain your second issue.

 Rick

 On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:



  I am using these tools on a windows machine.  Some problems I ran
  into.

  First of all I can't connect to a database that's name is more than 30
  chars long.  Error returned says it can't find the database and the
  database it's looking for has been truncated.

  When I connect to a database less than 30 chars long, I try to load a
  table and it complains that it cannot find the table.  The table is
  definitely there and I've tried many different table names as well
  that are available in the DB. Anyone know of a fix or is this a bug?

  ### Here is my code. #

  from sqlalchemy import *

  db_name = this_is_a_test_of_a_long_database_string
  db_user = lee
  db_pass = 
  db_conn = mssql://%s:[EMAIL PROTECTED]/%s % (db_user, db_pass,
  db_name)

  db = create_engine(db_conn, echo=True)
  metadata = BoundMetaData(db)

  users_table = Table(syscolumns, metadata, autoload=True)
  list(users_table.columns)[0].name

  # Ammonoosuc_Computer_Services_MSCRM
  # FilteredServiceAppointment


--~--~-~--~~~---~--~~
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: mssql using pymssql 0.8 and sqlalchemy 0.3.6

2007-03-28 Thread Lee Connell

There is a fix for column names, however I don't see anything to
overcome this issue if the database name is more than 30 chars?  Any
suggestions?

On Mar 28, 12:44 pm, Lee Connell [EMAIL PROTECTED] wrote:
 the table I'm trying to grab is under 30 chars.  Is there a way to
 change this limit?

 On Mar 28, 12:23 pm, Rick Morrison [EMAIL PROTECTED] wrote:

  Pymssql uses DBlib under the covers, and
  there's a 30-character identifier limit in DBlib.

  That limit applies to any identifier, including table and column names,
  which might explain your second issue.

  Rick

  On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:

   I am using these tools on a windows machine.  Some problems I ran
   into.

   First of all I can't connect to a database that's name is more than 30
   chars long.  Error returned says it can't find the database and the
   database it's looking for has been truncated.

   When I connect to a database less than 30 chars long, I try to load a
   table and it complains that it cannot find the table.  The table is
   definitely there and I've tried many different table names as well
   that are available in the DB. Anyone know of a fix or is this a bug?

   ### Here is my code. #

   from sqlalchemy import *

   db_name = this_is_a_test_of_a_long_database_string
   db_user = lee
   db_pass = 
   db_conn = mssql://%s:[EMAIL PROTECTED]/%s % (db_user, db_pass,
   db_name)

   db = create_engine(db_conn, echo=True)
   metadata = BoundMetaData(db)

   users_table = Table(syscolumns, metadata, autoload=True)
   list(users_table.columns)[0].name

   # Ammonoosuc_Computer_Services_MSCRM
   # FilteredServiceAppointment


--~--~-~--~~~---~--~~
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: Confused by foreign_keys argument

2007-03-28 Thread King Simon-NFHD78
That compiles and appears to run in the small test program attached, but
if you look at the query generated when accessing the 'cs' property, it
doesn't actually use the join condition:
 
SELECT c.id AS c_id, c.name AS c_name
FROM c, a_b, b_c
WHERE ? = a_b.a_id AND b_c.c_id = c.id ORDER BY a_b.oid
 
ie. the a_b.b_id = b_c.b_id clause is missing.
 
If you aren't keen on the 'viewonly' pattern, how would you recommend
doing this? Just by adding a normal python property and doing a query?
The main reason I like setting it up as a relation is for the potential
of making it eager-loading just by changing a single flag.
 
Thanks,
 
Simon



From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED]
On Behalf Of Michael Bayer
Sent: 28 March 2007 17:19
To: sqlalchemy@googlegroups.com
Subject: [sqlalchemy] Re: Confused by foreign_keys argument


what it cant locate are foreign keys between the parent and child
tables, a and cbecause there arent any.  when you have a
many-to-many, the rules for figuring out the relationship change, and it
knows to do that by the presence of the secondary argument. 

so if you can manufacture a secondary table you can do this:

secondary = a_b_table.join(b_c_table,
onclause=a_b_table.c.b_id==b_c_table.c.b_id)
mapper(
  A, a_table,
  properties={'cs': relation(C, secondary=secondary,
primaryjoin=a_table.c.id==secondary.c.a_b_a_id,
secondaryjoin=secondary.c.b_c_c_id==c_table.c.id,
 viewonly=True,
)
 }
   )

im not totally sure the lazy clause is going to work but try it out.

this goes back to my general dislike of viewonly and how i cant
generally support it, becuase as the rules for relationships get more
strict and accurate, cases like these become harder to model.



On Mar 28, 2007, at 10:39 AM, King Simon-NFHD78 wrote:


a_table = Table('a', metadata, 

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

Column('name', String(16)),

)




b_table = Table('b', metadata,

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

Column('name', String(16)),

)




c_table = Table('c', metadata,

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

Column('name', String(16)),

)




a_b_table = Table('a_b', metadata,

  Column('a_id', Integer, ForeignKey('a.id'),

 primary_key=True),

  Column('b_id', Integer, ForeignKey('b.id'),

 primary_key=True),

  )

b_c_table = Table('b_c', metadata,

  Column('b_id', Integer, ForeignKey('b.id'),

 primary_key=True),

  Column('c_id', Integer, ForeignKey('c.id'),

 primary_key=True)

  )




class A(object):

pass




class B(object):

pass




class C(object):

pass




mapper(B, b_table)

mapper(C, c_table)




#

# How can I create a mapper on A with a property that gives

# all the 'C' objects?

#

# This doesn't work - it requires the foreign_keys parameter

# to be passed, but I don't know what to pass.

mapper(

  A, a_table,

  properties={'cs': relation(primaryjoin=and_(a_table.c.id ==

a_b_table.c.a_id,

  a_b_table.c.b_id
==

b_c_table.c.b_id,

  c_table.c.id ==

b_c_table.c.c_id),

 viewonly=True,

 )

 }

   )






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



join2.py
Description: join2.py


[sqlalchemy] Re: UOW relation delete bug

2007-03-28 Thread Michael Bayer



On Mar 28, 1:15 pm, Rick Morrison [EMAIL PROTECTED] wrote:
 Hey Mike, this looks to be related to the parameters-as-ClauseParameters
 instead of Python dict() on a different thread.

you mean the thing i just checked in yesterday ?  OK yeah, youve
always been getting a ClauseParameters object, its just it subclassed
dict.  I removed that becuase the API of ClauseParameters was
getting totally muddy and i didnt even understand how it worked
anymore.  so now its more explicit fields with their behaviors more
clearly separated.  but it still has a __getitem__ and a __contains__
on it and we can put keys() there as well, so what more dictlike
behavior do you need ?


 I'm going to need some help or advice beating the MSSQL module into shape
 with the new convention. Where does the positional / non-positional
 specification go? I don't see it in any of the DB modules.

we are usually calling paramstyle off the DBAPI itself to figure
that out.  that might have to change soon when I address the
ImportError ticket.


--~--~-~--~~~---~--~~
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: UOW relation delete bug

2007-03-28 Thread Rick Morrison
Hey Mike, this looks to be related to the parameters-as-ClauseParameters
instead of Python dict() on a different thread.

I'm going to need some help or advice beating the MSSQL module into shape
with the new convention. Where does the positional / non-positional
specification go? I don't see it in any of the DB modules.

Looks like pymssql wants positional -style parameters, anyone know about
adbodbapi / pyodbc?.

Rick



On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:


 it works for me, the bind params are in sqlite:

 [[1], [3], [5]]

 in postgres:

 [{'id': 1}, {'id': 3}, {'id': 5}]

 in both cases, thats a list of three sets of bind params, one
 positional and the other named, which correspond to executemany().
 if this condition doesnt work with MS-SQL,  MS-SQL should get added
 to test/engine/execute.py, which test the various scenarios of
 *multiparams and **params that you can send to execute().  just pick
 the paramstyle that works with MS-SQL and add it to the supported
 list for that test.

 On Mar 28, 2007, at 1:36 AM, Rick Morrison wrote:

  Surprised no one has hit this one yet.
 
  When issuing a series of deletes in a UOW, SA issues the bogus
  delete statement
 
  DELETE child where id = [1,2,3]
 
  instead of using IN()
 
  Test case attached. Seems to work in Sqlite even while issuing the
  bogus SQL (which is probably why a unit test didn't pick it up),
  but MS-SQL doesn't like it; didn't check PG or others.
 
 
  
  from sqlalchemy import *
  import logging
 
  logging.basicConfig()
  logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
 
  #metadata = BoundMetaData('mssql://d:[EMAIL PROTECTED]/drvtest')
  metadata = BoundMetaData('sqlite:///:memory:')
 
  entity = Table('entity', metadata,
  Column('id',  INT,  primary_key=True, nullable=False),
  Column('typ', VARCHAR(12)),
  Column('lname',   VARCHAR(128))
  )
 
  entityattr = Table('entityattr', metadata,
Column('id',  INT,  primary_key=True,
  nullable=False),
Column('ident',   INT, ForeignKey('entity.id'),
  nullable=False),
Column('typ', VARCHAR(12), nullable=False),
Column('val', VARCHAR(128))
)
 
  metadata.create_all()
 
  class O(object):
  def __init__(self,**kw):
  for k,v in kw.items():
  setattr(self,k,v)
 
  class Ent(O): pass
  class Entattr(O): pass
 
  mapper(Ent, entity, properties = {'props':relation(Entattr,
  cascade=all, delete-orphan)})
  mapper(Entattr, entityattr)
 
  S = create_session()
 
  S.save(Ent(typ='A',lname='A',
 props = [Entattr(typ='A1', val='1'),
  Entattr(typ='A2', val='2'),
  Entattr(typ='A3', val='3'),
  Entattr(typ='A4', val='4'),
  Entattr(typ='A5', val='5'),
  Entattr(typ='A6', val='6')
  ]))
  S.flush()
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
 
  # remove some attributes
  e.props = [p for p in e.props if 0 == int(p.val) % 2]
 
  # put some back
  e.props.append(Entattr(typ='A6', val='6'))
  e.props.append(Entattr(typ='A7', val='7'))
  e.props.append(Entattr(typ='A8', val='8'))
 
  S.flush()# -- Delete issued here
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
  assert 6 == len(e.props)
 
  metadata.drop_all()


 


--~--~-~--~~~---~--~~
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: sqlalchemy orm doesn't create an instance of certain rows

2007-03-28 Thread Michael Bayer
the issue is that the built-in relationship joining facilities dont  
know how to generate joins for self-referential relationships that  
you could then reference externally in your criterion.  while its  
easy enough for the join to add in an alias there, all subsequent  
operations on the query would need some way of identifying a  
criterion as applied to the original table or the aliased table.  so  
its an API issue.  I just added an error message that will be raised  
as of r2456.

so the explicit way to do it is this:

nodealias = nodeTable.alias('nodealias')
query.select_from(nodeTable.join(nodealias,  
onclause=nodealias.c.node_id==nodeTable.c.console_id)).select 
(nodealias.c.name=='console1..com')

we can perhaps add some helpers to join() such as :

query.join('consoleNodes', using=nodealias)

so that at least the onclause construction wouldnt be needed.

but we'd have to define things like this mean:

query.join(['a', 'b, 'c', 'd'], using=[alias1, alias2, alias3])


On Mar 28, 2007, at 12:42 PM, Karthik Krishnamurthy wrote:

 #!/usr/bin/env python

 from sqlalchemy import *

 metadata = BoundMetaData('sqlite:///', name='opsdb')
 metadata.engine.echo = True
 session = create_session()

 class Node(object):
 def __repr__(self):
 return %s %s % (self.__class__.__name__, self.name)

 nodeTable = Table(
 'node', metadata,
 Column('node_id', Integer, primary_key=True, unique=True),
 Column('name', String(255), unique=True),
 Column('console_id', Integer, ForeignKey('node.node_id')),
 Column('switch_id', Integer, ForeignKey('node.node_id')),
 )

 mapper (Node, nodeTable,
 properties = {
 'id': nodeTable.c.node_id,
 'console': relation(
 Node,
 primaryjoin = nodeTable.c.console_id ==  
 nodeTable.c.node_id,
 remote_side = [nodeTable.c.node_id],
 backref = 'consoleNodes',
 ),
 'switch': relation(
 Node,
 primaryjoin = nodeTable.c.switch_id ==  
 nodeTable.c.node_id,
 remote_side = [nodeTable.c.node_id],
 backref = 'switchNodes',
 ),
 },
 )

 rows = (
 { 'node_id': 1, 'name': 'console1..com', 'console_id':  
 None, 'switch_id': 2 },
 { 'node_id': 2, 'name': 'switch1..com', 'console_id': 1,  
 'switch_id': None },
 { 'node_id': 3, 'name': 'node1..com', 'console_id': 1,  
 'switch_id': 2 },
 { 'node_id': 4, 'name': 'node2..com', 'console_id': 1,  
 'switch_id': 2 },
 { 'node_id': 5, 'name': 'node3..com', 'console_id': 1,  
 'switch_id': 2 },
 { 'node_id': 6, 'name': 'node4..com', 'console_id': 1,  
 'switch_id': 2 },
 { 'node_id': 7, 'name': 'node5..com', 'console_id': 1,  
 'switch_id': 2 },
 )

 nodeTable.create()
 i = nodeTable.insert()
 for row in rows:
 print row
 i.execute(**row)

 # now query
 query = session.query(Node)
 console = query.select_by(name='console1..com')[0]
 print console.consoleNodes

 # Isn't this a valid use of select_by with the relation mapper above ?
 print query.select_by(console=console)

 # trying to get list of rows/Node instances where console_id =  
 console.node_id
 # given console node name, preferably in one step.
 # I need to chain such conditions depending on the argument.
 query.join('consoleNodes').select_by(name='console1..com')


--~--~-~--~~~---~--~~
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: mssql using pymssql 0.8 and sqlalchemy 0.3.6

2007-03-28 Thread Lee Connell

pyodbc seems to do the trick.  Thanks for the recommendation.  I am
having problem selecting from views in ms sql database, it returns 0
rows, using the same statement in enterprise manager returns a bunch
of rows.  Is there anything special I need to do for selecting data
from views?

On Mar 28, 1:01 pm, Rick Morrison [EMAIL PROTECTED] wrote:
 DBlib is deprecated by MS, and it hasn't been updated in like five years,
 and is just never going to be updated ever.

 If you can't change the name of the database, then I would take a look at
 replacing pymssql with pyodbc, I have heard of people having good luck with
 it (Paul, want to jump in here?)

 Rick

 On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:



  There is a fix for column names, however I don't see anything to
  overcome this issue if the database name is more than 30 chars?  Any
  suggestions?

  On Mar 28, 12:44 pm, Lee Connell [EMAIL PROTECTED] wrote:
   the table I'm trying to grab is under 30 chars.  Is there a way to
   change this limit?

   On Mar 28, 12:23 pm, Rick Morrison [EMAIL PROTECTED] wrote:

Pymssql uses DBlib under the covers, and
there's a 30-character identifier limit in DBlib.

That limit applies to any identifier, including table and column
  names,
which might explain your second issue.

Rick

On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:

 I am using these tools on a windows machine.  Some problems I ran
 into.

 First of all I can't connect to a database that's name is more than
  30
 chars long.  Error returned says it can't find the database and the
 database it's looking for has been truncated.

 When I connect to a database less than 30 chars long, I try to load
  a
 table and it complains that it cannot find the table.  The table is
 definitely there and I've tried many different table names as well
 that are available in the DB. Anyone know of a fix or is this a bug?

 ### Here is my code. #

 from sqlalchemy import *

 db_name = this_is_a_test_of_a_long_database_string
 db_user = lee
 db_pass = 
 db_conn = mssql://%s:[EMAIL PROTECTED]/%s % (db_user, db_pass,
 db_name)

 db = create_engine(db_conn, echo=True)
 metadata = BoundMetaData(db)

 users_table = Table(syscolumns, metadata, autoload=True)
 list(users_table.columns)[0].name

 # Ammonoosuc_Computer_Services_MSCRM
 # FilteredServiceAppointment


--~--~-~--~~~---~--~~
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: mssql using pymssql 0.8 and sqlalchemy 0.3.6

2007-03-28 Thread Rick Morrison
As far as I know a view is treated like a table in SA - if you're getting
the query to run at all, it's most likely that SA is issuing a different
query that what you thought it might.  Either use the SQL profiler in MSSQL
to see the actual SQL going over the wire, or turn on logging in SA to see
what queries are being issued. Odds are you're sending two different
queries.

On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:


 pyodbc seems to do the trick.  Thanks for the recommendation.  I am
 having problem selecting from views in ms sql database, it returns 0
 rows, using the same statement in enterprise manager returns a bunch
 of rows.  Is there anything special I need to do for selecting data
 from views?

 On Mar 28, 1:01 pm, Rick Morrison [EMAIL PROTECTED] wrote:
  DBlib is deprecated by MS, and it hasn't been updated in like five
 years,
  and is just never going to be updated ever.
 
  If you can't change the name of the database, then I would take a look
 at
  replacing pymssql with pyodbc, I have heard of people having good luck
 with
  it (Paul, want to jump in here?)
 
  Rick
 
  On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:
 
 
 
   There is a fix for column names, however I don't see anything to
   overcome this issue if the database name is more than 30 chars?  Any
   suggestions?
 
   On Mar 28, 12:44 pm, Lee Connell [EMAIL PROTECTED] wrote:
the table I'm trying to grab is under 30 chars.  Is there a way to
change this limit?
 
On Mar 28, 12:23 pm, Rick Morrison [EMAIL PROTECTED] wrote:
 
 Pymssql uses DBlib under the covers, and
 there's a 30-character identifier limit in DBlib.
 
 That limit applies to any identifier, including table and column
   names,
 which might explain your second issue.
 
 Rick
 
 On 3/28/07, Lee Connell [EMAIL PROTECTED] wrote:
 
  I am using these tools on a windows machine.  Some problems I
 ran
  into.
 
  First of all I can't connect to a database that's name is more
 than
   30
  chars long.  Error returned says it can't find the database and
 the
  database it's looking for has been truncated.
 
  When I connect to a database less than 30 chars long, I try to
 load
   a
  table and it complains that it cannot find the table.  The table
 is
  definitely there and I've tried many different table names as
 well
  that are available in the DB. Anyone know of a fix or is this a
 bug?
 
  ### Here is my code. #
 
  from sqlalchemy import *
 
  db_name = this_is_a_test_of_a_long_database_string
  db_user = lee
  db_pass = 
  db_conn = mssql://%s:[EMAIL PROTECTED]/%s % (db_user,
 db_pass,
  db_name)
 
  db = create_engine(db_conn, echo=True)
  metadata = BoundMetaData(db)
 
  users_table = Table(syscolumns, metadata, autoload=True)
  list(users_table.columns)[0].name
 
  # Ammonoosuc_Computer_Services_MSCRM
  # FilteredServiceAppointment


 


--~--~-~--~~~---~--~~
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: UOW relation delete bug

2007-03-28 Thread Michael Bayer
are you sure thats right ?  ClauseParameters doesnt have any kind of  
__getattr__ logic going oni think the test you have there would  
return False in all cases.  are you sure you dont mean:

self.IINSERT = tbl.has_sequence.key in parameters[0]

has_key() has been removed in favor of just __contains__() since  
thats where py2.6/3000 is headed.

On Mar 28, 2007, at 3:16 PM, Rick Morrison wrote:

 The MSSQL module examines the parameter object, looking for whether  
 or not the query being executed has an explicit primary key on an  
 autoincrementing column. Inserting those things in MSSQL is a  
 special mode (don't get me started on how goofy that is...).

 The code was using key in parmobject to look for it; I changed it  
 to hasattr(), and it seems fine. Thanks for the explanation.

 Rick


 On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:



 On Mar 28, 1:15 pm, Rick Morrison [EMAIL PROTECTED] wrote:
  Hey Mike, this looks to be related to the parameters-as- 
 ClauseParameters
  instead of Python dict() on a different thread.

 you mean the thing i just checked in yesterday ?  OK yeah, youve
 always been getting a ClauseParameters object, its just it subclassed
 dict.  I removed that becuase the API of ClauseParameters was
 getting totally muddy and i didnt even understand how it worked
 anymore.  so now its more explicit fields with their behaviors more
 clearly separated.  but it still has a __getitem__ and a __contains__
 on it and we can put keys() there as well, so what more dictlike
 behavior do you need ?

 
  I'm going to need some help or advice beating the MSSQL module  
 into shape
  with the new convention. Where does the positional / non-positional
  specification go? I don't see it in any of the DB modules.

 we are usually calling paramstyle off the DBAPI itself to figure
 that out.  that might have to change soon when I address the
 ImportError ticket.

 


--~--~-~--~~~---~--~~
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: UOW relation delete bug

2007-03-28 Thread Rick Morrison
Working now...

Anyway, wouldn't this operation be a lot more efficient using IN() instead
of executemany()? Is detecting that too hard?

Rick


On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:


 it works for me, the bind params are in sqlite:

 [[1], [3], [5]]

 in postgres:

 [{'id': 1}, {'id': 3}, {'id': 5}]

 in both cases, thats a list of three sets of bind params, one
 positional and the other named, which correspond to executemany().
 if this condition doesnt work with MS-SQL,  MS-SQL should get added
 to test/engine/execute.py, which test the various scenarios of
 *multiparams and **params that you can send to execute().  just pick
 the paramstyle that works with MS-SQL and add it to the supported
 list for that test.

 On Mar 28, 2007, at 1:36 AM, Rick Morrison wrote:

  Surprised no one has hit this one yet.
 
  When issuing a series of deletes in a UOW, SA issues the bogus
  delete statement
 
  DELETE child where id = [1,2,3]
 
  instead of using IN()
 
  Test case attached. Seems to work in Sqlite even while issuing the
  bogus SQL (which is probably why a unit test didn't pick it up),
  but MS-SQL doesn't like it; didn't check PG or others.
 
 
  
  from sqlalchemy import *
  import logging
 
  logging.basicConfig()
  logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
 
  #metadata = BoundMetaData('mssql://d:[EMAIL PROTECTED]/drvtest')
  metadata = BoundMetaData('sqlite:///:memory:')
 
  entity = Table('entity', metadata,
  Column('id',  INT,  primary_key=True, nullable=False),
  Column('typ', VARCHAR(12)),
  Column('lname',   VARCHAR(128))
  )
 
  entityattr = Table('entityattr', metadata,
Column('id',  INT,  primary_key=True,
  nullable=False),
Column('ident',   INT, ForeignKey('entity.id'),
  nullable=False),
Column('typ', VARCHAR(12), nullable=False),
Column('val', VARCHAR(128))
)
 
  metadata.create_all()
 
  class O(object):
  def __init__(self,**kw):
  for k,v in kw.items():
  setattr(self,k,v)
 
  class Ent(O): pass
  class Entattr(O): pass
 
  mapper(Ent, entity, properties = {'props':relation(Entattr,
  cascade=all, delete-orphan)})
  mapper(Entattr, entityattr)
 
  S = create_session()
 
  S.save(Ent(typ='A',lname='A',
 props = [Entattr(typ='A1', val='1'),
  Entattr(typ='A2', val='2'),
  Entattr(typ='A3', val='3'),
  Entattr(typ='A4', val='4'),
  Entattr(typ='A5', val='5'),
  Entattr(typ='A6', val='6')
  ]))
  S.flush()
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
 
  # remove some attributes
  e.props = [p for p in e.props if 0 == int(p.val) % 2]
 
  # put some back
  e.props.append(Entattr(typ='A6', val='6'))
  e.props.append(Entattr(typ='A7', val='7'))
  e.props.append(Entattr(typ='A8', val='8'))
 
  S.flush()# -- Delete issued here
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
  assert 6 == len(e.props)
 
  metadata.drop_all()


 


--~--~-~--~~~---~--~~
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: UOW relation delete bug

2007-03-28 Thread Michael Bayer
I doubt theres any performance difference if the DBAPI does the right  
thing with a prepared statement.  also, IN() wont work too well if  
the rows are targeted by more than just one column; plus it generally  
limits to 1000 elements and presents a larger and non-consistent  
string to the DB which has to re-parse it each time.


On Mar 28, 2007, at 4:44 PM, Rick Morrison wrote:

 Working now...

 Anyway, wouldn't this operation be a lot more efficient using IN()  
 instead of executemany()? Is detecting that too hard?

 Rick


 On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:

 it works for me, the bind params are in sqlite:

 [[1], [3], [5]]

 in postgres:

 [{'id': 1}, {'id': 3}, {'id': 5}]

 in both cases, thats a list of three sets of bind params, one
 positional and the other named, which correspond to executemany().
 if this condition doesnt work with MS-SQL,  MS-SQL should get added
 to test/engine/execute.py, which test the various scenarios of
 *multiparams and **params that you can send to execute().  just pick
 the paramstyle that works with MS-SQL and add it to the supported
 list for that test.

 On Mar 28, 2007, at 1:36 AM, Rick Morrison wrote:

  Surprised no one has hit this one yet.
 
  When issuing a series of deletes in a UOW, SA issues the bogus
  delete statement
 
  DELETE child where id = [1,2,3]
 
  instead of using IN()
 
  Test case attached. Seems to work in Sqlite even while issuing the
  bogus SQL (which is probably why a unit test didn't pick it up),
  but MS-SQL doesn't like it; didn't check PG or others.
 
 
  
  from sqlalchemy import *
  import logging
 
  logging.basicConfig()
  logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
 
  #metadata = BoundMetaData('mssql://d:[EMAIL PROTECTED]/drvtest')
  metadata = BoundMetaData('sqlite:///:memory:')
 
  entity = Table('entity', metadata,
  Column('id',  INT,  primary_key=True,  
 nullable=False),
  Column('typ', VARCHAR(12)),
  Column('lname',   VARCHAR(128))
  )
 
  entityattr = Table('entityattr', metadata,
Column('id',  INT,  primary_key=True,
  nullable=False),
Column('ident',   INT, ForeignKey(' entity.id'),
  nullable=False),
Column('typ', VARCHAR(12), nullable=False),
Column('val', VARCHAR(128))
)
 
  metadata.create_all()
 
  class O(object):
  def __init__(self,**kw):
  for k,v in kw.items():
  setattr(self,k,v)
 
  class Ent(O): pass
  class Entattr(O): pass
 
  mapper(Ent, entity, properties = {'props':relation(Entattr,
  cascade=all, delete-orphan)})
  mapper(Entattr, entityattr)
 
  S = create_session()
 
  S.save(Ent(typ='A',lname='A',
 props = [Entattr(typ='A1', val='1'),
  Entattr(typ='A2', val='2'),
  Entattr(typ='A3', val='3'),
  Entattr(typ='A4', val='4'),
  Entattr(typ='A5', val='5'),
  Entattr(typ='A6', val='6')
  ]))
  S.flush()
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
 
  # remove some attributes
  e.props = [p for p in e.props if 0 == int(p.val) % 2]
 
  # put some back
  e.props.append(Entattr(typ='A6', val='6'))
  e.props.append(Entattr(typ='A7', val='7'))
  e.props.append(Entattr(typ='A8', val='8'))
 
  S.flush()# -- Delete issued here
  S.clear()
 
  e = S.query(Ent).options(eagerload('props')).select()[0]
  assert 6 == len(e.props)
 
  metadata.drop_all ()

 


--~--~-~--~~~---~--~~
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: func() bug ?

2007-03-28 Thread Paul Johnston

Hi,

any(:any) = :a_1
it should be :a_1 = any(:any)
  

This looks like odd Postgres behaviour, the equals operator not quite 
being commutative.

We could add a Postgres-specifc workaround, in PGCompiler something like 
(untested):

def visit_binary(self, binary):
if isinstance(binary.left, sql._Function) and 
binary.left.name.lower() == 'any' and binary.operator == '=':
binary.left, binary.right = binary.right, binary.left
super(PGCompiler, self).visit_binary(binary)

The MSSQL dialect uses a similar trick to work around some adodbapi bugs.

Paul

--~--~-~--~~~---~--~~
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: Automatic generation of changelog

2007-03-28 Thread Michael Bayer

dont have an example handy, but yeah youd want to make a
MapperExtension and work into the after_insert(), after_update() and
after_delete() hooks (or maybe the before_ versions of each one,
depending on how you detect changes).  you can issue writes to the
database immediately within those and theyll be within the current
transaction.

theres an example of a write side MapperExtension in examples/pickle/
custom_pickler.py .

if you want some help on actually detecting whats changed, you can
use some features of the attributes package to do so.  if you have an
instance of MyClass and want to inspect the history of
instance.someattribute:

history = MyClass.someattribute.get_history(instance, passive=True)

passive=True means dont fire off lazy loaders.  that call returns
to you an AttributeHistory object, with which you can say:

history.is_modified()
history.added_items() - returns a list of new values, a one-element
list for scalar attributes
history.deleted_items() - returns a list of deleted values, a one -
element list for scalar attributes
history.unchanged_items() - etc

note that by history, we mean things that have occured since the
instance was loaded from the database into the current session.

On Mar 28, 5:39 pm, Arnar Birgisson [EMAIL PROTECTED] wrote:
 Hi there,

 I have an old system that I'm porting over to SA. In the old system
 there is one entity that keeps a change history of itself. In the code
 that performs db updates, the current state of the object is examined
 and before it is updated I insert rows to a table with colums like
 this:

 object id
 change-event-id
 fieldname
 old-value
 new-value

 This is used to render a change history of the entity to the user.

 Now, can I automate this somehow with SA? Preferably I'd like to do
 this automatically on object update. Can I use the dirty set in the
 session to find out what columns of the mapped table have changed?

 How do I hook into the update action - I think I need a mapper
 extension, but can you point me to some examples?

 Has anyone done something similar (the whole changelog thing) with SA?

 Arnar


--~--~-~--~~~---~--~~
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: Automatic generation of changelog

2007-03-28 Thread Arnar Birgisson

Hi Dave,

Thank you very much, seems I should be able to do what I want. I'll
take a stab at it tomorrow and report.

On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:
 note that by history, we mean things that have occured since the
 instance was loaded from the database into the current session.

That history is cleared on session.flush() - right?

Arnar

--~--~-~--~~~---~--~~
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: [PATCH] Using entry points to load database dialects

2007-03-28 Thread Michael Bayer

ok anyway, im behind on patches (which i like to test and stuff) so
ive added ticket 521 to my in queue list.

if youd like to add a short unit test script that would be handy
(otherwise we might not have test coverage for the setuptools portion
of the feature).

On Mar 28, 12:26 pm, Monty Taylor [EMAIL PROTECTED] wrote:
 Michael Bayer wrote:
  dialects can be used on their own without the engine being present
  (such as, to generate SQL), also you can construct an engine passing
  in your own module object which might have been procured from
  somewhere else (or could be a mock object,for example).

 Ok, yes indeed. Those are good reasons. :)

  On Mar 26, 2007, at 11:45 PM, Monty Taylor wrote:

  Always one in every bunch. :)

  I hear what you're saying about the import errors. But does it really
  help to allow work to get done before throwing the error? I would
  think
  you'd want to know right up front if you don't have a driver loaded
  rather then letting a program actually get started up and think you
  can
  write data (think fat client app) only to get a connection exception.

  But I, of course, could be very wrong about this. I am about many
  things...

  Monty

  Michael Bayer wrote:
  yeah i dont like setup.py develop either :)but anyway,  patch is
  good.  one thing i have to nail down though is ticket #480.   the
  main point of that ticket is to cleanly isolate ImportErrors of
  actual DBAPI modules apart from the containing dialect module
  itself.   the dialects are catching all the DBAPI-related
  ImportErrors though so its not necessarily blocking this patch (its
  just they cant report them nicely).

  On Mar 26, 2007, at 1:34 PM, Monty Taylor wrote:

  Michael Bayer wrote:
  i think using entry points to load in external database dialects
  is a
  great idea.

  though the current six core dialects i think i still want to
  load via
  __import__ though since im a big fan of running SA straight out of
  the source directory (and therefore thered be no entry points for
  those in that case).

  so probably a check via __import__('sqlalchemy.databases') first,
  then an entry point lookup.  does that work ?
  Here is a patch that implements use of entry points to load
  dialects.
  The largest change is actually adding a get_dialect to replace the
  functionality of get_module, since entry points really want to
  return
  classes, and we only ever use the dialect class from the returned
  module
  anyway...

  This does not break code that I have that loads the mysql
  dialect, and
  it does work with my new code that adds a new dialect - although I
  suppose it's possible it could have broken something I didn't find.

  As a side note, I agree with Gaetan - you can run entry points and
  stuff
  out of the current directory, especially if you use setup.py
  develop ...
  but this code does the entry points second, after a check for the
  module
  the old way.

  Monty

  === modified file 'lib/sqlalchemy/engine/strategies.py'
  --- lib/sqlalchemy/engine/strategies.py2007-02-25 22:44:52 +
  +++ lib/sqlalchemy/engine/strategies.py2007-03-26 17:03:13 +
  @@ -42,16 +42,16 @@
   u = url.make_url(name_or_url)

   # get module from sqlalchemy.databases
  -module = u.get_module()
  +dialect_cls = u.get_dialect()

   dialect_args = {}
   # consume dialect arguments from kwargs
  -for k in util.get_cls_kwargs(module.dialect):
  +for k in util.get_cls_kwargs(dialect_cls):
   if k in kwargs:
   dialect_args[k] = kwargs.pop(k)

   # create dialect
  -dialect = module.dialect(**dialect_args)
  +dialect = dialect_cls(**dialect_args)

   # assemble connection arguments
   (cargs, cparams) = dialect.create_connect_args(u)
  @@ -71,7 +71,7 @@
   raise exceptions.DBAPIError(Connection
  failed, e)
   creator = kwargs.pop('creator', connect)

  -poolclass = kwargs.pop('poolclass', getattr(module,
  'poolclass', poollib.QueuePool))
  +poolclass = kwargs.pop('poolclass', getattr
  (dialect_cls, 'poolclass', poollib.QueuePool))
   pool_args = {}
   # consume pool arguments from kwargs, translating a
  few of the arguments
   for k in util.get_cls_kwargs(poolclass):

  === modified file 'lib/sqlalchemy/engine/url.py'
  --- lib/sqlalchemy/engine/url.py   2007-03-18 22:35:19 +
  +++ lib/sqlalchemy/engine/url.py   2007-03-26 16:47:01 +
  @@ -2,6 +2,7 @@
   import cgi
   import sys
   import urllib
  +import pkg_resources
   from sqlalchemy import exceptions

   Provide the URL object as well as the make_url parsing
  function.
  @@ -69,6 +70,23 @@
   s += '?' + .join([%s=%s % (k, self.query[k]) for
  k in keys])
   return s

  +def get_dialect(self):
  +Return the SQLAlchemy database dialect class
  corresponding 

[sqlalchemy] Re: UOW relation delete bug

2007-03-28 Thread Rick Morrison
yikes, you're right - fixed in rev 2458. thanks for having a look.


On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:

 are you sure thats right ?  ClauseParameters doesnt have any kind of
 __getattr__ logic going oni think the test you have there would return
 False in all cases.  are you sure you dont mean:
 self.IINSERT = tbl.has_sequence.key in parameters[0]
 has_key() has been removed in favor of just __contains__() since thats
 where py2.6/3000 is headed.

 On Mar 28, 2007, at 3:16 PM, Rick Morrison wrote:

 The MSSQL module examines the parameter object, looking for whether or not
 the query being executed has an explicit primary key on an autoincrementing
 column. Inserting those things in MSSQL is a special mode (don't get me
 started on how goofy that is...).

 The code was using key in parmobject to look for it; I changed it to
 hasattr(), and it seems fine. Thanks for the explanation.

 Rick


 On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:
 
 
 
 
  On Mar 28, 1:15 pm, Rick Morrison [EMAIL PROTECTED] wrote:
   Hey Mike, this looks to be related to the
  parameters-as-ClauseParameters
   instead of Python dict() on a different thread.
 
  you mean the thing i just checked in yesterday ?  OK yeah, youve
  always been getting a ClauseParameters object, its just it subclassed
  dict.  I removed that becuase the API of ClauseParameters was
  getting totally muddy and i didnt even understand how it worked
  anymore.  so now its more explicit fields with their behaviors more
  clearly separated.  but it still has a __getitem__ and a __contains__
  on it and we can put keys() there as well, so what more dictlike
  behavior do you need ?
 
  
   I'm going to need some help or advice beating the MSSQL module into
  shape
   with the new convention. Where does the positional / non-positional
   specification go? I don't see it in any of the DB modules.
 
  we are usually calling paramstyle off the DBAPI itself to figure
  that out.  that might have to change soon when I address the
  ImportError ticket.
 
 
 
 

 


--~--~-~--~~~---~--~~
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: Automatic generation of changelog

2007-03-28 Thread Michael Bayer


On Mar 28, 2007, at 6:07 PM, Arnar Birgisson wrote:


 Hi Dave,

 Thank you very much, seems I should be able to do what I want. I'll
 take a stab at it tomorrow and report.

 On 3/28/07, Michael Bayer [EMAIL PROTECTED] wrote:
 note that by history, we mean things that have occured since the
 instance was loaded from the database into the current session.

 That history is cleared on session.flush() - right?


yes




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