プライマリ・コンテンツに移動
Oracle® Database SecureFilesおよびラージ・オブジェクト開発者ガイド
12cリリース1 (12.1)
B71284-05
目次へ移動
目次
索引へ移動
索引

前
次

9 独自のDBFSストアの作成

DBFSコンテンツSPI (DBMS_DBFS_CONTENT_SPI)を使用して、独自のDBFSストアを作成できます。

ここでは、次の項目について説明します。

DBFSストアの作成および使用の概要

DBFSストアをカスタマイズするには、DBFSコンテンツSPI (DBMS_DBFS_CONTENT_SPI)を実装する必要があります。これは、DBFS SecureFilesストアやDFFS階層ストアなどの既存のストア、および作成する任意のユーザー定義DBFSストアの基礎となります。

PL/SQLインタフェースなどのクライアント側のアプリケーションは、DBFSコンテンツAPIでファンクションおよびプロシージャを起動します。これにより、DBFSコンテンツAPIは、DBFSコンテンツSPIで対応するサブプログラムを起動し、ストアを作成し、他の関連ファンクションを実行します。「DBFSコンテンツAPI」を参照してください。

DBFSストアを作成したら、「DBFS SecureFilesストア」で説明するように、SecureFilesストアの場合とほぼ同じ方法でこれを実行します。

図9-1 データベース・ファイルシステム(DBFS)

図9-1の説明が続きます。
「図9-1 データベース・ファイルシステム(DBFS)」の説明

DBFSコンテンツ・ストア・プロバイダ・インタフェース(DBFSコンテンツSPI)

DBFSコンテンツSPI (ストア・プロバイダ・インタフェース)は単なる仕様にすぎず、パッケージ本体はありません。

DBFSコンテンツAPIからのコールに応答するためにパッケージ本体を実装する必要があります。つまり、DBFSコンテンツSPIは、指定されたメソッド・シグネチャおよびセマンティクスを使用して実装する必要がある、必須プログラム仕様のコレクションです。

必要な場合、ファンクションおよびプロシージャをDBFSコンテンツSPIパッケージ本体に追加できます。実装によっては、その他のメソッドの実装および他のインタフェースの公開が可能ですが、DBFSコンテンツAPIはそれらのインタフェースを使用しません。

DBFSコンテンツSPIは、DBFSコンテンツAPI (パッケージDBMS_DBFS_CONTENT)で定義された各種の要素(定数、タイプおよび例外など)を参照します。

すべてのパス名参照がストア修飾であること、つまり、プロバイダSPIのメソッドを呼び出す前に、DBFSコンテンツAPIによってマウント・ポイントの概念および完全絶対パス名が正規化され、ストア修飾パス名に変換されていることが必要な点に注意してください。

DBFSコンテンツAPIおよびプロバイダSPIは1対多プラガブル・アーキテクチャであるため、DBFSコンテンツAPIでは動的SQLを使用してプロバイダSPIのメソッドが呼び出されます。これにより、プロバイダSPIの実装がこのドキュメントのプロバイダSPIの仕様に準拠していない場合、ランタイム・エラーが発生することがあります。

DBFSコンテンツAPIで特定のプロバイダSPIがプラグ化またはプラグ解除されるタイミングを示す明示的な初期または最終メソッドはありません。プロバイダSPIは、いずれかのSPIエントリ・ポイントで、自身を自動初期化できる必要があります。

関連項目:

  • DBMS_DBFS_CONTENT_SPIパッケージの構文の詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください

  • 詳細は、ファイル$ORACLE_HOME/rdbms/admin/dbmscapi.sqlを参照してください

カスタム・プロバイダの作成

DBFS用のこのストア・プロバイダの例(TaBleFileSystem Store Provider (tbfs))をカスタム・プロバイダのスケルトンまたは学習ツールとして使用することにより、DBFSとそのSPIについて詳しく理解できるようになります。

この例のDBFSのストア・プロバイダは、BLOB列が含まれるリレーショナル表をフラットな非階層ファイルシステム(つまり、名前付きファイルのコレクション)として公開します。

この例を使用するには、Oracle Database 12cをインストールしていること、DBFSの概念に詳しいこと、さらにdbfs_clientFUSEをインストールして使用し、標準SFSストア・プロバイダで支えられているファイルシステムのマウントとアクセスを行っていることが前提です。

TaBleFileSystemストア・プロバイダ(tbfs)は、豊富な機能の提供を意図したものではなく、まして機能を完備したものではありません。これは十分なデモンストレーションを提供することにより、DBFSのユーザーが独自のカスタム・プロバイダを作成して、dbfs_clientを介して表を従来のファイルシステム・プログラムに公開する際に役立ちます。

ここでは、次の項目について説明します。

仕組み

DBFSのストア・プロバイダの例であるTaBleFileSystemストア・プロバイダ(tbfs)のメカニズムを次に示します。

ここでは、次の項目について説明します。

インストールと設定

DBFS TaBleFileSystemストア・プロバイダ(tbfs)のインストールと設定には、特定のファイルが必要です。

TBFSは、次のSQLファイルから構成されています。

tbfs.sql        最上位ドライバ・スクリプト

