|
Программирование >> Oracle
Внешние процедуры на языке С Вначале в качестве языка программирования сервера Oracle и клиентских приложений, работающих на самом сервере Oracle, использовался исключительно PL/SQL. В версии Oracle 8.0 появилась возможность создавать хранимые процедуры на других языках. Эта возможность - поддержка внешних процедур - распространяется на хранимые процедуры на языке С (и все процедуры, которые можно вызвать из языка С) и на языке Java. В этой главе мы сконцентрируемся исключительно на языке С, а следующая глава посвящена использованию Java. В этой главе внешние процедуры рассматриваются с точки зрения архитектуры и показано, как они были реализованы разработчиками ядра Oracle. Кроме того, мы разберемся, как сконфигурировать сервер для поддержки внешних процедур и как должен конфигурироваться сервер с учетом защиты. Я продемонстрирую, как написать внешнюю процедуру с помощью прекомпилятора Oracle Pro*C. Эта внешняя процедура будет использоваться для записи содержимого любого большого объекта в файловую систему сервера. Однако прежде чем перейти к этому примеру, рассмотрим базовый пример, демонстрирующий, как передавать значения основных типов данных из языка PL/SQL в функции на языке С и получать результаты. Этот базовый пример позволит также создать шаблон для быстрой разработки всех последующих внешних процедур на языке С. Вы узнаете, как создавать код на языке С с учетом возможности использования его для выполнения сервером Oracle. Мы также рассмотрим реализацию SQL-оболочки для внешней процедуры. Я расскажу, как обеспечить возможность ее вызова из языков SQL и PL/SQL и как программировать оболочку, чтобы ее легко было использовать тем, кому нужен соответствующий код. Наконец, мы рассмотрим преимущества и недостатки вне- 1282 Глава 18 шних процедур, а также различные ошибки сервера (ошибки ORA-XXXX), которые могут возникнуть при их использовании. В примере на языке Рго*С будет создаваться недостающее средство сервера. В составе сервера Oracle поставляется пакет DBMS LOB для работы с большими объектами. В этом пакете есть процедура loadfromfile, позволяющая читать в большой объект баз: данных содержимое любого файла в файловой системе сервера. Однако в этом пакете нет функции writetofile, которая могла бы записывать в файловую систему содержимое большого объекта, а такая потребность часто возникает. Мы решим эту задачу, создав собственный пакет LOB IO. Этот пакет позволит записывать любой большой объект типа BLOB, CLOB или BFILE в отдельный файл вне базы данных (так что для объектов типа BFILE мы по сути создадим команду копирования, поскольку исходный объект BFILE уже находится вне базы данных). Когда используются внешние процедуры? Один язык или одна среда не может обеспечить средства и функции на все случаи жизни. У каждого языка есть недостатки: не все можно сделать с его помощью, недостает возможностей или средств, о которых разработчики не подумали. При разработке программ на языке С мне иногда приходится программировать на ассемблере. При программировании приложений для Oracle на Java иногда удобно использовать код на языке PL/SQL. Суть в том, что не нужно всегда использовать язык низкого уровня - иногда необходимо переходить на более высокий уровень. Внешние процедуры можно считать переходом на более низкоуровневый язык. Они обычно используются для интеграции существующего кода на языке С в виде библиотек функций (например, DLL - динамически компонуемых библиотек в Windows, созданных сторонним производителем, которые необходимо вызывать с сервера) или для расширения функциональных возможностей существующих пакетов, как в нашем случае. Именно эту технологию используют разработчики сервера Oracle для расширения его возможностей. Например, мы уже рассмотрели, как эта возможность использовалась в компоненте interMedia (в предыдущей главе) и в пакете DBMS OLAP (в главе 13, посвященной материализованным представлениям). Первая хранимая процедура, которую я написал, представляла собой реализацию простого клиента TCP/IP. С ее помощью в версии сервера 8.0.3 я получил возможность в PL/SQL открывать сокет TCP/IP для подключения к существующему серверу и обмена сообщениями с ним. Я мог подключаться к серверу дискуссионных групп по протоколу Net News Transport Protocol (NNTP), к серверу электронной почты по протоколам Internet Message Access Protocol (IMAP), Simple Mail Transfer Protocol (SMTP) или Post Office Protocol (POP), к Web-серверу и т.д. Научив язык PL/SQL использовать соке-ты, я откр1л широкий спектр новых возможностей. Теперь я мог: пос1лать сообщение электронной почты из триггера с помощью протокола SMTP; включать сообщения электронной почты в базу данных с помощью протокола POP; Внешние процедуры на языке С 1283 индексировать сообщения дискуссионн1х групп с помощью компонента interMedia Text и протокола NNTP; обращаться к любой доступной сетевой службе. Я стал использовать сервер Oracle также в качестве клиента прочих серверов. После включения полученных от них данных в свою базу я мог выполнять с ними множество действий (индексировать, выполнять поиск, представлять в другом виде и т.д.). Со временем это средство начали использовать настолько часто, что теперь оно стало интегрированной возможностью сервера. Начиная с версии 8.1.6 сервера Oracle, все возможности, которые обеспечивал простой клиент TCP/IP, теперь реализуются в пакете UTL TCP. С тех пор я написал еще несколько внешних процедур. Одни - для получения времени с помощью системных часов с большей точностью, чем возвращает встроенная функция SYSDATE, другие - для выполнения команд операционной системы, определения часового пояса системы или для получения списка файлов в указанном каталоге. Последней мной написана функция для записи во внешний файл содержимого любого большого объекта: символьного (Character LOB - CLOB), двоичного (Binary LOB - BLOB) или хранящегося во внешнем файле (BFILE). Полезным побочным эффектом созданного при этом пакета является обеспечение для двоичных файлов возможностей, предоставляемых пакетом UTL FILE (пакет UTL FILE не позволяет создавать двоич-н1е файлы). Поскольку сервер поддерживает временные большие объекты (Temporary LOB) и обеспечивает возможность записи (WRITE) во временный большой объект, этот новый пакет, который мы собираемся реализовать, даст возможность записывать из PL/SQL любой двоичный файл. Итак, этот пакет позволит: экспортировать любой большой объект во внешний файл на сервере; записывать на сервере двоичный файл практически любого размера и с любыми данными (аналогично пакету UTL FILE, который работает с текстовыми данными, но работу с произвольными двоичными данными не поддерживает). Из всего сказанного ясно, что причины использования внешних процедур могут быть многочисленны и разнообразны. Обычно они используются для: реализации отсутствующих функциональных возможностей; интегрирования существующего кода, который проверяет корректность данных; ускорения обработки; скомпилированный код на языке С всегда будет выполнять операции, требующие большого объема вычислений, быстрее, чем при реализации их на интерпретируемых языках PL/SQL или Java. Как обычно, решение использовать что-то вроде хранимых процедур требует опре-деленн1х издержек. Дополнительные издержки связаны с разработкой кода на языке С, что, как мне кажется, сложнее, чем разработка на PL/SQL. Приходится также жертвовать переносимостью или даже идти на потенциальную невозможность переноса кода. Если разработана DLL-библиотека для Windows, нет гарантии, что написанный исход-н1й код можно будет использовать на UNIX-машине, и наоборот. Я считаю, что внешнюю процедуру надо использовать лишь тогда, когда невозможно решить задачу с помощью языка PL/SQL.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.078
При копировании материалов приветствуются ссылки. |