[sqlalchemy] Inconsistent results in session.flush()

2007-03-16 Thread King Simon-NFHD78

Hi,

I'm having a problem where the results of session.flush() vary from one
run to another of my test suite. The unit of work transaction dump is
significantly different from one run to the next, similar to the issue
in ticket 461. I haven't managed to make a test case small enough to
post to the list yet, and I think I need to delve a little further into
the code to find out why it's failing.

(This is with both 0.3.5 and rev2416)

The logs from the UOWTransaction on a failing run and a passing run are
below. As well as the ordering being different, there is at least one
class (ReleaseLine) that doesn't appear in the bad run.

Unfortunately I don't know how to go about debugging this. I think I
need to see exactly what is going on in the dependency sort. Do you have
any suggestions for suitable places to add some extra logging?

This is a failing run:
INFO:sqlalchemy.orm.unitofwork.UOWTransaction.0x..30:Task dump:

 UOWTask(0x184b2b0, Component/component/None) (save/update phase)
   |
   |- UOWTask(0x184bb50, User/user/None) (save/update phase)
   |   |- Save User(0x1851870)
   |   |   |- Process User(0x1851870).branches
   |   |   |- Process User(0x1851870).reviews
   |   |   |- Process User(0x1851870).labels
   |   |   |- Process Branch(0x17ee310).user
   |   |   |- Process Branch(0x184b190).user
   |   |
   |   |- UOWTask(0x184bb70, ChangeOrigin/change_origin/None)
(save/update phase)
   |   |   |   |- Process Branch(0x17ee310).change_origin
   |   |   |   |- Process Branch(0x184b190).change_origin
   |   |   |
   |   |   |- UOWTask(0x184b590, Label/label/None) (save/update phase)
   |   |   |   |
   |   |   |   |- UOWTask(0x184b1b0, Branch/branch/None) (save/update
phase)
   |   |   |   |   |- Save Branch(0x17ee310)
   |   |   |   |   |- Save Branch(0x184b190)
   |   |   |   |   |   |- Process Branch(0x17ee310).review
   |   |   |   |   |   |- Process Branch(0x184b190).review
   |   |   |   |   |
   |   |   |   |   |- UOWTask(0x183f470, Review/review/None)
(save/update phase)

   |   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |- UOWTask(0x184bb30,
sqlalchemy.orm.dependency.MapperStub object at 0x0183FDF0)
(save/update phase)
   |   |   |   |   |   |   |- Process Branch(0x17ee310).label
   |   |   |   |   |   |   |- Process Branch(0x184b190).label
   |   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |
   |   |   |   |
   |   |   |   |- UOWTask(0x184bfb0, Counter/counter/None) (save/update
phase)
   |   |   |   |   |- Save Counter(0x184b0f0)
   |   |   |   |   |
   |   |   |   |
   |   |   |   |
   |   |   |
   |   |   |
   |   |
   |   |
   |
   |
   |- UOWTask(0x184bb50, User/user/None) (delete phase)
   |   |
   |   |- UOWTask(0x184bb70, ChangeOrigin/change_origin/None) (delete
phase)
   |   |   |
   |   |   |- UOWTask(0x184b590, Label/label/None) (delete phase)
   |   |   |   |
   |   |   |   |- UOWTask(0x184b1b0, Branch/branch/None) (delete phase)
   |   |   |   |   |
   |   |   |   |   |- UOWTask(0x183f470, Review/review/None) (delete
phase)
   |   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |- UOWTask(0x184bb30,
sqlalchemy.orm.dependency.MapperStub object at 0x0183FDF0) (delete
phase)
   |   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |   |
   |   |   |   |
   |   |   |   |
   |   |   |   |- UOWTask(0x184bfb0, Counter/counter/None) (delete
phase)
   |   |   |   |   |
   |   |   |   |
   |   |   |   |
   |   |   |
   |   |   |
   |   |
   |   |
   |
   |

And on a good run looks like this:

INFO:sqlalchemy.orm.unitofwork.UOWTransaction.0x..f0:Task dump:

 UOWTask(0x17f2610, User/user/None) (save/update phase)
   |- Save User(0x17fe9f0)
   |   |- Process User(0x17fe9f0).labels
   |   |- Process Branch(0x17caa10).user
   |   |- Process Branch(0x17f2470).user
   |   |- Process User(0x17fe9f0).reviews
   |   |- Process User(0x17fe9f0).branches
   |
   |- UOWTask(0x17f2a50, ChangeOrigin/change_origin/None) (save/update
phase)
   |   |   |- Process Branch(0x17caa10).change_origin
   |   |   |- Process Branch(0x17f2470).change_origin
   |   |
   |   |- UOWTask(0x17f29f0, Component/component/None) (save/update
phase)
   |   |   |
   |   |   |- UOWTask(0x17f2ad0, ReleaseLine/release_line/None)
(save/update phase)
   |   |   |   |   |- Process Branch(0x17caa10).release_line
   |   |   |   |   |- Process Branch(0x17f2470).release_line
   |   |   |   |   |- Process Counter(0x17fed10).release_line
   |   |   |   |
   |   |   |   |- UOWTask(0x17f2430, Counter/counter/None) (save/update
phase)
   |   |   |   |   |- Save Counter(0x17fed10)
   |   |   |   |   |
   |   |   |   |
   |   |   |   |
   |   |   |   |- UOWTask(0x17f2450, Branch/branch/None) (save/update
phase)
   |   |   |   |   |- Save Branch(0x17caa10)
   |   |   |   |   |- Save Branch(0x17f2470)
   |   |   |   |   |   |- Process Branch(0x17caa10).review
   |   |   |   |   |   

[sqlalchemy] Re: Inconsistent results in session.flush()

2007-03-16 Thread King Simon-NFHD78
I've just run the attached script about thirty times, and it succeeded 5
times and failed the rest. I've cut out a lot of unnecessary stuff, but
it's still a bit long I'm afraid. I'll cut it down some more, but since
you seemed so eager to see it ;-) I thought I'd send it along as is.

On a bad run, the dependency tuples look like this:

DEBUG:sqlalchemy.orm.unitofwork.UOWTransaction.0x..50:Dependency sort:
Mapper|User|user
  Mapper|Component|component
Mapper|ChangeOrigin|change_origin
  Mapper|Label|label (cycles: [Mapper|Label|label,
Mapper|ReleaseLine|release_line])
Mapper|Counter|counter
Mapper|Branch|branch
  sqlalchemy.orm.dependency.MapperStub object at 0x00D59590

And on a good run they look like this:

DEBUG:sqlalchemy.orm.unitofwork.UOWTransaction.0x..10:Dependency sort:
Mapper|User|user
  Mapper|Component|component
Mapper|ChangeOrigin|change_origin
  Mapper|ReleaseLine|release_line (cycles:
[Mapper|ReleaseLine|release_line,  Mapper|Label|label])
Mapper|Counter|counter
Mapper|Branch|branch
  sqlalchemy.orm.dependency.MapperStub object at 0x00D59670

Thanks a lot for looking at this,

Simon

