Как я могу сравнить два запроса SQLAlchemy, если они совпадают? - PullRequest
7 голосов
/ 24 октября 2019

У меня есть функция, возвращающая объект запроса SQLAlchemy, и я хочу проверить эту функцию, чтобы она строила правильный запрос.

Например:

import sqlalchemy

metadata = sqlalchemy.MetaData()
users = sqlalchemy.Table(
    "users",
    metadata,
    sqlalchemy.Column("email", sqlalchemy.String(255), nullable=False, unique=True),
    sqlalchemy.Column("username", sqlalchemy.String(50), nullable=False, unique=True),
)

def select_first_users(n):
    return users.select().limit(n)

def test_queries_are_equal(self):
    expected_query = users.select().limit(10)
    assert select_first_users(10) == expected_query  # fails here
    assert select_first_users(10).compare(expected_query)  # fails here too

Я понятия не имею, как сравниватьдва запроса на равенство. == здесь не работает, потому что, насколько я вижу, у этих объектов не определен метод __eq__, поэтому он сравнивает объекты по адресу в памяти и, безусловно, дает сбой. Метод compare также выполняет сравнение is.

Единственное решение, которое я вижу, выглядит так:

assert str(q1.compile()) == str(q2.compile())

, но странно и вместо него содержит заполнителифактических значений.

Так как я могу сравнить два запроса SQLAlchemy на равенство?

Я использую Python 3.7.4, SQLAlchemy==1.3.10.

1 Ответ

1 голос
/ 28 октября 2019

В функции компиляции есть параметр, который решает проблему заполнителя query.compile (compile_kwargs = {"literal_binds": True}), поэтому вместо

SELECT users.email,
       users.username
FROM users
LIMIT :param_1

вы получите

SELECT users.email,
       users.username
FROM users
LIMIT 10

Так что я думаю, что вы могли бы сделать что-то подобное

import sqlparse

def format_query(query):
    return sqlparse.format(str(query.compile(compile_kwargs={"literal_binds": True})), 
                           reindent=True, keyword_case='upper')


def test_queries_are_equal():
    expected_query = users.select().limit(10)
    assert format_query(expected_query) == format_query(select_first_users(10))

Если сравнение основано на точном совпадении строк, я думаю, что лучше обеспечить согласованное форматирование, следовательно, использование sqlparse.

Собственно он обрабатывает только int и строки, но его можно расширить, см. Документацию https://docs.sqlalchemy.org/en/13/faq/sqlexpressions.html#faq-sql-expression-string

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...