Skip to content

dates are returned as None #520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
albertz opened this issue Oct 5, 2016 · 12 comments
Closed

dates are returned as None #520

albertz opened this issue Oct 5, 2016 · 12 comments

Comments

@albertz
Copy link

albertz commented Oct 5, 2016

I have a table with a column of type date with entries like 2016-00-00 (only partially set, e.g. the year only). pymysql fails to return this.

import pymysql
conn = pymysql.connect(...)
cur = conn.cursor()
cur.execute("SELECT publish_date FROM pub")
for row in cur:
    print(row)

Will print only (None,).

I also reported this for peewee although it looks like this is a bug on pymysql side but I'm not exactly sure.

A work around is to use

cur.execute("SELECT CAST(publish_date AS char) FROM pub")

which will return the date as a string (e.g. it prints ("2016-00-00",)).

@methane
Copy link
Member

methane commented Oct 5, 2016

I haven't know MySQL allows such a broken date...
But Python's date doesn't allow such date.
What PyMySQL can do for everyone, not only for you?

Python 3.5.2 (default, Sep 28 2016, 18:08:09)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.date(2016, 0, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: month must be in 1..12

@albertz
Copy link
Author

albertz commented Oct 5, 2016

Maybe, as a simple solution for now, just return it as a string in that case?

Maybe there are also other datetime-like libraries which support a data structure which allows this, but I don't know any and this would add another dependency so that might not be an option.

@methane
Copy link
Member

methane commented Oct 5, 2016

Hm, But doesn't it break compatibility?

Some existing code (ORMs) may not expect string is returned for date column.
But all existing code should support it, since there are NULLABLE column...

Additionally, is the date is supported by MySQL when sql_mode is strict?

@methane
Copy link
Member

methane commented Oct 5, 2016

mysql> show variables like 'sql_mode';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                                     |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> create table test_date (id integer primary key, `date` date);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test_date (id, `date`) values (42, "2016-00-00");
ERROR 1292 (22007): Incorrect date value: '2016-00-00' for column 'date' at row 1

@methane
Copy link
Member

methane commented Oct 5, 2016

I think you shouldn't use date column type, string or integer is better.

@albertz
Copy link
Author

albertz commented Oct 5, 2016

I agree that this might be cleaner, however, I have an existing DB without NO_ZERO_IN_DATE and I still would like to use pymysql (and maybe even better peewee on top).

@albertz
Copy link
Author

albertz commented Oct 5, 2016

I think peewee also supports strings, as it could get strings from some other DB backends.

@methane
Copy link
Member

methane commented Oct 5, 2016

peewee is not only user of PyMySQL.
PyMySQL supports customizing converters for such a special edge cases.

from pymysql.constants import FIELD_TYPE
from pymysql.converters import conversions as conv, 
conv = conv.copy()

del conv[FIELD_TYPE.DATE]
del conv[FIELD_TYPE.DATETIME]
del conv[FIELD_TYPE.TIME]

conn = pymysql.connect(..., conv=conv)

@philgyford
Copy link

FWIW I have a MySQL database that I've been using for years, with no special configuration, which has always accepted dates like 2016-03-00 and 2016-00-00 and have just discovered this issue too.

It'd be good to have the stuff about customising the converters, and why you might want to do so, in the documentation.

@methane
Copy link
Member

methane commented Mar 10, 2017

I'm not good at English. Writing English is 1000x harder than writing Python.
Contribution is welcome.

@methane methane closed this as completed Mar 10, 2017
@methane
Copy link
Member

methane commented Mar 10, 2017

I still open this because I feel "fallback to string" is acceptable idea.

@methane methane reopened this Mar 10, 2017
philgyford added a commit to philgyford/PyMySQL that referenced this issue Mar 13, 2017
Including how to disable conversion for specific types.

For PyMySQL#520
@canuck-sailor
Copy link

MySQL 5.7; db with NO_ZERO_IN_DATE eliminated from default. Python 3.6 using Alchemy will find "1920-00-00" when specifically requested as "SELECT history-date FROM table;" but "SELECT * FROM table;" brings back a null. Using variable dict.
Any solutions?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants