Python 3 unicode problem in CursorWrapper.format_sql.
See original GitHub issueHello,
I have been trying to get django-pyodbc working to connect to a SQL Server 2000 MSDE instance. I am using Django 1.6.1, Python 3.3 on Ubuntu 12.04.
Trying to do a simple operation such as
from django.db import connections
cursor = connections['default'].cursor()
result = cursor.execute('select * from customer')
causes the following to happen
File "/.../python3.3/dist-packages/django_pyodbc/base.py", line 410, in execute
return self.cursor.execute(sql, params)
TypeError: The first argument to execute must be a string or unicode query.
Someone else experienced the same problem except they were running on Windows. They asked a question on StackOverflow here:
http://stackoverflow.com/questions/21272895/cant-query-sql-server-from-django-using-django-pyodbc
I tracked the problem down to line 367 in base.py:
sql = sql.encode('utf-8')
def format_sql(self, sql, n_params=None):
if not self.driver_supports_utf8 and isinstance(sql, text_type):
# Older FreeTDS (and other ODBC drivers?) don't support Unicode yet, so
# we need to encode the SQL clause itself in utf-8
sql = sql.encode('utf-8')
It seems that in Python 3, str.encode returns a bytes which is not a string type causing the TypeError to occur.
See this comment on StackOverflow for information on how the string/bytes changed from Python 2 to 3.
http://stackoverflow.com/a/11596746/1040695
This only seems to occur for the first query getting the product version. I need to do more analysis to see if happens later on.
File "/.../python3.3/dist-packages/django/db/backends/__init__.py", line 159, in cursor
cursor = util.CursorWrapper(self._cursor(), self)
File "/.../python3.3/dist-packages/django_pyodbc/base.py", line 290, in _cursor
if self.ops.sql_server_ver < 2005:
File "/.../python3.3/dist-packages/django_pyodbc/operations.py", line 31, in _get_sql_server_ver
cur.execute("SELECT CAST(SERVERPROPERTY('ProductVersion') as varchar)")
File "/.../python3.3/dist-packages/django/db/backends/util.py", line 51, in execute
return self.cursor.execute(sql)
File "/.../python3.3/dist-packages/django_pyodbc/base.py", line 410, in execute
return self.cursor.execute(sql, params)
TypeError: The first argument to execute must be a string or unicode query.
Anyway, my quick fix was to comment out lines 364-367 in base.py.
Alternatively, the bytes could be converted back to a string by changing line 367 to
sql = sql.encode('utf-8').decode('utf-8')
I hope this helps someone workaround this bug. I don’t know enough about django-pyodbc to be able to fix this properly.
Michael.
Issue Analytics
- State:
- Created 10 years ago
- Reactions:4
- Comments:14 (3 by maintainers)
Top GitHub Comments
No problem.
Christoph, I was assigned this ticket at work and on django 1.7.7, python 3.4 on ubuntu 14.04, connecting to MSSQL 2004 using django-pyodbc 0.2.6 (same stack as Adrian except I use ubuntu) I was able to get our API running with only ‘driver_supports_utf8’: True,’
I saw a second solution suggesting ‘autocommit’: True, ‘unicode_results’: True,
which doesn’t break it but doesn’t fix it without your driver_supports_utf8 suggestion. I would close this ticket with an explanation to explicitly set driver_supports_utf8=True, I don’t think this is a bug
I saw gonna dive in and change your source but changing this in settings.py was sufficient