tbl.sql         ファイルシステム用のテスト・ユーザー、表領域、表などを作成するスクリプト。

spec.sql        tbfsのSPI仕様

body.sql        tbfsのSPI実装

capi.sql        DBFS登録/マウント・スクリプト

TBFSをインストールするには、前述のファイルがすべて含まれるディレクトリでSYSDBAとしてtbfs.sqlのみを実行します。tbfs.sqlにより、他のSQLファイルが正しい順序でロードされます。

名前の競合を無視して、コンパイル・エラーなしですべてのSQLファイルがロードされます。すべてのSQLファイルは、ランタイム・エラーなしでロードされます。init.oraのplsql_warningsパラメータの値によっては、様々な警告が表示されますが問題はありません。

名前の競合(表領域名TBFS、データファイル名tbfs.f、ユーザー名TBFS、パッケージ名TBFS)がある場合は、様々なSQLファイルで該当する参照箇所を同じように変更する必要があります。

TBFSの使用

DBFSのストア・プロバイダの例であるTaBleFileSystemストア・プロバイダ(tbfs)がインストールされると、複数の異なる方法でファイルを追加または削除したり、TBFSに対して他の変更を加えることができるようになります。

ユーザーTBFSとして接続したdbfs_clientには、RDBMS表(TBFS.TBFST)に基づいて単純な非階層ファイルシステムが表示されます。

このファイルシステムでファイルを追加または削除するには、SQL (基礎となる表に対するDML)、Unixユーティリティ(dbfs_clientによって仲介)、またはPL/SQL (DBFS API使用)を使用します。

いずれかのアクセス方法によって行われたファイルシステムへの変更は、他のすべてのアクセス方法で確認でき、その際にはトランザクションの一貫性が維持されます(コミット/ロールバックの境界に対応します)。

TBFSの内部

TBFSは、本来の目的が学習用の例として使用することであるため、単純な構造になります。

ただし、その実装には、DBFSにプラグインできるとともに既存のリレーショナル・データをUNIXファイルシステムとして公開できる、強力な本番品質のカスタムSPIの構築に向けた道筋が示されます。

TBFSは、簡潔にするために様々な簡易化が行われています(ただし、これらはDBFSやSPIの制限ではないため、そのとおりにする必要はありません)。

  • TBFS SPIパッケージは、ハードコードされた名前(TBFS.TBFST)を持つ単一の表のみを処理します。動的SQLおよび追加構成情報を使用して、単一のSPIパッケージに複数の表をそれぞれ個別ファイルシステムとしてサポートさせることができます(複数の表内のデータを単一のファイルシステムとして統合することもできます)。

  • TBFSは、ファイルシステム階層をサポートしません。TBFSは、フラットなネームスペース(仮想ルート・ディレクトリ(/)の下で単純なアイテム名によって識別されるファイルのコレクション)を設定します。ディレクトリ階層の実装は、ストア・プロバイダが親/子関係を一貫性のある方法で管理する必要があるため、非常に複雑になります。

    さらに、通常、既存のリレーショナル・データ(TBFSがファイルシステムとして公開しようとしているデータの種類)には、ディレクトリ/ファイル階層を形成する行間の関係が含まれません。

  • TBFSではフラットなネームスペースしかサポートされないため、SPIのほとんどのメソッドは実装されず、メソッド本体によってdbms_dbfs_content.unsupported_operation例外が生成されます。この例外は、独自のカスタムSPIを作成する適切な出発点にもなります。まずDBMS_DBFS_CONTENT_SPIパッケージから単純なSPIスケルトンを複製して、この例外を生成したメソッド本体をすべてのメソッド本体のデフォルトとして設定し、その後、現実にあわせた実装を少しずつ追加します。

  • TBFSの基礎となる表は、最小限の構造(キー/名前列とLOB列)に近いものです。つまり、DBFSおよびdbfs_clientが使用または予期する様々なプロパティを動的に生成する必要があります(TBFS実装によって、std:guidプロパティの場合の方法が示されます)。

    他のプロパティ(Unix形式のタイムスタンプなど)はまったく実装されていません。この場合でも、驚くほど高機能のファイルシステムを実装できます。ただし、独自のカスタムSPIを作成すると、その他のDBFSプロパティのサポートを容易に組み込むことができます。それらのDBFSプロパティの値を提供するためには、基礎となる表の構造を拡張して必要に応じて列を増やすか、既存の表の既存の列を使用します。

  • TBFSでは名前変更や移動のメソッドは実装されません。そのためのサポート(renamePathメソッドの適切なUPDATE文)の追加はユーザーに任されています。

  • TBFSの例では、複数の場所(表領域、データファイル、ユーザー、パッケージ、さらにファイルシステム名)で文字列tbfsが使用されます。tbfsのこれらの使用箇所はすべて異なるネームスペースに属しており、どのネームスペースが文字列の特定のオカレンスに対応するかを示しています。このような例のtbfsは、DBFSの概念を明確に理解できているかどうかを確認するための学習課題として適切です。

TBFS.SQL

TBFS.SQLは、トップレベルのドライバ・スクリプトです。

TBFS.SQLスクリプト:

set echo on;
 
@tbl
@spec
@body
@capi
 
quit;

TBL.SQL

TBL.SQLスクリプトは、テスト・ユーザー、表領域、ファイルシステムをサポートする表などを作成します。

TBL.SQLスクリプト:

connect / as sysdba
 
create tablespace tbfs datafile 'tbfs.f' size 100m
    reuse autoextend on
    extent management local
    segment space management auto;
 
create user tbfs identified by tbfs;
alter user tbfs default tablespace tbfs;
grant connect, resource, dbfs_role to tbfs;
 
 
connect tbfs/tbfs;
 
drop table tbfst;
purge recyclebin;
 
create table tbfst(
    key     varchar2(256)
            primary key
            check           (instr(key, '/') = 0),
    data    blob)
        tablespace tbfs
    lob(data)
        store as securefile
            (tablespace tbfs);
 
grant select on tbfst to dbfs_role;
grant insert on tbfst to dbfs_role;
grant delete on tbfst to dbfs_role;
grant update on tbfst to dbfs_role;

spec.sql

spec.sqlスクリプトは、tbfsのSPI仕様を提供します。

spec.sqlスクリプト:

connect / as sysdba;
 
create or replace package tbfs
    authid current_user
as
 
 
 
    /*
     * Lookup store features (see dbms_dbfs_content.feature_XXX). Lookup
     * store id.
     *
     * A store ID identifies a provider-specific store, across
     * registrations and mounts, but independent of changes to the store
     * contents.
     *
     * I.e. changes to the store table(s) should be reflected in the
     * store ID, but re-initialization of the same store table(s) should
     * preserve the store ID.
     *
     * Providers should also return a "version" (either specific to a
     * provider package, or to an individual store) based on a standard
     * <a.b.c> naming convention (for <major>, <minor>, and <patch>
     * components).
     *
     */
 
    function    getFeatures(
        store_name          in      varchar2)
            return  integer;
 
    function    getStoreId(
        store_name          in      varchar2)
            return  number;
 
    function    getVersion(
        store_name          in      varchar2)
            return  varchar2;
 
 
 
    /*
     * Lookup pathnames by (store_name, std_guid) or (store_mount,
     * std_guid) tuples.
     *
     * If the underlying "std_guid" is found in the underlying store,
     * this function returns the store-qualified pathname.
     *
     * If the "std_guid" is unknown, a "null" value is returned. Clients
     * are expected to handle this as appropriate.
     *
     */
 
    function    getPathByStoreId(
        store_name          in      varchar2,
        guid                in      integer)
            return  varchar2;
 
 
 
    /*
     * DBFS SPI: space usage.
     *
     * Clients can query filesystem space usage statistics via the
     * "spaceUsage()" method. Providers are expected to support this
     * method for their stores (and to make a best effort determination
     * of space usage---esp. if the store consists of multiple
     * tables/indexes/lobs, etc.).
     *
     * "blksize" is the natural tablespace blocksize that holds the
     * store---if multiple tablespaces with different blocksizes are
     * used, any valid blocksize is acceptable.
     *
     * "tbytes" is the total size of the store in bytes, and "fbytes" is
     * the free/unused size of the store in bytes. These values are
     * computed over all segments that comprise the store.
     *
     * "nfile", "ndir", "nlink", and "nref" count the number of
     * currently available files, directories, links, and references in
     * the store.
     *
     * Since database objects are dynamically growable, it is not easy
     * to estimate the division between "free" space and "used" space.
     *
     */
 
    procedure   spaceUsage(
        store_name  in              varchar2,
        blksize     out             integer,
        tbytes      out             integer,
        fbytes      out             integer,
        nfile       out             integer,
        ndir        out             integer,
        nlink       out             integer,
        nref        out             integer);
 
 
 
    /*
     * DBFS SPI: notes on pathnames.
     *
     * All pathnames used in the SPI are store-qualified, i.e. a 2-tuple
     * of the form (store_name, pathname) (where the pathname is rooted
     * within the store namespace).
     *
     *
     * Stores/providers that support contentID-based access (see
     * "feature_content_id") also support a form of addressing that is
     * not based on pathnames. Items are identified by an explicit store
     * name, a "null" pathname, and possibly a contentID specified as a
     * parameter or via the "opt_content_id" property.
     *
     * Not all operations are supported with contentID-based access, and
     * applications should depend only on the simplest create/delete
     * functionality being available.
     *
     */
 
 
 
    /*
     * DBFS SPI: creation operations
     *
     * The SPI must allow the DBFS API to create directory, file, link,
     * and reference elements (subject to store feature support).
     *
     *
     * All of the creation methods require a valid pathname (see the
     * special exemption for contentID-based access below), and can
     * optionally specify properties to be associated with the pathname
     * as it is created. It is also possible for clients to fetch-back
     * item properties after the creation completes (so that
     * automatically generated properties (e.g. "std_creation_time") are
     * immediately available to clients (the exact set of properties
     * fetched back is controlled by the various "prop_xxx" bitmasks in
     * "prop_flags").
     *
     *
     * Links and references require an additional pathname to associate
     * with the primary pathname.
     *
     * File pathnames can optionally specify a BLOB value to use to
     * initially populate the underlying file content (the provided BLOB
     * may be any valid lob: temporary or permanent). On creation, the
     * underlying lob is returned to the client (if "prop_data" is
     * specified in "prop_flags").
     *
     * Non-directory pathnames require that their parent directory be
     * created first. Directory pathnames themselves can be recursively
     * created (i.e. the pathname hierarchy leading up to a directory
     * can be created in one call).
     *
     *
     * Attempts to create paths that already exist is an error; the one
     * exception is pathnames that are "soft-deleted" (see below for
     * delete operations)---in these cases, the soft-deleted item is
     * implicitly purged, and the new item creation is attempted.
     *
     *
     * Stores/providers that support contentID-based access accept an
     * explicit store name and a "null" path to create a new element.
     * The contentID generated for this element is available via the
     * "opt_content_id" property (contentID-based creation automatically
     * implies "prop_opt" in "prop_flags").
     *
     * The newly created element may also have an internally generated
     * pathname (if "feature_lazy_path" is not supported) and this path
     * is available via the "std_canonical_path" property.
     *
     * Only file elements are candidates for contentID-based access.
     *
     */
 
    procedure   createFile(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     in out nocopy   blob,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   createLink(
        store_name  in              varchar2,
        srcPath     in              varchar2,
        dstPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   createReference(
        store_name  in              varchar2,
        srcPath     in              varchar2,
        dstPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   createDirectory(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
 
 
    /*
     * DBFS SPI: deletion operations
     *
     * The SPI must allow the DBFS API to delete directory, file, link,
     * and reference elements (subject to store feature support).
     *
     *
     * By default, the deletions are "permanent" (get rid of the
     * successfully deleted items on transaction commit), but stores may
     * also support "soft-delete" features. If requested by the client,
     * soft-deleted items are retained by the store (but not typically
     * visible in normal listings or searches).
     *
     * Soft-deleted items can be "restore"d, or explicitly purged.
     *
     *
     * Directory pathnames can be recursively deleted (i.e. the pathname
     * hierarchy below a directory can be deleted in one call).
     * Non-recursive deletions can be performed only on empty
     * directories. Recursive soft-deletions apply the soft-delete to
     * all of the items being deleted.
     *
     *
     * Individual pathnames (or all soft-deleted pathnames under a
     * directory) can be restored or purged via the restore and purge
     * methods.
     *
     *
     * Providers that support filtering can use the provider "filter" to
     * identify subsets of items to delete---this makes most sense for
     * bulk operations (deleteDirectory, restoreAll, purgeAll), but all
     * of the deletion-related operations accept a "filter" argument.
     *
     *
     * Stores/providers that support contentID-based access can also
     * allow file items to be deleted by specifying their contentID.
     *
     */
 
    procedure   deleteFile(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        soft_delete in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   deleteContent(
        store_name  in              varchar2,
        contentID   in              raw,
        filter      in              varchar2,
        soft_delete in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   deleteDirectory(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        soft_delete in              integer,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   restorePath(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   purgePath(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   restoreAll(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   purgeAll(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
 
 
    /*
     * DBFS SPI: path get/put operations.
     *
     * Existing path items can be accessed (for query or for update) and
     * modified via simple get/put methods.
     *
     * All pathnames allow their metadata (i.e. properties) to be
     * read/modified. On completion of the call, the client can request
     * (via "prop_flags") specific properties to be fetched as well.
     *
     * File pathnames allow their data (i.e. content) to be
     * read/modified. On completion of the call, the client can request
     * (via the "prop_data" bitmaks in "prop_flags") a new BLOB locator
     * that can be used to continue data access.
     *
     * Files can also be read/written without using BLOB locators, by
     * explicitly specifying logical offsets/buffer-amounts and a
     * suitably sized buffer.
     *
     *
     * Update accesses must specify the "forUpdate" flag. Access to link
     * pathnames can be implicitly and internally deferenced by stores
     * (subject to feature support) if the "deref" flag is
     * specified---however, this is dangerous since symbolic links are
     * not always resolvable.
     *
     *
     * The read methods (i.e. "getPath" where "forUpdate" is "false"
     * also accepts a valid "asof" timestamp parameter that can be used
     * by stores to implement "as of" style flashback queries. Mutating
     * versions of the "getPath" and the "putPath" methods do not
     * support as-of modes of operation.
     *
     *
     * "getPathNowait" implies a "forUpdate", and, if implemented (see
     * "feature_nowait"), allows providers to return an exception
     * (ORA-54) rather than wait for row locks.
     *
     */
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     out    nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        forUpdate   in              integer,
        deref       in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   getPathNowait(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     out    nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        deref       in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in out          number,
        offset      in              number,
        buffer      out    nocopy   raw,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in out          number,
        offset      in              number,
        buffers     out    nocopy   dbms_dbfs_content_raw_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     in out nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in              number,
        offset      in              number,
        buffer      in              raw,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        written     out             number,
        offset      in              number,
        buffers     in              dbms_dbfs_content_raw_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t);
 
 
 
    /*
     * DBFS SPI: rename/move operations.
     *
     * Pathnames can be renamed or moved, possibly across directory
     * hierarchies and mount-points, but within the same store.
     *
     *
     * Non-directory pathnames previously accessible via "oldPath" are
     * renamed as a single item subsequently accessible via "newPath";
     * assuming that "newPath" does not already exist.
     *
     * If "newPath" exists and is not a directory, the rename implicitly
     * deletes the existing item before renaming "oldPath". If "newPath"
     * exists and is a directory, "oldPath" is moved into the target
     * directory.
     *
     *
     * Directory pathnames previously accessible via "oldPath" are
     * renamed by moving the directory and all of its children to
     * "newPath" (if it does not already exist) or as children of
     * "newPath" (if it exists and is a directory).
     *
     *
     * Stores/providers that support contentID-based access and lazy
     * pathname binding also support the "setPath" method that
     * associates an existing "contentID" with a new "path".
     *
     */
 
    procedure   renamePath(
        store_name  in              varchar2,
        oldPath     in              varchar2,
        newPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   setPath(
        store_name  in              varchar2,
        contentID   in              raw,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        ctx         in              dbms_dbfs_content_context_t);
 
 
 
    /*
     * DBFS SPI: directory navigation and search.
     *
     * The DBFS API can list or search the contents of directory
     * pathnames, optionally recursing into sub-directories, optionally
     * seeing soft-deleted items, optionally using flashback "as of" a
     * provided timestamp, and optionally filtering items in/out within
     * the store based on list/search predicates.
     *
     */
 
    function    list(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
            return  dbms_dbfs_content_list_items_t
                pipelined;
 
    function    search(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
            return  dbms_dbfs_content_list_items_t
                pipelined;
 
 
 
    /*
     * DBFS SPI: locking operations.
     *
     * Clients of the DBFS API can apply user-level locks to any valid
     * pathname (subject to store feature support), associate the lock
     * with user-data, and subsequently unlock these pathnames.
     *
     * The status of locked items is available via various optional
     * properties (see "opt_lock*" above).
     *
     *
     * It is the responsibility of the store (assuming it supports
     * user-defined lock checking) to ensure that lock/unlock operations
     * are performed in a consistent manner.
     *
     */
 
    procedure   lockPath(
        store_name  in              varchar2,
        path        in              varchar2,
        lock_type   in              integer,
        lock_data   in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
    procedure   unlockPath(
        store_name  in              varchar2,
        path        in              varchar2,
        ctx         in              dbms_dbfs_content_context_t);
 
 
 
    /*
     * DBFS SPI: access checks.
     *
     * Check if a given pathname (store_name, path, pathtype) can be
     * manipulated by "operation (see the various
     * "dbms_dbfs_content.op_xxx" opcodes) by "principal".
     *
     * This is a convenience function for the DBFS API; a store that
     * supports access control still internally performs these checks to
     * guarantee security.
     *
     */
 
    function    checkAccess(
        store_name  in              varchar2,
        path        in              varchar2,
        pathtype    in              integer,
        operation   in              varchar2,
        principal   in              varchar2)
            return  integer;
end;
/
show errors;
 
create or replace public synonym tbfs
    for sys.tbfs;
 
grant execute on tbfs
    to dbfs_role;

body.sql

body.sqlスクリプトは、tbfsのSPI仕様を提供します。

body.sqlスクリプト:

connect / as sysdba;
 
create or replace package body tbfs
as
 
 
 
    /*
     * Lookup store features (see dbms_dbfs_content.feature_XXX). Lookup
     * store id.
     *
     * A store ID identifies a provider-specific store, across
     * registrations and mounts, but independent of changes to the store
     * contents.
     *
     * I.e. changes to the store table(s) should be reflected in the
     * store ID, but re-initialization of the same store table(s) should
     * preserve the store ID.
     *
     * Providers should also return a "version" (either specific to a
     * provider package, or to an individual store) based on a standard
     * <a.b.c> naming convention (for <major>, <minor>, and <patch>
     * components).
     *
     */
 
    function    getFeatures(
        store_name          in      varchar2)
            return  integer
    is
    begin
        return dbms_dbfs_content.feature_locator;
    end;
 
    function    getStoreId(
        store_name          in      varchar2)
            return  number
    is
    begin
        return 1;
    end;
 
    function    getVersion(
        store_name          in      varchar2)
            return  varchar2
    is
    begin
        return '1.0.0';
    end;
 
 
 
    /*
     * Lookup pathnames by (store_name, std_guid) or (store_mount,
     * std_guid) tuples.
     *
     * If the underlying "std_guid" is found in the underlying store,
     * this function returns the store-qualified pathname.
     *
     * If the "std_guid" is unknown, a "null" value is returned. Clients
     * are expected to handle this as appropriate.
     *
     */
 
    function    getPathByStoreId(
        store_name          in      varchar2,
        guid                in      integer)
            return  varchar2
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: space usage.
     *
     * Clients can query filesystem space usage statistics via the
     * "spaceUsage()" method. Providers are expected to support this
     * method for their stores (and to make a best effort determination
     * of space usage---esp. if the store consists of multiple
     * tables/indexes/lobs, etc.).
     *
     * "blksize" is the natural tablespace blocksize that holds the
     * store---if multiple tablespaces with different blocksizes are
     * used, any valid blocksize is acceptable.
     *
     * "tbytes" is the total size of the store in bytes, and "fbytes" is
     * the free/unused size of the store in bytes. These values are
     * computed over all segments that comprise the store.
     *
     * "nfile", "ndir", "nlink", and "nref" count the number of
     * currently available files, directories, links, and references in
     * the store.
     *
     * Since database objects are dynamically growable, it is not easy
     * to estimate the division between "free" space and "used" space.
     *
     */
 
    procedure   spaceUsage(
        store_name  in              varchar2,
        blksize     out             integer,
        tbytes      out             integer,
        fbytes      out             integer,
        nfile       out             integer,
        ndir        out             integer,
        nlink       out             integer,
        nref        out             integer)
    is
        nblks       number;
    begin
        select count(*) into nfile
            from tbfs.tbfst;
        ndir  := 0;
        nlink := 0;
        nref  := 0;
 
        select sum(bytes) into tbytes
            from user_segments;
        select sum(blocks) into nblks
            from user_segments;
        blksize := tbytes/nblks;
        fbytes  := 0;                                    /* change as needed */
    end;
 
 
 
    /*
     * DBFS SPI: notes on pathnames.
     *
     * All pathnames used in the SPI are store-qualified, i.e. a 2-tuple
     * of the form (store_name, pathname) (where the pathname is rooted
     * within the store namespace).
     *
     *
     * Stores/providers that support contentID-based access (see
     * "feature_content_id") also support a form of addressing that is
     * not based on pathnames. Items are identified by an explicit store
     * name, a "null" pathname, and possibly a contentID specified as a
     * parameter or via the "opt_content_id" property.
     *
     * Not all operations are supported with contentID-based access, and
     * applications should depend only on the simplest create/delete
     * functionality being available.
     *
     */
 
 
 
    /*
     * DBFS SPI: creation operations
     *
     * The SPI must allow the DBFS API to create directory, file, link,
     * and reference elements (subject to store feature support).
     *
     *
     * All of the creation methods require a valid pathname (see the
     * special exemption for contentID-based access below), and can
     * optionally specify properties to be associated with the pathname
     * as it is created. It is also possible for clients to fetch-back
     * item properties after the creation completes (so that
     * automatically generated properties (e.g. "std_creation_time") are
     * immediately available to clients (the exact set of properties
     * fetched back is controlled by the various "prop_xxx" bitmasks in
     * "prop_flags").
     *
     *
     * Links and references require an additional pathname to associate
     * with the primary pathname.
     *
     * File pathnames can optionally specify a BLOB value to use to
     * initially populate the underlying file content (the provided BLOB
     * may be any valid lob: temporary or permanent). On creation, the
     * underlying lob is returned to the client (if "prop_data" is
     * specified in "prop_flags").
     *
     * Non-directory pathnames require that their parent directory be
     * created first. Directory pathnames themselves can be recursively
     * created (i.e. the pathname hierarchy leading up to a directory
     * can be created in one call).
     *
     *
     * Attempts to create paths that already exist is an error; the one
     * exception is pathnames that are "soft-deleted" (see below for
     * delete operations)---in these cases, the soft-deleted item is
     * implicitly purged, and the new item creation is attempted.
     *
     *
     * Stores/providers that support contentID-based access accept an
     * explicit store name and a "null" path to create a new element.
     * The contentID generated for this element is available via the
     * "opt_content_id" property (contentID-based creation automatically
     * implies "prop_opt" in "prop_flags").
     *
     * The newly created element may also have an internally generated
     * pathname (if "feature_lazy_path" is not supported) and this path
     * is available via the "std_canonical_path" property.
     *
     * Only file elements are candidates for contentID-based access.
     *
     */
 
    procedure   createFile(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     in out nocopy   blob,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
        guid        number;
    begin
        if (path = '/') then
            raise dbms_dbfs_content.invalid_path;
        end if;
 
        if content is null then
            content := empty_blob();
        end if;
 
        begin
            insert into tbfs.tbfst values (substr(path,2), content)
                returning data into content;
        exception
            when dup_val_on_index then
                raise dbms_dbfs_content.path_exists;
        end;
 
        select ora_hash(path) into guid from dual;
 
        properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:length',
                to_char(dbms_lob.getlength(content)),
                dbms_types.TYPECODE_NUMBER),
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
    end;
 
    procedure   createLink(
        store_name  in              varchar2,
        srcPath     in              varchar2,
        dstPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   createReference(
        store_name  in              varchar2,
        srcPath     in              varchar2,
        dstPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   createDirectory(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        prop_flags  in              integer,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: deletion operations
     *
     * The SPI must allow the DBFS API to delete directory, file, link,
     * and reference elements (subject to store feature support).
     *
     *
     * By default, the deletions are "permanent" (get rid of the
     * successfully deleted items on transaction commit), but stores may
     * also support "soft-delete" features. If requested by the client,
     * soft-deleted items are retained by the store (but not typically
     * visible in normal listings or searches).
     *
     * Soft-deleted items can be "restore"d, or explicitly purged.
     *
     *
     * Directory pathnames can be recursively deleted (i.e. the pathname
     * hierarchy below a directory can be deleted in one call).
     * Non-recursive deletions can be performed only on empty
     * directories. Recursive soft-deletions apply the soft-delete to
     * all of the items being deleted.
     *
     *
     * Individual pathnames (or all soft-deleted pathnames under a
     * directory) can be restored or purged via the restore and purge
     * methods.
     *
     *
     * Providers that support filtering can use the provider "filter" to
     * identify subsets of items to delete---this makes most sense for
     * bulk operations (deleteDirectory, restoreAll, purgeAll), but all
     * of the deletion-related operations accept a "filter" argument.
     *
     *
     * Stores/providers that support contentID-based access can also
     * allow file items to be deleted by specifying their contentID.
     *
     */
 
    procedure   deleteFile(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        soft_delete in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        if (path = '/') then
            raise dbms_dbfs_content.invalid_path;
        end if;
 
        if ((soft_delete <> 0)      or
            (filter is not null))   then
            raise dbms_dbfs_content.unsupported_operation;
        end if;
 
        delete from tbfs.tbfst t
            where ('/' || t.key) = path;
 
        if sql%rowcount <> 1 then
            raise dbms_dbfs_content.invalid_path;
        end if;
    end;
 
    procedure   deleteContent(
        store_name  in              varchar2,
        contentID   in              raw,
        filter      in              varchar2,
        soft_delete in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   deleteDirectory(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        soft_delete in              integer,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   restorePath(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   purgePath(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   restoreAll(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   purgeAll(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: path get/put operations.
     *
     * Existing path items can be accessed (for query or for update) and
     * modified via simple get/put methods.
     *
     * All pathnames allow their metadata (i.e. properties) to be
     * read/modified. On completion of the call, the client can request
     * (via "prop_flags") specific properties to be fetched as well.
     *
     * File pathnames allow their data (i.e. content) to be
     * read/modified. On completion of the call, the client can request
     * (via the "prop_data" bitmaks in "prop_flags") a new BLOB locator
     * that can be used to continue data access.
     *
     * Files can also be read/written without using BLOB locators, by
     * explicitly specifying logical offsets/buffer-amounts and a
     * suitably sized buffer.
     *
     *
     * Update accesses must specify the "forUpdate" flag. Access to link
     * pathnames can be implicitly and internally deferenced by stores
     * (subject to feature support) if the "deref" flag is
     * specified---however, this is dangerous since symbolic links are
     * not always resolvable.
     *
     *
     * The read methods (i.e. "getPath" where "forUpdate" is "false"
     * also accepts a valid "asof" timestamp parameter that can be used
     * by stores to implement "as of" style flashback queries. Mutating
     * versions of the "getPath" and the "putPath" methods do not
     * support as-of modes of operation.
     *
     *
     * "getPathNowait" implies a "forUpdate", and, if implemented (see
     * "feature_nowait"), allows providers to return an exception
     * (ORA-54) rather than wait for row locks.
     *
     */
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     out    nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        forUpdate   in              integer,
        deref       in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
        guid        number;
    begin
        if (deref <> 0) then
            raise dbms_dbfs_content.unsupported_operation;
        end if;
 
        select ora_hash(path) into guid from dual;
 
        if (path = '/') then
            if (forUpdate <> 0) then
                raise dbms_dbfs_content.unsupported_operation;
            end if;
 
            content    := null;
            item_type  := dbms_dbfs_content.type_directory;
            properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
 
            return;
        end if;
 
        begin
            if (forUpdate <> 0) then
                select t.data into content from tbfs.tbfst t
                    where ('/' || t.key) = path
                    for update;
            else
                select t.data into content from tbfs.tbfst t
                    where ('/' || t.key) = path;
            end if;
        exception
            when no_data_found then
                raise dbms_dbfs_content.invalid_path;
        end;
 
        item_type  := dbms_dbfs_content.type_file;
        properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:length',
                to_char(dbms_lob.getlength(content)),
                dbms_types.TYPECODE_NUMBER),
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
    end;
 
    procedure   getPathNowait(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     out    nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        deref       in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in out          number,
        offset      in              number,
        buffer      out    nocopy   raw,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
        content     blob;
        guid        number;
    begin
        if (path = '/') then
            raise dbms_dbfs_content.unsupported_operation;
        end if;
 
        begin
            select t.data into content from tbfs.tbfst t
                where ('/' || t.key) = path;
        exception
            when no_data_found then
                raise dbms_dbfs_content.invalid_path;
        end;
 
        select ora_hash(path) into guid from dual;
        dbms_lob.read(content, amount, offset, buffer);
 
        properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:length',
                to_char(dbms_lob.getlength(content)),
                dbms_types.TYPECODE_NUMBER),
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
    end;
 
    procedure   getPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in out          number,
        offset      in              number,
        buffers     out    nocopy   dbms_dbfs_content_raw_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        content     in out nocopy   blob,
        item_type   out             integer,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
        guid        number;
    begin
        if (path = '/') then
            raise dbms_dbfs_content.unsupported_operation;
        end if;
 
        if content is null then
            content := empty_blob();
        end if;
 
        update tbfs.tbfst t
            set t.data = content
            where ('/' || t.key) = path
            returning t.data into content;
 
        if sql%rowcount <> 1 then
            raise dbms_dbfs_content.invalid_path;
        end if;
 
        select ora_hash(path) into guid from dual;
 
        item_type  := dbms_dbfs_content.type_file;
        properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:length',
                to_char(dbms_lob.getlength(content)),
                dbms_types.TYPECODE_NUMBER),
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
    end;
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        amount      in              number,
        offset      in              number,
        buffer      in              raw,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
        content     blob;
        guid        number;
    begin
        if (path = '/') then
            raise dbms_dbfs_content.unsupported_operation;
        end if;
 
        begin
            select t.data into content from tbfs.tbfst t
                where ('/' || t.key) = path
                for update;
        exception
            when no_data_found then
                raise dbms_dbfs_content.invalid_path;
        end;
 
        select ora_hash(path) into guid from dual;
        dbms_lob.write(content, amount, offset, buffer);
 
        properties := dbms_dbfs_content_properties_t(
            dbms_dbfs_content_property_t(
                'std:length',
                to_char(dbms_lob.getlength(content)),
                dbms_types.TYPECODE_NUMBER),
            dbms_dbfs_content_property_t(
                'std:guid',
                to_char(guid),
                dbms_types.TYPECODE_NUMBER));
    end;
 
    procedure   putPath(
        store_name  in              varchar2,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        written     out             number,
        offset      in              number,
        buffers     in              dbms_dbfs_content_raw_t,
        prop_flags  in              integer,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: rename/move operations.
     *
     * Pathnames can be renamed or moved, possibly across directory
     * hierarchies and mount-points, but within the same store.
     *
     *
     * Non-directory pathnames previously accessible via "oldPath" are
     * renamed as a single item subsequently accessible via "newPath";
     * assuming that "newPath" does not already exist.
     *
     * If "newPath" exists and is not a directory, the rename implicitly
     * deletes the existing item before renaming "oldPath". If "newPath"
     * exists and is a directory, "oldPath" is moved into the target
     * directory.
     *
     *
     * Directory pathnames previously accessible via "oldPath" are
     * renamed by moving the directory and all of its children to
     * "newPath" (if it does not already exist) or as children of
     * "newPath" (if it exists and is a directory).
     *
     *
     * Stores/providers that support contentID-based access and lazy
     * pathname binding also support the "setPath" method that
     * associates an existing "contentID" with a new "path".
     *
     */
 
    procedure   renamePath(
        store_name  in              varchar2,
        oldPath     in              varchar2,
        newPath     in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   setPath(
        store_name  in              varchar2,
        contentID   in              raw,
        path        in              varchar2,
        properties  in out nocopy   dbms_dbfs_content_properties_t,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: directory navigation and search.
     *
     * The DBFS API can list or search the contents of directory
     * pathnames, optionally recursing into sub-directories, optionally
     * seeing soft-deleted items, optionally using flashback "as of" a
     * provided timestamp, and optionally filtering items in/out within
     * the store based on list/search predicates.
     *
     */
 
    function    list(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
            return  dbms_dbfs_content_list_items_t
                pipelined
    is
    begin
        for rws in (select * from tbfs.tbfst)
        loop
            pipe row(dbms_dbfs_content_list_item_t(
                '/' || rws.key, rws.key, dbms_dbfs_content.type_file));
        end loop;
    end;
 
    function    search(
        store_name  in              varchar2,
        path        in              varchar2,
        filter      in              varchar2,
        recurse     in              integer,
        ctx         in              dbms_dbfs_content_context_t)
            return  dbms_dbfs_content_list_items_t
                pipelined
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: locking operations.
     *
     * Clients of the DBFS API can apply user-level locks to any valid
     * pathname (subject to store feature support), associate the lock
     * with user-data, and subsequently unlock these pathnames.
     *
     * The status of locked items is available via various optional
     * properties (see "opt_lock*" above).
     *
     *
     * It is the responsibility of the store (assuming it supports
     * user-defined lock checking) to ensure that lock/unlock operations
     * are performed in a consistent manner.
     *
     */
 
    procedure   lockPath(
        store_name  in              varchar2,
        path        in              varchar2,
        lock_type   in              integer,
        lock_data   in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
    procedure   unlockPath(
        store_name  in              varchar2,
        path        in              varchar2,
        ctx         in              dbms_dbfs_content_context_t)
    is
    begin
        raise dbms_dbfs_content.unsupported_operation;
    end;
 
 
 
    /*
     * DBFS SPI: access checks.
     *
     * Check if a given pathname (store_name, path, pathtype) can be
     * manipulated by "operation (see the various
     * "dbms_dbfs_content.op_xxx" opcodes) by "principal".
     *
     * This is a convenience function for the DBFS API; a store that
     * supports access control still internally performs these checks to
     * guarantee security.
     *
     */
 
    function    checkAccess(
        store_name  in              varchar2,
        path        in              varchar2,
        pathtype    in              integer,
        operation   in              varchar2,
        principal   in              varchar2)
            return  integer
    is
    begin
        return 1;
    end;
end;
/
show errors;

capi.sql

capi.sqlスクリプトは、DBFSを登録およびマウントします。

capi.sqlスクリプト:

connect tbfs/tbfs;
 
exec dbms_dbfs_content.registerStore('MY_TBFS', 'table', 'TBFS');
exec dbms_dbfs_content.mountStore('MY_TBFS', singleton => true);
commit;