将Python字典打包/解包到/从MariaDB的动态列格式。
项目描述
未维护(2022-12-07)
由于该包从未流行,我停止了该包的维护。自从MariaDB添加了JSON支持,最好使用它进行可移植性,而不是自定义动态列格式。如果您想接管该包的维护,请给我发邮件。
将Python dict打包/解包到/从MariaDB的动态列格式。
快速示例
>>> 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'}
安装
使用pip
python -m pip install mariadb-dyncol
Python 3.7到3.11受支持。
在Django项目中工作? 查看我的书籍 Boost Your Django DX,该书籍涵盖了许多改进您开发体验的方法。
功能
从Python到SQL的合理类型映射
已针对MariaDB的示例进行测试,包括使用hypothesis(它非常棒并发现了许多错误)进行的属性/模糊测试
为什么?
将数据添加到动态列字段的常规方式是使用COLUMN_CREATE函数及其相关函数。这允许你做类似的事情
INSERT INTO mytable (attrs) VALUES (COLUMN_CREATE('key', 'value'))
不幸的是,Django ORM受限制,不能在所有情况下使用此类数据库函数,至少在Django 1.9之前是这样。当我在我自己的项目django-mysql中实现动态列字段时,遇到了这种限制,促使我创建了这个库。
通过预先打包动态列,上述查询可以直接插入数据块
INSERT INTO mytable (attrs) VALUES (X'0401000300000003006B65792176616C7565')
除了使用Django ORM更容易实现之外,这种在Python中打包/解包动态列的方法还有一些优点
所有数据类型在Python中都得到了适当的保留。MariaDB提供拉回动态列字段所有值的唯一方法是调用COLUMN_JSON,但JSON只支持字符串和整数。此外,COLUMN_JSON的深度限制为10,但格式实际上没有限制。
打包/解包动态列的CPU开销从您的数据库服务器转移到您的(可能是更可扩展的)客户端。
API
所有函数和名称都可以作为mariadb_dyncol模块的属性访问,您可以使用import mariadb_dyncol导入该模块。
pack(mapping)
将给定的映射(一个dict)打包成MariaDB动态列格式,并以字节字符串的形式返回(Python 3的bytes,Python 2的str)。这适用于作为常规查询的一部分插入到表中。
dict的键必须全部是Unicode字符串,而值必须全部是支持的数据类型之一
int在-(2 ** 32) + 1和(2 ** 64) - 1之间(Python 2:也支持long)
str最多4GB,以UTF-8编码(Python 2:支持unicode)
float - 除了NaN或+/- inf之外的任何内容
datetime.datetime - 支持完整范围
datetime.date - 支持完整范围
datetime.time - 支持完整范围
任何符合这些规则的dict,允许嵌套键。除了MariaDB的COLUMN_JSON函数限制深度为10之外,没有嵌套限制
请注意,这不支持MariaDB也支持(并自然会映射到Python的Decimal)的DECIMAL类型 - 打包/解包稍微有点复杂,尽管确实可能,而且欢迎提交pull请求。如果您尝试打包一个Decimal,将引发DynColNotSupported异常。
有关UTF-8编码的列名的其他限制,请参阅MariaDB文档
列名的最大长度为16383字节
所有列名的最大长度(在嵌套层次结构中的一级)为65535字节
所有其他不受支持的类型将引发DynColTypeError。超出范围的值将引发DynColValueError。
示例
>>> 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)
将MariaDB动态列数据编码的字节字符串解包成dict;您可以期望返回的类型如上所述。这适用于直接从MariaDB获取数据并在Python中解码,而不是使用MariaDB的COLUMN_JSON函数,保留JSON丢弃的类型。
如上所述,不支持DECIMAL值,解包将引发DynColNotSupported。此外,字符串仅使用MySQL字符集utf8或utf8mb4解码;具有其他字符集的字符串也将引发DynColNotSupported。
不受支持的列格式,例如旧的MariaDB编号动态列格式或损坏的数据,将引发DynColValueError。
示例
>>> 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}