comparison src/postgresql.c @ 406:b8cc9ab3f761 r21-2-33

Import from CVS: tag r21-2-33
author cvs
date Mon, 13 Aug 2007 11:17:09 +0200
parents 2f8bb876ab1d
children 501cfd01ee6d
comparison
equal deleted inserted replaced
405:0e08f63c74d2 406:b8cc9ab3f761
55 PQgetline (copy in/out) 55 PQgetline (copy in/out)
56 PQputline (copy in/out) 56 PQputline (copy in/out)
57 PQgetlineAsync (copy in/out Asynch.) 57 PQgetlineAsync (copy in/out Asynch.)
58 PQputnbytes (copy in/out Asynch.) 58 PQputnbytes (copy in/out Asynch.)
59 PQendcopy (copy in/out) 59 PQendcopy (copy in/out)
60 PQsetenvStart (Asynch. Queries)
61 PQsetenvPoll (Asynch. Queries)
62 PQsetenvHandle (Asynch. Queries)
63 60
64 Unsupported functions: 61 Unsupported functions:
65 PQsetdbLogin -- This function is deprecated, has a subset of the 62 PQsetdbLogin -- This function is deprecated, has a subset of the
66 functionality of PQconnectdb, and is better done in Lisp. 63 functionality of PQconnectdb, and is better done in Lisp.
67 PQsetdb -- Same as for PQsetdbLogin 64 PQsetdb -- Same as for PQsetdbLogin
93 interface to lcrecord handling has changed with 21.2, so unfortunately 90 interface to lcrecord handling has changed with 21.2, so unfortunately
94 we will need a few snippets of backwards compatibility code. 91 we will need a few snippets of backwards compatibility code.
95 */ 92 */
96 #if (EMACS_MAJOR_VERSION == 21) && (EMACS_MINOR_VERSION < 2) 93 #if (EMACS_MAJOR_VERSION == 21) && (EMACS_MINOR_VERSION < 2)
97 #define RUNNING_XEMACS_21_1 1 94 #define RUNNING_XEMACS_21_1 1
95 #define POSTGRES_INCLUDE(file) <file>
98 #endif 96 #endif
99 97
100 /* #define POSTGRES_LO_IMPORT_IS_VOID 1 */ 98 /* #define POSTGRES_LO_IMPORT_IS_VOID 1 */
101 99
102 #include "lisp.h" 100 #include "lisp.h"
103 #include "sysdep.h" 101 #include "sysdep.h"
104 #include "buffer.h" 102 #include "buffer.h"
105 103
106 #include <libpq-fe.h> 104 #include POSTGRES_INCLUDE (libpq-fe.h)
107 /* Undefine the following when asynchronous setenvs are fixed in libpq. */
108 /* #define LIBPQ_7_0_IS_FIXED */
109 #include "postgresql.h" 105 #include "postgresql.h"
110 106
111 #ifdef RUNNING_XEMACS_21_1 /* handle interface changes */ 107 #ifdef RUNNING_XEMACS_21_1 /* handle interface changes */
112 #define I_HATE_CONST CONST 108 #define I_HATE_CONST CONST
113 #define PG_OS_CODING FORMAT_FILENAME 109 #define PG_OS_CODING FORMAT_FILENAME
394 NULL, NULL, 390 NULL, NULL,
395 0, 391 0,
396 Lisp_PGresult); 392 Lisp_PGresult);
397 #endif 393 #endif
398 394
399 /****/
400 #ifdef HAVE_POSTGRESQLV7
401 /* PGsetenvHandle is an opaque object and we need to be able to store them in
402 Lisp code so we can make asynchronous environmental calls.
403
404 Asynchronous setenv calls were introduced in libpq-7.0.
405 */
406 #ifdef LIBPQ_7_0_IS_FIXED
407
408 Lisp_Object Qpgsetenvp;
409
410 static Lisp_Object
411 make_pgsetenv (Lisp_PGsetenvHandle *pgsetenv)
412 {
413 Lisp_Object lisp_pgsetenv;
414 XSETPGSETENV (lisp_pgsetenv, pgsetenv);
415 return lisp_pgsetenv;
416 }
417
418 static Lisp_Object
419 #ifdef RUNNING_XEMACS_21_1
420 mark_pgsetenv (Lisp_Object obj, void (*markobj) (Lisp_Object))
421 #else
422 mark_pgsetenv (Lisp_Object obj)
423 #endif
424 {
425 return Qnil;
426 }
427
428 static void
429 print_pgsetenv (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
430 {
431 char *fmt = "#<PGsetenvHandle %s>";
432 char buf[1024];
433 PGsetenvHandle *h;
434
435 h = (XPGSETENV (obj))->pgsetenv;
436
437 sprintf (buf, fmt, h ? "live" : "DEAD");
438
439 /* There are no accessor functions to retrieve any fields, so we must */
440 /* treat this as being completely opaque. */
441 if (print_readably)
442 error ("printing unreadable object %s", buf);
443 else
444 write_c_string (buf, printcharfun);
445 }
446
447 static Lisp_PGsetenvHandle *
448 allocate_pgresult (void)
449 {
450 #ifdef RUNNING_XEMACS_21_1
451 Lisp_PGsetenvHandle *pgsetenv =
452 alloc_lcrecord_type (Lisp_PGsetenvHandle, lrecord_pgsetenv);
453 #else
454 Lisp_PGsetenvHandle *pgsetenv =
455 alloc_lcrecord_type (Lisp_PGsetenvHandle, &lrecord_pgsetenv);
456 #endif
457 pgsetenv->pgsetenv = (PGsetenvState *)NULL;
458 return pgsetenv;
459 }
460
461 static void
462 finalize_pgsetenv (void *header, int for_disksave)
463 {
464 Lisp_PGsetenvHandle *pgsetenv = (Lisp_PGsetenvHandle *)header;
465
466 if (for_disksave)
467 signal_simple_error ("Can't dump an emacs containing PGsetenvHandle objects",
468 make_pgsetenv (pgsetenv));
469
470 /* #### PGsetenvHandle's are allocated with malloc(), however in
471 libpq-7.0 the treatment of them is little short of disastrous.
472 We don't dare attempt to free it, because there are many code
473 paths which lead to the handle being freed internally. The
474 connection routines leak setenv handles and so will we until
475 libpq gets cleaned up.
476 Actually, in 7.0b1 asynchronous setenv cannot work outside libpq, so
477 these functions are disabled in this API.
478 */
479 if (pgsetenv->pgsetenv)
480 {
481 free (pgsetenv->pgsetenv);
482 pgsetenv->pgsetenv = (PGsetenvHandle *)NULL;
483 }
484 }
485
486 #ifdef RUNNING_XEMACS_21_1
487 DEFINE_LRECORD_IMPLEMENTATION ("pgresult", pgresult,
488 mark_pgresult, print_pgresult, finalize_pgresult,
489 NULL, NULL,
490 Lisp_PGresult);
491 #else
492 DEFINE_LRECORD_IMPLEMENTATION ("pgresult", pgresult,
493 mark_pgresult, print_pgresult, finalize_pgresult,
494 NULL, NULL,
495 0,
496 Lisp_PGresult);
497 #endif /* RUNNING_XEMACS_21_1 */
498
499 #endif /* LIBPQ_7_0_IS_FIXED */
500 #endif /* HAVE_POSTGRESQLV7 */
501
502 /***********************/ 395 /***********************/
503 396
504 /* notices */ 397 /* notices */
505 static void 398 static void
506 xemacs_notice_processor (void *arg, I_HATE_CONST char *msg) 399 xemacs_notice_processor (void *arg, I_HATE_CONST char *msg)
1685 CHECK_LIVE_CONNECTION (P); 1578 CHECK_LIVE_CONNECTION (P);
1686 1579
1687 return PQendcopy (P) ? Qt : Qnil; 1580 return PQendcopy (P) ? Qt : Qnil;
1688 } 1581 }
1689 1582
1690 /* The setenv suite of functions. The author of the libpq manual doesn't
1691 know a whole lot about them, and neither do I.
1692 */
1693 #if !defined (HAVE_POSTGRESQLV7) || defined (LIBPQ_7_0_IS_FIXED)
1694 DEFUN ("pq-setenv", Fpq_setenv, 1, 1, 0, /*
1695 Set environmental parameters on the backend synchronously.
1696 Returns t if the operation was successful, nil otherwise.
1697 */
1698 (conn))
1699 {
1700 PGconn *P;
1701
1702 CHECK_PGCONN (conn);
1703 P = (XPGCONN (conn))->pgconn;
1704 CHECK_LIVE_CONNECTION (P);
1705
1706 return PQsetenv (P) ? Qt : Qnil;
1707 }
1708 #endif
1709
1710 #ifdef LIBPQ_7_0_IS_FIXED
1711
1712 DEFUN ("pq-setenv-start", Fpq_setenv_start, 1, 1, 0, /*
1713 Set environmental parameters on the backend asynchronously.
1714 A PGsetenvHandle is returned on success, nil otherwise.
1715 */
1716 (conn))
1717 {
1718 PGconn *P;
1719 PGsetenvHandle *handle;
1720 Lisp_setenvHandle *lseh;
1721
1722 CHECK_PGCONN (conn);
1723 P = (XPGCONN (conn))->pgconn;
1724 CHECK_LIVE_CONNECTION (P);
1725
1726 handle = PQsetenvStart (P);
1727 if (!handle) error ("out of memory?");
1728
1729 lseh = allocate_pgsetenv ();
1730 lseh->setenv = handle;
1731
1732 return make_pgsetenv (lseh);
1733 }
1734
1735 DEFUN ("pq-setenv-poll", Fpq_setenv_poll, 1, 1, 0, /*
1736 Poll an asynchronous setenv operation for completion.
1737 */
1738 (conn))
1739 {
1740 PGconn *P;
1741 PostgresPollingStatusType pst;
1742
1743 CHECK_PGCONN (conn);
1744 P = (XPGCONN (conn))->pgconn;
1745 CHECK_LIVE_CONNECTION (P);
1746
1747 pst = PQsetenvPoll (P);
1748 switch (pst)
1749 {
1750 case PGRES_POLLING_FAILED:
1751 /* Something Bad has happened */
1752 {
1753 char *e = PQerrorMessage (P);
1754 error ("libpq: %s", e);
1755 }
1756 case PGRES_POLLING_OK:
1757 return Qpgres_polling_ok;
1758 case PGRES_POLLING_READING:
1759 return Qpgres_polling_reading;
1760 case PGRES_POLLING_WRITING:
1761 return Qpgres_polling_writing;
1762 case PGRES_POLLING_ACTIVE:
1763 return Qpgres_polling_active;
1764 default:
1765 /* they've added a new field we don't know about */
1766 error ("Help! Unknown status code %08x from backend!", PS);
1767 }
1768 }
1769
1770 DEFUN ("pq-setenv-abort", Fpq_setenv_abort, 1, 1, 0, /*
1771 Attempt to abort an in-progress asynchronous setenv operation.
1772 */
1773 (handle))
1774 {
1775 PGsetenvHandle *h;
1776
1777 CHECK_PGSETENV (handle);
1778 h = (XPGSETENV (handle))->pgsetenv;
1779 PUKE_IF_NULL (h);
1780
1781 PQsetenvAbort (h);
1782 /* PQsetenvAbort usually free(3)'s the handle, don't take any chances. */
1783 (XSETENV (handle))->pgsetenv = (PGsetenvHandle *)NULL;
1784
1785 return Qt;
1786 }
1787 #endif /* LIBPQ_7_0_IS_FIXED */
1788
1789 void 1583 void
1790 syms_of_postgresql(void) 1584 syms_of_postgresql(void)
1791 { 1585 {
1792 #ifndef RUNNING_XEMACS_21_1 1586 #ifndef RUNNING_XEMACS_21_1
1793 INIT_LRECORD_IMPLEMENTATION (pgconn); 1587 INIT_LRECORD_IMPLEMENTATION (pgconn);
1794 INIT_LRECORD_IMPLEMENTATION (pgresult); 1588 INIT_LRECORD_IMPLEMENTATION (pgresult);
1795 #ifdef LIBPQ_7_0_IS_FIXED
1796 INIT_LRECORD_IMPLEMENTATION (pgsetenv);
1797 #endif
1798 #endif 1589 #endif
1799 defsymbol (&Qpostgresql, "postgresql"); 1590 defsymbol (&Qpostgresql, "postgresql");
1800 1591
1801 /* opaque exported types */ 1592 /* opaque exported types */
1802 defsymbol (&Qpgconnp, "pgconnp"); 1593 defsymbol (&Qpgconnp, "pgconnp");
1905 DEFSUBR (Fpq_get_line); 1696 DEFSUBR (Fpq_get_line);
1906 DEFSUBR (Fpq_put_line); 1697 DEFSUBR (Fpq_put_line);
1907 DEFSUBR (Fpq_get_line_async); 1698 DEFSUBR (Fpq_get_line_async);
1908 DEFSUBR (Fpq_put_nbytes); 1699 DEFSUBR (Fpq_put_nbytes);
1909 DEFSUBR (Fpq_end_copy); 1700 DEFSUBR (Fpq_end_copy);
1910
1911 /* The value of the setenv functions is questioned in the libpq manual. */
1912 #if !defined (HAVE_POSTGRESQLV7) || defined (LIBPQ_7_0_IS_FIXED)
1913 DEFSUBR (Fpq_setenv);
1914 #endif
1915 #ifdef LIBPQ_7_0_IS_FIXED
1916 DEFSUBR (Fpq_setenv_start);
1917 DEFSUBR (Fpq_setenv_poll);
1918 DEFSUBR (Fpq_setenv_abort);
1919 #endif /* LIBPQ_7_0_IS_FIXED */
1920 } 1701 }
1921 1702
1922 void 1703 void
1923 vars_of_postgresql(void) 1704 vars_of_postgresql(void)
1924 { 1705 {