Michael Bayer wrote:
 
 I can actually read a fair degree from these dumps, i need 
 mostly to know what the actual dependencies are (i.e. which 
 classes are dependent on what, whats the error).  also when 
 you do the full debug echoing the UOW should illustrate a 
 series of dependency tuples  
 which will show what pairs of classes the UOW perceives as 
 dependent on each other.
 
 On Mar 16, 2007, at 6:59 AM, King Simon-NFHD78 wrote:
 
 
  Hi,
 
  I'm having a problem where the results of session.flush() vary from 
  one run to another of my test suite. The unit of work 
 transaction dump 
  is significantly different from one run to the next, similar to the 
  issue in ticket 461. I haven't managed to make a test case small 
  enough to post to the list yet, and I think I need to delve 
 a little 
  further into the code to find out why it's failing.
 
  (This is with both 0.3.5 and rev2416)
 
  The logs from the UOWTransaction on a failing run and a passing run 
  are below. As well as the ordering being different, there 
 is at least 
  one class (ReleaseLine) that doesn't appear in the bad run.
 
  Unfortunately I don't know how to go about debugging this. 
 I think I 
  need to see exactly what is going on in the dependency sort. Do you 
  have any suggestions for suitable places to add some extra logging?
 
  This is a failing run:
  INFO:sqlalchemy.orm.unitofwork.UOWTransaction.0x..30:Task dump:
 
   UOWTask(0x184b2b0, Component/component/None) (save/update phase)
 |
 |- UOWTask(0x184bb50, User/user/None) (save/update phase)
 |   |- Save User(0x1851870)
 |   |   |- Process User(0x1851870).branches
 |   |   |- Process User(0x1851870).reviews
 |   |   |- Process User(0x1851870).labels
 |   |   |- Process Branch(0x17ee310).user
 |   |   |- Process Branch(0x184b190).user
 |   |
 |   |- UOWTask(0x184bb70, ChangeOrigin/change_origin/None)
  (save/update phase)
 |   |   |   |- Process Branch(0x17ee310).change_origin
 |   |   |   |- Process Branch(0x184b190).change_origin
 |   |   |
 |   |   |- UOWTask(0x184b590, Label/label/None) 
 (save/update phase)
 |   |   |   |
 |   |   |   |- UOWTask(0x184b1b0, Branch/branch/None) 
 (save/update
  phase)
 |   |   |   |   |- Save Branch(0x17ee310)
 |   |   |   |   |- Save Branch(0x184b190)
 |   |   |   |   |   |- Process Branch(0x17ee310).review
 |   |   |   |   |   |- Process Branch(0x184b190).review
 |   |   |   |   |
 |   |   |   |   |- UOWTask(0x183f470, Review/review/None)
  (save/update phase)
 
 |   |   |   |   |   |
 |   |   |   |   |
 |   |   |   |   |
 |   |   |   |   |- UOWTask(0x184bb30,
  sqlalchemy.orm.dependency.MapperStub object at 0x0183FDF0) 
  (save/update phase)
 |   |   |   |   |   |   |- Process Branch(0x17ee310).label
 |   |   |   |   |   |   |- Process Branch(0x184b190).label
 |   |   |   |   |   |
 |   |   |   |   |
 |   |   |   |   |
 |   |   |   |
 |   |   |   |
 |   |   |   |- UOWTask(0x184bfb0, Counter/counter/None) (save/ 
  update
  phase)
 |   |   |   |   |- Save Counter(0x184b0f0)
 |   |   |   |   |
 |   |   |   |
 |   |   |   |
 |   |   |
 |   |   |
 |   |
 |   |
 |
 |
 |- UOWTask(0x184bb50, User/user/None) (delete phase)
 |   |
 |   |- UOWTask(0x184bb70, 
 ChangeOrigin/change_origin/None) (delete
  phase)
 |   |   |
 |   |   |- UOWTask(0x184b590, Label/label/None) (delete phase)
 |   |   |   |
 |   |   |   |- UOWTask(0x184b1b0, Branch/branch/None) (delete  
  phase)
 |   |   |   |   |
 |   |   |   |   |- UOWTask(0x183f470, Review/review/None) (delete
  phase

[sqlalchemy] Re: table name bind param

2007-03-15 Thread King Simon-NFHD78

tml wrote:
 
 also to clarify, the text actually has :table_name used in many other
 places:
 
 t = metadata.engine.text(LOCK TABLE :table_name WRITE; 
UPDATE :table_name SET rgt=rgt + 
 2 WHERE rgt  :insert_node_val and parent_id = :parent_id;
UPDATE :table_name SET lft=lft + 
 2 WHERE lft  :insert_node_val and parent_id = :parent_id;
..
 
 so if i had it as %s, i would have to repeat the same name 
 multiple times in % (name, name, name). I'm ok with this, 
 just curious if there is a better way.
 

I don't think bind parameters can be used for table names, so you are
stuck with python format strings, but you can use a dictionary instead
of a tuple when formatting strings. Instead of using %s, you use
%(name)s, and instead of the tuple (name, name, name) you pass a single
dictionary {'name': your_table_name}

http://docs.python.org/lib/typesseq-strings.html

Hope that helps,

Simon

--~--~-~--~~~---~--~~
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: Polymorphic collections / ticket #500

2007-03-06 Thread King Simon-NFHD78
I wanted to do something like this in the past, and in the end, rather
than using polymorphic mappers it made more sense to create a
MapperExtension which overrides create_instance. In create_instance you
can examine your 'typ' column to decide what class to create, selecting
one of your Manager/Demigod classes if necessary, or falling back to the
Person class otherwise.
 
Hope that helps,
 
Simon




From: sqlalchemy@googlegroups.com
[mailto:[EMAIL PROTECTED] On Behalf Of Rick Morrison
Sent: 06 March 2007 01:12
To: sqlalchemy
Subject: [sqlalchemy] Polymorphic collections / ticket #500


The fix for ticket #500 breaks a pattern I've been using.

It's most likely an anti-pattern, but I don't see a way to get
what I want in SA otherwise.

I've got a series of entities

class Person():
   pass

class Manager(Person):
   def __init__(self):
   # do manager stuff

class Demigod(Person):
   def __init__(self):
   # do demigod stuff

etc.

there are mappers for each of these entities that inherit from
Person(), so all of the normal Person() properties exist, but Person()
itself is not polymorphic. That's on purpose, and because the class
hierarchy of Manager(), etc, is not exhaustive, and I occasionally  want
to save instances of Person() directly.  
If I make the Person() class polymorphic on a column of say
typ, then SA clears whatever typ I may have tried to set directly,
and seems to make me specify an exhaustive list of sub-types. 

And so I leave Person() as non-polymorphic. I also have a
collection of Person() objects on a different mapper, which can load
entity objects of any type. 

Before rev #2382, I could put a Manager() in a Person()
collection, and  it would flush OK. Now it bitches that it wants a real
polymorphic mapper. I don't want to use a polymorphic mapper, because I
don't want to specify an exhaustive list of every class that I'm ever
going to use. 

What to do?

Thanks,
Rick





--~--~-~--~~~---~--~~
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] Table being removed from nested query

2007-03-06 Thread King Simon-NFHD78
Hi,

I have a problem in which a table is being removed from the FROM clause
of a nested query. The attached file should show the problem, which I've
tested on 0.3.5 and rev 2383.

In the example, there are two tables, department and employee, such that
one department has many employees. The inner query joins the two tables
and returns department IDs:

  inner = select([departments.c.department_id],
 employees.c.department_id ==
departments.c.department_id)
  inner = inner.alias('filtered_departments')

The SQL looks like:

 SELECT departments.department_id
 FROM departments, employees
 WHERE employees.department_id = departments.department_id

I then join this query back to the department table:

 join = inner.join(departments,
 
onclause=inner.c.department_id==departments.c.department_id)

SQL for the join condition looks like:

 (SELECT departments.department_id
  FROM departments, employees
  WHERE employees.department_id = departments.department_id)
  AS filtered_departments
  JOIN departments ON filtered_departments.department_id =
departments.department_id

This still looks correct to me. However, I then base a query on this
join:

  outer = select([departments.c.name],
 from_obj=[join],
 use_labels=True)

At this point, the 'departments' table is no longer part of the inner
query. The SQL looks like:

 SELECT departments.name
 FROM (SELECT departments.department_id AS department_id
   FROM employees
   WHERE employees.department_id = departments.department_id)
AS filtered_departments
  JOIN departments ON filtered_departments.department_id =
departments.department_id

...and the query doesn't run.

I think I can work around it by putting the join condition in the
whereclause of the select, instead of from_obj, but is there a reason
why the join version doesn't work?

Thanks,

Simon

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



inner_query_test.py
Description: inner_query_test.py


[sqlalchemy] Re: Associations in a cleaner way

2007-03-05 Thread King Simon-NFHD78

 
Knut Aksel Røysland wrote:
 
 [snip]
 
 However, an instance of D also needs a reference to an instance of C.
 If the appropriate instance of C exists in the database (or 
 is pending to go into it), I want to pick this one, or 
 otherwise create a new instance of C.
 
 What I am looking for is the most clean way to achieve this. 
 I have run into trouble trying to use session.get(C, c_id) to 
 lookup instances of C that have not been flushed yet. (I 
 guess this might have something to do with primary keys not 
 working before instances have become persistent?)
 
 Furthermore, I want the constructor of D to be where I lookup 
 or create the appropriate instance of P, which seems to 
 require that I pass the session object to the constructor so 
 it can use session.get to look for an existing instance of P. 
 I feel this passing of the session object around, is going to 
 clutter the code, so I am looking for a cleaner way.
 
 [snip]

You may find the UniqueObject recipe useful:

http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject

It should help with the 'use-existing-or-create-new' part of your problem. I 
had a few difficulties when I tried to use it, but on reflection I think that 
was because I held references to objects after I had cleared the session. It 
also makes it difficult when you really do want to check whether an object 
exists in the DB without creating it, but it shouldn't be too difficult to 
adapt.

Instead of passing the session object around, you might be able to use the 
object_session function, which returns the session which the object is 
associated with, so in your constructor you could try 'session = 
object_session(self)'

Hope that helps,

Simon

--~--~-~--~~~---~--~~
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: SQA failing on table creation

2007-03-02 Thread King Simon-NFHD78

percious wrote:
 Here is the dump:
 ...snip...
 sqlalchemy.exceptions.SQLError: (OperationalError) (1071, 
 'Specified key was too long; max key length is 999 bytes') 
 '\nCREATE TABLE `Album` (\n\tid INTEGER NOT NULL 
 AUTO_INCREMENT, \n\tname VARCHAR(128), \n\tdirectory 
 VARCHAR(512), \n\t`imageOrder` VARCHAR(512), \n\t`coverImage` 
 INTEGER, \n\tPRIMARY KEY (id), \n\t UNIQUE (directory), \n\t 
 FOREIGN KEY(`coverImage`) REFERENCES `Image` (id)\n)\n\n' ()
 
 Here is the table code:
 AlbumTable = Table('Album', metadata,
 Column('id', Integer, primary_key=True),
 Column('name', Unicode(128)),
 Column('directory', Unicode(512), unique=True),
 Column('imageOrder', Unicode(512)),
 Column('coverImage', Integer, ForeignKey('Image.id')),
 )
 Mysql version 5.0.27
 
 TIA
 -chris

I think this is because of your 'unique=True' on your Unicode directory
column. MySQL is building a unique index on that column, and the number
of bytes that it uses per character varies depending on the encoding. If
it is UTF-16, for example, it will use 2 bytes per character, so your
VARCHAR(512) column would be 1024 bytes, and as the error message says,
the max key length is 999 bytes. This is a MySQL problem, not
SQLAlchemy.

I don't know what the solution is - you may need to play with MySQL's
character encoding.

See for example things like:

http://www.xaprb.com/blog/2006/04/17/max-key-length-in-mysql/

Hope that helps,

Simon

--~--~-~--~~~---~--~~
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: How do I tell if an object has been INSERTed or UPDATEd?

2007-02-26 Thread King Simon-NFHD78

Marco Mariani wrote:
 
 Simon Willison wrote:
  I've got a bit of code that looks like this:
 
  session = get_session()
  session.save(obj)
  session.flush()

 You can see what's going to be inserted/updated/deleted by 
 accessing session.new, session.dirty, session.deleted
 
 http://www.sqlalchemy.org/docs/unitofwork.myt
 
  What's the best way of telling if obj has been newly 
 created (INSERT) 
  or merely updated (UPDATE)? I tried just checking for 
 obj.id is None
  but I can't garauntee that my primary key is called 'id'.
 I would hope so! :-))
 

If you are wanting to know _after_ the session.flush(), I don't think
session.new/dirty/deleted will help you. Also, your primary key will be
read back from the database immediately after INSERT, so it won't be
None. Between, the save and the flush, obj in session.new should do
the job.

Simon

--~--~-~--~~~---~--~~
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: Lazy loading advantages and disadvantages

2007-02-22 Thread King Simon-NFHD78

Adam M Peacock wrote:
 Is there a difference in the SQL executed when using lazy vs eager  
 loading?  Specifically, if I use eager loading will everything be  
 queried at once with a more efficient join, or will it still use the  
 lazy style (as far as I understand it) of generating a ton extra  
 queries as it loads each relation separately?  If it is the former,  
 more efficient case (an eager relation uses a join) is it possible to

 override the loader type at query time, such as being lazy by default

 but being nice to the database when I know I'm going to need all the  
 data from the relation (especially if I'm calling a  couple thousand  
 rows for a report)? 

Eager loads are performed using a join, so only a single query is
issued. You can change the eager/lazy behaviour at query time by using
the 'options' method on the query object.

See
http://www.sqlalchemy.org/docs/datamapping.myt#datamapping_selectrelati
ons_eagerload and
http://www.sqlalchemy.org/docs/datamapping.myt#datamapping_selectrelati
ons_options for more.

Hope that helps,

Simon


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



[sqlalchemy] Re: new setuptools vs local SA copy

2007-02-06 Thread King Simon-NFHD78

Rick Morrison wrote:
 
 I keep two versions of SA installed here, one is a stable 
 version installed in the Python site-packages folder, and one 
 is current trunk with some local patches for testing.
 
 I used to be able to run tests and programs using the local 
 version by just inserting the local directory into the Python 
 path, and imports would then use that.
 
 I've recently upgraded to setuptools 0.6c5 and that doesn't 
 seem to work anymore -- I now always get the version from the 
 site-packages folder.
 
 Anyone running this kind of configuration out there run into 
 something like this?
 

The way I've done this is to run 'python setup.py develop' in the SVN
checkout. This puts the path to the checkout in easy-install.pth, and it
also creates an SQLAlchemy.egg-link file with the same path - I don't
know what this is used for.

To go back to the stable version I run 'easy_install -U SQLAlchemy'.
This seems to work on both Windows and Linux, but I am only on
setuptools 0.6c3.

This is probably more complicated than it needs to be - I would have
thought you can switch just by editing the easy-install.pth file.

The correct way is probably to use setuptools' --multi-version switch,
and put pkg_resources.require() somewhere in your application, but I've
not used that yet.

Another thing that I've found very useful (on Linux) is this:

 
http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-p
ython

Particularly with fast-moving projects like SQLAlchemy and TurboGears,
trying to share a single copy of a library between multiple applications
without breaking them every time I upgraded the library was getting
tricky. There's also working-env:

 http://blog.ianbicking.org/workingenv-update.html

which I haven't tried yet, but has the advantage of working on Windows
(apparently).

Hope that helps,

Simon

--~--~-~--~~~---~--~~
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: SelectResults, counts and one-to-many relationships

2007-02-06 Thread King Simon-NFHD78

Michael Bayer wrote:
 
 I added distinct() to selectresults as a method and made the 
 unit test a little clearer (since i dont like relying on the 
 selectresults mod)...
 
 q = sess.query(Department)
 d = SelectResults(q)
 d =
 d.join_to('employees').filter(Employee.c.name.startswith('J'))
 d = d.distinct()
 d = d.order_by([desc(Department.c.name)])
 
 

...and...

 
 for the order by getting removed during the select, that 
 seemed to be an optimization that got stuck in there and 
 since this is a really fringe use case its never come up, so 
 i removed it and added your test case (only with 
 distinct=True) in rev 2301.
 

I think you're slipping - I had to wait a whole three and a half hours
for this fix ;-) Seriously, thanks again,

Simon

--~--~-~--~~~---~--~~
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: iteration over mapper

2007-01-31 Thread King Simon-NFHD78

Jose Soares wrote:
 Hi all,
 
 Probably this is a stupid question,  :-[ but I don't 
 understand how to iterate an object mapper to get fields value.
 ---
 
 user = session.query(User).select(id=1)
 
 for j in user.c:
print j.name
 
 logname
 id
 password
 
 
 
 for j in user.c:
print j.value
 
 'Column' object has no attribute 'value'
 

The fields are attributes of the 'user' object itself, so the values are
at user.logname, user.id and user.password. To get an attribute whose
name is stored in a variable, you can use 'getattr':

for col in user.c:
  value = getattr(user, col.name)
  print col.name, value

Hope that helps,

Simon

--~--~-~--~~~---~--~~
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] Using .label() on boolean expressions

2007-01-19 Thread King Simon-NFHD78


Hi,

I don't know if this is valid SQL, but MySQL seems to accept it... I'd
like to write a query that looks like:

 SELECT s.result LIKE 'Pass%' AS pass
 ...

Which would return 1 or 0 for each row depending on whether the result
column begins with Pass. In SQLAlchemy this would become:

 sa.select([s.c.result.startswith('Pass').label('pass')] ...)

Without the .label(), this works, but I can't label it because
BooleanExpressions don't have a label method.

Is there another way to do this?

Thanks,

Simon

--~--~-~--~~~---~--~~
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: Using .label() on boolean expressions

2007-01-19 Thread King Simon-NFHD78


Simon King wrote:


I don't know if this is valid SQL, but MySQL seems to accept 
it... I'd like to write a query that looks like:


  SELECT s.result LIKE 'Pass%' AS pass
  ...

Which would return 1 or 0 for each row depending on whether 
the result column begins with Pass.




Another way I tried to do this was to use the SQL:

SELECT IF(s.result LIKE 'Pass%', 'Pass', 'Fail') AS pass
...

because that would be a function rather than a boolean expression, and
functions can be labelled. I knew I couldn't call 'sa.func.if', but I
thought it would be nice if you could use sa.func.if_  - the
_FunctionGateway object could strip the trailing underscore from the
name. It took me a while to realise I could use sa.func.IF, but the
capital letters look ugly :-). Alternatively, _FunctionGateway could be
given a __call__ method which would take the name as a parameter, so you
could use 'sa.func(if)'.

Just an idea.

Simon

--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-18 Thread King Simon-NFHD78


Michael Bayer wrote:

