From: Magnus <ma...@th...> - 2003-05-26 14:41:00
|
At 05:07 2003-05-25 -0500, Ian Bicking wrote: >On Sun, 2003-05-25 at 04:43, Magnus Lyck=E5 wrote: > > That will at least cause problems with dates for my current > > backend, MS Access 97, since the warped SQL dialect there uses > > dates like #1999-04-12# instead of '1999-04-12'. :( > >That's really dumb, but I guess it's not your fault ;) I agree on both points! :) >You could mess around with SQLBuilder.sqlRepr if you don't mind making >incompatible modifications. That's where the current quoting of >mxDateTime values goes. I've thought about hooks for database-specific >quoting, exactly like this situation, but I haven't done it. There's >only a couple cases, since there's a reasonable lowest-common- >denominator for most databases and data types. The problem is that then I somehow have to figure out what database I have behind my ODBC source. I'm not even sure the problem exists in all Access version. As far as I understand, more modern versions can be coerced into being more SQL92-like in their behaviour. I don't want to mess with this at all, I think the really correct way to handle this is to use parameter passing the way it's intended and supported by the interface, and let the lower layers pass in the parameters. Why should we solve a problem that is already solved in the ODBC drivers? >You probably won't be able to use your date object directly, but if an >instance defines a sqlRepr method, that will be used. So it could be >something like: But Date is really just an example... The thing is that if I use something like "INSERT INTO X (a,b,c) VALUES (?,?,?)" or "SELECT * FROM X WHERE A < ?", and pass in the literals in a params tuple, the problem goes away, regadless of what kind of data this might be. (Of course, I still have to provide data in the right format, but I don't have to solve quoting or escaping.) After all, the point with the second parameter to cursor.execute() is there to promote this kind of coding. As far as I understand, neither MySQL, PostGreSQL or SQLite supports Dynamic SQL or the SQL CLI properly, so there %s is used, and the parameters are passed into the SQL string in the interface, but for interfaces to databases with proper Dynamic SQL support, both the SQL string with question marks and the parameter tuple are just passed to a lower layer, and handled by the database vendor's driver. I think this is the right way to do it. There are certinaly lots of other problems in various SQL dialects that we can't solve with this fix. Contatenation operators and join syntax etc makes it difficult to always get SQL to work cross platform, but for handling of quoting and escaping of literals used in SQL queries, there *is* a right way to do it, so trying to solve it again in the Python layer seems...well, non-optimal. As far as I understand, it's only the code for INSERT and UPDATE that I *need* to fix. For INSERT it seems that the easiest way is to fix it in _queryInsertID and not even call _insertSQL. Just call execute with the values as a separate parameter, and pass in ",".join(['?']*len(values)) in the second parenthesis. For updates I need to override _SO_update so that I just insert "SET A =3D ?, B =3D ?" and pass the parameters to self.query. This in turn means that I need to add an optional param parameter to query and _query, but it seems like a reasonable thing to do. Then I still don't have perfect support for selects, but I can do without that for now I think. >Well, for select in particular, maybe params would be fine. However, >SQLObject has maintained database independence fairly well, and the >annoying paramstyle issue would make code that uses params less >portable. So far, you ony seem to support backends that don't support parameter passing though. > Though I'm certainly okay with: > > Person.select('birthdate < %s', params=3D(Date(1999, 4, 12),)) > >Where any non-param %'s have to be quoted (like %%), then the database >connection changes %s to ? or whatever the paramstyle is. Should be >easy enough to implement. As you might have seen in the db-sig mailing list, I recently wrote code that goes the other way: ? to %s. This has the advantage that you can write your SQL queries just the way a proper SQL book describes them, i.e. you can write "SELECT * FROM X WHERE A =3D ? AND B LIKE 'X%'" without having to think about doubling % or using any other non-SQL construct in the SQL code. It's also fairly simple to convert qmark style SQL to named, numbered or even Sybase @-style quoting if that is needed. >I don't use params, and don't plan to, for other SQL construction. >Mostly it's because I like having complete control over the SQL, which I >do when I do the string substitution myself. I think you are doing more work than you have to that way. As I said, for MySQL, PostgreSQL and SQLite it's no big difference, since they do that in a simple way in the interface code anyway, but for most commercial it might well be. At least for interfaces like ADO and ODBC where you use one interface but can have any of many backends behind that interface. This also means that you place a burden on the application developer to solve this right for filtering in the select statement. I do realize that changing this now is quite some work though... -- Magnus Lycka (It's really Lyckå), ma...@th... Thinkware AB, Sweden, www.thinkware.se I code Python ~ The shortest path from thought to working program =20 |