Проблема Psycopg2 не может адаптировать тип 'tuple', возникающая периодически
Недавно мы обновили Django & Python до следующей версии
Python 3.9.5, Django 3.2, Psycopg2 2.9.1, Httpd 2,4.2, Postgres 12.8
Заметили, что приложение периодически выходило из строя с ошибкой psycopg2.ProgrammingError: can't adapt type 'tuple'
Ниже приведены запрос и параметры, зарегистрированные перед выполнением cursor.execute()
{'employer_id': 200176, 'approximate_age_band': ('30-39', '50-59')
SELECT month_key as cadence_val, sum(eligible_count) as eligible
FROM xyz_table_name
WHERE employer_id = %(employer_id)s
AND approximate_age_band IN %(approximate_age_band)s GROUP BY 1 ORDER BY 1;
Ниже приведена полная трассировка стека
2021-10-27 05:00:52,280 [ERROR] django.request: Internal Server Error: mobile_report/reports
Traceback (most recent call last):
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: can't adapt type 'tuple'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/var/www/service_rest/service/api/views.py", line 375, in mobile_visits
data = get_report_data(request, "VisitsReport", src_employer_id)
File "/var/www/service_rest/service/api/views.py", line 453, in get_report_data
data = get_data(src_employer_id, filter_params, report_key, **params)
File "/var/www/service_rest/service/api/views.py", line 466, in get_data
data = report_obj.get_data(employer, filter_values, **params)
File "/var/www/service_rest/service/reports/pulse/mobile.py", line 49, in get_data
rows1, cadence_list = self.get_rows_from_query(cursor, sql1, employer_id, table_name,
File "/var/www/service_rest/service/reports/__init__.py", line 1415, in get_rows_from_query
cursor.execute(sql, params)
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/var/www/pulse_preprod/service/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.Error: can't adapt type 'tuple'
Во время нескольких попыток запрос работает нормально несколько раз (возвращая ожидаемые данные из БД), но случайным образом выдает эту ошибку.
Это вроде как исключает зависимость от python или расширение psycopg2 или проблемы с данными БД, верно?
Любая помощь будет принята с благодарностью.
Самым простым исправлением будет использование approximate_age_band
в качестве списка:
cur = connection.cursor()
values = {'employer_id': 200176, 'approximate_age_band': ['30-39', '50-59']}
query = """select *
from test t
where t.approximate_age_band = ANY(%(approximate_age_band)s)
"""
print(cur.mogrify(query, values).decode('utf-8')) # Show the executed SQL statement
cur.execute(query, values)
print(cur.fetchall())
Выход:
select *
from test t
where t.approximate_age_band = ANY(ARRAY['30-39','50-59'])
[
(None, None, 420, 509, '50-59'),
(None, None, 210, 508, '30-39')
]