Simon King wrote:
 [requirements for instances returned from
  MapperExtension.create_instance]

at this point the entity_name should get set after your 
custom create_instance is called (at least thats in the 
trunk).  init_attr is not required, it pre-sets attributes on 
the object that are otherwise auto-created later (but the 
autocreation step throws a single AttributeError per 
attribute, which hits performance a little bit).




Thanks a lot for explaining that. It looks to me like I would be better
off simply using this method to load my class hierarchy, rather than
trying to twist polymorphic_identity into something that it was never
meant to do. Also, adding get_polymorphic_identity as a MapperExtension
method would add an overhead for every single object load for what is
probably a very infrequently used feature - I'd hate to be responsible
for that! Yet again, SQLAlchemy is already able to do exactly what I
want - sorry it's taken a while for me to realise it.

Cheers,

Simon

--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-15 Thread King Simon-NFHD78


Micheal Bayer wrote:


id rather just add another plugin point on MapperExtension 
for this, which takes place before the polymorphic decision 
stage at the top of the _instance method, like 
get_polymorphic_identity().  that way you could do all of 
this stuff cleanly in an extension (and id do that instead of 
making polymorphic_identity into a list).  hows that sound?




That would be ideal for me, and would seem to be the most flexible
solution as well - it leaves the decision for which class to use up to
the application. What would it actually return, though? An instance
ready to be populated?

Thanks a lot,

Simon

--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-12 Thread King Simon-NFHD78

Michael Bayer wrote:
 
 i think using the polymorphic_map is OK.  i downplayed its 
 existence since I felt it was confusing to people, which is 
 also the reason i made the _polymorphic_map argument to 
 mapper private; it was originally public.  but it seemed 
 like it was producing two ways of doing the same thing so i 
 made it private.

OK - I'll carry on using that then.


 using class_mapper() function instead of class.mapper


Ah - that's what I was missing. I hadn't seen the class_mapper function.
Thanks for that.

 
 as far as having multiple polymorphic_identity values map 
 to the same class, i would think we could just have 
 polymorphic_identity be a list instead of a scalar.  right 
 now, if you just inserted multiple values for the same class 
 in polymorphic_map, it would *almost* work except that the 
 save() process is hardwiring the polymorphic_on column to the 
 single polymorphic_identity value no matter what its set to.
 
 so attached is an untested patch which accepts either a 
 scalar or a list value for polymorphic_identity, and if its a 
 list then instances need their polymorphic_on attribute set 
 to a valid entry before flushing.  try this out and see if it 
 does what you need, and i can easily enough add this to the 
 trunk to be available in the next release (though id need to 
 write some tests also).
 

I think this would definitely be a useful feature, and in fact I was
originally going to attempt (or at least suggest!) something like that
myself. I'll try the patch and let you know how well it works.

However, I still have a situation where I would like to be able to use a
default class for unknown types. I don't want to hard-code all the
possible options up-front - only the ones that I actually want to treat
specially. I've been playing around with some different options, and
this is what I've ended up with:

class EmployeeMeta(type):
def __call__(cls, kind, _fix_class=True, **kwargs):
if not _fix_class:
return type.__call__(cls, kind=kind, **kwargs)
cls = get_employee_class(kind)
return cls(kind=kind, _fix_class=False, **kwargs)

def get_employee_class(kind):
if kind == 'manager':
return Manager
else:
return Employee

class Employee(object):
__metaclass__ = EmployeeMeta

class Manager(Employee):
pass


class EmployeeMapperExtension(sa.MapperExtension):
def create_instance(self, mapper, selectcontext, row, class_):
cls = get_employee_class(row[employee_table.c.kind])
if class_ != cls:
return sa.class_mapper(cls)._instance(selectcontext, row)
return sa.EXT_PASS

assign_mapper(ctx,
  Employee, employee_table,
  extension=EmployeeMapperExtension())
assign_mapper(ctx,
  Manager,
  inherits=Employee.mapper)


This seems to do the right thing - Manager instances get created for
managers, but any other row becomes an Employee. To add a subclass for
another row type, I just need to adapt the get_employee_class function
and add another call to assign_mapper. With a bit more work in the
metaclass, it could all be done with a special attribute in the
subclass.

The only thing I'm not sure about is the mapper extension - is it OK to
call the mapper._instance method, or is there a better way to do this?

Thanks again,

Simon


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


inheritance_test.py
Description: inheritance_test.py


<    1   2   3