Repository navigation
sqlite3.create_collation() doesn't get called for custom types #92742
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on May 12, 2022 - addedextension-modulesC modules in the Modules dirC modules in the Modules dir
on May 12, 2022 TL;DR: The adapter function returns a
bytesobject, which means the data is stored with the SQLite type BLOB; collations only work with strings. Fixed by forcing the adapter to store the data as a string.The lack of any prints from
reverse_collation_funcfor theMyObjobjectsThis is because
pickle.dumpsreturns abytesobject, which translates into the SQLite BLOB type.
In Python 2, astrobject is returned:$ python2 WARNING: Python 2.7 is not recommended. This version is included in macOS for compatibility with legacy software. Future versions of macOS will not include Python 2.7. Instead, it is recommended that you transition to using 'python3' from within Terminal. Python 2.7.18 (default, Jan 4 2022, 17:47:56) [GCC Apple LLVM 13.0.0 (clang-1300.0.29.10) [+internal-os, ptrauth-isa=deployme on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> type(pickle.dumps(1)) <type 'str'> >>> ^D $ python3 Python 3.11.0b1 (v3.11.0b1:8d32a5c8c4, May 6 2022, 22:45:29) [Clang 13.0.0 (clang-1300.0.29.30)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> type(pickle.dumps(1)) <class 'bytes'>
Collations only work on strings. Quoting the SQLite docs:
Collating functions only matter when comparing string values. Numeric values are always compared numerically, and BLOBs are always compared byte-by-byte using memcmp().
If you force
pickle.dumpsto return a string, for example using thestrbuilt-in, you'll see that your collation function works as expected.The order of the
objvalues is not reversed as it was for python v2.7This is probably because the collation function was not run.
Suggesting closing this as not-a-bug.
Ah ha! Indeed using the following
def adapter_func(obj): return pickle.dumps(obj, protocol=0).decode('utf-8') def converter_func(data): return pickle.loads(data.encode('utf-8'))does indeed work.
Thanks!
Suggesting closing this as not-a-bug.
Agreed
Reacted by Erlend E. Aasland@erlend-aasland, on a related note the https://docs.python.org/3/library/sqlite3.html documentation for
create_collationsays:the callable will get its parameters as Python bytestrings
However, you can see from the output above that
reverse_collation_funcis actually receiving strings given that the output is:reverse_collation_func: '1', '2'and not:
reverse_collation_func: b'1', b'2'Do you agree the the documentation is incorrect? If so I'll raise a new issue for that
Do you agree the the documentation is incorrect? If so I'll raise a new issue for that
Yeah, I believe the docs can be improved; please open a new issue. Thanks!
- added and removedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on May 13, 2022
Bug report
The following example demonstrates that
sqlite3.create_collation()works for a basic type such asintbut doesn't for a custom type. It used to work in python 2.7.18 but hasn't worked since v3.0.0 on Windows 10 x64.Your environment
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] on win32produces the following output:Python 3.0 (r30:67507, Dec 3 2008, 19:44:23) [MSC v.1500 64 bit (AMD64)] on win32through toPython 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32produce:Note:
reverse_collation_funcfor theMyObjobjectsobjvalues is not reversed as it was for python v2.7Operating system and architecture: