2014-02-07 80 views
4

我怎麼做的方式是安全的SQLAclhemy ORM IN搜索不敏感的情況下?SQLAlchemy不區分大小寫IN基於搜索查詢?

我自己和其他人在我的項目已經看過了這一點,但我們不能似乎發現了什麼適合我們的需要。

在原始的SQL我可以這樣做:

SELECT * FROM TABLENAME WHERE UPPER(FIELDNAME) IN (UPPER('foo'), UPPER('bar')); 

..如果FOO和BAR都不在未知的情況下,用戶的輸入。正因爲如此,我擔心的是以下幾點:

  1. 安全:我不想從鮑比表(http://xkcd.com/327/)在SQL注入的形式訪問Attack.and我找不到,告訴我的文檔如何在SQLAlchemy中轉義字符串,或者我會覺得加入字符串更安全(但仍然覺得髒)。
  2. 速度的處理主要是通過索引,但顯然,發出的查詢會比告訴DB做得更快之前做的情況下更正內存,所以我不會去做上查詢,除非我真的服了。然而,以上是展示我想要做什麼的最佳方式。但是,它不應該做任何瘋狂的事情。
  3. 平臺無關的代碼。我將在多個數據庫類型運行這一點 - 它要進行全面的測試是我對此事的任何說 - 我不希望查詢綁定到SQL的一個特定的對話框。畢竟,我爲什麼使用SQLAlchemy。 :)

如果有幫助,我們目前綁定到8.4版本的SQLAlchemy由於我們使用其他庫。

回答

8

這應該編譯正是...

query(models.Object)\ 
.filter( 
    sqlalchemy.func.upper(models.Object.fieldname)\ 
    .in_((sqlalchemy.func.upper(foo) , sqlalchemy.func.upper(bar),)) 
)\ 
.all() 

  1. 你也可以只通過在大寫文字。親自,我會做in_(foo.uppercase() , bar.uppercase())

  2. SqlAlchemy與DBAPI一起將綁定參數傳遞到後端數據存儲中。翻譯 - 值會自動轉義。


,如果你想要做一個字符串列表,這樣的事情應該工作

.in_([ i.upper() for i in inputs ]) 
.in_([ sqlalchemy.func.upper(i) for i in inputs ]) 

只是想補充一點,如果你想優化這些選擇的速度,並且在Postgres或Oracle上,您可以創建一個'函數索引'

CREATE INDEX table_fieldname_lower_idx ON table(lower(fieldname)) 

查詢規劃器(在數據庫中)將知道在使用lower(fieldname)查詢進行搜索時使用lower(fieldname)索引。

+0

所以,如果我輸入的是什麼字符串列表? – honestduane

+0

我的第一篇文章使用了錯誤的語法。 in_期望可迭代。所以你可以拋出一個列表,list_comprehension,generator,lambda/map /等。 –

+1

將此設置爲答案;我的團隊和Bobby Table的母親都非常感謝你。 – honestduane