[英]Dialect-specific SQLAlchemy declarative Column defaults
簡潔版本
在SQLAlchemy的ORM列聲明中,如何在一個方言中使用server_default=sa.FetchedValue()
在另一個方言中使用default=somePythonFunction
,這樣我的真實DBMS可以使用觸發器填充內容,我的測試代碼可以針對sqlite編寫?
背景
我正在使用SQLAlchemy的聲明性ORM來處理Postgres數據庫,但是嘗試針對sqlite:///:memory:
編寫單元測試,並且遇到了在主鍵上計算了默認值的列的問題。 最小的例子:
CREATE TABLE test_table(
id VARCHAR PRIMARY KEY NOT NULL
DEFAULT (lower(hex(randomblob(16))))
)
SQLite本身對這個表定義( sqlfiddle )非常滿意,但是SQLAlchemy似乎無法計算出新創建的行的ID。
class TestTable(Base):
__tablename__ = 'test_table'
id = sa.Column(
sa.VARCHAR,
primary_key=True,
server_default=sa.FetchedValue())
像這樣的定義在postgres中工作得很好,但是當我調用Session.commit
時,死在sqlite中(正如你在Ideone上看到的那樣 )和FlushError
:
sqlalchemy.orm.exc.FlushError
:實例<TestTable at 0x7fc0e0254a10>
具有NULL
身份密鑰。 如果這是自動生成的值,請檢查數據庫表是否允許生成新的主鍵值,以及映射的Column對象是否配置為期望這些生成的值。 還要確保此flush()
沒有在不適當的時間發生,例如在load()
事件中。
FetchedValue
的文檔警告我們,這可能發生在不支持INSERT
上的RETURNING
子句的方言上 :
對於使用觸發器生成主鍵值的特殊情況,並且正在使用的數據庫不支持RETURNING子句,可能需要放棄使用觸發器,而是將SQL表達式或函數應用為“預執行”表達:
t = Table('test', meta, Column('abc', MyType, default=func.generate_new_value(), primary_key=True) )
func.generate_new_value
沒有在SQLAlchemy中的任何其他地方定義 ,因此它們似乎打算在Python中生成默認值,或者編寫一個單獨的函數來執行SQL查詢以在DBMS中生成默認值。 我可以這樣做,但問題是,我只想為SQLite做這 FetchedValue
,因為FetchedValue
完全符合我想要的postgres。
死胡同
子類化Column
可能不起作用。 我在源中找不到任何內容,告訴Column使用什么方言, default
和server_default
字段的行為是在類外定義的
編寫一個在真實DBMS上手動調用觸發器的python函數會產生競爭條件。 通過更改隔離級別來避免競爭條件會導致死鎖。
我當前的解決方法
糟糕,因為它打破了連接到真正的postgres的集成測試。
import sys
import sqlalchemy as sa
def trigger_column(*a, **kw):
python_default = kw.pop('python_default')
if 'unittest' in sys.modules:
return sa.Column(*a, default=python_default, **kw)
else
return sa.Column(*a, server_default=sa.FetchedValue(), **kw)
不是直接回答你的問題,但希望對某人有幫助
我的問題是想要根據方言改變整理,這是我的解決方案:
from sqlalchemy import Unicode
from sqlalchemy.ext.compiler import compiles
@compiles(Unicode, 'sqlite')
def compile_unicode(element, compiler, **kw):
element.collation = None
return compiler.visit_unicode(element, **kw)
這會僅為sqlite更改所有Unicode列的排序規則。
這里有一些文檔: http : //docs.sqlalchemy.org/en/latest/core/custom_types.html#overriding-type-compilation
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.