home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre2.z / postgre2 / ref / large_objects < prev    next >
Encoding:
Text File  |  1992-08-27  |  20.1 KB  |  868 lines

  1. .\" XXX standard disclaimer belongs here....
  2. .\" $Header: /private/postgres/ref/RCS/large_objects,v 1.8 1992/07/14 05:54:17 ptong Exp $
  3. .ds UX "\\s-2UNIX\\s0
  4. .SS "LARGE OBJECTS" 6/14/90
  5. .XA 0 "Section 7 \*- Large Objects"
  6. .sp 2i
  7. .ps 14
  8. .ce
  9. .b "SECTION 7 \*- LARGE OBJECTS"
  10. .sp 3
  11. .uh NAME
  12. .lp
  13. .lp
  14. Large Object Interface \*- interface to \*(PP large objects
  15. .uh DESCRIPTION
  16. .lp
  17. In \*(PP,
  18. data values are stored in tuples,
  19. and individual tuples cannot span multiple data pages.
  20. Since the size of a data page is 8192 bytes,
  21. the upper limit on the size of a data value is relatively low.
  22. To support the storage of larger atomic values,
  23. \*(PP provides a
  24. .i "large object"
  25. interface.
  26. This interface provides file-oriented access to user data
  27. that has been explicitly declared to be a large type.
  28. .lp
  29. Version 4 of \*(PP supports two different implementations of large
  30. objects.
  31. These two implementations allow users to trade off speed of access
  32. against transaction protection and crash recovery on large object data.
  33. Applications that can tolerate lost data may store object data in
  34. conventional files that are fast to access,
  35. but cannot be recovered in the case of system crashes.
  36. For applications that require stricter guarantees of durability,
  37. a transaction-protected large object implementation is available.
  38. This section describes the two implementations
  39. and the programmatic and query language interfaces to large object
  40. data.
  41. .lp
  42. Unlike the BLOB support provided by most commercial relational
  43. database management systems,
  44. \*(PP allows users to define specific large object types.
  45. \*(PP large objects are first-class objects in the database,
  46. and any operation that can be applied to a conventional (small)
  47. abstract data type (ADT) may also be applied to a large one.
  48. For example,
  49. two different large object types,
  50. such as
  51. .i image
  52. and
  53. .i voice ,
  54. may be created.
  55. Functions that operate on image data,
  56. and other functions that operate on voice data,
  57. may be declared to the database system.
  58. The data manager will distinguish between image and voice data
  59. automatically,
  60. and will allow users to invoke the appropriate functions on values
  61. of each of these types.
  62. In addition,
  63. indices may be created large data values,
  64. or on functions of them.
  65. Finally,
  66. operators may be defined that operate on large values.
  67. Users may invoke these functions and operators from the query language.
  68. The database system will enforce type restrictions on large
  69. object data values.
  70. .lp
  71. The \*(PP large object interface is modeled after the Unix file system
  72. interface, with analogs of open(), read(), write(), lseek(), etc.
  73. User functions call these routines to retrieve only the data of
  74. interest from a large object.
  75. For example,
  76. if a large object type called
  77. .CW mugshot
  78. existed that stored photographs of faces,
  79. then a function called
  80. .CW beard
  81. could be declared on
  82. .CW mugshot
  83. data.
  84. .CW Beard
  85. could look at the lower third of a photograph,
  86. and determine the color of the beard that appeared there,
  87. if any.
  88. The entire large object value need not be buffered,
  89. or even examined,
  90. by the
  91. .CW beard
  92. function.
  93. As mentioned above,
  94. \*(PP supports functional indices on large object data.
  95. In this example,
  96. the results of the
  97. .CW beard
  98. function could be stored in a B-tree index to provide
  99. fast searches for people with red beards.
  100. .uh "\*(UX FILES AS LARGE OBJECT ADTS"
  101. .lp
  102. The simplest large object interface supplied with \*(PP is also
  103. the least robust.
  104. It does not support transaction protection,
  105. crash recovery,
  106. or time travel.
  107. On the other hand,
  108. it can be used on existing data files
  109. (such as word-processor files)
  110. that must be accessed simultaneously by the database system
  111. and existing application programs.
  112. .pp
  113. This implementation stores large object data in a \*(UX file,
  114. and stores only the file name in the database.
  115. Importing a large object into the database is as simple as storing the
  116. file name in a distinguished
  117. .q "large object name"
  118. relation.
  119. Interface routines allow the database system to open,
  120. seek,
  121. read,
  122. write,
  123. and close these \*(UX files by an internal large object identifier.
  124. .lp
  125. The functions
  126. .CW lo_filein
  127. and
  128. .CW lo_fileout
  129. convert between \*(UX filenames and internal large
  130. object identifiers.
  131. These functions are \*(PP registered functions,
  132. meaning they can be used directly in Postquel queries as well as from
  133. dynamically loaded C functions.
  134. If you are defining a simple large object ADT,
  135. these functions can be used as your
  136. .q input
  137. and
  138. .q output
  139. functions (see 
  140. .b "define type"
  141. and the \*(PP Manual sections concerning user-defined types for details).
  142. .(b
  143. .ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i
  144. char *lo_filein(filename)
  145.     char *filename;
  146. .sp 0.5v
  147. .i
  148.         Import a new \*(UX file storing large object
  149.         data into the database system.  This routine stores
  150.         the filename in a large object naming relation and
  151.         assigns it a unique large object identifier.
  152. .r
  153. .sp
  154. char * lo_fileout (object)
  155.     LargeObject *object;
  156. .sp 0.5v
  157. .i
  158.         This routine returns the \*(UX filename associated
  159.         with a large object.
  160. .r
  161. .)b
  162. .lp
  163. The file storing the large object must be accessible on the machine
  164. on which \*(PP is running.
  165. The data is not copied into the database system,
  166. so if the file is later removed,
  167. it is unrecoverable.
  168. .lp
  169. Large objects are accessible from both the \*(PP backend,
  170. using dynamically-loaded functions,
  171. and from the front-end,
  172. using the LIBPQ interface.
  173. These interfaces will be described in detail below.
  174. .uh "INVERSION LARGE OBJECTS"
  175. .lp
  176. In contrast to \*(UX files as large objects,
  177. the Inversion large object implementation guarantees transaction protection,
  178. crash recovery,
  179. and time travel on user large object data.
  180. This implementation breaks large objects up into
  181. .q chunks
  182. and stores the chunks in tuples in the database.
  183. A B-tree index guarantees fast searches for the correct chunk number
  184. when doing random access reads and writes.
  185. .lp
  186. If a transaction that has made changes to an Inversion large object
  187. subsequently aborts,
  188. the changes are backed out in the normal way.
  189. Inversion large objects are stored in the database,
  190. and so are not directly accessible to other programs.
  191. Only programs that use the \*(PP data manager can read and
  192. write Inversion large objects.
  193. .lp
  194. To use Inversion large objects,
  195. a new large object should be created using the LOcreat()
  196. interface,
  197. defined below.
  198. Afterwards,
  199. the name of the large object can be stored in an ordinary
  200. tuple.
  201. .lp
  202. The next section describes the programmatic interface to both
  203. \*(UX and Inversion large objects.
  204. .uh "BACKEND INTERFACE TO LARGE OBJECTS"
  205. .lp
  206. Large object data is accessible from front-end programs
  207. linked with the LIBPQ library,
  208. and from dynamically-loaded routines that execute in the \*(PP
  209. backend.
  210. This section describes access from dynamically loaded C functions.
  211. .uh "Creating New Large Objects"
  212. .lp
  213. The routine
  214. .(b
  215. .ft C
  216. int LOcreat(path, mode, objtype)
  217.     char *path;
  218.     int mode;
  219.     int objtype;
  220. .ft
  221. .)b
  222. creates a new large object.
  223. .lp
  224. The pathname is a slash-separated list of components,
  225. and must be a unique pathname in the \*(PP large object namespace.
  226. There is a virtual root directory (``/'') in which objects
  227. may be placed.
  228. .lp
  229. The
  230. .CW objtype
  231. parameter can be one of
  232. .CW Inversion
  233. or
  234. .CW Unix ,
  235. which are symbolic constants defined in
  236. .(b
  237. .ft C
  238. ~postgres/src/lib/H/catalog/pg_lobj.h
  239. .ft
  240. .)b
  241. The interpretation of the
  242. .CW mode
  243. argument depends on the
  244. .CW objtype
  245. selected.
  246. .lp
  247. For \*(UX files,
  248. .CW mode
  249. is the mode used to protect the file on the \*(UX file system.
  250. On creation,
  251. the file is open for reading and writing.
  252. .lp
  253. For Inversion large objects,
  254. .CW mode
  255. is a bitmask describing several different attributes
  256. of the new object.
  257. The symbolic constants listed here are defined in
  258. .(b
  259. .ft C
  260. ~postgres/src/lib/H/tmp/libpq-fs.h
  261. .ft
  262. .)b
  263. The access type (read, write, or both) is controlled by
  264. OR'ing together the bits INV_READ and INV_WRITE.
  265. If the large object should be archived \*-
  266. that is,
  267. if historical versions of it should be moved periodically
  268. to a special archive relation \*-
  269. then the INV_ARCHIVE bit should be set.
  270. The low-order sixteen bits of
  271. .CW mask
  272. are the storage manager number on which the large object
  273. should reside\**.
  274. .(f
  275. \**
  276. In the distributed version of \*(PP,
  277. only the magnetic disk storage manager is supported.
  278. For users running \*(PP at UC Berkeley,
  279. additional storage managers are available.
  280. .)f
  281. For sites other than Berkeley,
  282. these bits should always be zero.
  283. At Berkeley,
  284. storage manager zero is magnetic disk,
  285. storage manager one is a Sony optical disk jukebox,
  286. and storage manager two is main memory.
  287. .lp
  288. The commands below open large objects of the two types
  289. for writing and reading.
  290. The Inversion large object is not archived,
  291. and is located on magnetic disk:
  292. .(b
  293. .ft C
  294. unix_fd = LOcreat("/my_unix_obj", 0600, Unix);
  295. .ft
  296. .sp 0.5v
  297. .ft C
  298. inv_fd = LOcreat("/my_inv_obj",
  299.                  INV_READ|INV_WRITE, Inversion);
  300. .ft
  301. .)b
  302. .uh "Opening Large Objects"
  303. .lp
  304. Existing large objects may be opened for reading or writing by
  305. calling the routine
  306. .(b
  307. .ft C
  308. int LOopen(path, mode)
  309.     char *path;
  310.     int mode;
  311. .ft
  312. .)b
  313. The
  314. .CW path
  315. argument specifies the large object's pathname,
  316. and is the same as the pathname used to create the object.
  317. The
  318. .CW mode
  319. argument is interpreted by the two implementations differently.
  320. For \*(UX large objects,
  321. values should be chosen from the set of mode bits passed to the
  322. .CW open
  323. system call;
  324. that is,
  325. O_CREAT,
  326. O_RDONLY,
  327. O_WRONLY,
  328. O_RDWR,
  329. and O_TRUNC.
  330. For Inversion large objects,
  331. only the bits
  332. INV_READ and INV_WRITE have any meaning.
  333. .lp
  334. To open the two large objects created in the last example,
  335. a programmer would issue the commands
  336. .(b
  337. .ft C
  338. unix_fd = LOopen("/my_unix_obj", O_RDWR);
  339. .ft
  340. .sp 0.5v
  341. .ft C
  342. inv_fd = LOopen("/my_inv_obj", INV_READ|INV_WRITE);
  343. .ft
  344. .)b
  345. .lp
  346. If a large object is opened before it has been created,
  347. then a new large object is created using the \*(UX
  348. implementation,
  349. and the new object is opened.
  350. .uh "Seeking on Large Objects"
  351. .lp
  352. The command
  353. .(b
  354. .ft C
  355. int
  356. LOlseek(fd, offset, whence)
  357.     int fd;
  358.     int offset;
  359.     int whence;
  360. .ft
  361. .)b
  362. moves the current location pointer for a large object to the
  363. specified position.
  364. The
  365. .CW fd
  366. parameter is the file descriptor returned by either
  367. .CW LOcreat
  368. or
  369. .CW LOopen .
  370. .CW Offset
  371. is the byte offset in the large object to which to seek.
  372. The only legal value for
  373. .CW whence
  374. in the current release of the system is
  375. .CW L_SET ,
  376. as defined in <sys/files.h>.
  377. .lp
  378. \*(UX large objects allow holes to exist in objects;
  379. that is,
  380. a program may seek well past the end of the object and write
  381. bytes.
  382. Intervening blocks will not be created;
  383. reading them will return zero-filled blocks.
  384. Inversion large objects do not support holes.
  385. .lp
  386. The following code
  387. seeks to byte location 100000 of the example large objects:
  388. .(b
  389. .ft C
  390. unix_status = LOlseek(unix_fd, 100000, L_SET);
  391. .ft
  392. .sp 0.5v
  393. .ft C
  394. inv_status = LOlseek(inv_fd, 100000, L_SET);
  395. .ft
  396. .)b
  397. On error,
  398. .CW LOlseek
  399. returns a value less than zero.
  400. On success,
  401. the new offset is returned.
  402. .uh "Writing to Large Objects"
  403. .lp
  404. Once a large object has been created,
  405. it may be filled by calling
  406. .(b
  407. .ft C
  408. int
  409. LOwrite(fd, wbuf)
  410.     int fd;
  411.     struct varlena *wbuf;
  412. .)b
  413. Here,
  414. .CW fd
  415. is the file descriptor returned by
  416. .CW LOcreat
  417. or
  418. .CW LOopen ,
  419. and
  420. .CW wbuf
  421. describes the data to write.
  422. The
  423. .CW varlena
  424. structure in \*(PP consists of four bytes in which the length
  425. of the datum is stored,
  426. followed by the data itself.
  427. The four length bytes include themselves.
  428. .lp
  429. For example,
  430. to write 1024 bytes of zeroes to the sample large objects:
  431. .(b
  432. .ft C
  433. struct varlena *vl;
  434.  
  435. vl = (struct varlena *) palloc(1028);
  436. VARSIZE(vl) = 1028;
  437. bzero(VARDATA(vl), 1024);
  438.  
  439. nwrite_unix = LOwrite(unix_fd, vl);
  440. .sp 0.5v
  441. nwrite_inv = LOwrite(inv_fd, vl);
  442. .ft
  443. .)b
  444. .CW LOwrite
  445. returns the number of bytes actually written,
  446. or a negative number on error.
  447. For Inversion large objects,
  448. the entire write is guaranteed to succeed or fail.
  449. That is,
  450. if the number of bytes written is non-negative,
  451. then it equals VARSIZE(vl).
  452. .lp
  453. The VARSIZE()
  454. and VARDATA()
  455. macros are declared in the file
  456. .(b
  457. .ft C
  458. ~postgres/src/lib/H/tmp/postgres.h
  459. .ft
  460. .)b
  461. .uh "Reading from Large Objects"
  462. .lp
  463. Data may be read from large objects by calling the routine
  464. .(b
  465. .ft C
  466. struct varlena *
  467. LOread(fd, len)
  468.     int fd;
  469.     int len;
  470. .)b
  471. This routine returns the byte count actually read
  472. and the data in a varlena structure.
  473. For example,
  474. .(b
  475. .ft C
  476. struct varlena *unix_vl, *inv_vl;
  477. int nread_ux, nread_inv;
  478. char *data_ux, *data_inv;
  479.  
  480. unix_vl = LOread(unix_fd, 100);
  481. nread_ux = VARSIZE(unix_vl);
  482. data_ux = VARDATA(unix_vl);
  483. .sp 0.5v
  484. inv_vl = LOread(inv_fd, 100);
  485. nread_inv = VARSIZE(inv_vl);
  486. data_inv = VARDATA(inv_vl);
  487. .ft
  488. .)b
  489. The returned varlena structures have been allocated by the
  490. \*(PP memory manager
  491. .CW palloc ,
  492. and may be
  493. .CW pfree d
  494. when they are no longer needed.
  495. .uh "Closing a Large Object"
  496. Once a large object is no longer needed,
  497. it may be closed by calling
  498. .(b
  499. .ft C
  500. int
  501. LOclose(fd)
  502.     int fd;
  503. .ft
  504. .)b
  505. where
  506. .CW fd
  507. is the file descriptor returned by
  508. .CW LOopen
  509. or
  510. .CW LOcreat .
  511. On success,
  512. .CW LOclose
  513. returns zero.
  514. A negative return value indicates an error.
  515. .lp
  516. For example,
  517. .(b
  518. .ft C
  519. if (LOclose(unix_fd) < 0)
  520.     /* error */;
  521. .sp 0.5v
  522. if (LOclose(inv_fd) < 0)
  523.     /* error */
  524. .ft
  525. .)b
  526. .uh "LIBPQ LARGE OBJECT INTERFACE"
  527. .lp
  528. Large objects may also be accessed from database client
  529. programs that link the LIBPQ library.
  530. This library provides a set of routines that support opening,
  531. reading, writing, closing,
  532. and seeking on large objects.
  533. The interface is similar to that provided via the backend,
  534. but rather than using varlena structures,
  535. a more conventional \*(UX-style buffer scheme is used.
  536. .lp
  537. In version 4 of \*(PP,
  538. large object operations must be enclosed in a transaction
  539. block.
  540. This is true even for \*(UX large objects,
  541. which are not transaction-protected.
  542. This is due to a shortcoming in the memory management scheme
  543. for large objects,
  544. and will be rectified in version 4.1.
  545. The end of this section shows a short example program
  546. that correctly transaction-protects its file system operations.
  547. .lp
  548. This section describes the LIBPQ interface in detail.
  549. .uh "Creating a Large Object"
  550. .lp
  551. The routine
  552. .(b
  553. .ft C
  554. int
  555. p_creat(path, mode, objtype)
  556.     char *path;
  557.     int mode;
  558.     int objtype;
  559. .ft
  560. .)b
  561. creates a new large object.
  562. The
  563. .CW path
  564. argument specifies a large-object system pathname.
  565. .lp
  566. The
  567. .CW objtype
  568. parameter can be one of
  569. .CW Inversion
  570. or
  571. .CW Unix ,
  572. which are symbolic constants defined in
  573. .(b
  574. .ft C
  575. ~postgres/src/lib/H/catalog/pg_lobj.h
  576. .ft
  577. .)b
  578. The interpretation of the
  579. .CW mode
  580. argument depends on the
  581. .CW objtype
  582. selected.
  583. .lp
  584. For \*(UX files,
  585. .CW mode
  586. is the mode used to protect the file on the \*(UX file system.
  587. On creation,
  588. the file is open for reading and writing.
  589. .lp
  590. For Inversion large objects,
  591. .CW mode
  592. is a bitmask describing several different attributes
  593. of the new object.
  594. The symbolic constants listed here are defined in
  595. .(b
  596. .ft C
  597. ~postgres/src/lib/H/tmp/libpq-fs.h
  598. .ft
  599. .)b
  600. The access type (read, write, or both) is controlled by
  601. OR'ing together the bits INV_READ and INV_WRITE.
  602. If the large object should be archived \*-
  603. that is,
  604. if historical versions of it should be moved periodically
  605. to a special archive relation \*-
  606. then the INV_ARCHIVE bit should be set.
  607. The low-order sixteen bits of
  608. .CW mask
  609. are the storage manager number on which the large object
  610. should reside.
  611. For sites other than Berkeley,
  612. these bits should always be zero.
  613. At Berkeley,
  614. storage manager zero is magnetic disk,
  615. storage manager one is a Sony optical disk jukebox,
  616. and storage manager two is main memory.
  617. .lp
  618. The commands below open large objects of the two types
  619. for writing and reading.
  620. The Inversion large object is not archived,
  621. and is located on magnetic disk:
  622. .(b
  623. .ft C
  624. unix_fd = p_creat("/my_unix_obj", 0600, Unix);
  625. .sp 0.5v
  626. inv_fd = p_creat("/my_inv_obj",
  627.                  INV_READ|INV_WRITE, Inversion);
  628. .ft
  629. .)b
  630. .uh "Opening an Existing Large Object"
  631. .lp
  632. To open an existing large object,
  633. call
  634. .(b
  635. .ft C
  636. int
  637. p_open(path, mode)
  638.     char *path;
  639.     int mode;
  640. .ft
  641. .)b
  642. .lp
  643. The
  644. .CW path
  645. argument specifies the large object pathname for the object to open.
  646. The mode bits control whether the object is opened for reading,
  647. writing,
  648. or both.
  649. For \*(UX large objects,
  650. the appropriate flags are
  651. O_CREAT,
  652. O_RDONLY,
  653. O_WRONLY,
  654. O_RDWR,
  655. and O_TRUNC.
  656. For Inversion large objects,
  657. only INV_READ and INV_WRITE are recognized.
  658. .lp
  659. If a large object is opened before it is created,
  660. it is created by default using the \*(UX file implementation.
  661. .uh "Writing Data to a Large Object"
  662. .lp
  663. The routine
  664. .(b
  665. .ft C
  666. int
  667. p_write(fd, buf, len)
  668.     int fd;
  669.     char *buf;
  670.     int len;
  671. .ft
  672. .)b
  673. writes
  674. .CW len
  675. bytes from
  676. .CW buf
  677. to large object
  678. .CW fd .
  679. The
  680. .CW fd
  681. argument must have been returned by a previous
  682. .CW p_creat
  683. or
  684. .CW p_open .
  685. .lp
  686. The number of bytes actually written is returned.
  687. In the event of an error,
  688. the return value is negative.
  689. .uh "Reading Data from a Large Object"
  690. .lp
  691. The routine
  692. .(b
  693. .ft C
  694. int
  695. p_read(fd, buf, nbytes)
  696.     int fd;
  697.     char *buf;
  698.     int nbytes;
  699. .ft
  700. .)b
  701. reads
  702. .CW nbytes
  703. bytes into buffer
  704. .CW buf
  705. from the large object descriptor
  706. .CW fd .
  707. The number of bytes actually read is returned.
  708. In the event of an error,
  709. the return value is less than zero.
  710. .uh "Seeking on a Large Object"
  711. .lp
  712. To change the current read or write location on a large object,
  713. call
  714. .(b
  715. .ft C
  716. int
  717. p_lseek(fd, offset, whence)
  718.     int fd;
  719.     int offset;
  720.     int whence;
  721. .ft
  722. .)b
  723. This routine moves the current location pointer for the large object
  724. described by
  725. .CW fd
  726. to the new location specified by
  727. .CW offset .
  728. For this release of \*(PG,
  729. only
  730. .CW L_SET
  731. is a legal value for
  732. .CW whence .
  733. .uh "Closing a Large Object"
  734. .lp
  735. A large object may be closed by calling
  736. .(b
  737. .ft C
  738. int
  739. p_close(fd)
  740.     int fd;
  741. .ft
  742. .)b
  743. where
  744. .CW fd
  745. is a large object descriptor returned by
  746. .CW p_creat
  747. or
  748. .CW p_open .
  749. On success,
  750. .CW p_close
  751. returns zero.
  752. On error,
  753. the return value is negative.
  754. .uh "SAMPLE LARGE OBJECT PROGRAMS"
  755. .lp
  756. The \*(PP large object implementation serves as the basis
  757. for a file system (the
  758. .q Inversion
  759. file system)
  760. built on top of the data manager.
  761. This file system provides time travel,
  762. transaction protection,
  763. and fast crash recovery to clients of ordinary
  764. file system services.
  765. It uses the Inversion large object implementation to
  766. provide these services.
  767. .lp
  768. The programs that comprise the Inversion file system are
  769. included in the \*(PP source distribution,
  770. in directories
  771. .(b
  772. .ft C
  773. $POSTGRESHOME/test/postfs
  774. $POSTGRESHOME/test/postfs.usr.bin
  775. .ft
  776. .)b
  777. These directories contain a set of programs for manipulating
  778. files and directories.
  779. These programs are based on the Berkeley Software Distribution
  780. NET-2 release.
  781. .lp
  782. These programs are useful in manipulating inversion files,
  783. but they also serve as examples of how to code large object
  784. accesses in LIBPQ.
  785. All of the programs are LIBPQ clients,
  786. and all use the interfaces that have been described
  787. in this section.
  788. .lp
  789. Interested readers should refer to the files in the postfs
  790. directories for in-depth examples of the use of large objects.
  791. Below,
  792. a more terse example is provided.
  793. This code fragment creates a new large object managed
  794. by Inversion,
  795. fills it with data from a \*(UX file,
  796. and closes it.
  797. .(b
  798. .ft C
  799. #include "tmp/c.h"
  800. #include "tmp/libpq-fe.h"
  801. #include "tmp/libpq-fs.h"
  802. #include "catalog/pg_lobj.h"
  803.  
  804. #define    MYBUFSIZ    1024
  805.  
  806. main()
  807. {
  808.     int inv_fd;
  809.     int fd;
  810.     char *qry_result;
  811.     char buf[MYBUFSIZ];
  812.     int nbytes;
  813.     int tmp;
  814.  
  815.     PQsetdb("mydatabase");
  816.  
  817.     /* large object accesses must be */
  818.         /* transaction-protected         */
  819.     qry_result = PQexec("begin");
  820.  
  821.     if (*qry_result == 'E')    /* error */
  822.         exit (1);
  823.  
  824.     /* open the unix file */
  825.     fd = open("/my_unix_file", O_RDONLY, 0666);
  826.     if (fd < 0)    /* error */
  827.         exit (1);
  828.  
  829.     /* open the inversion file */
  830.     inv_fd = p_open("/inv_file", INV_WRITE, Inversion);
  831.     if (inv_fd < 0)    /* error */
  832.         exit (1);
  833.  
  834.     /* copy the unix file to the inversion */
  835.         /* large object                        */
  836.     while ((nbytes = read(fd, buf, MYBUFSIZ)) > 0)
  837.     {
  838.         tmp = p_write(inv_fd, buf, nbytes);
  839.         if (tmp < nbytes)    /* error */
  840.             exit (1);
  841.     }
  842.  
  843.     (void) close(fd);
  844.     (void) close(inv_fd);
  845.  
  846.     /* commit the transaction */
  847.     qry_result = PQexec("end");
  848.  
  849.     if (*qry_result == 'E')    /* error */
  850.         exit (1);
  851.  
  852.     /* by here, success */
  853.     exit (0);
  854. }
  855. .ft
  856. .)b
  857. .uh "BUGS"
  858. .lp
  859. Shouldn't have to distinguish between Inversion and \*(UX large
  860. objects when you open an existing large object.
  861. The system knows which implementation was used.
  862. The flags argument should be the same in these two cases.
  863. .uh "SEE ALSO"
  864. .lp
  865. define type(commands),
  866. define function(commands),
  867. load (commands).
  868.