如何使用 SQLite 在 SQLAlchemy 中执行 REGEXP_REPLACE?

How can I do REGEXP_REPLACE in SQLAlchemy with SQLite?

我有一个 Postgres 支持的网站,并使用 REGEXP_REPLACE 替换某些列中值的第一个实例。这可以。问题出在我需要 运行 CI 的地方,出于一个原因和另一个原因(Github 操作和 Windows 虚拟机的限制),我无法在我的系统中使用 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?

解决方案原来是将 regexp_replace 注册为 GenericFunction (docs), and add a dialect-specific compiler (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}'))"
    )

也可以按照建议使用 SQLite C 扩展 ,但我没有考虑让它工作。