Package: mariadb-dyncol
Unmaintained (2022-12-07)I stopped maintaining this package as it has never been popular.
Since MariaDB added JSON support, it’s better to use that for portability, rather than the custom dynamic columns format.
If you’d like to take over maintenance of this package please email me.Pack/unpack Pythondicts into/out of MariaDB’sDynamic Columnsformat.A quick example:>>>mariadb_dyncol.pack({"key":"value"})b'\x04\x01\x00\x03\x00\x00\x00\x03\x00key!value'>>>mariadb_dyncol.unpack(mariadb_dyncol.pack({"key":"value"})){'key': 'value'}InstallationUsepip:python-mpipinstallmariadb-dyncolPython 3.7 to 3.11 supported.Working on a Django project?Check out my bookBoost Your Django DXwhich covers many ways to improve your development experience.FeaturesSensible type mapping from Python to SQLTested against examples from MariaDB, including property/fuzz testing withhypothesis(which is
amazing and found many bugs)Why?The normal way for adding data into dynamic columns fields is with theCOLUMN_CREATEfunction, and its relatives. This allows you to do things
like:INSERTINTOmytable(attrs)VALUES(COLUMN_CREATE('key','value'))Unfortunately the Django ORM is restricted and cannot use database functions
like this in every instance, at least not until Django 1.9. It was this
limitation I hit whilst implementing a dynamic columns field for my projectdjango-mysqlthat spurred the
creation of this library.By pre-packing the dynamic columns, the above query can just insert the blob
of data directly:INSERTINTOmytable(attrs)VALUES(X'0401000300000003006B65792176616C7565')Asides from being more easily implemented with the Django ORM, this approach
of packing/unpacking dynamic columns in Python also has some advantages:All data types are properly preserved in Python. The only way MariaDB
provides of pulling back all values for a dynamic columns field is to callCOLUMN_JSON, but JSON only supports strings and integers. AlsoCOLUMN_JSONhas a depth limit of 10, but the format has no actual limit.The CPU overhead of packing/unpacking the dynamic columns is moved from you
database server to your (presumably more scalable) clients.APIAll functions and names are accessible as attributes of themariadb_dyncolmodule, which you can import withimport mariadb_dyncol.pack(mapping)Packs the given mapping (adict) into the MariaDB Dynamic Columns
format for named columns and returns it as a byte string (Python 3’sbytes,
Python 2’sstr). This is suitable for then inserting into a table as part
of a normal query.Thedict's keys must all be unicode strings, and the values must all be
one of the supported data types:intbetween-(2** 32) + 1and(2 ** 64) - 1(Python 2:longis supported too)strup to 4GB encoded in UTF-8 (Python 2:unicode)float- anything exceptNaNor+/- infdatetime.datetime- full range supporteddatetime.date- full range supporteddatetime.time- full range supportedAnydictthat is valid by these rules, allowing nested keys. There is no
nesting limit except from for MariaDB’sCOLUMN_JSONfunction which
restricts the depth to 10Note that this does not support theDECIMALtype that MariaDB does (and
would naturally map to Python’sDecimal) - it is a little more fiddly to
pack/unpack, though certainly possible, and pull requests are welcomed. If you
try and pack aDecimal, aDynColNotSupportedexception will be raised.There are other restrictions on the UTF-8 encoded column names as documented in
MariaDB:The maximum length of a column name is 16383 bytesThe maximum length of all column names (at one level in nested hierarchies)
is 65535 bytesAll other unsupported types will raise aDynColTypeError. Out of range
values will raise aDynColValueError.Examples:>>>mariadb_dyncol.pack({"a":1})b'\x04\x01\x00\x01\x00\x00\x00\x00\x00a\x02'>>>mariadb_dyncol.pack({"a":"💩"})b'\x04\x01\x00\x01\x00\x00\x00\x03\x00a!\xf0\x9f\x92\xa9'unpack(bytestring)Unpacks MariaDB dynamic columns data encoded byte string into a dict; the types
you can expect back are those listed above. This is suitable for fetching the
data direct from MariaDB and decoding in Python as opposed to with MariaDB’sCOLUMN_JSONfunction, preserving the types that JSON discards.As noted above,DECIMALvalues are not supported, and unpacking this
will raiseDynColNotSupported. Also strings will only be decoded with the
MySQL charsetsutf8orutf8mb4; strings with other charsets will raiseDynColNotSupportedas well.Unsupported column formats, for example the old MariaDB numbered dynamic
columns format, or corrupt data, will raiseDynColValueError.Examples:>>>mariadb_dyncol.unpack(b"\x04\x01\x00\x01\x00\x00\x00\x03\x00a!\xf0\x9f\x92\xa9"){"a": "💩"}>>>mariadb_dyncol.unpack(b"\x04\x01\x00\x01\x00\x00\x00\x00\x00a\x02"){"a": 1}