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

  1. .\" XXX standard disclaimer belongs here....
  2. .\" $Header: /private/postgres/ref/RCS/libpq,v 1.17 1992/07/31 17:02:31 mer Exp $
  3. .SS LIBPQ 6/14/90
  4. .XA 0 "Section 5 \*- Libpq"
  5. .sp 2i
  6. .ps 14
  7. .ce
  8. .b "SECTION 5 \*- LIBPQ"
  9. .sp 3
  10. .uh NAME
  11. .lp
  12. libpq \*- programmer's interface to \*(PP
  13. .uh DESCRIPTION
  14. .lp
  15. LIBPQ is the programmer's interface to \*(PP.  LIBPQ is a set of
  16. library routines which allow queries to pass to the \*(PP back-end
  17. and instances to return through an IPC channel.
  18. .lp
  19. This version of the documentation is based on the C library.
  20. .uh "CONTROL AND INITIALIZATION"
  21. .lp
  22. .uh VARIABLES
  23. .lp
  24. The following five environment variables can be used to set
  25. up default values for an environment and to avoid hard-coding
  26. database names into an application program:
  27. .lp
  28. .(l
  29. .bu
  30. \fBPGHOST\fR sets the default server name.
  31. .bu
  32. \fBPGDATABASE\fR sets the default \*(PP database name.
  33. .bu
  34. \fBPGPORT\fR sets the default communication port with the \*(PP back-end.
  35. .bu
  36. \fBPGTTY\fR sets the tty on the PQhost back-end on which debugging messages are displayed.
  37. .)l
  38. .lp
  39. The following internal variables of libpq can be accessed by
  40. the programmer:
  41. .lp
  42. .(1
  43. .nf
  44. .ft C
  45. char *PQhost;           /* the server on which \*(PP
  46.                            back-end is running. */
  47.  
  48. char *PQport = NULL;    /* The communication port with the
  49.                            \*(PP back-end. */
  50.  
  51. char *PQtty;            /* The tty on the PQhost back-end on
  52.                            which back-end messages are
  53.                            displayed. */
  54.  
  55. char *PQoption;         /* Optional arguements to the back-end */
  56.  
  57. char *PQdatabase;       /* Back-end database to access */
  58.  
  59. int  PQportset = 0;     /* 1 if communication with
  60.                            back-end is established */
  61.  
  62. int  PQxactid = 0;      /* Transaction ID of the current
  63.                            transaction */
  64.  
  65. int  PQtracep = 0;      /* 1 to print out front-end
  66.                            debugging messages */
  67.  
  68. int  PQAsyncNotifyWaiting = 0; /* 1 if one or more asynchronous
  69.                                   notifications have been
  70.                                   triggered */
  71. .ft
  72. .)1
  73. .fi
  74. .uh "QUERY EXECUTION FUNCTIONS"
  75. .lp
  76. The following routines control the execution of queries
  77. from a C program.
  78.  
  79. .(1
  80. PQsetdb \*- Make the specified database the current database, 
  81.  
  82. .nf
  83. .ft C
  84. void PQsetdb ( dbname )
  85.     char    *dbname;
  86. .ft
  87.  
  88. PQsetdb also resets communication via PQreset (see below).
  89.  
  90. PQdb \*- Return the current database being accessed.
  91.  
  92. .ft C
  93. char * PQdb ()
  94. .ft
  95. .)1
  96. .fi
  97. .lp
  98. Returns the name of the \*(PP database
  99. being accessed, or NIL if no database is open.
  100. Only one database can be accessed at a time.  The database
  101. name is a string limited to 16 characters.
  102. .lp
  103. .nf
  104. .(1
  105. PQreset \*- Reset the communication port with the back-end in case of errors.
  106.  
  107. .ft C
  108. void PQreset()
  109. .ft
  110.  
  111. .fi
  112. This function will close the IPC socket connection to the backend thereby
  113. causing the next PQexec() call to ask for a new one from the postmaster.
  114. When the backend notices the socket was closed it will exit, and when the
  115. postmaster is asked for the new connection it will start a new back-end.
  116. .nf
  117.  
  118. PQfinish \*- Close communication ports with the back-end.
  119.  
  120. .ft C
  121. void PQfinish ()
  122. .ft
  123. .)1
  124. .fi
  125. .lp
  126. Terminates communications and frees up the memory taken up
  127. by the libpq buffer.
  128. .nf
  129.  
  130. .(1
  131. PQfn \*- Send a function call to the \*(PP backend.
  132.  
  133. .ft C
  134. char *PQfn(fnid, result_buf, result_len,
  135.            result_is_int, args, nargs)
  136.     int fnid;
  137.     int *result_buf;    /* can't use void, the */
  138.     int result_len;     /* compiler complains  */
  139.     int result_is_int;
  140.     PQArgBlock *args;
  141.     int nargs;
  142. .ft
  143.  
  144. .fi
  145. PQfn provides access to the \*(PP fastpath facility, a trapdoor into
  146. the system internals.  See \fBFASTPATH\fR.
  147. .nf
  148.  
  149. .(1
  150. PQexec \*- Submit a query to \*(PP.  
  151.  
  152. .ft C
  153. char *    PQexec (query)
  154.     char    * query;
  155. .ft
  156. .)1
  157. .fi
  158. .lp
  159. This function returns a status indicator or an error message.  If the query
  160. returns data (e.g. fetch), PQexec returns a string consisting of 'P' followed
  161. by the name of the portal buffer.  
  162. When the query does not return instances, PQexec
  163. will return a string consisting of 'C' followed by the command tag (e.g.
  164. "CREPLACE").  If an error occured during the execution of the query 
  165. PQexec will return (for historical reasons) an "R".
  166.  
  167. .uh "PORTAL FUNCTIONS"
  168. .lp
  169. A portal is a \*(PP buffer from which instances can be fetched.
  170. Each portal has a string name (currently limited to 16 bytes).
  171. A portal is initialized by submitting a retrieve statement
  172. using the PQexec function, for example:
  173. .(l
  174. .ft C
  175. retrieve portal foo ( EMP.all )
  176. .ft
  177. .)l
  178. .lp
  179. The programmer can then move data from the portal into LIBPQ
  180. by executing a \fIfetch\fR statement, e.g:
  181. .(l
  182. .ft C
  183. fetch 10 in \fIfoo\fR
  184. .ft
  185.  
  186. .ft C
  187. fetch all in \fIfoo\fR
  188. .ft
  189. .)l
  190. .lp
  191. If no portal name is specified in a query, the default
  192. portal name is the string "blank", known as the "blank portal."
  193. All qualifying instances in a blank portal are fetched
  194. immediately, without the need for the programmer to issue a
  195. seperate fetch command.
  196. .lp
  197. Data fetched from a portal into LIBPQ is moved into a portal
  198. buffer.  Portal names are mapped to portal buffers through
  199. an internal table.  Each instance in a portal buffer has
  200. an index number locating its position in the buffer.  In addition,
  201. each field in an instance has a name and a field number.
  202. .lp
  203. A single retrieve command can return multiple types
  204. of instances.
  205. This can happen if a \*(PP function is executed
  206. in the evaluation of a query or if the query
  207. returns multiple instance types from an inheritance
  208. hierarchy.
  209. Consequently, the instances in a portal are set up
  210. in groups.
  211. Instances in the same group are guaranteed to have the
  212. same instance format.
  213. .lp
  214. Portals that are associated with normal user commands
  215. are called synchronous.
  216. In this case, the application program is expected
  217. to issue a retrieval followed by one or more
  218. fetch commands.
  219. The functions that follow can now be used to
  220. manipulate data in the portal.
  221. .(l
  222. PQnportals \*- Return the number of open portals.
  223.  
  224. .ft C
  225. int PQnportals ( rule_p )
  226.     int    rule_p ;
  227. .ft
  228.  
  229. If rule_p is not 0, then only return the number of asynchronous portals.
  230.  
  231. PQpnames \*- Return all portal names.
  232.  
  233. .ft C
  234. void PQpnames  ( pnames, rule_p)
  235.     char    *pnames [MAXPORTALS];
  236.     int    rule_p ;
  237. .ft
  238.  
  239. If rule_p is not 0, then only return the names of asynchronous
  240. portals.
  241.  
  242. PQparray \*- Return the portal buffer given a portal name.
  243.  
  244. .ft C
  245. PortalBuffer * PQparray ( pname )
  246.     char    *pname;
  247. .ft
  248.  
  249. PQclear \*- free storage claimed by named portal.
  250.  
  251. .ft C
  252. void PQclear ( pname )
  253.     char    *pname;
  254. .ft
  255.  
  256. PQntuples \*- Return the number of instances in a portal buffer.
  257.  
  258. .ft C
  259. int PQntuples (portal)
  260.     PortalBuffer    *portal;
  261. .ft
  262.  
  263. PQngroups \*- Return the number of instance groups in a portal buffer.
  264.  
  265. .ft C
  266. int PQngroups (portal)
  267.     PortalBuffer *portal
  268. .ft
  269.  
  270. PQntuplesGroup \*- Return the number of instances in an instance group.
  271.  
  272. .ft C
  273. int PQntuplesGroup (portal, group_index)
  274.     PortalBuffer    *portal;
  275.     int    group_index;
  276. .ft
  277.  
  278. PQnfieldsGroup \*- Return the number of fields in an instance group.
  279.  
  280. .ft C
  281. int PQnfieldsGroup ( portal, group_index)
  282.     PortalBuffer    *portal;
  283.     int    group_index;
  284. .ft
  285.  
  286. PQfnameGroup \*- Return the field name given the group and field index.
  287.  
  288. .ft C
  289. char * PQfnameGroup (portal, group_index, field_number )
  290.     PortalBuffer    *portal;
  291.     int    group_index;
  292.     int    field_number;
  293. .ft
  294.  
  295. PQfnumberGroup \*- Return the field number (index) given the group index and field name.
  296.  
  297. .ft C
  298. int PQfnumberGroup (portal, group_index, field_name)
  299.     PortalBuffer    *portal;
  300.     int    group_index;
  301.     char    *field_name;
  302. .ft
  303.  
  304. PQgetgroup \*- Returns the index of the group that a particular instance is in.
  305.  
  306. .ft C
  307. int PQgetgroup ( portal, tuple_index )
  308.     PortalBuffer    *portal;
  309.     int    tuple_index;
  310. .ft
  311.  
  312. PQnfields \*- Return the number of fields in an instance.
  313.  
  314. .ft C
  315. int PQnfields (portal, tuple_index )
  316.     PortalBuffer    *portal;
  317.     int    tuple_index;
  318. .ft
  319.  
  320. PQfnumber \*- Return the field index of a given field name within an instance.
  321.  
  322. .ft C
  323. int PQfnumber ( portal, tuple_index, field_name)
  324.     PortalBuffer    *portal;
  325.     int    tuple_index;
  326.     char    *field_name;
  327. .ft
  328.  
  329. PQfname \*- Return the name of a field.
  330.  
  331. .ft C
  332. char * PQfname ( portal, tuple_index, field_number )
  333.     PortalBuffer    *portal;
  334.     int    tuple_index;
  335.     int    field_number;
  336. .ft
  337.  
  338. PQftype \*- Return the type of a field.  
  339.  
  340. .ft C
  341. int PQftype ( portal, tuple_index, field_number )
  342.     PortalBuffer    *portal;
  343.     int    tuple_index;
  344.     int    field_number;
  345. .ft
  346.  
  347. The type returned is an internal coding of a type.
  348.  
  349. PQsametype \*- Return 1 if two instances have the same attributes.
  350.  
  351. .ft C
  352. int PQsametype ( portal, tuple_index1, tuple_index2 )
  353.     PortalBuffer    *portal;
  354.     int    tuple_index1, tuple_index2;
  355. .ft
  356.  
  357. PQgetvalue \*- Return an attribute (field) value.  
  358.  
  359. .ft C
  360. char * PQgetvalue ( portal, tuple_index, field_number )
  361.     PortalBuffer    *portal;
  362.     int    tuple_index;
  363.     int    field_number;
  364. .ft
  365.  
  366. .ft
  367.  
  368. PQgetlength \*- Return the length of an attribute (field) value in bytes.
  369. If the field is a varlena, the length of the attribute returned here
  370. does not include the longword size field of the varlena, e.g. it is 4
  371. bytes less.
  372.  
  373. .ft C
  374. char * PQgetlength ( portal, tuple_index, field_number )
  375.     PortalBuffer    *portal;
  376.     int    tuple_index;
  377.     int    field_number;
  378. .ft
  379.  
  380. PQNotifies \*- Return the list of relations on which notification has occurred.
  381.  
  382. .ft C
  383. PQNotifyList *PQNotifies()
  384. .ft
  385.  
  386. PQRemoveNotify \*- Remove the notification from the list of unhandled 
  387.            notifications.
  388.  
  389. .ft C
  390. PQNotifyList *PQRemoveNotify(pqNotify)
  391.     PQNotifyList *pqNotify;
  392. .ft
  393. .)l
  394. .lp
  395. If the portal is blank, or specified with the
  396. .b portal 
  397. keyword, all
  398. values are returned as strings.  It is the programmer's responsibility
  399. to convert them to the correct type.  If the portal is specified with the
  400. .b iportal
  401. keyword, all values are returned in internal format, namely in the format 
  402. generated by the
  403. .i input
  404. function specified through the 
  405. .b definetype
  406. command.  Again, it is the programmer's responsibility to convert the
  407. data to the correct type.
  408.  
  409. .uh "ASYNCHRONOUS PORTALS/NOTIFICATION"
  410. .lp
  411. Asynchronous portals, query results of rules, are implemented using
  412. two mechanisms: relations and notification.  The query result is
  413. transferred through a relation.  The notification is done with special
  414. postquel commands and frontend/backend protocol.
  415.  
  416. Referring to the second sample program, after executing "listen
  417. relation_name" in the frontend process, periodically check
  418. PQAsyncNotifyWaiting.  If it is non-zero, then the "notify
  419. relation_name" command has been executed by some backend.  Immediately
  420. clear PQAsyncNotifyWaiting, then do a NULL query, i.e.  PQexec(" "),
  421. to retrieve the actual notification data.  Then call PQNotifies() to
  422. get the list of relations on which notification has occurred.  After
  423. handling the notification, do PQRemoveNotify on each element of the
  424. list that has been handled to prevent further handling by you.
  425.  
  426. .uh "FUNCTIONS ASSOCIATED WITH THE COPY COMMAND"
  427. .lp
  428. The
  429. .i copy
  430. command in \*(PP has options to read from or write to the network
  431. connection used by LIBPQ.  Therefore, functions are necessary to access
  432. this network connection directly so applications may take full advantage
  433. of this capability.
  434. .lp
  435. For more information about the 
  436. .i copy
  437. command, see copy(commands).
  438. .lp
  439.  
  440. .(1
  441. .ft C
  442. PQgetline(string, length)
  443. .ft
  444. \*- Reads a null-terminated line into string.
  445.  
  446. .ft C
  447. char *string;
  448. int length
  449. .ft
  450.  
  451. .ft C
  452. PQputline(string)
  453. .ft
  454. \*- Sends a null-terminated string.
  455.  
  456. .ft C
  457. char *string;
  458. .ft
  459.  
  460. .ft C
  461. int
  462. PQendcopy()
  463. .ft
  464. \*- Syncs with the back-end.
  465.  
  466. This function waits until the backend has finished processing the copy.
  467. It should either be issued when the last string has been sent to the
  468. backend using PQputline() or when the last string has been received from
  469. the backend using PGgetline().  It must be issued or the backend may get
  470. "out of sync" with the frontend.  Upon return from this function, the
  471. backend is ready to receive the next query.
  472.  
  473. The return value is 0 on successful completion, nonzero otherwise.
  474.  
  475. \fBFor Example:\fR
  476.  
  477. .nf
  478. .ft C
  479. PQexec("create foo (a=int4, b=char16, d=float8)");
  480. PQexec("copy foo from stdin");
  481. PQputline("3<TAB>hello world<TAB>4.5\n");
  482. PQputline("4<TAB>goodbye world<TAB>7.11");
  483. ...
  484. PQputline(".\en");
  485. PQendcopy();
  486. .ft
  487. .fi
  488. .)1
  489.  
  490. .uh "TRACING FUNCTIONS"
  491. .lp
  492. .(1
  493. PQtrace \*- Enable tracing.
  494.  
  495. .ft C
  496. void PQtrace ()
  497. .ft
  498.  
  499. The routine sets the PQtracep variable to 1 which causes debug messages to
  500. be printed.  You should note that the
  501. messages will be printed to stdout by default.  If you would like different
  502. behavior you must set the variable FILE *debug_port to the appropriate stream.
  503.  
  504. PQuntrace \*- Disable tracing.
  505.  
  506. .ft C
  507. void PQuntrace ()
  508. .ft
  509. .)1
  510. .uh BUGS
  511. .lp
  512. The query buffer is only 8192 bytes long, and queries over that
  513. length will be silently truncated.
  514.  
  515. .uh "SAMPLE PROGRAM"
  516. .lp
  517. .(1
  518. .nf
  519. .ft C
  520. /*
  521.  * testlibpq.c \*-
  522.  *     Test the C version of Libpq, the \*(PP frontend library.
  523.  */
  524. #include <stdio.h>
  525. #include "libpq.h"
  526.  
  527. main ()
  528. {
  529.     int i, j, k, g, n, m, t;
  530.     PortalBuffer *p;
  531.     char pnames[MAXPORTALS][portal_name_length];
  532.  
  533.     /* Specify the database to access. */
  534.     PQsetdb ("pic_demo");
  535.  
  536.     /* Start a transaction block for eportal */
  537.     PQexec ("begin");
  538.  
  539.     /* Fetch instances from the EMP class. */
  540.     PQexec ("retrieve portal eportal (EMP.all)");
  541.     PQexec ("fetch all in eportal");
  542.  
  543.     /* Examine all the instances fetched. */
  544.     p = PQparray ("eportal");
  545.     g = PQngroups (p);
  546.     t = 0;
  547.     
  548.     for (k = 0; k < g; k++) {
  549.     printf ("\enA new instance group:\en");
  550.     n = PQntuplesGroup (p, k);
  551.     m = PQnfieldsGroup (p, k);
  552.  
  553.     /* Print out the attribute names. */
  554.     for (i = 0; i < m; i++)
  555.         printf ("%-15s", PQfnameGroup (p, k, i));
  556.     printf ("\en");
  557.     
  558.     /* Print out the instances. */
  559.     for (i = 0; i < n; i++) {
  560.         for (j = 0; j < m; j++)
  561.         printf("%-15s", PQgetvalue(p, t+i, j));
  562.         printf ("\en");
  563.     }
  564.     t += n;
  565.     }
  566.  
  567.     /* Close the portal. */
  568.     PQexec ("close eportal");
  569.  
  570.     /* End the transaction block */
  571.     PQexec("end");
  572.  
  573.     /* Try out some other functions. */
  574.     
  575.     /* Print out the number of portals. */
  576.     printf ("\enNumber of portals open: %d.\en",
  577.             PQnportals ());
  578.  
  579.     /* If any tuples are returned by rules, print out
  580.      * the portal name. */
  581.     if (PQnportals (1)) {
  582.     printf ("Tuples are returned by rules. \en");
  583.     PQpnames (pnames, 1);
  584.     for (i = 0; i < MAXPORTALS; i++)
  585.         if (pnames[i] != NULL)
  586.         printf ("portal used by rules: %s\en", pnames[i]);
  587.     }
  588.  
  589.     /* finish execution. */
  590.     PQfinish ();
  591. }
  592. .ft
  593. .)1
  594.  
  595. .uh "SAMPLE PROGRAM 2"
  596. .lp
  597. .(1
  598. .nf
  599. .ft C
  600. /*
  601.  * Testing of asynchronous portal interface.
  602.  * 
  603.  * Do the following at the monitor:
  604.  *
  605.  
  606.  create test1 (i = int4) \eg
  607.  create test1a (i = int4) \eg
  608.  
  609.  define rule r1 is on append to test1 do
  610.     [append test1a (i = new.i)
  611.     notify test1a]
  612.  
  613.  \eg
  614.  * Then start up this process.
  615.  
  616.  append test1 (i = 10) \eg
  617.  
  618.  * The value i=10 should be printed by this process.
  619.  */
  620.  
  621. #include "tmp/simplelists.h"
  622. #include "tmp/libpq.h"
  623.  
  624. void main()
  625. {
  626.     extern int PQAsyncNotifyWaiting;
  627.     PQNotifyList *l;
  628.     PortalBuffer *portalbuf;
  629.     char *res;
  630.     int ngroups,tupno, grpno, ntups, nflds;
  631.     PQsetdb(getenv("USER"));
  632.  
  633.     PQexec("listen test1a");
  634.  
  635.     while(1) {
  636.         sleep(1);
  637.         if (PQAsyncNotifyWaiting) {
  638.         PQAsyncNotifyWaiting = 0;
  639.             PQexec(" ");
  640.             l = PQnotifies();
  641.             if (l != NULL) {
  642.                 printf("notification on relation %s\en",
  643.                l->relname);
  644.                 res = PQexec("retrieve (test1a.i)");
  645.                 if (*res == 'E') {
  646.                     fprintf(stderr,"%s\enfailed",++res);
  647.                     goto exit_error;
  648.                 }
  649.                 if (*res != 'P') {
  650.                     fprintf(stderr,"%s\enno portal",++res);
  651.                 }
  652.                 /* get tuples in relation */
  653.                 portalbuf = PQparray(++res);
  654.                 ngroups = PQngroups(portalbuf);
  655.                 for (grpno = 0; grpno < ngroups; grpno++) {
  656.                     ntups = PQntuplesGroup(portalbuf,grpno);
  657.             nflds = PQnfieldsGroup(portalbuf,grpno);
  658.                     if (nflds != 1) {
  659.                         fprintf(stderr,
  660.               "expected 1 attributes, got %d\en",
  661.               nflds);
  662.                         goto exit_error;
  663.                     }
  664.                     for (tupno = 0; tupno < ntups; tupno++) {
  665.                         printf("got i=%s\en",
  666.               PQgetvalue(portalbuf,tupno,0));
  667.                     }
  668.                 }
  669.                 break;
  670.             }
  671.         }
  672.     }
  673.  
  674.     PQfinish();
  675.     exit(0);
  676.   exit_error:
  677.     PQfinish();
  678.     exit(1);
  679.  
  680. }
  681. .ft
  682. .)1
  683.  
  684. .uh "SAMPLE PROGRAM 3"
  685. .lp
  686. .(1
  687. .nf
  688. .ft C
  689. /*
  690.  * Testing of new binary portal interface.
  691.  * 
  692.  * Do the following at the monitor:
  693.  *
  694.  
  695.  create test1 (i = int4,d = float4,p = polygon) \eg
  696.  append test1 (i = 7, d=3.567,p="(1.0,2.0,3.0,4.0)"::polygon) \eg
  697.  
  698.  -- Anything else you can think of. 
  699.  * Start up this program.
  700.  * The correct contents of test1 should be printed
  701.  */
  702.  
  703. #include "tmp/simplelists.h"
  704. #include "tmp/libpq.h"
  705. #include "utils/geo-decls.h"
  706.  
  707. void main()
  708. {
  709.     extern int PQAsyncNotifyWaiting;
  710.     PQNotifyList *l;
  711.     PortalBuffer *portalbuf;
  712.     char *res;
  713.     int ngroups,tupno, grpno, ntups, nflds;
  714.     PQsetdb(getenv("USER"));
  715.  
  716.     PQexec("begin");
  717.     res = (char *)PQexec("retrieve iportal junk (test1.all)");
  718.     if (*res == 'E') {
  719.     fprintf(stderr,"%s\enfailed",++res);
  720.     goto exit_error;
  721.     }
  722.     res = (char *)PQexec("fetch all in junk");
  723.     if (*res != 'P') {
  724.     fprintf(stderr,"\enno portal");
  725.     goto exit_error;
  726.     }
  727.     /* get tuples in relation */
  728.     portalbuf = PQparray(++res);
  729.     ngroups = PQngroups(portalbuf);
  730.     for (grpno = 0; grpno < ngroups; grpno++) {
  731.     ntups = PQntuplesGroup(portalbuf, grpno);
  732.     if ((nflds = PQnfieldsGroup(portalbuf, grpno)) != 3) {
  733.         fprintf(stderr, "expected 3 attributes, got %d\en", nflds);
  734.         goto exit_error;
  735.     }
  736.     for (tupno = 0; tupno < ntups; tupno++) {
  737.         int *bla1;
  738.         char *bla2;
  739.         POLYGON *bla3;
  740.         bla1 = (int *)PQgetvalue(portalbuf,tupno,0);
  741.         bla2 = PQgetvalue(portalbuf,tupno,1);
  742.         bla3 = PQgetvalue(portalbuf,tupno,2)-4;
  743.  
  744.         printf ("got i=%d(%d bytes), d=(%f)(%d bytes)|%x|%x|%x|%x\en\e
  745.  Polygon(%d bytes)\e
  746.   %d points (%f,%f,%f,%f)\en",
  747.             *bla1,PQgetlength(portalbuf,tupno,0),
  748.             *((float *)bla2),
  749.             PQgetlength(portalbuf,tupno,1),
  750.             *bla2,*(bla2+1),*(bla2+2),*(bla2+3),
  751.             PQgetlength(portalbuf,tupno,2),
  752.             bla3->npts,
  753.             bla3->boundbox.xh,bla3->boundbox.yh,
  754.             bla3->boundbox.xl,bla3->boundbox.yl);
  755.     }
  756.     }
  757.  
  758.     PQexec("end");
  759.     PQfinish();
  760.     exit(0);
  761.   exit_error:
  762.     PQexec("end");
  763.     PQfinish();
  764.     exit(1);
  765.  
  766. }
  767. .ft
  768. .)1
  769.