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
Fixed #29251 -- Added CharField converter to the MySQL backend. #9816
Conversation
def convert_charfield_value(self, value, expression, connection): | ||
if isinstance(value, bytes): | ||
return force_text(value) | ||
return value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this does follow other existing methods, but:
return force_text(value) if isinstance(value, bytes) else value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I updated this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is force_text()
needed as opposed to value.decode()
? If so, can you add a test to demonstrate?
tests/db_functions/tests.py
Outdated
def test_funct_string_combination(self): | ||
Author.objects.create(name='Rhonda', alias='john_smith') | ||
authors = Author.objects.annotate(filled=LPad('name', Length('alias'), output_field=CharField())) | ||
self.assertQuerysetEqual(authors, [' Rhonda'], lambda a: a.filled, ordered=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why ordered=False
with a result of length 1.
tests/db_functions/tests.py
Outdated
@@ -671,3 +671,8 @@ def test_function_as_filter(self): | |||
Author.objects.exclude(alias=Upper(V('smithj'))), | |||
['Rhonda'], lambda x: x.name | |||
) | |||
|
|||
def test_funct_string_combination(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
funct -> func -- I think? or "function"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo 🤦♂️ Thanks.
@timgraham Thanks for the review. You're right |
I note that |
Yes, there's a ticket to audit |
Then non-ASCII character case doesn't work on Oracle (leading spaces are missing). |
|
@timgraham I checked and IMO there doesn't exist a good workaround for ... In most character sets, this is also the number of characters in the return value. However, in some multibyte character sets, the display length of a character string can differ from the number of characters in the string. I think it's fine to add a note in documentation about this restriction. |
Sure, if you think is deserves a mention. We can't document everything about each database. :-) |
You're right, it's impossible to describe all Oracle's caveats 😉 I've left a note in the ticket 28643, this should be enough. I updated tests, it works on Oracle. |
Would it be worth benchmarking the speed overhead of this addition? |
mysqlclient returns bytes instead of string in some edge cases. Thanks Tim Graham and Nick Pope for reviews.
@claudep I wrote simple benchmark with
|
Oh thanks! So does that mean we are ~20% slower with the patch? (sorry, I'm not so great at stats) |
I think so, but even if def convert_charfield_value(self, value, expression, connection):
return value the result is
|
That's probably the overhead cost of adding converters (function calls et al). Then I think we should find another way of solving this issue. Slowing the whole stack just to fix this edge case is not very sound IMHO. |
I've prepared alternative PR #9835 with conversion only in affected database functions. |
Closing due to the alternative approach in #9835. |
https://code.djangoproject.com/ticket/29251
I'm not convinced that this is the best solution, but I haven't found a better way to solve this issue.