четверг, 1 декабря 2011 г.

История одного расследования (missing expression).

Всем привет.

Хочу рассказать историю, как я пытался создать простой интерфейс, нашел "ошибку" в одном из модулей знаний свежего ODI и как я узнал, где используется то, что я не понимал зачем нужно.

Часть 1.
Решил я создать интерфейс. Интерфейс должен был затянуть данные из одной таблицы в Oracle в другую таблицу в Oracle, но на другом сервере. Для того, чтобы данный интеграционный процесс заработал, необходимо было правильно создать серверы данных, прописать схемы и контексты, об этом есть немного в описании инсталляции ODI.

Создавал я его в новой версии ODI, которая 11g, поэтому, предварительно, импортировал в репозиторий необходимые мне модули знаний, в частности LKM Oracle to Oracle (DBLINK) и IKM Oracle Incremental Update. Об инсталляции ODI 11g расскажу как-нибудь в следующий раз, но, честно говоря, у меня получилось сделать это по той же схеме, что и для 10й версии (читал документацию, если что-то было неясно ;).

После создания нового интерфейса пытался его запускать. Как и планировалось, ODI для загрузки данных с другого сервера применял следующий алгоритм:
  1. Создание таблицы или представления на сервере источнике, для выборки данных из таблиц этого сервера данных.
  2. Удаление синонима на целевом сервере.
  3. Создание синонима к таблице или представлению из пункта 1 на целевом сервере.
  4. Выполнение интеграционного модуля знаний, в котором одним из источников является созданный в предыдущем пункте синоним.
  5. Удаление синонима на целевом сервере.
  6. Удаление таблицы или представления на сервере источнике.

В указанном LKM есть опция автоматического создания необходимого линка из целевой СУБД в источник (дблинк), я даже попробовал ее использовать, но мне не очень понравился результат. Но об этом тоже в следующий раз.

Итак, после пяти - десяти запусков и исправлений в Топологии и интерфейсе, я добрался таки до шага IKM, называемого Insert flow into I$ table, т.е. до процесса заполнения флоу таблицы данными из источника. Вернее, добрался до этого шага процесс выполнения интерфейса. На этом шаге Oracle, выполнявший сгенерированный ODI код, показал ошибку под номером ORA-00936 или - отсутствует выражение.

Дальше будут картинки. В том числе.

Часть 2.
Смотрим на код, который вызвал ошибку:


Между выражением where и первым условием находится ключевое слово and. Неужели в модуле знаний есть ошибка, и там не используется стандартный подход, когда в каждое where выражение добавляется некое всегда выполняющееся условие, вроде 1 = 1?

Откроем соответствующий шаг модуля знаний и посмотрим:


Действительно, так и есть. Сейчас быстро добавим туда 1 = 1 и все будет как нужно. Странно, конечно, что такой явный баг не заметили и не исправили очень давно. Хотя...

Что-то такое вспоминается, связанное с параметрами методов подстановки, манипулируя которыми можно для первой строки из последовательности получить один префикс, а для остальных другой. Специально открываю заметку с описанием методов подстановки ODI (часть 2) и вижу там описание нужного метода. Еще один внимательный просмотр кода модуля знаний показывает, что там всё верно:


В первую очередь генерируются строки без and в начале, но для колонок с установленным значением флага UK, затем уже генерируются строки для следующего блока колонок без флага UK, и перед этими строками будет стоять ключевое слово and.

Значит, у меня в интерфейсе нет ни одной колонки с флагом UK. Ну, думаю, скорее всего об этом написано в описании к модулю знаний. Наверняка описано.

Так и есть:


Часть 3.
Я начал искать, где же необходимо устанавливать этот флаг в интерфейсе ODI? Опущу длительные описания, хотя я даже запускал 10ю версию, чтобы поискать в более привычном для меня интерфейсе интерфейса. В конце концов выяснилось следующее.

При создании интерфейса, при перетаскивании таблицы из модели в целевую область, если у данной таблицы есть заданный первичный ключ, и он был сохранен в свойствах таблицы, то ODI автоматически выберет этот первичный ключ как ключ обновления:


При этом в целевой области рядом с колонкой появится соответствующая пиктограмма - желтый ключик:


Но если вы не внесете в маппинг для этой колонки никакого значения, сохраните и закроете интерфейс, а затем откроете его снова, то этот признак исчезнет:


При этом установить вручную ключ UK у вас не получится, так как соответствующий элемент будет недоступен:


Исправить эту ситуацию можно двумя путями. Первый - и более длинный: пойти в свойства целевой таблицы интрефейса, убрать использование первичного ключа из модели, как ключа обновления; второй - просто еще раз перетащить целевую таблицу из модели в интерфейс. Так выйдет немного быстрее, плюс, по крайней мере так было в 10й версии, колонки целевой таблицы выстроятся автоматически в том порядке, в котором они существуют в БД.

Мне кажется, что это скорее ошибка, чем особенность (баг, а не фича), так что я занесу описание этой ошибки в лист пожеланий.

Если что-то интересное будет в продолжении попытки загрузить данные из одной таблицы в другую и на это найдется время - я обязательно расскажу.

Напиши +1 в комментах, если ты умеешь читать скрытый текст!

2 комментария:

  1. UK обязателен при всех Incremental Update. И в 50% случаев он совпадает с PK, который ставится автоматом. Так что в большинстве случаев интерфейс сам "угадает" за вас UK. Если не устраивает - в Update Key можно выбрать импортированный в модель уникальный ключ. Либо - просто Undefined, и расставить UK ручками. Мне кажется такое поведение правильным. В общем, я уже привык )))

    ОтветитьУдалить
  2. Поведение, когда если есть первичный ключ он автоматически становится ключом обновления - оно правильное.

    Неправильно терять признаки, если в текст маппинга ничего не заносится, это ошибка.

    ОтветитьУдалить