本節では、PostgreSQLのlibpqクライアントインタフェースライブラリで提供されるラージオブジェクトへのアクセス手段について説明します。
PostgreSQLラージオブジェクトインタフェースは、Unixファイルシステムインタフェースに因んで設計されており、open
、read
、write
、lseek
など同様のインタフェースを有しています。
ラージオブジェクトファイル記述子はトランザクションの間でしか有効でありませんので、これらの関数を使用したラージオブジェクトの操作はすべてSQLトランザクションブロック内で行われなければなりません。
これらの関数のいずれか1つの実行時にエラーが発生した場合、関数は他ではあり得ない値、通常は0または-1を返します。
エラーを説明するメッセージは接続オブジェクト内に格納され、PQerrorMessage
を用いて取り出すことができます。
これらの関数を使用するクライアントアプリケーションは、libpq/libpq-fs.h
ヘッダファイルをインクルードし、libpqライブラリとリンクしなければなりません。
Oid lo_creat(PGconn *conn, int mode);
この関数はラージオブジェクトを新規に作成します。
戻り値は新規ラージオブジェクトに割り当てられたOIDで、失敗時にはInvalidOid
(0)が返されます。
PostgreSQL 8.1では、mode
は使用されず、無視されます。
しかし、以前のリリースとの後方互換性を保持するために、これをINV_READ
、INV_WRITE
、INV_READ
|
INV_WRITE
に設定することが最善です。
(これらの定数シンボルはlibpq/libpq-fs.h
ヘッダファイルで定義されています。)
以下に例を示します。
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);
Oid lo_create(PGconn *conn, Oid lobjId);
この関数もラージオブジェクトを新規に作成します。
割り当てられるOIDをlobjId
で指定することができます。
こうした場合、そのOIDが他のラージオブジェクトですでに使用されていた場合、失敗します。
lobjId
がInvalidOid
(0)の場合、lo_create
は未使用のOIDを割り当てます。
(これはlo_creat
と同じ動作です。)
戻り値は新規ラージオブジェクトに割り当てられたOIDで、失敗時にはInvalidOid
(0)が返されます。
lo_create
はPostgreSQL 8.1から導入されました。
この関数を古いバージョンで実行させると失敗し、InvalidOid
が返されます。
例を示します。
inv_oid = lo_create(conn, desired_oid);
オペレーティングシステム上のファイルをラージオブジェクトとしてインポートするには、以下の関数を呼び出します。
Oid lo_import(PGconn *conn, const char *filename);
filename
には、ラージオブジェクトとしてインポートするオペレーティングシステム上のファイルのパス名を指定します。
戻り値は、新規ラージオブジェクトに割り当てられたOIDです。
失敗時はInvalidOid
(0)が返されます。
このファイルがサーバではなく、クライアントインタフェースライブラリから読み取られることに注意してください。
ですから、このファイルはクライアントのファイルシステム上に存在し、クライアントアプリケーションから読み取り可能でなければなりません。
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
この関数も新規のラージオブジェクトをインポートします。
割り当てられるOIDをlobjId
で指定することができます。
こうした場合、そのOIDが他のラージオブジェクトですでに使用されていた場合、失敗します。
lobjId
がInvalidOid
(0)の場合、lo_import_with_oid
は未使用のOIDを割り当てます(これはlo_import
と同じ動作です)。
戻り値は新規ラージオブジェクトに割り当てられたOIDで、失敗時にはInvalidOid
(0)が返されます。
lo_import_with_oid
はPostgreSQL 8.4から導入され、8.1から導入されたlo_create
を内部で使用しています。
この関数を8.0以前のバージョンで実行させると失敗し、InvalidOid
が返されます。
ラージオブジェクトをオペレーティングシステム上のファイルにエクスポートするには、以下の関数を呼び出します。
int lo_export(PGconn *conn, Oid lobjId, const char *filename);
lobjId
引数には、エクスポートさせるラージオブジェクトのOIDを指定し、filename
引数には、オペレーティングシステム上のファイルのパス名を指定します。
このファイルはサーバではなく、クライアントインタフェースライブラリによって書き込まれることに注意してください。
成功時には1、失敗時には-1が返されます。
読み取りまたは書き込みのために既存のラージオブジェクトを開く場合は、以下の関数を呼び出します。
int lo_open(PGconn *conn, Oid lobjId, int mode);
lobjId
引数には開きたいラージオブジェクトのOIDを指定します。
mode
の各ビットは、そのオブジェクトを読み取りのみ(INV_READ
)、書き込みのみ(INV_WRITE
)、またはその両方できるように開くのかを制御するものです。
(これらの定数シンボルはlibpq/libpq-fs.h
ヘッダファイルで定義されています。)
lo_open
は、lo_read
、lo_write
、lo_lseek
、lo_lseek64
、lo_tell
、lo_tell64
、lo_truncate
、lo_truncate64
、lo_close
で使用する(非負の)ラージオブジェクト記述子を返します。
この記述子は現在のトランザクション期間のみで有効です。
失敗時には-1が返されます。
現時点では、サーバはINV_WRITE
モードとINV_READ
|
INV_WRITE
モードとを区別しません。
どちらの場合でも記述子から読み取り可能です。
しかし、これらのモードとINV_READ
だけのモードとの間には大きな違いがあります。
INV_READ
モードでは記述子に書き込むことができません。
そして、読み込んだデータは、このトランザクションや他のトランザクションで後で書き込んだかどうかは関係なく、lo_open
を実行した時に有効だったトランザクションスナップショットの時点のラージオブジェクトの内容を反映したものになります。
INV_WRITE
を付けて開いた記述子から読み取ると、現在のトランザクションによる書き込みや他のトランザクションがコミットした書き込みすべてを反映したデータが返されます。
これは、通常のSELECT
SQLコマンドにおけるREPEATABLE READ
トランザクションの動作とREAD COMMITTED
トランザクションの動作の違いに似ています。
ラージオブジェクトにSELECT
権限が与えられていなかったり、INV_WRITE
が指定されていて、かつUPDATE
権限が与えられていないと、lo_open
は失敗します。
(PostgreSQL 11よりも前では、こうした権限チェックはディスクリプタを使って最初に読み出し、あるいは書き込みの呼び出しを実際に行う際に実施されていました。)
この権限チェックは、lo_compat_privileges実行時パラメータで無効にすることができます。
以下に例を示します。
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
len
バイトを、buf
(len
サイズでなければなりません)からfd
ラージオブジェクト記述子に書き込みます。
fd
引数は事前に実行したlo_open
の戻り値でなければいけません。
実際に書き込まれたバイト数が返されます(現在の実装ではエラーが発生しない限りlen
と常に等しくなります)。
エラーイベントが発生した場合は、-1を返します。
len
パラメータはsize_t
として宣言されていますが、この関数はINT_MAX
より大きな値を拒絶します。
実際には、多くても数メガバイトのチャンクでデータを転送することが最善です。
int lo_read(PGconn *conn, int fd, char *buf, size_t len);
len
長のバイトを、fd
ラージオブジェクト記述子からbuf
(len
サイズでなければなりません)に読み込みます。
fd
引数は事前に実行したlo_open
の戻り値でなければいけません。
実際に読み込まれたバイト数が返されます。
ラージオブジェクトの最後に先に達した場合はlen
より小さな値になります。
エラーイベントが発生した場合は、-1値を返します。
len
パラメータはsize_t
として宣言されていますが、この関数はINT_MAX
より大きな値を拒絶します。
実際には、多くても数メガバイトをチャンク内にデータを転送することが最善です。
ラージオブジェクト記述子に関連付けされている、現在の読み取りまたは書き込みを行う位置を変更するには、以下の関数を呼び出します。
int lo_lseek(PGconn *conn, int fd, int offset, int whence);
この関数はfd
で識別されるラージオブジェクト識別子の現在の位置を指すポインタを、offset
で指定した新しい位置に変更します。
whence
に指定可能な値は、SEEK_SET
(オブジェクトの先頭位置からシーク)、SEEK_CUR
(現在位置からシーク)、SEEK_END
(オブジェクトの末尾位置からシーク)のいずれかです。
戻り値は新しい位置ポインタで、エラー時に-1が返されます。
2GBを超えるサイズのラージオブジェクトを取り扱う場合は代わりに以下を使用してください。
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
この関数はlo_lseek
と同じ動作をしますが、offset
として2GBを超える値を受付け、2GBより大きな結果を出力します。
lo_lseek
は2GBを超える新しい位置ポインタが指定された場合に失敗することに注意してください。
lo_lseek64
はPostgreSQL 9.3にて追加されました。
この関数をより古いバージョンのサーバに対して実行した場合には失敗し、-1が返ります。
ラージオブジェクト記述子の現在の読み取り、書き込み位置を入手するには、以下の関数を呼び出します。
int lo_tell(PGconn *conn, int fd);
エラーが発生した場合は-1が返されます。
サイズが2GBを超える可能性があるラージオブジェクトを取り扱う場合は代わりに以下を使用します。
pg_int64 lo_tell64(PGconn *conn, int fd);
この関数はlo_tell
と同じ動作をしますが、2GBより大きな結果を出力します。
lo_tell
は2GBを超える新しい位置での読み書きに失敗します。
lo_tell64
はPostgreSQL 9.3にて追加されました。
この関数をより古いバージョンのサーバに対して実行した場合には失敗し、-1が返ります。
ラージオブジェクトを指定した長さに切り詰めるには、以下を呼び出します。
int lo_truncate(PGcon *conn, int fd, size_t len);
この関数はラージオブジェクト記述子fd
をlen
長に切り詰めます。
fd
引数は前もってlo_open
が返したものでなければなりません。
len
が現在のラージオブジェクト長より大きければ、ラージオブジェクトは指定された長さまでヌルバイト('\0')で拡張されます。
成功時lo_truncate
はゼロを返します。
失敗時の戻り値は-1です。
fd
ディスクリプタの読み取り/書き出し位置は変わりません。
len
パラメータはsize_t
として宣言されていますが、lo_truncate
はINT_MAX
より大きな値を拒絶します。
2GBを超える可能性があるラージオブジェクトを取り扱う場合は代わりに以下を使用します。
int lo_truncate64(PGcon *conn, int fd, pg_int64 len);
この関数はlo_truncate
と同じ動作をしますが、2GBを超えるlen
を受け付けることができます。
lo_truncate
はPostgreSQL 8.3で新規に導入されました。
この関数を古いバージョンのサーバに対して実行した場合は失敗し、-1が返されます。
lo_truncate64
はPostgreSQL 9.3にて追加されました。
この関数をより古いバージョンのサーバに対して実行した場合には失敗し、-1が返ります。