[DB-SIG] How to know what to do with parameters...
Anthony Tuininga
anthony at computronix.com
Fri May 16 17:41:58 EDT 2003
A very interesting concept. I think it needs to be extended a little,
however. :-)
It would be nice if any object at all could be bound without requiring
constant conversion -- or rather, writing the code in one place and not
have to write code like this.
cursor.execute(statement, [ ConvertArg(instanceOfMoney) ] )
Perhaps the following would work instead? The object must define the
following functions:
_dbapi_type()
which will return one of the types defined in the DB API and
_dbapi_value()
which will return the value in the format required by the DB API to be
compatible with the type specified above
Then the following would be permitted:
cursor.execute(statement, [ instanceOfMoney ] )
Any thoughts on that? The names are always the hardest thing to agree
on, so if you have a better name, let me know.
On Fri, 2003-05-16 at 10:22, Magnus Lyckå wrote:
> I would like to suggest that the DB-API will stipulate
> that the DBinterfaces should check whether an object has
> a method of a certain, standardized name, and use that
> method to extract the stringified value to put in the
> SQL statement, it the object has such a method. Pysqlite
> has such a hook, but "_quote" might not be the best name.
> Maybe "_dbapi_string"? Like this:
>
> if hasattr(value, '_dbapi_string'):
> return value._dbapi_string()
>
> One of Tim Peters Python Zen tenets is:
> "In the face of ambiguity, refuse the temptation to guess."
> I think this is something to consider.
>
> So, how can a DBI programmer know how to convert data?
>
> Well, if he knows the type or class involved, he can know of
> course, and should normally handle that, but as Chris said
> it might not be a good thing to fall back on using repr if
> we don't recognize the object.
>
> If the interface can't positively indentify the type or
> class as something it knows for sure how to handle, it
> should require explicit instructions from the application
> programmer.
>
> Let's imagine I use a Money class, and my DBI has no
> support for that. I think I should be able to tell
> the DBI how to present my money values to SQL. I
> probably want it to be presented as a decimal number
> with two decimals, but I'm not sure that I want
> __str__ or __repr__ to display like that. They should
> probably both show the currency.
>
> Using C/python format codes is a way of doing that. It
> means that the application programmer has to take the
> responsibility that his object can properly handle the
> format code he chooses to use in his SQL statement.
>
> In this case I could probably implement __float__ and
> use %f or even %.2f.
>
> This approach has two problems though:
> 1. It doesn't work with ? or :name.
> 2. The format codes seems to suggest that it's just like
> the %-operator, and as we've noted it isn't quite so
> for strings, unicode or None at least. Trying to do
> things like %.1s will backfire.
>
> The approach today will be to cast to a string, and that
> usually works, but it seems silly to have a numeric value
> cast that to a string with quotes around and perform a check
> to see if it contains any ' that need to be escaped, and then
> send it to the backend which will convert it back to a number.
>
> I just tried a little in MySQL, and I imagine they put some
> effort into getting this right, but I still think it's a
> bit awkward...and I'm not sure things will always work out
> the way we plan.
>
> SELECT * FROM a_table WHERE 0.1 = 0.10000000000000001
> will return rows.
> SELECT * FROM a_table WHERE 0.1 = '0.10000000000000001'
> will also return rows, as will
> SELECT * FROM a_table WHERE '0.1' = 0.10000000000000001
> but not
> SELECT * FROM a_table WHERE '0.1' = '0.10000000000000001'
> or
> SELECT * FROM a_table WHERE 0.1 = 0.1000000000000001
> which has one zero less between the ones.
>
> What if I want to do "WHERE A = B + C" and A = 0.6, B = 0.2
> and C = 0.4? :) Perhaps you know that your backend will handle
> that by viewing the numbers as exact decimals (MySQL fails,
> just like Python).
>
> Passing as float will give you
> "WHERE 0.59999999999999998 = 0.20000000000000001 + 0.40000000000000002"
> which will fail, and passing as strings with rounded values will
> produce quotes, and you get: "WHERE '0.6'='0.2'+'0.4' which will
> obviously fail.
>
> I would feel much happier if I could make the DB-API send
> "WHERE 0.6 = 0.2 + 0.4" for me. An object with a _dbapi_string
> method, and an interface that recognized that would fix this for
> me.
>
>
>
> --
> Magnus Lycka (It's really Lyckå), magnus at thinkware.se
> Thinkware AB, Sweden, www.thinkware.se
> I code Python ~ The shortest path from thought to working program
>
>
> _______________________________________________
> DB-SIG maillist - DB-SIG at python.org
> http://mail.python.org/mailman/listinfo/db-sig
--
Anthony Tuininga
anthony at computronix.com
Computronix
Distinctive Software. Real People.
Suite 200, 10216 - 124 Street NW
Edmonton, AB, Canada T5N 4A3
Phone: (780) 454-3700
Fax: (780) 454-3838
http://www.computronix.com
More information about the DB-SIG
mailing list