gpt4 book ai didi

python - SQLAlchemy 中的编译扩展 : functions used in indexes

转载 作者:行者123 更新时间:2023-11-28 21:56:02 25 4
gpt4 key购买 nike

我想在 SQLAlchemy 中创建一个不区分大小写的唯一约束,它适用于 Postgres 和 SQLite。

在 Postgres 中是这样实现的:

  • SQL: 在 my_table (lower(my_field)) 上创建唯一索引 my_index;
  • SQLAlchemy:Index('my_index', func.lower(my_field), unique=True)

在 SQLite 中,它是通过以下方式实现的:

  • SQL: CREATE UNIQUE INDEX my_index ON my_table (my_field COLLATE NOCASE);
  • SQLAlchemy:Index('my_index', collat​​e(my_field, 'nocase'), unique=True)

所以我尝试子类化 FunctionElement 以创建我自己的类似函数的构造,它将编译为 my_field COLLATE NOCASElower (my_field) 取决于 DBMS。我试着关注 the guide to compilation extension ,但我收到一个错误(请参阅下面的回溯),我可以通过 SQLAlchemy 源代码进行跟踪,但我无法理解。我尝试子类化其他东西,例如 ColumnElementColumnClauseClauseElement,但我遇到了类似的错误。

这是重现错误的代码。我使用了 SQLAlchemy 的 0.8.2 版。

from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.types import TypeDecorator, VARCHAR
from sqlalchemy import func, Index, collate
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import (
# Not sure which one to subclass
FunctionElement, ColumnElement, ColumnClause, ClauseElement
)


engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()


class CaseInsensitive(FunctionElement):
name = 'CaseInsensitive'
type = VARCHAR()


@compiles(CaseInsensitive, 'sqlite')
def case_insensitive_sqlite(element, compiler, **kw):
arg1, = list(element.clauses)
return collate(compiler.process(arg1), 'nocase')


@compiles(CaseInsensitive, 'postgresql')
def case_insensitive_postgresql(element, compiler, **kw):
arg1, = list(element.clauses)
return func.lower(compiler.process(arg1))


class MyTable(Base):

__tablename__ = 'my_table'

id = Column(Integer, primary_key=True)

my_field = Column(String)

__table_args__ = (
Index('idx', CaseInsensitive(my_field), unique=True),
)

Traceback (most recent call last):
File "tmp.py", line 33, in <module>
class MyTable(Base):
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 50, in __init__
_as_declarative(cls, classname, cls.__dict__)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 222, in _as_declarative
**table_kw)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/schema.py", line 332, in __new__
table._init(name, metadata, *args, **kw)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/schema.py", line 400, in _init
self._init_items(*args)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/schema.py", line 65, in _init_items
item._set_parent_with_dispatch(self)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/events.py", line 236, in _set_parent_with_dispatch
self._set_parent(parent)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/schema.py", line 2421, in _set_parent
ColumnCollectionMixin._set_parent(self, table)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/schema.py", line 2035, in _set_parent
self.columns.add(col)
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2477, in add
self[column.key] = column
File "/Users/vladimir/git/wb/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2296, in __getattr__
key)
AttributeError: Neither 'CaseInsensitive' object nor 'Comparator' object has an attribute 'key'

最佳答案

@compiles 方法必须返回一个字符串。此外,Index 在此处遍历函数元素的方式存在一些问题,因此我们需要一个小的解决方法:

class CaseInsensitive(FunctionElement):
__visit_name__ = 'notacolumn'
name = 'CaseInsensitive'
type = VARCHAR()


@compiles(CaseInsensitive, 'sqlite')
def case_insensitive_sqlite(element, compiler, **kw):
arg1, = list(element.clauses)
return compiler.process(collate(arg1, 'nocase'), **kw)


@compiles(CaseInsensitive, 'postgresql')
def case_insensitive_postgresql(element, compiler, **kw):
arg1, = list(element.clauses)
return compiler.process(func.lower(arg1), **kw)

关于python - SQLAlchemy 中的编译扩展 : functions used in indexes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22154917/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com