[Zope-DB] Dynamically generate sql-query in ZSQL Method

Ian Bicking ianb at colorstudy.com
Tue Apr 6 23:11:55 EDT 2004


On Apr 6, 2004, at 6:35 PM, Peter Sabaini wrote:
> Out of curiosity -- what is so horrible about ZSQL Methods? I use them 
> quite extensively (though mostly to talk to stored procedures) and may 
> have some nits but dont find them _that_ horrible...

Oh, where to start?

There's several ways to write a query, depending on how many of the Z 
SQL features you use (e.g., dtml-and, dtml-sqltest, dtml-sqlgroup, 
etc).  They all look quite different, and some will feel very foreign 
to someone who knows SQL but not Z SQL.

It uses DTML, or DTML-like constructs.  Most of the things that are bad 
about DTML for templates are also bad for DTML generating SQL.  You 
could write entire books about why DTML is bad.

It usually looks like normal SQL, but is far enough away from SQL to be 
difficult to work with in source form, since it uses <dtml-sqlvar> 
instead of like parameters like ? or even %s.  It's usually a long way 
from Z SQL source to something you can feed to EXPLAIN.

It is difficult to debug.  There's one largely hidden feature in being 
able to pass src__ in as a keyword argument to see what the SQL source 
actually is.  That's about all the debugging you get.  AFAIK, there's 
not good log of the SQL queries sent, how long they took, etc.

Connection paths are pretty much hard-coded.  You can't tell a method 
to use a different connection.  This would be useful if you wanted to 
use database-level security, and so you need two separate connections 
with separate users.  You might be able to do this with acquisition, 
but whole books could be written on why acquisition is bad.  Actually, 
it would probably be a chapter in the DTML book.

It has crufty parameters.  Put "a, b, c" in , and you get parameters 
with names like "a,", "b," and "c".  Default parsing seems wonky too.

It doesn't signal errors properly -- if you forget to pass in a keyword 
argument, it's pretty much ignored.  Or if you pass in extra arguments. 
  Why have a parameter list at all?

It doesn't deal with failures very well.  Why not give me the SQL in 
the exception when there's an error?  It doesn't deal with any of the 
hard parts of failure in general, connection failures, concurrency 
conflicts, etc.

You can't nest or factor your methods well.  This is largely DTML's 
fault, but Z SQL makes it worse since all methods are concrete.  You 
can't save values, go through control structures, etc., except using 
plain DTML constructs which have their own issues.  For instance, 
consider turning a list of items into SQL for use with IN, like 
(<dtml-in items prefix=loop><dtml-unless 
loop_start>,</dtml-unless><dtml-sqlvar loop_item type=int></dtml-in>).  
That's lame, *and* you can't abstract out the lameness.  Well, maybe 
with the use of src__ and other stuff, but that's it's own lameness.  
(Hmm... I see now there's an option to dtml-sqlvar to handle this 
particular case... so many options, but I can't use any of them from 
the outside, nest dtml expressions, etc)

Oh, on the subject, every issue is dealt with using another dtml-sqlvar 
option or another tag, there's not a good set of orthogonal functions.

SQL Brains are cool, if a still little under powered.  But they don't 
see updates unless you go twiddle all sorts of forms.

You can't set any attributes on result rows.  Even if you know why it 
might not be a good idea.  Even if you try really hard.  (Though you 
can add a dummy column to your query, and then reassign the column)  
This is annoying particularly when using brains.

Caching is stupid.  You can cache, but you can't invalidate the cache.  
There's a product out there that provides a cacheable SQL method, but 
it's a whole separate product and item type, and you can't easily go 
back and forth, or even upgrade.

All methods return result objects with multiple rows.  It's common to 
see:

   <dtml-in "get_some_object(id=whatever)"><dtml-var 
some_column>...</dtml-in>

When in fact you only expect their to be one row in the result.  This 
is where DTML's suckiness gets involved (dtml-in/dtml-with, all the 
flattened namespaces, etc).

You start needing all sorts of methods for little things.  Like, say 
you want to fetch a value from a sequence, like "SELECT 
nextval('sequence_name') as seq".  Do you create a new method for this? 
  What an annoying process!  (ZMI partially at fault)  And you get 
lameness like <dtml-in get_sequence_name><dtml-var seq></dtml-in>  Oh, 
it hurts me just to type this!  Or container.get_sequence_name()[0][0]. 
  This leads to code being highly coupled.  You want to put a Python 
Script in the middle for some reason?  Now you have to return something 
like [[id]].  Or [{'seq': id'}]?  Only one way to find out... oh, the 
coupled pain!  (This is why I keep a firm Python Script barrier between 
my Z SQL methods and my "good code" -- I don't want Z SQL cruftiness to 
infect everything else with it's lameness)

No positional parameters.  Seems like an okay idea, except for all the 
methods that are fetch-row-with-this-id, where positional is better.  
(Something else for the Python Script barrier)

SQL methods are often tightly bound to specific scripts, templates, 
etc.  But it's hard to express this, and they are just more cruft in 
the ZMI.  If something is tightly coupled, I want to know it, I want to 
know that changes effect only one place, or that I shouldn't use it 
from the outside.  At least inline SQL gives you this.

dtml-sqlvar doesn't have any good types.  type=date please?  Some 
attempt at making database more compatible would be nice.  Strings and 
floats are easy.  Solving difficult problems is actually useful, just 
solving easy problems is a programming cop-out.

Doesn't do anything with database introspection.  Again, I know it's 
hard, but hard is useful.  And it's not that hard.

The test pane is really lame.  I won't go into all of why it's lame.  
It could be useful, but it's only distracting.  (I might *think* I can 
just test a quick query in it, but I'm always wrong)

I think that's it.  I'd say it felt good to vent, except I'm going to 
have to work with Z SQL methods again tomorrow, and venting doesn't 
make up for that.

--
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org




More information about the Zope-DB mailing list