【问题标题】:How can I do REGEXP_REPLACE in SQLAlchemy with SQLite?如何使用 SQLite 在 SQLAlchemy 中执行 REGEXP_REPLACE?
【发布时间】:2020-07-18 06:04:42
【问题描述】:

我有一个 Postgres 支持的网站,并使用 REGEXP_REPLACE 替换某些列中值的第一个实例。这可以。问题出现在我需要运行 CI 的地方,并且出于某种原因(Github Actions 和 Windows VM 的限制),我无法在测试中使用 Postgres。

选择 SQLite 产生了一些测试失败,我意识到 SQLite 没有内置 REGEXP_REPLACE

    def do_execute(self, cursor, statement, parameters, context=None):
>       cursor.execute(statement, parameters)
E       sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such function: regexp_replace
E       [SQL: SELECT job_site.created_at AS job_site_created_at, ..., job_site.neighborhood_id AS job_site_neighborhood_id 
E       FROM job_site 
E       WHERE regexp_replace(job_site.name, ?, ?) = ?]
E       [parameters: (' - ', ':', 'BGS:NEEA - 1894 - 05700 Brown Islands Suite 681')]
E       (Background on this error at: http://sqlalche.me/e/e3q8)

如何在 SQLAlchemy 中将此函数添加到 SQLite?

【问题讨论】:

    标签: python sqlite sqlalchemy regexp-replace


    【解决方案1】:

    最终解决方案是将regexp_replace 注册为GenericFunction (docs),并添加一个特定方言的编译器(docs),以便在运行SQLite 引擎时使用。

    from sqlalchemy.ext.compiler import compiles
    from sqlalchemy.sql.functions import GenericFunction
    
    
    class regexp_replace(GenericFunction):
        type = String
        identifier = "regexp_replace"
    
    
    @compiles(regexp_replace, "sqlite")
    def visit_regexp_replace(element, compiler, **kw):
        column, pattern, replacement = list(element.clauses)
        return (
            f"SUBSTR({column}, 0, INSTR ({column}, '{pattern.value}')) "
            f"|| '{replacement.value}' "
            f"|| SUBSTR({column}, INSTR ({column}, '{pattern.value}') + LENGTH('{pattern.value}'))"
        )
    

    也可以按照here 的建议使用 SQLite C 扩展,但我没有考虑过这样做。

    【讨论】:

    • 另一种可用的技术是在 SQLite 中将 Python 函数注册为 regexp_replacedocs.python.org/3/library/…。这将允许您执行实际的正则表达式替换。
    • @IljaEverilä 我确实在文档中看到了这一点,但不清楚何时/何时使用 SQLAlchemy 进行注册
    • 一种选择是在创建 DB-API 连接时执行此操作。在 SQLite 中启用外键检查的部分中有一个示例:docs.sqlalchemy.org/en/13/dialects/…
    猜你喜欢
    • 1970-01-01
    • 2011-02-06
    • 2018-12-06
    • 2019-03-27
    • 2014-02-11
    • 1970-01-01
    相关资源
    最近更新 更多