Skip to main content

RQLite 的非官方 python 客户端

项目描述

rqdb

这是rqlite的非官方 python 客户端,一个基于 SQLite 的轻量级分布式关系数据库。

此客户端支持 SQLite 语法、真正的参数化查询和让人想起 DB API 2.0 的调用语法。

此外,此客户端具有与底层 rqlite API 匹配的便捷异步方法。

安装

pip install rqdb

用法

同步查询:

import rqdb
import secrets

conn = rqdb.connect(['127.0.0.1:4001'])
cursor = conn.cursor()
cursor.execute('CREATE TABLE persons (id INTEGER PRIMARY KEY, uid TEXT UNIQUE NOT NULL, name TEXT NOT NULL)')
cursor.execute('CREATE TABLE pets (id INTEGER PRIMARY KEY, name TEXT NOT NULL, owner_id INTEGER NOT NULL REFERENCES persons(id) ON DELETE CASCADE)')

# standard execute
cursor.execute('INSERT INTO persons (uid, name) VALUES (?, ?)', (secrets.token_hex(8), 'Jane Doe'))
assert cursor.rows_affected == 1

# The following is stored in a single Raft entry and executed within a transaction.

person_name = 'John Doe'
person_uid = secrets.token_urlsafe(16)
pet_name = 'Fido'
result = cursor.executemany3((
    (
        'INSERT INTO persons (uid, name) VALUES (?, ?)',
        (person_uid, person_name)
    ),
    (
        'INSERT INTO pets (name, owner_id) '
        'SELECT'
        '  ?, persons.id '
        'FROM persons '
        'WHERE uid = ?',
        (pet_name, person_uid)
    )
)).raise_on_error()
assert result[0].rows_affected == 1
assert result[1].rows_affected == 1

异步查询:

import rqdb
import secrets

async def main():
    async with rqdb.connect_async(['127.0.0.1:4001']) as conn:
        cursor = conn.cursor()

        result = await cursor.execute(
            'INSERT INTO persons (uid, name) VALUES (?, ?)',
            (secrets.token_hex(8), 'Jane Doe')
        )
        assert result.rows_affected == 1

附加的功能

读取一致性

在游标级别选择读取一致性,可以通过传递 read_consistency给游标构造函数 ( conn.cursor()) 或直接设置实例变量read_consistency。可用的一致性是strongweaknone。您还可以freshness在光标级别指示值。

有关详细信息,请参阅CONSISTENCY.md

默认一致性是weak.

外键

rqlite 中的外键支持默认禁用,以匹配 sqlite。这是一个常见的混淆来源。它不能由客户端可靠地配置。如 FOREIGN_KEY_CONSTRAINTS.md中所述启用外键支持

空值

在参数化查询中替换“NULL”可能容易出错。特别是,sqlite 需要以非常特殊的方式发送 null,而 rqlite 服务器历来没有正确处理。

默认情况下,如果您尝试使用“None”作为查询的参数,此包将在正确的位置执行值为“NULL”的字符串替换。但是要小心 - 您仍然需要在查询中正确处理空值,因为“col = NULL”和“col IS NULL”不一样。特别NULL = NULL 是 is NULL,它的计算结果为假。一种可以处理的方法是

name: Optional[str] = None

# never matches a row since name is None, even if the rows name is null
cursor.execute('SELECT * FROM persons WHERE name = ?', (name,))

# works as expected
cursor.execute('SELECT * FROM persons WHERE ((? IS NULL AND name IS NULL) OR name = ?)', (name, name))

备份

可以使用 启动备份conn.backup(filepath: str, raw: bool = False)。下载将流式传输到给定的文件路径。支持 sql 格式和压缩的 sqlite 格式。

日志记录

默认情况下,这将使用标准logging模块记录。这可以log=Falseconnect通话中禁用。如果需要记录但只需要稍微配置,可以按如下方式完成:

import rqdb
import logging

conn = rqdb.connect(
    ['127.0.0.1:4001'],
    log=rqdb.LogConfig(
        # Started a SELECT query
        read_start={
            'enabled': True,
            'level': logging.DEBUG,  # alternatively, 'method': logging.debug
        },

        # Started a UPDATE/INSERT query
        write_start={
            'enabled': True,
            'level': logging.DEBUG,
        },

        # Got the response from the database for a SELECT query
        read_response={
            'enabled': True,
            'level': logging.DEBUG,,
            'max_length': 1024,  # limits how much of the response we log
        },

        # Got the response from the database for a UPDATE/INSERT query
        write_response={
            'enabled': True,
            'level': logging.DEBUG,
        },

        # Failed to connect to one of the nodes.
        connect_timeout={
            'enabled': True,
            'level': logging.WARNING,
        },

        # Failed to connect to any node for a query
        hosts_exhausted={
            'enabled': True,
            'level': logging.CRITICAL,
        },

        # The node returned a status code other than 200-299 or
        # a redirect when a redirect is allowed.
        non_ok_response={
            'enabled': True,
            'level': logging.WARNING
        }
    )
)

限制

交易缓慢

主要限制是由于 rqlite 的无连接特性,虽然事务是可能的,但必须预先指定整个事务。也就是说,您不能打开事务、执行查询,然后在关闭事务之前使用该查询的结果执行另一个查询。

这也可以看作是一种祝福,因为这些类型的事务是传统应用程序中最常见的性能问题来源。它们需要很容易导致 N^2 性能的长期持有的锁。使用 uid 几乎总是可以实现相同的行为,如示例中所示。重复的 UID 查找会导致一致的开销,这对于长事务的不可预测的负反馈循环性质非常可取。

其他注意事项

在处理复杂查询时,将此库与pypika等 sql 构建器结合起来通常很有帮助。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

rqdb-1.0.9.tar.gz (20.4 kB 查看哈希

已上传 source

内置分布

rqdb-1.0.9-py3-none-any.whl (24.7 kB 查看哈希

已上传 py3