Настройка MSDTS для работы с IBProvider
Привет.
Сегодня на email поддержки пришло письмо, из за которого пришлось прервать противоестественную увлекательную работу с IBProvider-ом из .NET кода. Письмо просило помощи в решении проблем с MSDTS. Суть проблемы, собственно говоря, проста — ничего не работает. Поскольку про это «не работает» уже было давно известно и уже были некоторые соображения по-этому поводу, я решил замучать эту тему «по-взрослому».
Немного по-подробнее о проблеме.
При попытке экспортировать данные из таблицы БД Firebird/Interbase через «Мастер импорта и экспорта SQL Server» свеже-установленного MSSQL 2008, после настройки источника (LCPI.IBProvider.3, разрешаем автоматические транзакции) и приемника (SQL Server Native Client 10.0), получается приблизительно такая картина:
Здесь «TEST_COLUMNS» — это тестовая таблица, структуру которой можно посмотреть в c:\Program Files (x86)\LCPI_IBProvider\TestCode\ActiveX\IBP\test_database\sql\test_columns.sql. Как видим, в столбце «тип» для «COL_BLOB_TEXT» указан идентификатор 130 (это OLEDB тип DBTYPE_WSTR) вместо имени. В подсказке же говорится, что исходный столбец имеет тип «BLOB SUB_TYPE TEXT».
У MSSQL есть интересный каталог «c:\Program Files\Microsoft SQL Server\100\DTS\MappingFiles», в котором хранятся XML-файлы с правилами преобразования типов между разными источниками.
После ряда экспериментов, с участием Firebird 2.5 и базой данных третьего диалекта, были созданы два файла IBProviderToMSSql10.xml и IBProviderToSSIS10.xml. Копируем эти файлы в «MappingFiles». Перезапускаем визард. Настраиваем источник и приемник. Выбираем «копирование данных из одной или нескольких таблиц или представлений». Выбираем нашу тестовую таблицу «TEST_COLUMNS» и смотрим на сопоставление столбцов (кнопка «изменить» в диалоге выбора таблиц):
Ага, зер гуд. Закрываем это окно и проходим все остальные окна визарда вплоть до запуска.
Нажимаем на кнопку «Готово» и видим:
Ну, вообщем, тоже известная проблема. MSDTS получает данные через IOpenRowset::OpenRowset и передает туда заковыченное имя таблицы. А провайдер такое не любит. Хотя раньше любил, но эту «функциональность» пришлось зарезать. Но это так, к слову.
Закрываем окно с ошибкой. Отматываем визард назад до выбора способа копирования. Говорим, что будем указывать запрос.
В этом случае MSDTS будет получать данные через команду (ICommand::Execute).
Указываем запрос.
Нажимаем далее. Здесь я отредактировал «пункт назначения» — заменил «[dbo].[Запрос]» на «[dbo].[TEST_COLUMNS]»
Можно нажать на «Изменить», чтобы еще раз посмотреть на сопоставление столбцов.
Так, теперь проматываем визард вперед до упора запуска. Запускаем копирование данных.
В моей адской таблице нет записей, она предназначена исключительно для тестирования работы с различными практически всеми видами простых колонок (исключая массивы).
Проделывание тех же самых операций для таблицы EMPLOYEE из стандартной базы данных, выдает на финише такую картинку:
Предупреждения (по всей видимости) вылазят из-за кодовой страницы NONE, которая используется для текстовых колонок employee.fdb. Такие данные передаются провайдером в виде мультибайтных строк (DBTYPE_STR), для которых подразумевается какая-нибудь кодовая страница. Об этом «копирователь» данных нас и предупреждает.
Теперь можно чем нибудь подключиться к той базе данных MSSQL, куда мы копировали данные, и визуально посмотреть что там и как.
Я еще до кучи экспериментировал с копированием RDB$PROCEDURES, «dbtype_rules=1″ и включением эмуляции типов. Все работает корректно. То есть правила, описанные в XML-ных файлах, охватывают все возможные типы колонок. Ну, кроме массивов, разумеется.
Обратное копирование из MSSQL в Interbase/Firebird.
Было бы странно (хотя не, не было бы) если бы я не попробовал скопировать данные обратно. Все хорошо, за исключением двух вещей.
1. Firebird не поддерживает BINARY и VARBINARY. Без них как-то проблематично описывать колонки с бинарным данными. В правилах нельзя написать что-то типа «CHAR(%SOURCE_STRING_LENGTH%) CHARACTER SET OCTETS». Потому что — смотри п.2.
2. Тупорылость Ограниченные возможности XML-ных файлов с правилами. Кстати, вот они, эти правила — DataTypeMapping.xsd. Могли бы и побольше возможностей дать. Вплоть до использования нормальных текстовых шаблонов для описания типов.
Так что вот. Что касается провайдера, то я найду время чтобы опционально вернуть зарезанную функциональность с IOpenRowset::OpenRowset. А вот насчет BINARY/VARBINARY — это обращайтесь к машинистам серверо-писателям. Тем более что эти типы вроде как введены в стандарт SQL 2008.
Kovalenko on 5 февраля, 2012
Вообщем, «пацан сказал, пацан сделал» 🙂
У меня была мысль создать пошаговую инструкцию в отдельной записи. Но потом решил ограничиться комментарием в к этой. Инструкцию создадим после полного осмысления сделанного 🙂
1. На сайт выложен новый триал (сборка 13110). Скачать и инсталлировать.
2. В каталоге «c:\Program Files (x86)\LCPI_IBProvider\Integrations» находятся файлы с правилами отображения типов (для копирования из Interbase/Firebird в MS SQL 2008): IBProviderToMSSql10.xml, IBProviderToSSIS10.xml. Их нужно скопировать в «{Folder with installation of Microsoft SQL Server 2008}\100\DTS\MappingFiles»
Поддержку для 2005 сервера я решил пока не делать.
Про обратное копирование из MSSQL 2008 я уже писал — там проблемы с описанием правил. Эти же проблемы относятся и к копированию между FB и IB.
3. В провайдер добавлено новое свойство инициализации «open_rowset__sql«. При работе с MS DTS (или SSIS) это свойство нужно выставить в true. Для того чтобы не копаться в километровом списке свойств (на странице «Все»), на дополнительную вкладку добавлен checkbox «SQL через OpenRowset». Ставим галочку и обретаем счастье.
4. Общие сведения по поводу перекачки данных
— Не забываем разрешать «автоматические транзакции». Включается на первой вкладке настроек.
— Про «open_rowset__sql=true» я уже сказал выше.
— Если текстовые данные хранятся в колонках с кодовой страницей NONE, то надо указать «ctype_none=<имя кодовой страницы данных>«. В противном случае могут быть всякие проблемы.
— По умолчанию, провайдер работает в UNICODE режиме — не надо его отключать.
— Если вы выгружаете данные из FB ниже v2.5 или из Interbase — укажите кодовую страницу подключения.
— Можно еще указать «dbtime_rules=1″, чтобы перенести данные TIME без потери микросекунд.
—
На этом, пожалуй, пока можно и остановиться.