четверг, 13 октября 2016 г.

Python: проблема с подключением к MSSQL при наличии триггера входа

История такова. Жил-был под линуксом скрипт, написанный когда-то на Python 2.7 и использующий pymssql, который успешно подключался к Microsoft SQL Server. В один прекрасный момент подключаться он перестал с ошибкой:
Logon failed for login 'huhmuh' due to trigger execution. DB-Lib error message 20018, severity 14:
General SQL Server error: Check messages from the SQL Server
DB-Lib error message 20002, severity 9:
Adaptive Server connection failed

Расследование выявило интересные вещи. Оказывается, pymssql использовал FreeTDS, который, собственно, и заглючил. Обмен FreeTDS можно подслушать примерно так:
import os
import pymssql

os.environ['TDSDUMP'] = 'stdout'

conn = pymssql.connect(host='mySQLserver', user='huhmuh', password='', charset='UTF-8', database='master', appname='my Application')
conn.close()
Анализ дампа выявил, что используется FreeTDS версии 0.91. Обновление до версии 1.00 не помогло.

При этом в соседнем каталоге лежит другая программа, написанная на C, которая через unixODBC получает данные с того же сервера без всяких проблем. Дальнейшие раскопки показали, что этот самый unixODBC взаимодействует с сервером через Microsoft SQL Server Native Client.

В конце концов оказалось, что на сервере разработчики добавили триггер входа. При наличии этого триггера FreeTDS не может нормально подключиться к базе данных.

Как перенацелить pymssql на использование нативного клиента, найти не удалось, поэтому пришлось перетаскивать скрипт на pyodbc. Тут тоже нашлась пара подводных камней. Самый крупный из которых - ошибка при выполнении пакета команд в одном запросе: Error: No results. Previous SQL was not a query. В этом случае виноваты, во-первых, всякие сообщения сервера "1 rows affected", которые легко подавить командой SET NOCOUNT ON в начале запроса, и, во-вторых, результаты работы команд print, причудливо раскиданных разработчиками внутри хранимых процедур, используемых в нашем пакете. Эти последние подавить нельзя, поэтому пришлось часть пакетов переписывать в виде группы отдельных запросов.

В общем, тот ещё опыт.

Комментариев нет:

Отправить комментарий