From: Brad B. <br...@bb...> - 2004-10-09 10:57:53
|
On Friday, October 8, 2004, at 06:40 PM, Ian Bicking wrote: > Colin Stewart wrote: [snip] >> Using the db driver's quoting would also mean that the SQL can be >> cached as prepared statements by the DB. For some (e.g. Oracle) that >> can lead to a pretty significant speed up in itself. > > I don't know enough about prepared statements to know if it would > help. If it's possible to prepare, up front, three or four statements > for every class, then it could help. If you have to prepare a > statement, then use it several times, then prepare another statement, > it's unlike to help, since SQLObject doesn't know enough to predict > what statements are going to be used in sequence often enough to help. > > Also, the postgres and mysql drivers (and probably sqlite) don't have > any prepared statements, and do all the quoting on the client side. > I'm most interested in those backends, so there's not a huge amount to > be gained. They probably do the quoting in C, though, with some > performance gain there. My interest is in PostgreSQL, so I'll comment on that. psycopg claims to support the DB-API v2, and thus should have prepared statements. So here's a unit test that demonstrates, perhaps, a decent way of hooking up bare SQL to a method (untested, I stayed up till 4am last night playing Mao, and I'm off to Heathrow in 10 minutes, so please forgive me if this code is a bit dirty. :) This may need to be molded around slightly to solve your problem but I hope it illustrates an interesting new idea and gets some thinking going on about this problem: class SQLMethodTest(SQLObjectTest): def testSQLMethod(self): class USAddressesResult(object): class USCitizen(object): def __init__(self, id, name, address): self.id = id self.name = name self.address = address def __init__(self, results): self.results = results def __iter__(self): for r in self.results: yield USCitizen(r[0], r[1], r[2]) class Person(SQLObject): usaddresses = SQLMethod( sql = """\ SELECT p.id, p.name, a.address FROM person p, address a WHERE p.id = a.personid AND a.country_code = 'US'""", result = USAddressesResult) usaddresses = classmethod(usaddresses) uscitizens = list(Person.usaddresses()) self.assertEquals(len(uscitizens), 2) self.assertEquals(uscitizens[0].name, "Ford Prefect") self.assertEquals(uscitizens[0].address, "Somewhere near Betelgeuse") The benefits gained from this feature would be: 1. The speed of working with raw SQL. 2. Being able to get a resultset that actually does what you need (since the current concept that "an element in a result set maps to one row in a table" often doesn't make sense, as each row returned from a SELECT query is often *not* a row in a table.) 3. You could, of course, use placeholders in the SQL statement and then the SQLMethod method would accept that many params. Thoughts, comments, feedback welcome. Gotta run, -- Brad Bollenbach |