2016-10-31 50 views
2

我是唯一一個有這個問題的人嗎?SQLAlchemy轉換爲二進制(N)

我想寫的表達,這將等同於這個SQL在MySQL上運行:

select * from table1 where table1.some_column = cast('xyz' as Binary(32)) 

我在SQLAlchemy中試圖爲:

session.Query(table1) 
.filter(table1.some_column == cast('xyz', Binary(length=32)) 
.all() 

然而,這是不正確地翻譯成:

select * from table1 where table1.some_column = cast('xyz' as Binary) 

任何想法?

我試着類似,但使用的,而不是二進制數字類型,和它的工作如預期。

+0

我最初的想法是,任何列聲明爲'二進制( N)'在MySQL中的任何'Binary(n)'時總是與'N'的值在0和255之間相同。例如,MSSQL/SQLAlchemy中的整數列只需要知道max-length知道是否使用tinyint,smallint,int或bigint。在他們各自的範圍內,我認爲價值並不重要。 – sytech

+0

如果我嘗試執行沒有長度參數的查詢二進制類型,我沒有得到任何結果。如果我用二進制類型的長度參數執行它,我得到一行作爲結果。就那麼簡單。 – buhtla

回答

1

你不必改變SQLAlchemy的來源得到它以不同的編譯東西。編譯BinaryBINARY的相關代碼here

class MySQLCompiler(compiler.SQLCompiler): 
    ... 

    def visit_typeclause(self, typeclause, type_=None): 
     if type_ is None: 
      type_ = typeclause.type.dialect_impl(self.dialect) 
     if isinstance(type_, sqltypes.TypeDecorator): 
      return self.visit_typeclause(typeclause, type_.impl) 
     elif isinstance(type_, sqltypes.Integer): 
      if getattr(type_, 'unsigned', False): 
       return 'UNSIGNED INTEGER' 
      else: 
       return 'SIGNED INTEGER' 
     elif isinstance(type_, sqltypes.TIMESTAMP): 
      return 'DATETIME' 
     elif isinstance(type_, (sqltypes.DECIMAL, sqltypes.DateTime, 
           sqltypes.Date, sqltypes.Time)): 
      return self.dialect.type_compiler.process(type_) 
     elif isinstance(type_, sqltypes.String) \ 
       and not isinstance(type_, (ENUM, SET)): 
      adapted = CHAR._adapt_string_for_cast(type_) 
      return self.dialect.type_compiler.process(adapted) 
     elif isinstance(type_, sqltypes._Binary): 
      return 'BINARY' # <-------------------------------- RIGHT HERE 
     elif isinstance(type_, sqltypes.JSON): 
      return "JSON" 
     elif isinstance(type_, sqltypes.NUMERIC): 
      return self.dialect.type_compiler.process(
       type_).replace('NUMERIC', 'DECIMAL') 
     else: 
      return None 

所以,我們只需要截取的是與我們自己的編譯邏輯:

from sqlalchemy.sql.elements import TypeClause 
from sqlalchemy.types import _Binary 
from sqlalchemy.ext.compiler import compiles 

@compiles(TypeClause, "mysql") 
def _compile_typeclause(element, compiler, **kwargs): 
    if isinstance(element.type, _Binary): 
     t = "BINARY" 
     if element.type.length: 
      t += "({})".format(element.type.length) 
     return t 
    return compiler.visit_typeclause(element, **kwargs)