Oracle для профессионалов

         

Генерация списка файлов каталога


Пакет UTL_FILE, который мы уже несколько раз использовали по ходу изложения, хорошо справляется с чтением и записью текстовых файлов. Очень часто, однако, необходимо обработать все файлы в указанном каталоге. Этого пакет не позволяет сделать. Для получения списков файлов каталога нет встроенных методов ни в SQL, ни в PL/SQL. На Java его очень легко получить. Вот как это делается:

tkyte@TKYTE816> create global temporary table DIR_LIST 2 (filename varchar2(255)) 3 on commit delete rows 4 / Table created.

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

Необходим следующий фрагмент Java-кода:

tkyte@TKYTE816> create or replace 2 and compile java source named "DirList" 3 as 4 import java.io.*; 5 import java.sql.*; 6 7 public class DirList 8 { 9 public static void getList(String directory) 10 throws SQLException 11 { 12 File path = new File(directory); 13 String[] list = path.list(); 14 String element; 15 16 for(int i = 0; i < list.length; i++) 17 { 18 element = list[i]; 19 #sql { INSERT INTO DIR_LIST (FILENAME) 20 VALUES (:element) }; 21 } 22 } 23 24 } 25 /

Java created.

Я решил использовать SQLJ, чтобы сократить программу. Подключение к базе данных уже выполнено, поэтому реализация с помощью интерфейса JDBC потребовала лишь нескольких дополнительных строк кода. Но с помощью препроцессора SQLJ выполнять SQL-операторы в Java так же просто, как и в PL/SQL. Теперь, конечно же, необходимо создать спецификацию вызова:

tkyte@TKYTE816> create or replace 2 procedure get_dir_list(p_directory in varchar2) 3 as language java 4 name 'DirList.getList(java.lang.String)'; 5 /

Procedure created.

Прежде чем запускать эту процедуру, следует учесть еще один нюанс. Необходимо предоставить процедуре право делать то, что она должна — читать список файлов каталога. В данном случае я обладаю правами администратора базы данных, поэтому могу предоставить соответствующие привилегии сам себе, но обычно приходится обращаться с соответствующим запросом к администратору. Если помните, во введении к этой главе я писал:

"... Java-код всегда работает с правами владельца ПО Oracle, поэтому хранимая процедура на Java при предоставлении соответствующих привилегий может переписать файл параметров инициализации сервера, INIT.ORA (или другие, еще более важные файлы, например файлы данных)."


Сервер Oracle защищается от этого следующим образом: для выполнения небезопасных действий необходимо явно получить соответствующую привилегию. Попытавшись использовать эту процедуру до получения необходимых привилегий, мы получим следующее сообщение об ошибке:

tkyte@TKYTE816> exec get_dir_list('c:\temp'); BEGIN get_dir_list('c:\temp'); END;

* ERROR at line 1: ORA-29532: Java call terminated by uncaught Java exception: java.security.AccessControlException: the Permission (java.io.FilePermission c:\temp read) has not been granted by dbms_java.grant_permission to SchemaProtectionDomain(TKYTE|PolicyTableProxy(TKYTE)) ORA-06512: at "TKYTE.GET_DIR_LIST", line 0 ORA-06512: at line 1

Поэтому предоставим себе право получать список файлов в соответствующем каталоге:

tkyte@TKYTE816> begin 2 dbms_java.grant_permission 3 (USER, 4 'java.io.FilePermission', 5 'c:\temp', 6 'read'); 7 end; 8 /

PL/SQL procedure successfully completed.

И можно выполнять процедуру:

tkyte@TKYTE816> exec get_dir_list('c:\temp');

PL/SQL procedure successfully completed.

tkyte@TKYTE816> select * from dir_list where rownum < 5;

FILENAME ---------------------------------- a.sql abc.dat activation activation8i.zip

Соответствующие права доступа определяются спецификацией Java2 Standard Edition (J2SE) и подробно описаны на странице http://java.sun.com/j2se/1.3/docs/api/java/security/Permission.html. В приложении А мы подробно рассмотрим пакет DBMS_JAVA и его использование.

Есть еще один нюанс, который необходимо учитывать. Oracle 8.1.6 —

первая версия СУБД Oracle, поддерживающая систему прав доступа, задаваемую спецификацией J2SE. В Oracle 8.1.5 для этого приходилось использовать роли. К сожалению, роль была ровно одна: JAVASYSPRIV. Ее использование будет подобно предоставлению роли администратора базы данных каждому пользователю только потому, что ему необходимо создать представление, — это слишком мощная роль для выполнения такого простого действия. При наличии роли JAVASYSPRIV можно делать все, что угодно. Будьте осторожны при использовании этой роли в версии 8.1.5 и постарайтесь перейти на следующие версии, где принята более избирательная модель привилегий.


Содержание раздела