The libpq client library provides a Unix file-system–style interface for accessing large objects in PostgreSQL. The interface mirrors familiar system calls — open, read, write, lseek, and so on — so C application developers can work with large objects using patterns they already know.
Before you start:
Include the header file
libpq/libpq-fs.hin your application.Link against the libpq library.
Execute all large object operations inside an SQL transaction block. Large object descriptors are only valid for the duration of a transaction.
If a function fails, it returns an otherwise-impossible value — typically 0 or -1. Retrieve the error message with PQerrorMessage.
Create a large object
Use lo_create to create a large object with a specific OID:
Oid lo_create(PGconn *conn, Oid lobjId);Pass a desired OID in lobjId. If that OID is already in use, the function fails. Pass InvalidOid (zero) to let the server assign an unused OID automatically. Returns the assigned OID on success, or InvalidOid on failure.
lo_createwas introduced in PostgreSQL 8.1. Running it against an older server returnsInvalidOid.
Example:
inv_oid = lo_create(conn, desired_oid);If you need to work with servers older than PostgreSQL 8.1, use the legacy lo_creat instead:
Oid lo_creat(PGconn *conn, int mode);lo_creat always assigns an unused OID. The mode parameter is ignored as of PostgreSQL 8.1; for backward compatibility, set it to INV_READ, INV_WRITE, or INV_READ | INV_WRITE. These constants are defined in libpq/libpq-fs.h.
Example:
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);Import a large object
To import an operating system file as a large object, call:
Oid lo_import(PGconn *conn, const char *filename);filename is the path to the file on the client file system — the file is read by the client library, not the server. Returns the assigned OID on success, or InvalidOid on failure.
To import a file and assign a specific OID, use:
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);Behavior is the same as lo_import, with the addition that you can specify the OID via lobjId. If that OID is already in use, the function fails. Pass InvalidOid to assign an unused OID automatically.
lo_import_with_oidwas introduced in PostgreSQL 8.4 and relies onlo_createinternally. Running it against PostgreSQL 8.0 or earlier returnsInvalidOid.
Export a large object
To write a large object to an operating system file, call:
int lo_export(PGconn *conn, Oid lobjId, const char *filename);lobjId is the OID of the large object to export. filename is the output path on the client file system — the file is written by the client library, not the server. Returns 1 on success, -1 on failure.
Open an existing large object
Before reading or writing, open the large object to get a descriptor:
int lo_open(PGconn *conn, Oid lobjId, int mode);Set mode to control access:
| Mode | Access |
|---|---|
INV_READ | Read-only |
INV_WRITE | Read/write |
INV_READ | INV_WRITE | Read/write (same as INV_WRITE) |
Returns a non-negative descriptor on success, or -1 on failure. The descriptor is valid only for the current transaction and can be used with lo_read, lo_write, lo_lseek, lo_lseek64, lo_tell, lo_tell64, lo_truncate, lo_truncate64, and lo_close.
Read visibility by mode:
INV_READ— data reflects the large object's state at the transaction snapshot taken whenlo_openwas called, regardless of subsequent writes. This is similar to the behavior ofREPEATABLE READ.INV_WRITE— data reflects all committed writes from other transactions as well as writes from the current transaction. This is similar to the behavior ofREAD COMMITTED.
lo_openrequiresSELECTprivilege on the large object. IfINV_WRITEis specified,UPDATEprivilege is also required. Before PostgreSQL 11, these checks were deferred to the first actual read or write call. To disable the checks, set thelo_compat_privilegesrun-time parameter.
Example:
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);Write data to a large object
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);Writes len bytes from buf to the large object descriptor fd. fd must be a descriptor returned by lo_open. Returns the number of bytes written (always equal to len in the current implementation), or -1 on error.
Although len is declared as size_t, the function rejects values larger than INT_MAX. Transfer data in chunks of a few megabytes at most.
Read data from a large object
int lo_read(PGconn *conn, int fd, char *buf, size_t len);Reads up to len bytes from the large object descriptor fd into buf. fd must be a descriptor returned by lo_open. Returns the number of bytes actually read — fewer than len if the end of the large object is reached first — or -1 on error.
Although len is declared as size_t, the function rejects values larger than INT_MAX. Transfer data in chunks of a few megabytes at most.
Seek in a large object
To move the read/write position within a large object, call:
int lo_lseek(PGconn *conn, int fd, int offset, int whence);offset specifies the new position relative to the anchor set by whence:
whence value | Anchor |
|---|---|
SEEK_SET | Beginning of the object |
SEEK_CUR | Current position |
SEEK_END | End of the object |
Returns the new position on success, or -1 on error. lo_lseek fails if the resulting position exceeds 2 GB.
For large objects that may exceed 2 GB, use:
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);lo_lseek64 accepts offsets larger than 2 GB and returns positions larger than 2 GB.
lo_lseek64was introduced in PostgreSQL 9.3. Running it against an older server returns-1.
Get the current position in a large object
int lo_tell(PGconn *conn, int fd);Returns the current read/write position, or -1 on error. Fails if the position exceeds 2 GB.
For large objects that may exceed 2 GB, use:
pg_int64 lo_tell64(PGconn *conn, int fd);lo_tell64 returns positions larger than 2 GB.
lo_tell64was introduced in PostgreSQL 9.3. Running it against an older server returns-1.
Truncate a large object
int lo_truncate(PGcon *conn, int fd, size_t len);Truncates the large object descriptor fd to len bytes. fd must be a descriptor returned by lo_open. If len is greater than the current length, the object is extended with null bytes ('\0'). The read/write position is not changed. Returns 0 on success, -1 on error.
lo_truncate rejects len values larger than INT_MAX.
For large objects that may exceed 2 GB, use:
int lo_truncate64(PGcon *conn, int fd, pg_int64 len);lo_truncate64 accepts len values exceeding 2 GB.
lo_truncatewas introduced in PostgreSQL 8.3;lo_truncate64was introduced in PostgreSQL 9.3. Running either function against an older server returns-1.
Close a large object descriptor
int lo_close(PGconn *conn, int fd);Closes the large object descriptor fd returned by lo_open. Returns 0 on success, -1 on error.
Any descriptors still open at the end of a transaction are closed automatically.
Remove a large object
int lo_unlink(PGconn *conn, Oid lobjId);Removes the large object identified by lobjId from the database. Returns 1 on success, -1 on failure.