簡體   English   中英

SQLAlchemy中的按位運算符:使用Oracle數據庫時出錯

[英]Bitwise operator in SQLAlchemy: Error when using Oracle Database

我需要使用按位邏輯AND / OR編寫一些查詢,但是僅當我使用oracle數據庫時,才會收到以下錯誤:

sqlalchemy.exc.DatabaseError:(cx_Oracle.DatabaseError)ORA-01036:非法變量名稱/編號[SQL:'SELECT“ Cars”。“ Id”,“ Cars”。“ Name”,“ Cars”。“ Price” \\ nFROM “汽車” \\ nWHERE(“汽車”。“價格”&:Price_1)>:param_1'] [參數:{'Price_1':32768,'param_1':0}]

如果我使用PostgreSql或Sqlite,則會收到預期的答案。

create_engine('sqlite:///cars.sqlite3')好! create_engine('postgresql + psycopg2:// xxx:yyy @ localhost:5432 / db_sql_alchemy')OK! create_engine('oracle + cx_oracle:// xxx:yyy @ localhost:49161 / xe')錯誤!

其他操作(例如select,where子句,表創建)在所有3個數據庫中均按預期工作。

看着錯誤日志,似乎查詢未正確轉換為oracle語法。 我期待這樣的事情:

從“汽車”中選擇“汽車”。“ Id”,“汽車”。“名稱”,“汽車”。“價格”(BitAnd(“汽車”。“價格”,32768)> 0);

產生錯誤的操作是:

stm = stm.where(cars.c.Price.op('&')(0x8000)> 0)

我正在使用Python 2.7.12和SQLAlchemy == 1.1.2。

這是一個創建自定義運算符的示例,該運算符在不同的后端進行不同的編譯:

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.elements import ColumnElement, Visitable, Grouping
from sqlalchemy.sql.operators import custom_op, is_precedent

class BitwiseAnd(ColumnElement):
    type = Integer()
    operator = custom_op("&", precedence=6)

    def __init__(self, left, right):
        if not isinstance(left, Visitable):
            left = bindparam("bitand", left, unique=True)
        if not isinstance(right, Visitable):
            right = bindparam("bitand", right, unique=True)
        self.left = left
        self.right = right

    def self_group(self, against=None):
        if is_precedent(self.operator, against):
            return Grouping(self)
        else:
            return self


@compiles(BitwiseAnd)
def _compile_bitwise_and(element, compiler, **kwargs):
    left = element.left.self_group(against=element.operator)
    right = element.right.self_group(against=element.operator)
    return compiler.process(element.operator(left, right))


@compiles(BitwiseAnd, "oracle")
def _compile_bitwise_and_oracle(element, compiler, **kwargs):
    return compiler.process(func.BITAND(element.left, element.right))

q = select([BitwiseAnd(BitwiseAnd(1, 2), BitwiseAnd(3, 4))])
print(q.compile(dialect=mysql.dialect()))
# SELECT (%s & %s) & (%s & %s) AS anon_1
print(q.compile(dialect=oracle.dialect()))
# SELECT BITAND(BITAND(:bitand_1, :bitand_2), BITAND(:bitand_3, :bitand_4)) AS anon_1 FROM DUAL

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM