<!--
$Header: /usr/prj/pg/cvsroot/doc/doc/src/sgml/lobj.sgml,v 1.9 2001/09/13 01:00:21 junichi Exp $
-->

 <chapter id="largeObjects">
  <!--<title id="largeObjects-title">Large Objects</title>-->
      <title id="largeObjects-title">ラージオブジェクト</title>
<indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary></indexterm>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary></indexterm>
  <para>
   <!--In <productname>Postgres</productname>,
   data values are stored in tuples and 
   individual tuples cannot span data pages. Since the size of
   a data page is 8192 bytes, the upper limit on the  size
   of a data value is relatively low. To support the storage 
   of larger atomic values, 
   <productname>Postgres</productname> provides a  large
   object   interface.    This  interface  provides  file
   oriented access to user data that has been declared  to
   be a large type.
   This  section describes the implementation and the 
   programming and query  language  interfaces  to 
   <productname>Postgres</productname>
   large object data.-->

   <productname>Postgres</productname>では、データ値はタプルに格納され、各タプルはデータページを跨ることができません。データページのサイズは8,192バイトなので、データ値の最大制限は比較的小さいものとなります。大きいサイズのものを格納するために、<productname>Postgres</productname>ではラージオブジェクトインターフェイスを提供しています。この節では、その実装とプログラム作成方法、<productname>Postgres</productname>ラージオブジェクトデータへの問い合わせ言語インターフェイスについて説明します。
  </para>

  <sect1 id="lo-history">
   <!--<title>Historical Note</title>-->
   <title>歴史的背景</title>

   <para>
    <!--Originally, <productname>Postgres 4.2</productname> supported three standard 
    implementations of large objects: as files external 
    to <productname>Postgres</productname>,  as
    external files managed by <productname>Postgres</productname>, and as data
    stored within the <productname>Postgres</productname> database. It causes  
    considerable confusion among users. As a result, we only 
    support large objects as data stored within  the  <productname>Postgres</productname>
    database  in  <productname>PostgreSQL</productname>.  Even  though it is slower to
    access, it provides stricter data  integrity.
    For historical reasons, this storage scheme is referred to as 
    Inversion large objects. (We will use  Inversion  and  large
    objects  interchangeably to mean the same thing in this
    section.)
    Since <productname>PostgreSQL 7.1</productname> all large objects are placed in
    one system table called pg_largeobject.-->

    当初、<productname>Postgres 4.2</productname>ではラージオブジェクトに関して、3つの標準的な実装をサポートしていました。それらは<productname>Postgres</productname>の外部ファイル、<productname>Postgres</productname>で管理される外部ファイル、<productname>Postgres</productname>データベースに格納されるデータの3つです。これはかなりユーザーの混乱を招きました。よって、<productname>Postgres</productname>では<productname>PostgreSQL</productname>データベースに格納されるデータのみをサポートするようにしました。これによってアクセスが少々遅くなりましたが、より厳密に一貫性を持ったデータを提供するようになりました。歴史的な理由により、この格納の仕組みは転置ラージオブジェクトと呼ばれています（この節では、「転置」と「ラージオブジェクト」の両方を使用していますが、どちらも同じ意味です）。<productname>PostgreSQL 7.1</productname>からは、すべてのラージオブジェクトはpg_largeobjectと呼ばれる、1つのシステムテーブルに格納されます。<indexterm><primary>pg_largeobject</primary></indexterm><indexterm><primary>PostgreSQL</primary><secondary>pg_largeobject</secondary></indexterm>
   </para>
  </sect1>

  <sect1 id="lo-implementation">
   <!--<title>Implementation Features</title>-->
   <title>実装機能</title>

   <para>
    <!--The Inversion large object implementation breaks  large
    objects  up  into  "chunks"  and  stores  the chunks in
    tuples in the database.  A B-tree index guarantees fast
    searches for the correct chunk number when doing random
    access reads and writes.-->

    転置ラージオブジェクトの実装では、ラージオブジェクトを「チャンク」に分割し、チャンクをデータベース内のタプルに格納しています。B-treeインデックスは読み書き用のランダムアクセスに際して、正確なチャンク番号の高速検索を保証しています。
   </para>
  </sect1>

  <sect1 id="lo-interfaces">
   <!--<title>Interfaces</title>-->
   <title>インターフェイス</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="いんたーふぇいす">インターフェイス</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="いんたーふぇいす">インターフェイス</secondary></indexterm>
   <para>
    <!--The  facilities  <productname>Postgres</productname> provides  to
    access large objects,  both  in  the backend as part of user-defined
    functions or the front end as part  of  an  application
    using  the   interface, are described below. For users
    familiar with <productname>Postgres 4.2</productname>,
    <productname>PostgreSQL</productname> has a new set of
    functions  providing  a  more  coherent  interface.-->

    <productname>Postgres</productname>システムでは、ユーザー定義関数の一部としてバックエンド側から、もしくは、アプリケーションの一部としてフロントエンド側からのラージオブジェクトへのアクセスに使用されるインターフェイスを提供しています。これらは後で説明があります。<productname>Postgres 4.2</productname>に慣れているユーザー向けに、<productname>PostgreSQL</productname>はより理路整然としたインターフェイスを提供する新しい関数群を持っています。
</para>

    <note>
     <para>
      <!--All large object manipulation <emphasis>must</emphasis> take
      place within an SQL transaction. This requirement is strictly
      enforced as of Postgres 6.5, though it has been an
      implicit requirement in previous versions, resulting in
      misbehavior if ignored.-->

      すべてのラージオブジェクトの操作は<emphasis>必ず</emphasis>SQLのトランザクション内で行う必要があります。この制約は、Postgres 6.5以前のバージョンでは暗黙の必要条件でしたが、それ以降のバージョンでは厳しく強制されています。
      
     </para>
    </note>

   <para>
    <!--The  <productname>Postgres</productname>  large  object interface is modeled after
    the <acronym>Unix</acronym>  file  system  interface,  with  analogues  of
    <function>open(2)</function>,  <function>read(2)</function>,
    <function>write(2)</function>,
    <function>lseek(2)</function>, etc.  User 
    functions call these routines to retrieve only the data  of
    interest  from a large object.  For example, if a large
    object type called mugshot  existed  that  stored  
    photographs  of  faces, then a function called beard could
    be declared on mugshot data.  Beard could look  at  the
    lower third of a photograph, and determine the color of
    the beard that appeared  there,  if  any.   The  entire
    large  object value need not be buffered, or even 
    examined, by the beard function.
    Large objects may be accessed from dynamically-loaded <acronym>C</acronym>
    functions  or  database  client  programs that link the
    library.  <productname>Postgres</productname> provides a set of routines that 
    support opening, reading, writing, closing, and seeking on
    large objects.-->
 
    <productname>Postgres</productname>ラージオブジェクトインターフェイスは、<acronym>Unix</acronym>ファイルシステムにならって作成され、<function>open(2)</function>、<function>read(2)</function>、<function>write(2)</function>、<function>lseek(2)</function>などと酷似したインターフェイスを持っています。ユーザー関数は、ラージオブジェクトから必要なデータだけを取り出すときにこれらの処理を呼び出します。たとえば、顔写真を格納するmugshotという名前のラージオブジェクト型があり、beardという名前の関数で、mugshotデータについて宣言したとします。beard関数は写真の下1/3をみて、もしあれば、そこにあるひげの色を測定するものとします。beard関数では、ラージオブジェクトの値全体をバッファに取り出すことも、全体を確認することも必要ありません。ラージオブジェクトは、動的に読み込まれる<acronym>C</acronym>関数、または、ライブラリとリンクされたデータベースクライアントプログラムのどちらからでもアクセスできます。<productname>Postgres</productname>は、ラージオブジェクトについて「開く」、「読む」、「書く」、「閉じる」、「シークする」機能を提供しています。
   </para>

   <sect2>
    <!--<title>Creating a Large Object</title>-->
    <title>ラージオブジェクトの作成</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="さくせい">作成</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="さくせい">作成</secondary></indexterm>

     <!--The routine-->
<synopsis>
Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <replaceable class="parameter">mode</replaceable>)
</synopsis>

<para>
     <!--creates a new large  object.  
     <replaceable class="parameter">mode</replaceable>  is  a  bitmask
     describing  several  different  attributes  of  the new
     object.  The symbolic constants listed here are defined
     in
     <filename>$<envar>PGROOT</envar>/src/include/libpq/libpq-fs.h</filename>
     The access type (read, write, or both) is controlled by
     OR ing together the bits <acronym>INV_READ</acronym>  and
     <acronym>INV_WRITE</acronym>.  The low-order sixteen bits of mask  are
     the  storage  manager  number on which the large object
     should reside.  For sites other  than  Berkeley,  these
     bits should always be zero.
     The commands below create an (Inversion) large object:-->

     この処理は、新しいラージオブジェクトを作成します。<indexterm><primary>lo_creat()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_creat()</secondary></indexterm>引数<replaceable class="parameter">mode</replaceable>は新しいオブジェクト用の複数の異なる属性を示すビットマスクです。以下で使用する定数シンボルは、<filename>$<envar>PGROOT</envar>/src/include/libpq/libpq-fs.h</filename>で定義されています。アクセスタイプ（読み取り、書き込み、または両方）は、<acronym>INV_READ</acronym>ビット、<acronym>INV_WRITE</acronym>ビットの論理和で指定できます。マスクの下位16ビットは、ラージオブジェクトが属するストレージマネージャの番号です。バークレイ以外のサイトでは、これらのビット列は常に0となります。次のコマンドは、（転置）ラージオブジェクトを作成します。</para>

<programlisting>
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);
</programlisting>
   </sect2>

   <sect2>
    <!--<title>Importing a Large Object</title>-->
    <title>ラージオブジェクトのインポート</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="いんぽーと">インポート</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="いんぽーと">インポート</secondary></indexterm>

    <para>
     <!--To import a <acronym>UNIX</acronym> file as a large object, call-->
     <acronym>UNIX</acronym>ファイルをラージオブジェクトとしてインポートするには、以下の関数を呼び出します。<indexterm><primary>lo_import()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_import()</secondary></indexterm>
</para>

<synopsis>
Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const char *<replaceable class="parameter">filename</replaceable>)
</synopsis>

<para>
     <!--<replaceable class="parameter">filename</replaceable> 
     specifies the  <acronym>Unix</acronym>  pathname  of
     the file to be imported as a large object.-->

     引数<replaceable class="parameter">filename</replaceable>には、ラージオブジェクトとしてインポートする<acronym>Unix</acronym>ファイルのパス名を指定します。

    </para>
   </sect2>

   <sect2>
    <!--<title>Exporting a Large Object</title>-->
    <title>ラージオブジェクトのエクスポート</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="えくすぽーと">エクスポート</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="えくすぽーと">エクスポート</secondary></indexterm>

    <para>
     <!--To export a large object
     into <acronym>UNIX</acronym> file, call-->

     ラージオブジェクトを<acronym>UNIX</acronym>ファイルにエクスポートするには、以下の関数を呼び出します。<indexterm><primary>lo_export()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_export()</secondary></indexterm>
</para>

<synopsis>
int lo_export(PGconn *<replaceable class="parameter">conn</replaceable>, Oid <replaceable class="parameter">lobjId</replaceable>, const char *<replaceable class="parameter">filename</replaceable>)
</synopsis>

<para>
     <!--The lobjId argument specifies  the  Oid  of  the  large
     object  to  export  and the filename argument specifies
     the <acronym>UNIX</acronym> pathname of the file.-->

     引数lobjIdには、エクスポートしたいラージオブジェクトのoidを指定し、引数filenameには、<acronym>UNIX</acronym>ファイルのパス名を指定します。
    </para>
   </sect2>

   <sect2>
    <!--<title>Opening an Existing Large Object</title>-->
    <title>既存のラージオブジェクトのオープン</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="おーぷん">オープン</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="おーぷん">オープン</secondary></indexterm>

    <para>
     <!--To open an existing large object, call-->
     既存のラージオブジェクトを開く場合は、以下の関数を呼び出します。<indexterm><primary>lo_open()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_open()</secondary></indexterm>
</para>

<synopsis>
int lo_open(PGconn *conn, Oid lobjId, int mode)
</synopsis>

<para>
     <!--The lobjId argument specifies  the  Oid  of  the  large
     object  to  open.   The  mode  bits control whether the
     object is opened  for  reading  INV_READ),  writing  or
     both.
     A  large  object cannot be opened before it is created.
     <function>lo_open</function> returns a large object descriptor
     for later use in <function>lo_read</function>, <function>lo_write</function>,
     <function>lo_lseek</function>, <function>lo_tell</function>, and
     <function>lo_close</function>.-->

     引数lobjIdには開きたいラージオブジェクトのoidを指定します。引数modeの各ビットは、そのオブジェクトを読み取りのみ（INV_READ）、書き込みのみ、またはその両方できるように開くのかを制御するものです。作成していないラージオブジェクトを開くことはできません。<function>lo_open</function>は、<function>lo_read</function>、<function>lo_write</function>、<function>lo_lseek</function>、<function>lo_tell</function>、<function>lo_close</function>で使用するラージオブジェクト記述子を返します。
</para>
</sect2>

<sect2>
<!--<title>Writing Data to a Large Object</title>-->
<title>ラージオブジェクトへのデータの書き込み</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="でーたのかきこみ">データの書き込み</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="でーたのかきこみ">データの書き込み</secondary></indexterm><indexterm><primary>lo_write()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_write()</secondary></indexterm>

     <!--The routine-->
<programlisting>
int lo_write(PGconn *conn, int fd, const char *buf, size_t len)
</programlisting>

     <!--writes len bytes from buf to large object fd.   The  fd
     argument must have been returned by a previous <function>lo_open</function>.
     The number of bytes actually written is  returned.   In
     the event of an error, the return value is negative.-->

<para>この処理は、引数len長のバイトを、引数bufから引数fdが示すラージオブジェクトに書き込みます。引数fdは事前に実行した<function>lo_open</function>の戻り値でなければいけません。実際に書き込まれたバイト数が返されます。エラーが発生した場合は、負の値を返します。
</para>
</sect2>

<sect2>
<!--<title>Reading Data from a Large Object</title>-->
<title>ラージオブジェクトからのデータの読み込み</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="でーたのよみこみ">データの読み込み</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="でーたのよみこみ">データの読み込み</secondary></indexterm>


     <!--The routine-->
<programlisting>
int lo_read(PGconn *conn, int fd, char *buf, size_t len)
</programlisting>

     <!--reads len bytes from large object fd into buf. The  fd
     argument must have been returned by a previous <function>lo_open</function>.
     The number of bytes actually read is returned. In
     the event of an error, the return value is negative.-->

<para>この処理は、引数len長のバイトを、引数fdが示すラージオブジェクトからbufに読み込みます。引数fdは事前に実行した<function>lo_open</function>の戻り値でなければいけません。実際に読み込まれたバイト数が返されます。エラーが発生した場合は、負の値を返します。<indexterm><primary>lo_read()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_read()</secondary></indexterm>
</para>
</sect2>

<sect2>
<!--<title>Seeking on a Large Object</title>-->
<title>ラージオブジェクトのシーク</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="しーく">シーク</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="しーく">シーク</secondary></indexterm>

<para>
     <!--To change the current read or write location on a large
     object, call-->

     ラージオブジェクトの現在の読み取り、または、書き込みを行う位置を変更するには、以下の関数を呼び出します。<indexterm><primary>lo_lseek()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_lseek()</secondary></indexterm></para>

<programlisting>
int lo_lseek(PGconn *conn, int fd, int offset, int whence)
</programlisting>

     <!--This routine moves the current location pointer for the
     large object described by fd to the new location specified 
     by offset.  The valid values for whence are
     SEEK_SET, SEEK_CUR, and SEEK_END.-->

<para>この処理は、引数fdで指定されたラージオブジェクトの現在の位置を指すポインタを、引数offsetで指定した新しい位置に変更します。引数whenceに指定可能な値は、SEEK_SET、SEEK_CUR、SEEK_ENDのいずれかです。

</para>
</sect2>

<sect2>
<!--<title>Closing a Large Object Descriptor</title>-->
<title>ラージオブジェクト記述子を閉じる</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="きじゅつしのくろーず">記述子のクローズ</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="きじゅつしのくろーず">記述子のクローズ</secondary></indexterm>


     <!--A large object may be closed by calling-->

<programlisting>
int lo_close(PGconn *conn, int fd)
</programlisting>

     <!--where  fd  is  a  large  object  descriptor returned by
     <function>lo_open</function>.  On success, <function>lo_close</function>
     returns zero.  On error, the return value is negative.-->

<para>上記の関数を呼び出すことで、ラージオブジェクトを閉じることができます。ここで、fdは<function>lo_open</function>の戻り値であるラージオブジェクト記述子です。成功すると、<function>lo_close</function>は0を返します。失敗すると、負の値を返します。<indexterm><primary>lo_close()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_close()</secondary></indexterm>

</para>
</sect2>

   <sect2>
    <!--<title>Removing a Large Object</title>-->
    <title>ラージオブジェクトの削除</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="さくじょ">削除</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="さくじょ">削除</secondary></indexterm>

    <para>
     <!--To remove a large object from the database, call-->

     ラージオブジェクトをデータベースから削除するには、以下の関数を呼び出します。<indexterm><primary>lo_unlink()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_unlink()</secondary></indexterm>
</para>

<synopsis>
Oid lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lobjId)
</synopsis>

<para>
     <!--The lobjId argument specifies  the  Oid  of  the  large
     object  to  remove.-->

     引数lobjIdは削除したいラージオブジェクトのoidを示します。

    </para>
   </sect2>


</sect1>

<sect1 id="lo-funcs">
<!--<title>Built in registered functions</title>-->
<title>組み込み済みの登録された関数</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="くみこみかんすう">組み込み関数</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="くみこみかんすう">組み込み関数</secondary></indexterm>

<para>
     <!-- There  are two built-in registered functions, <acronym>lo_import</acronym>
     and <acronym>lo_export</acronym> which  are  convenient  for  use
     in  <acronym>SQL</acronym>
     queries.
     Here is an example of their use-->

     <acronym>SQL</acronym>問い合わせで便利な、<acronym>lo_import</acronym>と<acronym>lo_export</acronym>という2つの組み込み済みの登録された関数があります。これらの使用例を以下に示します。<indexterm><primary>lo_import()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_import()</secondary></indexterm><indexterm><primary>lo_export()</primary></indexterm><indexterm><primary sortas="かんすう">関数</primary><secondary>lo_export()</secondary></indexterm></para>

<programlisting>
CREATE TABLE image (
    name            text,
    raster          oid
);

INSERT INTO image (name, raster)
    VALUES ('beautiful image', lo_import('/etc/motd'));

SELECT lo_export(image.raster, '/tmp/motd') from image
    WHERE name = 'beautiful image';
</programlisting>
</sect1>

<sect1 id="lo-libpq">
<!--<title>Accessing Large Objects from LIBPQ</title>-->
<title>LIBPQからラージオブジェクトへのアクセス</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="libpq">libpq</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="libpq">libpq</secondary></indexterm><indexterm><primary>libpq</primary><secondary sortas="らーじおぶじぇくとへのあくせす">ラージオブジェクトへのアクセス</secondary></indexterm>

<para>
     <!--Below is a sample program which shows how the large object  
     interface
     in  LIBPQ  can  be used.  Parts of the program are 
     commented out but are left in the source for  the  readers
     benefit.  This program can be found in
<filename>
../src/test/examples
</filename>
     Frontend applications which use the large object interface  
     in  LIBPQ  should   include   the   header   file
     libpq/libpq-fs.h and link with the libpq library.-->

     以下にLIBPQを使ったラージオブジェクトインターフェイスの使い方の例を示します。プログラムの一部はコメントアウトされていますが、読者にわかりやすいようにそのまま残してあります。このプログラムは、<filename>../src/test/examples</filename>にあります。LIBPQ内のラージオブジェクトインターフェイスを使用するフロントエンドアプリケーションは、libpq/libpq-fs.hというヘッダーファイルをインクルードし、libpqライブラリをリンクする必要があります。

</para>
</sect1>

<sect1 id="lo-sample">
<!--<title>Sample Program</title>-->
<title>サンプルプログラム</title>
<indexterm><primary>PostgreSQL</primary><secondary sortas="らーじおぶじぇくと">ラージオブジェクト</secondary><tertiary sortas="さんぷるぷろぐらむ">サンプルプログラム</tertiary></indexterm><indexterm><primary sortas="らーじおぶじぇくと">ラージオブジェクト</primary><secondary sortas="さんぷるぷろぐらむ">サンプルプログラム</secondary></indexterm>

<programlisting>
/*--------------------------------------------------------------
 *
 * testlo.c--
<!-- *    test using large objects with libpq-->
 * libpqでラージオブジェクトを使うテスト
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    /usr/local/devel/pglite/cvs/src/doc/manual.me,
 *    v 1.16 1995/09/01 23:55:00 jolly Exp
 *
 *--------------------------------------------------------------
 */
#include &lt;stdio.h&gt;
#include &quot;libpq-fe.h&quot;
#include &quot;libpq/libpq-fs.h&quot;

#define BUFSIZE          1024

/*
<!-- * importFile *    import file &quot;in_filename&quot; into database as large object &quot;lob
jOid&quot;-->
 * importFile *    ファイル &quot;in_filename&quot; をラージオブジェクト &quot;lobjOid&quot;
                   としてデータベースにインポート
 *
 */
Oid
importFile(PGconn *conn, char *filename)
{
    Oid         lobjId;
    int         lobj_fd;
    char        buf[BUFSIZE];
    int         nbytes,
                tmp;
    int         fd;

    /*
     * open the file to be read in
     */
    fd = open(filename, O_RDONLY, 0666);
    if (fd &lt; 0)
    {                           /* error */
        fprintf(stderr, &quot;can't open unix file %s&bsol;n&quot;, filename);
    }

    /*
     * create the large object
     */
    lobjId = lo_creat(conn, INV_READ | INV_WRITE);
    if (lobjId == 0)
        fprintf(stderr, &quot;can't create large object&bsol;n&quot;);

    lobj_fd = lo_open(conn, lobjId, INV_WRITE);

    /*
     * read in from the Unix file and write to the inversion file
     */
    while ((nbytes = read(fd, buf, BUFSIZE)) &gt; 0)
    {
        tmp = lo_write(conn, lobj_fd, buf, nbytes);
        if (tmp &lt; nbytes)
            fprintf(stderr, &quot;error while reading large object&bsol;n&quot;);
    }

    (void) close(fd);
    (void) lo_close(conn, lobj_fd);

    return lobjId;
}

void
pickout(PGconn *conn, Oid lobjId, int start, int len)
{
    int         lobj_fd;
    char       *buf;
    int         nbytes;
    int         nread;

    lobj_fd = lo_open(conn, lobjId, INV_READ);
    if (lobj_fd &lt; 0)
    {
        fprintf(stderr, &quot;can't open large object %d&bsol;n&quot;,
                lobjId);
    }

    lo_lseek(conn, lobj_fd, start, SEEK_SET);
    buf = malloc(len + 1);

    nread = 0;
    while (len - nread &gt; 0)
    {
        nbytes = lo_read(conn, lobj_fd, buf, len - nread);
        buf[nbytes] = ' ';
        fprintf(stderr, &quot;&gt;&gt;&gt; %s&quot;, buf);
        nread += nbytes;
    }
    free(buf);
    fprintf(stderr, &quot;&bsol;n&quot;);
    lo_close(conn, lobj_fd);
}

void
overwrite(PGconn *conn, Oid lobjId, int start, int len)
{
    int         lobj_fd;
    char       *buf;
    int         nbytes;
    int         nwritten;
    int         i;

    lobj_fd = lo_open(conn, lobjId, INV_READ);
    if (lobj_fd &lt; 0)
    {
        fprintf(stderr, &quot;can't open large object %d&bsol;n&quot;,
                lobjId);
    }

    lo_lseek(conn, lobj_fd, start, SEEK_SET);
    buf = malloc(len + 1);

    for (i = 0; i &lt; len; i++)
        buf[i] = 'X';
    buf[i] = ' ';

    nwritten = 0;
    while (len - nwritten &gt; 0)
    {
        nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
        nwritten += nbytes;
    }
    free(buf);
    fprintf(stderr, &quot;&bsol;n&quot;);
    lo_close(conn, lobj_fd);
}

/*
<!-- * exportFile *    export large object &quot;lobjOid&quot; to file &quot;out_filename&quot;-->
 * exportFile *    ラージオブジェクト &quot;lobjOid&quot; をファイル &quot;out_filename&quot;
                   にエクスポート
 *
 */
void
exportFile(PGconn *conn, Oid lobjId, char *filename)
{
    int         lobj_fd;
    char        buf[BUFSIZE];
    int         nbytes,
                tmp;
    int         fd;

    /*
     * create an inversion &quot;object&quot;
     */
    lobj_fd = lo_open(conn, lobjId, INV_READ);
    if (lobj_fd &lt; 0)
    {
        fprintf(stderr, &quot;can't open large object %d&bsol;n&quot;,
                lobjId);
    }

    /*
     * open the file to be written to
     */
    fd = open(filename, O_CREAT | O_WRONLY, 0666);
    if (fd &lt; 0)
    {                           /* error */
        fprintf(stderr, &quot;can't open unix file %s&bsol;n&quot;,
                filename);
    }

    /*
     * read in from the Unix file and write to the inversion file
     */
    while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) &gt; 0)
    {
        tmp = write(fd, buf, nbytes);
        if (tmp &lt; nbytes)
        {
            fprintf(stderr, &quot;error while writing %s&bsol;n&quot;,
                    filename);
        }
    }

    (void) lo_close(conn, lobj_fd);
    (void) close(fd);

    return;
}

void
exit_nicely(PGconn *conn)
{
    PQfinish(conn);
    exit(1);
}

int
main(int argc, char **argv)
{
    char       *in_filename,
               *out_filename;
    char       *database;
    Oid         lobjOid;
    PGconn     *conn;
    PGresult   *res;

    if (argc != 4)
    {
        fprintf(stderr, &quot;Usage: %s database_name in_filename out_filename&bsol;n&quot;,
                argv[0]);
        exit(1);
    }

    database = argv[1];
    in_filename = argv[2];
    out_filename = argv[3];

    /*
     * set up the connection
     */
    conn = PQsetdb(NULL, NULL, NULL, NULL, database);

    /* check to see that the backend connection was successfully made */
    if (PQstatus(conn) == CONNECTION_BAD)
    {
        fprintf(stderr, &quot;Connection to database '%s' failed.&bsol;n&quot;, database);
        fprintf(stderr, &quot;%s&quot;, PQerrorMessage(conn));
        exit_nicely(conn);
    }

    res = PQexec(conn, &quot;begin&quot;);
    PQclear(res);

    printf(&quot;importing file %s&bsol;n&quot;, in_filename);
/*  lobjOid = importFile(conn, in_filename); */
    lobjOid = lo_import(conn, in_filename);
/*
    printf(&quot;as large object %d.&bsol;n&quot;, lobjOid);

    printf(&quot;picking out bytes 1000-2000 of the large object&bsol;n&quot;);
    pickout(conn, lobjOid, 1000, 1000);

    printf(&quot;overwriting bytes 1000-2000 of the large object with X's&bsol;n&quot;);
    overwrite(conn, lobjOid, 1000, 1000);
*/

    printf(&quot;exporting large object to file %s&bsol;n&quot;, out_filename);
/*    exportFile(conn, lobjOid, out_filename); */
    lo_export(conn, lobjOid, out_filename);

    res = PQexec(conn, &quot;end&quot;);
    PQclear(res);
    PQfinish(conn);
    exit(0);
}
</programlisting>

</sect1>
</chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode:sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/lib/sgml/catalog")
sgml-local-ecat-files:nil
End:
-->
