]> granicus.if.org Git - postgresql/blob - doc/src/sgml/lobj.sgml
grammar cleanup
[postgresql] / doc / src / sgml / lobj.sgml
1 <Chapter Id="largeObjects">
2 <Title>Large Objects</Title>
3
4 <Para>
5      In <ProductName>Postgres</ProductName>, data values are stored in tuples and 
6      individual tuples cannot span data pages. Since the size of
7      a data page is 8192 bytes, the upper limit on the  size
8      of a data value is relatively low. To support the storage 
9      of larger atomic values, <ProductName>Postgres</ProductName> provides a  large
10      object   interface.    This  interface  provides  file
11      oriented access to user data that has been declared  to
12      be a large type.
13      This  section describes the implementation and the 
14      programmatic and query  language  interfaces  to  <ProductName>Postgres</ProductName>
15      large object data.
16 </Para>
17
18 <Sect1>
19 <Title>Historical Note</Title>
20
21 <Para>
22      Originally, <ProductName>Postgres 4.2</ProductName> supported three standard 
23      implementations of large objects: as files external 
24      to <ProductName>Postgres</ProductName>,  as  <Acronym>UNIX</Acronym>  files managed by <ProductName>Postgres</ProductName>, and as data
25      stored within the <ProductName>Postgres</ProductName> database. It causes  
26      considerable confusion among users. As a result, we only 
27      support large objects as data stored within  the  <ProductName>Postgres</ProductName>
28      database  in  <ProductName>PostgreSQL</ProductName>.  Even  though it is slower to
29      access, it provides stricter data  integrity.
30      For historical reasons, this storage scheme is referred to as 
31      Inversion large objects. (We will use  Inversion  and  large
32      objects  interchangeably to mean the same thing in this
33      section.)
34 </Para>
35 </Sect1>
36
37 <Sect1>
38 <Title>Inversion Large Objects</Title>
39
40 <Para>
41      The Inversion large object implementation breaks  large
42      objects  up  into  "chunks"  and  stores  the chunks in
43      tuples in the database.  A B-tree index guarantees fast
44      searches for the correct chunk number when doing random
45      access reads and writes.
46 </Para>
47 </Sect1>
48
49 <Sect1>
50 <Title>Large Object Interfaces</Title>
51
52 <Para>
53      The  facilities  <ProductName>Postgres</ProductName>  provides  to  access   large
54      objects,  both  in  the backend as part of user-defined
55      functions or the front end as part  of  an  application
56      using  the   interface, are described below. (For users
57      familiar with <ProductName>Postgres 4.2</ProductName>, <ProductName>PostgreSQL</ProductName> has a new set of
58      functions  providing  a  more  coherent  interface. The
59      interface is the same for  dynamically-loaded  C  
60      functions as well as for XXX LOST TEXT? WHAT SHOULD GO HERE??.
61
62      The  <ProductName>Postgres</ProductName>  large  object interface is modeled after
63      the <Acronym>UNIX</Acronym>  file  system  interface,  with  analogues  of
64      <Function>open(2)</Function>,  <Function>read(2)</Function>, <Function>write(2)</Function>,
65  <Function>lseek(2)</Function>, etc.  User 
66      functions call these routines to retrieve only the data  of
67      interest  from a large object.  For example, if a large
68      object type called mugshot  existed  that  stored  
69      photographs  of  faces, then a function called beard could
70      be declared on mugshot data.  Beard could look  at  the
71      lower third of a photograph, and determine the color of
72      the beard that appeared  there,  if  any.   The  entire
73      large  object value need not be buffered, or even 
74      examined, by the beard function.
75      Large objects may be accessed from dynamically-loaded <Acronym>C</Acronym>
76      functions  or  database  client  programs that link the
77      library.  <ProductName>Postgres</ProductName> provides a set of routines that 
78      support opening, reading, writing, closing, and seeking on
79      large objects.
80 </Para>
81
82 <Sect2>
83 <Title>Creating a Large Object</Title>
84
85 <Para>
86      The routine
87 <ProgramListing>
88 Oid lo_creat(PGconn *conn, int mode)
89 </ProgramListing>
90      creates a new large  object.  The  mode  is  a  bitmask
91      describing  several  different  attributes  of  the new
92      object.  The symbolic constants listed here are defined
93      in
94 <FileName>
95 PGROOT/src/backend/libpq/libpq-fs.h
96 </FileName>
97      The access type (read, write, or both) is controlled by
98      OR ing together the bits <Acronym>INV_READ</Acronym>  and  <Acronym>INV_WRITE</Acronym>.   If
99      the large object should be archived -- that is, if 
100      historical versions of it should be moved periodically  to
101      a  special archive relation -- then the <Acronym>INV_ARCHIVE</Acronym> bit
102      should be set.  The low-order sixteen bits of mask  are
103      the  storage  manager  number on which the large object
104      should reside.  For sites other  than  Berkeley,  these
105      bits should always be zero.
106      The commands below create an (Inversion) large object:
107 <ProgramListing>
108 inv_oid = lo_creat(INV_READ|INV_WRITE|INV_ARCHIVE);
109 </ProgramListing>
110 </Para>
111 </Sect2>
112
113 <Sect2>
114 <Title>Importing a Large Object</Title>
115
116 <Para>
117 To import a <Acronym>UNIX</Acronym> file as
118      a large object, call
119 <ProgramListing>
120 Oid lo_import(PGconn *conn, text *filename)
121 </ProgramListing>
122      The filename argument specifies the  <Acronym>UNIX</Acronym>  pathname  of
123      the file to be imported as a large object.
124 </Para>
125 </Sect2>
126
127 <Sect2>
128 <Title>Exporting a Large Object</Title>
129
130 <Para>
131 To export a large object
132      into <Acronym>UNIX</Acronym> file, call
133 <ProgramListing>
134 int lo_export(PGconn *conn, Oid lobjId, text *filename)
135 </ProgramListing>
136      The lobjId argument specifies  the  Oid  of  the  large
137      object  to  export  and the filename argument specifies
138      the <Acronym>UNIX</Acronym> pathname of the file.
139 </Para>
140 </Sect2>
141
142 <Sect2>
143 <Title>Opening an Existing Large Object</Title>
144
145 <Para>
146      To open an existing large object, call
147 <ProgramListing>
148 int lo_open(PGconn *conn, Oid lobjId, int mode, ...)
149 </ProgramListing>
150      The lobjId argument specifies  the  Oid  of  the  large
151      object  to  open.   The  mode  bits control whether the
152      object is opened  for  reading  INV_READ),  writing  or
153      both.
154      A  large  object cannot be opened before it is created.
155      lo_open returns a large object descriptor for later use
156      in  lo_read, lo_write, lo_lseek, lo_tell, and lo_close.
157 </Para>
158 </Sect2>
159
160 <Sect2>
161 <Title>Writing Data to a Large Object</Title>
162
163 <Para>
164      The routine
165 <ProgramListing>
166 int lo_write(PGconn *conn, int fd, char *buf, int len)
167 </ProgramListing>
168      writes len bytes from buf to large object fd.   The  fd
169      argument must have been returned by a previous lo_open.
170      The number of bytes actually written is  returned.   In
171      the event of an error, the return value is negative.
172 </Para>
173 </Sect2>
174
175 <Sect2>
176 <Title>Seeking on a Large Object</Title>
177
178 <Para>
179      To change the current read or write location on a large
180      object, call
181 <ProgramListing>
182 int lo_lseek(PGconn *conn, int fd, int offset, int whence)
183 </ProgramListing>
184      This routine moves the current location pointer for the
185      large object described by fd to the new location specified 
186      by offset.  The valid values  for  .i  whence  are
187      SEEK_SET SEEK_CUR and SEEK_END.
188 </Para>
189 </Sect2>
190
191 <Sect2>
192 <Title>Closing a Large Object Descriptor</Title>
193
194 <Para>
195      A large object may be closed by calling
196 <ProgramListing>
197 int lo_close(PGconn *conn, int fd)
198 </ProgramListing>
199      where  fd  is  a  large  object  descriptor returned by
200      lo_open.  On success, <Acronym>lo_close</Acronym> returns zero.  On error,
201      the return value is negative.
202 </Para>
203 </sect2>
204 </Sect1>
205
206 <Sect1>
207 <Title>Built in registered functions</Title>
208
209 <Para>
210      There  are two built-in registered functions, <Acronym>lo_import</Acronym>
211      and <Acronym>lo_export</Acronym> which  are  convenient  for  use  in  <Acronym>SQL</Acronym>
212      queries.
213      Here is an example of their use
214 <ProgramListing>
215 CREATE TABLE image (
216     name            text,
217     raster          oid
218 );
219
220 INSERT INTO image (name, raster)
221     VALUES ('beautiful image', lo_import('/etc/motd'));
222
223 SELECT lo_export(image.raster, "/tmp/motd") from image
224     WHERE name = 'beautiful image';
225 </ProgramListing>
226 </Para>
227 </Sect1>
228
229 <Sect1>
230 <Title>Accessing Large Objects from LIBPQ</Title>
231
232 <Para>
233      Below is a sample program which shows how the large object  
234      interface
235      in  LIBPQ  can  be used.  Parts of the program are 
236      commented out but are left in the source for  the  readers
237      benefit.  This program can be found in
238 <FileName>
239 ../src/test/examples
240 </FileName>
241      Frontend applications which use the large object interface  
242      in  LIBPQ  should   include   the   header   file
243      libpq/libpq-fs.h and link with the libpq library.
244 </Para>
245 </Sect1>
246
247 <Sect1>
248 <Title>Sample Program</Title>
249
250 <Para>
251 <ProgramListing>
252 /*--------------------------------------------------------------
253           *
254           * testlo.c--
255           *    test using large objects with libpq
256           *
257           * Copyright (c) 1994, Regents of the University of California
258           *
259           *
260           * IDENTIFICATION
261           *    /usr/local/devel/pglite/cvs/src/doc/manual.me,v 1.16 1995/09/01 23:55:00 jolly Exp
262           *
263           *--------------------------------------------------------------
264           */
265          #include &lt;stdio.h&gt;
266          #include "libpq-fe.h"
267          #include "libpq/libpq-fs.h"
268
269          #define BUFSIZE          1024
270
271          /*
272           * importFile *    import file "in_filename" into database as large object "lobjOid"
273           *
274           */
275          Oid importFile(PGconn *conn, char *filename)
276          {
277              Oid lobjId;
278              int lobj_fd;
279              char buf[BUFSIZE];
280              int nbytes, tmp;
281              int fd;
282
283              /*
284               * open the file to be read in
285               */
286              fd = open(filename, O_RDONLY, 0666);
287              if (fd &lt; 0)  {   /* error */
288               fprintf(stderr, "can't open unix file %s\n", filename);
289              }
290
291              /*
292               * create the large object
293               */
294              lobjId = lo_creat(conn, INV_READ|INV_WRITE);
295              if (lobjId == 0) {
296               fprintf(stderr, "can't create large object\n");
297              }
298
299              lobj_fd = lo_open(conn, lobjId, INV_WRITE);
300              /*
301               * read in from the Unix file and write to the inversion file
302               */
303              while ((nbytes = read(fd, buf, BUFSIZE)) &gt; 0) {
304               tmp = lo_write(conn, lobj_fd, buf, nbytes);
305               if (tmp &lt; nbytes) {
306                   fprintf(stderr, "error while reading large object\n");
307               }
308              }
309
310              (void) close(fd);
311              (void) lo_close(conn, lobj_fd);
312
313              return lobjId;
314          }
315
316          void pickout(PGconn *conn, Oid lobjId, int start, int len)
317          {
318              int lobj_fd;
319              char* buf;
320              int nbytes;
321              int nread;
322
323              lobj_fd = lo_open(conn, lobjId, INV_READ);
324              if (lobj_fd &lt; 0) {
325               fprintf(stderr,"can't open large object %d\n",
326                    lobjId);
327              }
328
329              lo_lseek(conn, lobj_fd, start, SEEK_SET);
330              buf = malloc(len+1);
331
332              nread = 0;
333              while (len - nread &gt; 0) {
334               nbytes = lo_read(conn, lobj_fd, buf, len - nread);
335               buf[nbytes] = ' ';
336               fprintf(stderr,"&gt;&gt;&gt; %s", buf);
337               nread += nbytes;
338              }
339              fprintf(stderr,"\n");
340              lo_close(conn, lobj_fd);
341          }
342
343          void overwrite(PGconn *conn, Oid lobjId, int start, int len)
344          {
345              int lobj_fd;
346              char* buf;
347              int nbytes;
348              int nwritten;
349              int i;
350
351              lobj_fd = lo_open(conn, lobjId, INV_READ);
352              if (lobj_fd &lt; 0) {
353               fprintf(stderr,"can't open large object %d\n",
354                    lobjId);
355              }
356
357              lo_lseek(conn, lobj_fd, start, SEEK_SET);
358              buf = malloc(len+1);
359
360              for (i=0;i&lt;len;i++)
361               buf[i] = 'X';
362              buf[i] = ' ';
363
364              nwritten = 0;
365              while (len - nwritten &gt; 0) {
366               nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
367               nwritten += nbytes;
368              }
369              fprintf(stderr,"\n");
370              lo_close(conn, lobj_fd);
371          }
372
373          /*
374           * exportFile *    export large object "lobjOid" to file "out_filename"
375           *
376           */
377          void exportFile(PGconn *conn, Oid lobjId, char *filename)
378          {
379              int lobj_fd;
380              char buf[BUFSIZE];
381              int nbytes, tmp;
382              int fd;
383
384              /*
385               * create an inversion "object"
386               */
387              lobj_fd = lo_open(conn, lobjId, INV_READ);
388              if (lobj_fd &lt; 0) {
389               fprintf(stderr,"can't open large object %d\n",
390                    lobjId);
391              }
392
393              /*
394               * open the file to be written to
395               */
396              fd = open(filename, O_CREAT|O_WRONLY, 0666);
397              if (fd &lt; 0)  {   /* error */
398               fprintf(stderr, "can't open unix file %s\n",
399                    filename);
400              }
401
402              /*
403               * read in from the Unix file and write to the inversion file
404               */
405              while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) &gt; 0) {
406               tmp = write(fd, buf, nbytes);
407                  if (tmp &lt; nbytes) {
408                   fprintf(stderr,"error while writing %s\n",
409                        filename);
410               }
411              }
412
413              (void) lo_close(conn, lobj_fd);
414              (void) close(fd);
415
416              return;
417          }
418
419          void
420          exit_nicely(PGconn* conn)
421          {
422            PQfinish(conn);
423            exit(1);
424          }
425
426          int
427          main(int argc, char **argv)
428          {
429              char *in_filename, *out_filename;
430              char *database;
431              Oid lobjOid;
432              PGconn *conn;
433              PGresult *res;
434
435              if (argc != 4) {
436               fprintf(stderr, "Usage: %s database_name in_filename out_filename\n",
437                    argv[0]);
438               exit(1);
439              }
440
441              database = argv[1];
442              in_filename = argv[2];
443              out_filename = argv[3];
444
445              /*
446               * set up the connection
447               */
448              conn = PQsetdb(NULL, NULL, NULL, NULL, database);
449
450              /* check to see that the backend connection was successfully made */
451              if (PQstatus(conn) == CONNECTION_BAD) {
452               fprintf(stderr,"Connection to database '%s' failed.\n", database);
453               fprintf(stderr,"%s",PQerrorMessage(conn));
454               exit_nicely(conn);
455              }
456
457              res = PQexec(conn, "begin");
458              PQclear(res);
459
460              printf("importing file %s\n", in_filename);
461          /*  lobjOid = importFile(conn, in_filename); */
462              lobjOid = lo_import(conn, in_filename);
463          /*
464              printf("as large object %d.\n", lobjOid);
465
466              printf("picking out bytes 1000-2000 of the large object\n");
467              pickout(conn, lobjOid, 1000, 1000);
468
469              printf("overwriting bytes 1000-2000 of the large object with X's\n");
470              overwrite(conn, lobjOid, 1000, 1000);
471          */
472
473              printf("exporting large object to file %s\n", out_filename);
474          /*    exportFile(conn, lobjOid, out_filename); */
475              lo_export(conn, lobjOid,out_filename);
476
477              res = PQexec(conn, "end");
478              PQclear(res);
479              PQfinish(conn);
480              exit(0);
481          }
482 </ProgramListing>
483 </Para>
484
485 </Sect1>
486 </Chapter>