четверг, 14 октября 2010 г.

Отправляем письмо из ODI (улучшенная версия).

Пакет SEND_MAIL, описанный в предыдущем сообщении меня устраивал всем. Всем, кроме невозможности отправить многострочное письмо. В принципе, отправить две и более строки из ODI совсем не сложно. Вставляем в пакет odisendmail компоненту, где пишем все, что прийдет в голову:


Но хотелось бы, все же, использовать для этой цели пакет, а вернее, сгенерированный из пакета сценарий.

Причина, по которой нельзя использовать SEND_MAIL для отправки многострочного текста заключается в том, что тело письма отправляется через переменную. А значение переменной из вызывающего пакета в пакет SEND_MAIL попадает через текстовую команду. В которой параметры передаются примерно в следующем виде:

"-PROJECT.MAIL_BODY=Текст тела письма"

Ну и если попробовать передать многострочный текст, агент его распарсить правильно не сможет.

"-PROJECT.MAIL_BODY=Текст
тела
письма"


Результат:


java.lang.Exception: Unmatching quotes .... ! - вот и весь ответ на мою попытку передачи параметра в пакет.

Дальше моя мысль шла примерно так: раз нельзя передать много строк через переменную, возможно, получится передать способ получения этих строк. Т.е. передаем не результат, а только то, как его получить.

А при работе с СУБД лучший способ что-то получить - это выполнить SQL запрос. Вот какие изменения я внес в первую версию пакета после нескольких попыток:


  1. Добавляется переменная #MAIL_SQL_QUERY, через которую передается запрос, который необходимо выполнить, чтобы получить тело письма.
  2. Проверяется, если запрос в пакет не передан, переходим к пункту 6.
  3. Функция, которая создает функцию PL/SQL из переданного запроса.
  4. Вызываем рефреш переменной #MAIL_SQL_QUERY, чтобы получить результат созданной ранее функции
  5. Удаляем созданную функцию из БД и переходим на определение адресов доставки
  6. Сюда мы попадаем, если запрос в сценарий не передавался. Переносим значение переменной #MAIL_BODY в переменную #MAIL_SQL_QUERY и переходим на определение адресов доставки.
Важный аспект, хорошо показывающий возможности ODI, процедура создания функции в БД. Процедура состоит из одного шага, текст которого выглядит так:

create or replace function prepmail_<%=odiRef.getSession("SESS_NO")%> return varchar2
is v_Result varchar2(4000) := '';
begin
for my_rec in (<%=odiRef.getOption("SQL")%>)
loop
v_Result := v_Result || TRIM(my_rec.txt_value) || chr(10);
end if;
end loop;
return(v_Result);
end prepmail_<%=odiRef.getSession("SESS_NO")%>


Через опцию <%=odiRef.getOption("SQL")%> передается текст sql запроса, который будет в функции. Остается только забрать результат в значение переменной:


Не забудьте указать одну и ту же схему в процедуре создания и удаления функции и на закладке обновления переменной #MAIL_SQL_QUERY.

Чтобы обеспечить возможность одновременного выполнения нескольких разных сценариев SEND_MAIL, возможно, с разными SQL запросами, к имени функции добавляется номер сессии <%=odiRef.getSession("SESS_NO")%>.

Переход от 4 к 5 пункту на диаграмме пакета будет происходить и в случае неуспешного выполнения обновления переменной в пункте 4. Мы в любом случае должны удалить созданную нами функцию, так как при каждом запуске сценария отправки почты мы будем получать новую функцию. По этой же причине удаление функции производится сразу после того, как мы прочитали значение в переменную, а не после отправки почты.

Еще одно условие, которое накладывается на текст sql запроса, передаваемого в пакет SEND_MAIL. Запрос должен возвращать одну колонку с названием txt_value.

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

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