python - sqlalchemy:如何为方言自定义标准类型(例如 DateTime() 参数绑定(bind)处理)?

标签 python apache-spark-sql sqlalchemy

给出以下代码片段

t = Table(
    "foo",
    MetaData(),
    Column("bar", DateTime()),
)
engine.execute(t.insert((datetime(1900, 1, 1),)))
engine.execute(t.insert(("1900-01-01",))) 

最后一条语句适用于 postgresql,但不适用于 Spark 例如

Cannot safely cast 'bar': string to timestamp
[SQL: INSERT INTO TABLE `foo` VALUES (%(bar)s)]
[parameters: {'bar': '1900-01-01'}]

我可以使用自定义类型来管理它,例如

class MyDateTime(TypeDecorator):
    impl = DateTime
    def process_bind_param(self, value, dialect):
        if dialect.name == "hive" and isinstance(value, str):
            return datetime.strptime(value, "%Y-%m-%d")
        return value


t = Table(
    "foo",
    MetaData(),
    Column("bar", MyDateTime()),
)

但解决方案

  • 当我们直接检查方言名称时,这看起来很hacky
  • 我需要为方言自定义现有类型,而不是实现新类型,因为我们有 DateTime 类型的代码库

sqlalchemy 有没有自定义现有类型的解决方案?

最佳答案

没有内置方法可以为特定方言自定义标准 SQLAlchemy 类型(例如 DateTime())的参数绑定(bind)处理。不过,您可以使用一些解决方法。

一种解决方法是创建一个自定义类型来包装标准类型并重写 process_bind_param() 方法。例如,以下代码显示了一个自定义类型,该类型重写 process_bind_param() 方法以将字符串转换为 Hive 方言的日期时间对象:

class MyDateTime(TypeDecorator):
    impl = DateTime

    def process_bind_param(self, value, dialect):
        if dialect.name == "hive" and isinstance(value, str):
            return datetime.strptime(value, "%Y-%m-%d")
        return value

然后,您可以在 SQLAlchemy 架构中使用此自定义类型,而不是标准 DateTime() 类型。例如:

t = Table(
    "foo",
    MetaData(),
    Column("bar", MyDateTime()),
)

另一个解决方法是使用自定义方言来覆盖标准 DateTime() 类型的 bind_param() 方法。例如,以下代码显示了一个自定义方言,该方言重写 bind_param() 方法以将字符串转换为 Hive 方言的日期时间对象:

class MyHiveDialect(postgresql.PGDialect):
    def bind_param(self, value, type_):
        if type_ == DateTime and isinstance(value, str):
            return datetime.strptime(value, "%Y-%m-%d")
        return super().bind_param(value, type_)

然后,您可以在创建 SQLAlchemy 引擎时使用此自定义方言。例如:

engine = create_engine("postgresql://localhost/foo", dialect=MyHiveDialect())

您选择哪种解决方法取决于您的具体需求。如果您只需要为单一方言的特定类型自定义参数绑定(bind)处理,那么第一个解决方法可能是最简单的解决方案。如果您需要为多种类型或多种方言自定义参数绑定(bind)处理,那么第二种解决方法可能是更好的解决方案。

请注意,这两种解决方法都被认为是“hacky”解决方案。没有官方方法可以为特定方言的标准 SQLAlchemy 类型自定义参数绑定(bind)处理。如果您需要这样做,那么您应该意识到您的代码可能很脆弱,并且可能无法与 SQLAlchemy 的 future 版本一起使用。

关于python - sqlalchemy:如何为方言自定义标准类型(例如 DateTime() 参数绑定(bind)处理)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77018288/

相关文章:

python - 如何将 Google Cloud Firestore 本地模拟器用于 python 和测试目的

python - 如何让 Python 分析器工作?

scala - 不支持的文字类型类 scala.runtime.BoxedUnit

scala - 在 Scala Spark 中将 csv 文件作为数据帧读取时提供架构

python - 解析 sqlalchemy 存储过程执行的结果

python - 如何在 SQLAlchemy 中的主节点上两次加入详细信息?

python - 从字符串中删除范围内的字符

android - 如何在 Python 中将 Google 帐户身份验证添加到 Google Cloud Endpoints

python - 如何在 PySpark 中将行值(时间序列)转置为列值?

python-3.x - SQLAlchemy 表达式语言和 SQLite 的删除级联