MySQLdb select

Andy Todd andy47 at halfcooked.com
Thu Aug 5 14:31:16 EDT 2004


Sibylle Koczian wrote:
> Dennis Lee Bieber schrieb:
> 
>>
>>     Except that the conversion function, .literal(),  /does/  accept
>> a single item, a sequence (tuple OR list), or a mapping (dictionary).
>> The arguments are just passed through .execute(), which doesn't really
>> care one way or the other.
>>
>>     Tediously, .execute() calls ._execute(), which has:
>> ...
>>         try:
>>             if args is None:
>>                 r = self._query(query)
>>             else:
>>                 r = self._query(query % self.connection.literal(args))
>>         except TypeError, m:
>> ...
>>
>>     Since .literal() accepts single objects (well, in truth, I'd
>> guess one would have to say that it is .escape() that processes the
>> arguments -- I can't say what that does, as it is likely in the binary
>> module. However, the actual forming of the final query string /is/ the
>> standard Python "string" % arg operator, which, in my experience, has
>> never complained about not being given a 1-tuple.
>>  
> 
> True. I had hopes that this might explain another riddle I couldn't 
> solve: datefield is a database column of type date, and I execute two 
> queries:
> 
> a) SELECT * FROM mytable WHERE datefield = %s
> 
> b) SELECT * FROM mytable WHERE datefield IN (%s, %s)
> 
> case a): the parameter for %s can be a mx.DateTime object, a 
> datetime.date object or the sort of DateTime object MySQLdb returns from 
> another query; or it can be a string with format 'YYYY-MM-DD'. The 
> results of the query are correct in every case.
> 
> case b): the parameters must be strings of the form 'YYYY-MM-DD'. With 
> all other sorts of parameters (DateTime objects, strings in other date 
> formats) the query doesn't find anything.
> 
> I tried this with different versions of MySQL, MySQLdb and Python, under 
> Windows and Linux, always with the same results.
> 
> Now I've looked at conn.literal(args) for a pair of DateTime objects and 
> for a single one:
> 
>  >>> arg
> <DateTime object for '2004-06-18 00:00:00.00' at 1199da0>
>  >>> arglist
> [<DateTime object for '2004-07-29 00:00:00.00' at 117af20>, <DateTime 
> object for '2004-07-07 00:00:00.00' at 1199de0>]
>  >>> conn.literal(arglist)
> ("'2004-07-29 00:00:00'", "'2004-07-07 00:00:00'")
>  >>> conn.literal(arg)
> "'2004-06-18 00:00:00'"
>  >>> s1 = 'SELECT * FROM fehllief WHERE fehltag IN (%s, %s)'
>  >>> s1 % conn.literal(arglist)
> "SELECT * FROM fehllief WHERE fehltag IN ('2004-07-29 00:00:00', 
> '2004-07-07 00:00:00')"
>  >>> s2 = 'SELECT * FROM fehllief WHERE fehltag = %s'
>  >>> s2 % conn.literal(arg)
> "SELECT * FROM fehllief WHERE fehltag = '2004-06-18 00:00:00'"
>  >>> curs.execute(s1, arglist)
> 0L
>  >>> curs.execute(s2, arg)
> 1L
> 
> Why doesn't the query using IN find anything while the query using = 
> does? The records are there, of course.
> 
> Koczian

It's a bug. I think it is a bug in MySQL. I'm using 4.0.18 on Debian and 
an interactive session shows the problem;

"""
andy47 at vetinari:~$ mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 25 to server version: 4.0.18-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use portfolio
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select count(*) from stock_prices where price_date = '2004-07-30';
+----------+
| count(*) |
+----------+
|        7 |
+----------+
1 row in set (0.00 sec)

mysql> select count(*) from stock_prices where price_date = '2004-07-30 
00:00:00';
+----------+
| count(*) |
+----------+
|        7 |
+----------+
1 row in set (0.00 sec)
"""

When using '=' the two forms of date are identical, but if we switch to 
using 'in';

"""
mysql> select count(*) from stock_prices where price_date in ('2004-07-30');
+----------+
| count(*) |
+----------+
|        7 |
+----------+
1 row in set (0.00 sec)

mysql> select count(*) from stock_prices where price_date in 
('2004-07-30 00:00:00');
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql>
"""

Ta-da. Of course, this may have already been notified to MySQL AB, I'd 
check their web site (http://www.mysql.com) or try one of their mailing 
lists.

Regards,
Andy
-- 
--------------------------------------------------------------------------------
 From the desk of Andrew J Todd esq - http://www.halfcooked.com/




More information about the Python-list mailing list