howto sql-query directly from my products methods?
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it? thx hans -- -------------------------------------------------------------- hans augustin (software developer) hans@beehive.de beehive elektronische medien GmbH http://www.beehive.de phone: +49 30 847-82 0 fax: +49 30 847-82 299
[hans]
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it? thx hans
Well, the extreme and simplest case is to have one zsql method that takes a single parameter called, say, "sql": &dtml-sql; The sql parameter would contain the entire query, that is, an entire select statement or insert statement or whatever. This is easy and flexible, but has no security at all. If someone posted you a DELETE statement, you might end up very unhappy, for example. Still it is an easy approach to use when you are tuning up a query, as long as you don't let it loose outside your system. The next level up from this is to have your page, or a method called by the page, construct a query statement using values from a form, then hand the query to your friendly general zsql method. This is quite a bit more more secure, but you still need to make sure it's going to be safe. A next step up in security is to make sure that any query that can be constructed and passed to the zsql method can only access non-updateable views. There's a tradeoff between having highly specialized zsql methods, which could be the most secure but can lead to you having to maintain many individual methods, and the completely general approach I've outlined above where you only need one method but have to manage the security issues. Cheers, Tom P
On Mon, 4 Mar 2002, Thomas B. Passin wrote:
[hans]
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it? thx hans
Well, the extreme and simplest case is to have one zsql method that takes a single parameter called, say, "sql":
&dtml-sql;
The sql parameter would contain the entire query, that is, an entire select statement or insert statement or whatever.
This is easy and flexible, but has no security at all. If someone posted you a DELETE statement, you might end up very unhappy, for example. Still it is an easy approach to use when you are tuning up a query, as long as you don't let it loose outside your system.
The next level up from this is to have your page, or a method called by the page, construct a query statement using values from a form, then hand the query to your friendly general zsql method. This is quite a bit more more secure, but you still need to make sure it's going to be safe.
A next step up in security is to make sure that any query that can be constructed and passed to the zsql method can only access non-updateable views.
There's a tradeoff between having highly specialized zsql methods, which could be the most secure but can lead to you having to maintain many individual methods, and the completely general approach I've outlined above where you only need one method but have to manage the security issues.
I also wrote back with this idea, Tom, but forgot to mention that you need to be really careful about the security, especially as some of us get lazy about simply refer to things as <dtml-var foo> without being specific about where foo comes from. Can someone post form variables with script?sql=DELETE FROM tblImportant ? Thanks for being on top of things to include this warning! -- Joel BURTON | joel@joelburton.com | joelburton.com | aim: wjoelburton Independent Knowledge Management Consultant
On Mon, Mar 04, 2002 at 03:32:24PM -0500, Thomas B. Passin wrote:
[hans]
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it? thx hans
Well, the extreme and simplest case is to have one zsql method that takes a single parameter called, say, "sql":
&dtml-sql;
The sql parameter would contain the entire query, that is, an entire select statement or insert statement or whatever.
This is easy and flexible, but has no security at all. If someone posted you a DELETE statement, you might end up very unhappy, for example. Still it is an easy approach to use when you are tuning up a query, as long as you don't let it loose outside your system.
The next level up from this is to have your page, or a method called by the page, construct a query statement using values from a form, then hand the query to your friendly general zsql method. This is quite a bit more more secure, but you still need to make sure it's going to be safe.
A next step up in security is to make sure that any query that can be constructed and passed to the zsql method can only access non-updateable views.
There's a tradeoff between having highly specialized zsql methods, which could be the most secure but can lead to you having to maintain many individual methods, and the completely general approach I've outlined above where you only need one method but have to manage the security issues.
These parameterized ZSQL methods are generally a bad idea. They occur to everyone at some point early in their Zope career. I know they did to me, I wrote a howto on it. But, they are almost always a bad idea. Mind you, not only is there a security tradeoff, but there are also managability, testability, and correctness tradeoffs. If you use concrete zsql methods, then you have only to examine the method to determine what arguments are needed, and often you can directly read what is being returned, modified, or deleted. That is, understanding the database interactions of the code in a folder is often as simple as looking at the ZSQL methods in the folder. If you use one of the "statement is a parameter" forms, then you have to read (at least) all the code in the folder, everything, every dtml method, pythonscript, external method, etc. to determine the interactions with the database. Worse, you learn about mistakes too late. With concrete ZSQL methods you can use the Test Tab to make sure that the method does what it is supposed to do. You are reasonably confident that the method does what it should, no more and no less, before you ever let it loose. With "statement is a parameter" code, you don't learn that there is a problem until run time. My current belief is that you should never use any ZSQL method with anything more complicated than a sqlgroup in it, and that you want to be sparing with sqlgroups. One other thing -- keep your ZSQL methods close to the folder they are accessed from. Only very common queries should be closer to the root. I suspect that in many, if not most, cases, the set of databases that you need to work with in a single folder is pretty small. I think that this is due to programmer forethought, that is, that you naturally design your databases and your folder structure to be compatible. Now, if you are operating with only one, two, or three tables per folder, then you probably need no more than a few insert, delete, select, or updates per table. This translates to four to ten ZSQL methods per table used. If you have only three tables you are working with in a paritcular folder, this is just not all that onerous. Jim Penny
Cheers,
Tom P
[Jim Penny]
On Mon, Mar 04, 2002 at 03:32:24PM -0500, Thomas B. Passin wrote:
Well, the extreme and simplest case is to have one zsql method that takes a single parameter called, say, "sql":
&dtml-sql;
The sql parameter would contain the entire query, that is, an entire select statement or insert statement or whatever.
This is easy and flexible, but has no security at all. If someone posted you a DELETE statement, you might end up very unhappy, for example. Still it is an easy approach to use when you are tuning up a query, as long as you don't let it loose outside your system.
Mind you, not only is there a security tradeoff, but there are also managability, testability, and correctness tradeoffs.
If you use concrete zsql methods, then you have only to examine the method to determine what arguments are needed, and often you can directly read what is being returned, modified, or deleted. That is, understanding the database interactions of the code in a folder is often as simple as looking at the ZSQL methods in the folder.
If you use one of the "statement is a parameter" forms, then you have to read (at least) all the code in the folder, everything, every dtml method, pythonscript, external method, etc. to determine the interactions with the database.
I find I spend most of my effort developing queries and browsing tables as I develop code. I like to use zsql methods that make this easy and flexible. So I tend to write my own SQL statements by hand, even in a textarea. You can still test them using the test tab. When you go to a production query, I go along with everything you said. Same for using Cold Fusion. Cheers, Tom P
On Mon, 4 Mar 2002, hans wrote:
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it? thx hans
Either: . write a single ZSQL method with the text <dtml-var SQL_statement> and put a prewritten SQL_statement var in the param list for the ZSQL method. or . WRite a Py external method that queries the DB and returns the results #1 is a tiny bit of hack but works fine, can still use ZSQLMethods caching, etc. It just gives you a chance to move some of the SQL-statement-crafting logic elsewhere rather than in DTML-in-ZSQMethod. #2 is too low-level for my tastes: it would need to be edited for different databases, wouldn't be cached like ZSQL Methods, etc. -- Joel BURTON | joel@joelburton.com | joelburton.com | aim: wjoelburton Independent Knowledge Management Consultant
hans wrote:
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it?
thanks a lot for your answers. the minimal version with just one zsql method i like. but i should have explained more clearly that my queries will be fixed except for the date. Background is, a weekly report should be generated (like CMFArticle, but CMF is too much) including some grafics (statistics), where those grafics derive from queries (generate w PIL). so the queries are fixed (except for date) and the users will never come anywhere near them, security is just some non-issue. secondly, as i understood the zsql-method code, they dynamically aquire their database connectors on each call, ie they are more flexible than my needs, and i thought, i could save on that also. Again: i know the DA (or could aquire at product instantiation), i know the queries and could hard code them in my "render_gif"-methods. If there is a simpler solution than 1 zsql-method w <dtml-var query> im curious. With zope, solutions generally spread fine grained w many objects all over the place and i like to keep things together. still, thanks anyway. -------------------------------------------------------------- hans augustin (software developer) hans@beehive.de beehive elektronische medien GmbH http://www.beehive.de phone: +49 30 847-82 0 fax: +49 30 847-82 299
hans wrote:
well, i could instantiate a bunch of zsql methods, each with its own query and then call them from my products methods. but how could i obviate the need to have these zsql methods and query directly? Or is it just not worth it?
This is what I've done. However, it's a hack in the sense I'm relying on the current SQL() class implementation and am using Zope-2.3.3. Still, I've been quite happy with the results and does what you've been looking for. This may have to be cleaned up a little for later versions and would be curious of any updates. Hopefully one of the Zope developers will make something like this part of the Zope API. Enjoy, Albert ---------------------------------------------------------------------- # -*- mode: python; -*- import Globals import OFS import StringIO from Products.ZSQLMethods.SQL import SQL # given a connection_id string, the ZSQL template, variable list, and # definitions, execute the ZSQL statement. Return a ZSQL Result object. # Example: # # expresion = '''SELECT FirstName,LastName FROM Users # WHERE Users.Email=<dtml-sqlvar email type="string">''' # result = query(self,expression,"email",email="foo@bar.com") # # This does not store a ZSQL object in the ZODB, so that ZODB remains # unchange. IMHO, this provides the most flexibility, allowing us to # create an arbitrary number of ZSQL statements from python code, # without being tied down to the traditional point&click editing. def query(self,connection_id,template,vars="",**keywords): id = "__custom_query" sql = SQL(id, id, connection_id, vars, template) # normally if we create a ZSQL method in zope (or add sql instance # to self object), the sql instance would hold the ZSQL DA object. # So we need to manually set it. # # note that we don't store the sql object into the zope object, as # the transaction gets stored in the Data.fs. Even deleting later # makes it worse, as the "undo" records gets updated setattr(sql,sql.connection_id, getattr(self,sql.connection_id)) if keywords.has_key(MAX_ROWS): # DA parses max_rows and saves it in max_rows_ sql.max_rows=sql.max_rows_=keywords[MAX_ROWS] else: sql.max_rows=sql.max_rows_=1000 results = sql(keywords) return results
participants (5)
-
Albert Ting -
hans -
Jim Penny -
Joel Burton -
Thomas B. Passin