Что дает репозитарий XML DB и как с ним работать... Зажгу свечу пред каждым сундуком, Репозитарий XML DB фактически является древовидно-организованой файловой системой внутри БД, элементами которой выступают ресурсы : каталоги (папки) и файлы. В статье показано, как можно работать с репозитарием XML DB. ВведениеXML DB, созданная в рамках БД Oracle, дает возможность следующего:
Репозитарий XML DB, фактически является древовидно-организованой файловой системой внутри БД, элементами которой выступают ресурсы: каталоги (папки) и произвольные файлы. Папки можно заводить и удалять, а файлы - заводить, удалять и извлекать. Технически ресурсы репозитария XML DB суть документы XML. Элемент Contents каждого такого документа представляет содержание ресурса, а все остальные элементы являются метаданными, описывающими ресурс. Средствами доступа к ресурсам, составляющим репозитарий, могут служить:
Здесь рассматриваются две первые категории средств, а последняя оставлена для самостоятельных упражнений. Доступ к ресурсам средствами SQLДве производные таблицы (из исходных, в схеме XDB) позволяют узнать информацию о ресурсах XML DB: PATH_VIEW и RESOURCE_VIEW: SQL> DESCRIBE resource_view Name Null? Type ----------- -------- ----------------------------------------------- RES SYS.XMLTYPE(XMLSchema "http://xmlns.oracle.com/xdb/XDBResource.xsd" Element "Resource") ANY_PATH VARCHAR2(4000) RESID RAW(16) SQL> DESCRIBE path_view Name Null? Type ----------- -------- ----------------------------------------------- PATH VARCHAR2(1024) RES SYS.XMLTYPE(XMLSchema "http://xmlns.oracle.com/xdb/XDBResource.xsd" Element "Resource") LINK SYS.XMLTYPE RESID RAW(16) Обе таблицы хранят список ресурсов с путями доступа, однако благодаря возможности определять связки (links), подобно как в файловой системе, путей доступа к одному ресурсу может оказаться несколько; их-то все и покажет таблица PATH_VIEW, в отличие от RESOURCE_VIEW. Примеры запросов. Список ресурсов в репозитарии: SELECT any_path FROM resource_view; Описание первого попавшегося ресурса: SELECT res FROM resource_view WHERE ROWNUM = 1; Для просмотра дерева ресурсов, помимо обычных, существуют специальные функции: UNDER_PATH EQUALS_PATH PATH Выдать описания ресурсов, имеющихся в папке /sys/acls: SELECT res FROM resource_view WHERE UNDER_PATH ( res, '/sys/acls' ) = 1 ; Выдать относительные имена ресурсов, имеющихся в папке /sys/acls (в данном случае это будут имена файлов), и их полные имена: SELECT path ( 1 ), any_path FROM resource_view WHERE UNDER_PATH ( res, '/sys/acls', 1 ) = 1 ; Описание ресурса-папки /sys/acls: SELECT res FROM resource_view WHERE EQUALS_PATH ( res, '/sys/acls' ) = 1 ; Полное описание ресурса-файла /sys/acls/all_all_acl.xml: SELECT r.res.GETCLOBVAL ( ) FROM resource_view r WHERE EQUALS_PATH ( res, '/sys/acls/all_all_acl.xml' ) = 1 ; С запросами последнего типа следует соблюдать осторожность, так как элемент Contents результирующего документа XML хранит для ресурса-файла его содержимое, а оно может оказаться очень большим. Содержание ресурса-файла /sys/acls/all_all_acl.xml с содержимым в формате XML: SELECT r.res.EXTRACT ( '//Contents' ) FROM resource_view r WHERE EQUALS_PATH ( res, '/sys/acls/all_all_acl.xml' ) = 1 ; Другие типы файлов могут хранить описание содержимого в элементе /Resource/Contents/text или /Resource/Contents/binary. Работа с ресурсами в программеЗаводить, изменять свойства и удалять ресурсы в репозитарии XML DB можно с помощью пакета PL/SQL DBMS_XDB. Примеры: CONNECT scott/tiger DECLARE retb BOOLEAN; BEGIN retb := DBMS_XDB.CREATEFOLDER ( '/public/myfolder' ); retb := DBMS_XDB.CREATERESOURCE ( '/public/myfolder/file1.txt' , 'First line' // CHR ( 10 ) // 'Second line' ); retb := DBMS_XDB.CREATERESOURCE ( '/public/myfolder/file2.xml' , '<doc><line>First line</line><line>Second line</line></doc>' ); END; / Проверка: SQL> SELECT r.res.EXTRACT ( 'Resource/Contents' ) AS xml 2 FROM resource_view r 3 WHERE EQUALS_PATH ( res, '/public/myfolder/file2.xml' ) = 1; XML -------------------------------------------------------------- <Contents xmlns="http://xmlns.oracle.com/xdb/XDBResource.xsd"> <doc xmlns=""> <line>First line</line> <line>Second line</line> </doc> </Contents> SQL> SELECT r.res.EXTRACT ( 'Resource/Contents/text/text()' ) AS text 2 FROM resource_view r 3 WHERE EQUALS_PATH ( res, '/public/myfolder/file1.txt' ) = 1; TEXT -------------------------------------------------------------- Firstline Secondline Обратите внимание, что XML DB по-разному хранит файл в зависимости от его расширения (упражнение: убедитесь, что XML DB интерпретирует содержимое, в зависимости именно от расширения файла, а не содержимого). Соответствие расширений файлов типам MIME устанавливается и выясняется в файле-ресурсе /xdbconfig.xml. Создание связи (link): BEGIN DBMS_XDB.LINK( '/public/myfolder/file1.txt' , '/public' , 'myfolderfile1.txt' ); END; / Проверка: SQL> SELECT r.res.EXTRACT ( 'Resource/Contents/text/text()' ) AS text 2 FROM resource_view r 3 WHERE EQUALS_PATH ( res, '/public/myfolderfile1.txt' ) = 1 SQL> / TEXT ---------------------------------------------------------------- First line Second line SQL> SELECT 2 p.path AS path 3 , p.link.extract('/LINK/ChildName/text()') AS link 4 FROM path_view p 5* WHERE UNDER_PATH ( p.res, '/public' ) = 1 SQL> / PATH LINK --------------------------------------------- --------------------- /public/myfolder myfolder /public/myfolderfile1.txt file1.txt /public/myfolder/file1.txt file1.txt /public/myfolder/file2.xml file2.xml Обратите внимание на два пути доступа в репозитарии к одному и тому же файлу (ресурсу). Удаление: CALL DBMS_XDB.DELETERESOURCE ( '/public/myfolderfile1.txt' ); CALL DBMS_XDB.DELETERESOURCE ( '/public/myfolder/file1.txt' ); CALL DBMS_XDB.DELETERESOURCE ( '/public/myfolder/file2.xml' ); CALL DBMS_XDB.DELETERESOURCE ( '/public/myfolder' ); Упражнение. Проверьте реакцию XML DB на попытку удалить несуществующий файл или непустую папку. В отличие от производных таблиц (view) словаря-стправочника в Oracle, производные таблицы RESOURCE_VIEW и PATH_VIEW обновляемы. Это позволяет, например, удалить связь также и командой DELETE, или переместить существующий ресурс в другую папку обычной операцией UPDATE: UPDATE path_view SET путь = новый _ путь WHERE equals_path ( res, путь ) = 1 ; Пример помещения в репозитарий файла ОС: CONNECT / AS SYSDBA CREATE DIRECTORY courses AS 'c:\crs'; GRANT READ ON DIRECTORY courses TO scott; CONNECT scott/tiger DECLARE retb BOOLEAN; BEGIN retb := DBMS_XDB.CREATERESOURCE ( '/public/OracleXML.doc' , BFILENAME ( 'COURSES', 'OracleXML.doc' ) ); END; / Проверка: SQL> SELECT res AS resource_description 2 FROM resource_view 3 WHERE EQUALS_PATH ( res, '/public/OracleXML.doc' ) = 1 4 ; RESOURCE_DESCRIPTION ----------------------------------------------------------------- <Resource xmlns="http://xmlns.oracle.com/xdb/XDBResource.xsd"> <CreationDate>2006-09-05T12:47:57.547000</CreationDate> <ModificationDate>2006-09-05T12:47:57.547000</ModificationDate> <DisplayName>OracleXML.doc</DisplayName> <Language>en-US</Language> <CharacterSet>WINDOWS-1251</CharacterSet> <ContentType>application/msword</ContentType> <RefCount>1</RefCount> </Resource> Технически файлы репозитария размещаются служебных таблицах БД (документы XML) или в объектах LOB (файлы всех остальных типов). Использование формата MIME для хранения двоичных файлов не является самым экономным. Разграничение доступаРепозитарий XML DB использует собственную схему защиты доступа, access control list (ACL), созданной в рамках модели ACL для WebDAV. Основными понятиями ACL являются:
В XML DB имеются несколько встроенных ACL, заданных следующими ресурсами: /sys/acls/all_all_acl.xml /sys/acls/all_owner_acl.xml /sys/acls/bootstrap_acl.xml /sys/acls/ro_all_acl.xml ACL файла /public/OracleXML.doc в программе можно узнать так: SELECT r.res.EXTRACT ( 'Resource/ACL' ) AS text FROM resource_view r WHERE EQUALS_PATH ( res, '/public/OracleXML.doc' ) = 1; Пример замены ACL ресурса: BEGIN DBMS_XDB.SETACL ( '/public/OracleXML.doc' , '/sys/acls/all_all_acl.xml' ); END; / Создадим в БД роль и создадим в XML DB соответствующий ей файл ACL: CONNECT / AS SYSDBA CREATE ROLE mygroup; CONNECT xdb/xdb DECLARE aclxml VARCHAR2 ( 4000 ) := ' <acl description="All privileges to MYGROUP, no to others" xmlns="http://xmlns.oracle.com/xdb/acl.xsd" xmlns:dav="DAV:" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/xdb/acl.xsd http://xmlns.oracle.com/xdb/acl.xsd" > <ace> <principal>MYGROUP</principal> <grant>true</grant> <privilege> <all/> </privilege> </ace> </acl> ' ; retb BOOLEAN; BEGIN retb := DBMS_XDB.CREATERESOURCE ( '/sys/acls/all_mygroup_acl.xml', aclxml ) ; END; / Защитим файл /public/OracleXML.doc созданым ACL: CONNECT scott/tiger BEGIN DBMS_XDB.SETACL ( '/public/OracleXML.doc' , '/sys/acls/all_mygroup_acl.xml' ); END; / COMMIT; Проверим видимость ресурса пользователем SCOTT. Для удобства создадим сначала файл с запросом: SELECT any_path FROM resource_view WHERE UNDER_PATH ( res, '/public' ) = 1 . SAVE publicpaths Проверка: SQL> CONNECT scott/tiger Connected. SQL> @publicpaths no rows selected SQL> CONNECT / as sysdba Connected. SQL> GRANT mygroup TO scott; Grant succeeded. SQL> CONNECT scott/tiger Connected. SQL> @publicpaths ANY_PATH ------------------------------------------ /public/OracleXML.doc При включении пользователя в группу ресурс стал виден. Тип XDBURITYPE для работы с ресурсамиДля работы с ресурсами репозитария можно использовать системный подтип XDBURITYPE абстрактного типа URITYPE. В частности, методы типа XDBURITYPE позволяют извлекать из репозитария содержимое ресурсов. Пример определения длины файла /public/OracleXML.doc : SELECT DBMS_LOB.GETLENGTH ( XDBURITYPE ( '/public/OracleXML.doc' ).GETBLOB ( ) ) AS bytes FROM dual ; Результат: BYTES ---------- 504320 Таким же образом можно извлечь большой файл (содержимое, а не длину) в переменную программы. Одно из применений типа XDBURITYPE - дать возможность ссылаться на данные в репозитарии XBM DB из полей обычных таблиц. Пример: CREATE TABLE projects AS SELECT 1 AS pid , XDBURITYPE ( '/public/OracleXML.doc' ) AS description FROM dual ; SELECT DBMS_LOB.GETLENGTH ( p.description.GETBLOB ( ) ) AS bytes FROM projects p; Получим: BYTES ---------- 504320 Обратите внимание, что сослаться на файл в репозитарии из БД можно и через тип HTTPURITYPE, однако в этом случае в ссылке появится имя компьютера и номер порта - признаки, внешние по отношению к содержимому БД, неконтролируемые средствами БД и, в отличие от ссылок извне, по сути ненужные. Другие возможностиЛюбой ресурс репозитария можно перевести в режим версионного доступа (version control resource, VCR). С этой целью, и с целью самого доступа, следует использовать особый пакет DBMS_XDB_VERSION. Любой ресурс репозитария можно снабдить собственным описанием (метаданными; в дополнение к «системным» метаданным), добавив в его описание XML («системное») свои элементы. Для этой цели можно использовать разные средства:
- в SQL - операции INSERT, UPDATE, DELETE применительно к полю RES (производной) таблицы RESOURCE_VIEW; - методом PROPPATCH протокола WebDAV. Подробности имеются в документации по Oracle. |