Mercurial > hg > xemacs-beta
comparison modules/postgresql/postgresql.c @ 4985:358aa3bb603f
Automatic merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Feb 2010 12:12:28 -0600 |
parents | 4aebb0131297 |
children | b5df3737028a |
comparison
equal
deleted
inserted
replaced
4984:f23cd0184dcf | 4985:358aa3bb603f |
---|---|
95 #endif | 95 #endif |
96 | 96 |
97 /* #define POSTGRES_LO_IMPORT_IS_VOID 1 */ | 97 /* #define POSTGRES_LO_IMPORT_IS_VOID 1 */ |
98 | 98 |
99 #include "lisp.h" | 99 #include "lisp.h" |
100 #include "sysdep.h" | |
101 | 100 |
102 #include "buffer.h" | 101 #include "buffer.h" |
103 #include "postgresql.h" | 102 #include "postgresql.h" |
104 #include "process.h" | 103 #include "process.h" |
105 #ifdef HAVE_SHLIB | 104 #ifdef HAVE_SHLIB |
106 # include "emodules.h" | 105 # include "emodules.h" |
107 #endif | 106 #endif |
107 #include "sysdep.h" | |
108 #include "sysfile.h" | |
108 | 109 |
109 #ifdef RUNNING_XEMACS_21_1 /* handle interface changes */ | 110 #ifdef RUNNING_XEMACS_21_1 /* handle interface changes */ |
110 #define PG_OS_CODING FORMAT_FILENAME | 111 #define PG_OS_CODING FORMAT_FILENAME |
111 #define TO_EXTERNAL_FORMAT(a,from,b,to,c) GET_C_STRING_EXT_DATA_ALLOCA(from,FORMAT_FILENAME,to) | 112 #define TO_EXTERNAL_FORMAT(a,from,b,to,c) GET_C_STRING_EXT_DATA_ALLOCA(from,FORMAT_FILENAME,to) |
112 #else | 113 #else |
121 #define CHECK_LIVE_CONNECTION(P) \ | 122 #define CHECK_LIVE_CONNECTION(P) \ |
122 do \ | 123 do \ |
123 { \ | 124 { \ |
124 if (!P || (PQstatus (P) != CONNECTION_OK)) \ | 125 if (!P || (PQstatus (P) != CONNECTION_OK)) \ |
125 { \ | 126 { \ |
126 const Ibyte *err; \ | 127 Lisp_Object err; \ |
127 \ | 128 \ |
128 if (P) \ | 129 if (P) \ |
129 err = NEW_EXTERNAL_TO_C_STRING (PQerrorMessage (P), PG_OS_CODING); \ | 130 err = build_extstring (PQerrorMessage (P), PG_OS_CODING); \ |
130 else \ | 131 else \ |
131 err = (const Ibyte *) "bad value"; \ | 132 err = build_msg_string ("Bad value"); \ |
132 signal_ferror (Qprocess_error, "dead connection [%s]", err); \ | 133 signal_error (Qprocess_error, "Dead connection", err); \ |
133 } \ | 134 } \ |
134 } \ | 135 } \ |
135 while (0) | 136 while (0) |
136 | 137 |
137 #define PUKE_IF_NULL(p) \ | 138 #define PUKE_IF_NULL(p) \ |
138 do \ | 139 do \ |
139 { \ | 140 { \ |
140 if (!p) signal_error (Qinvalid_argument, "bad value", Qunbound); \ | 141 if (!p) signal_error (Qinvalid_argument, "Bad value", Qunbound); \ |
141 } \ | 142 } \ |
142 while (0) | 143 while (0) |
144 | |
145 #define SIGNAL_ERROR(p, reason) \ | |
146 do \ | |
147 { \ | |
148 signal_error (Qprocess_error, reason, \ | |
149 build_extstring (PQerrorMessage (p), PG_OS_CODING)); \ | |
150 } \ | |
151 while (0) | |
143 | 152 |
144 static Lisp_Object VXPGHOST; | 153 static Lisp_Object VXPGHOST; |
145 static Lisp_Object VXPGUSER; | 154 static Lisp_Object VXPGUSER; |
146 static Lisp_Object VXPGOPTIONS; | 155 static Lisp_Object VXPGOPTIONS; |
147 static Lisp_Object VXPGPORT; | 156 static Lisp_Object VXPGPORT; |
477 | 486 |
478 /* PQconnectdb Makes a new connection to a backend. | 487 /* PQconnectdb Makes a new connection to a backend. |
479 PGconn *PQconnectdb(const char *conninfo) | 488 PGconn *PQconnectdb(const char *conninfo) |
480 */ | 489 */ |
481 | 490 |
482 /* ###autoload */ | 491 #ifdef HAVE_POSTGRESQLV7 |
483 DEFUN ("pq-connectdb", Fpq_connectdb, 1, 1, 0, /* | 492 #define USED_IF_V7(x) x |
484 Make a new connection to a PostgreSQL backend. | 493 #else |
485 */ | 494 #define USED_IF_V7(x) UNUSED (x) |
486 (conninfo)) | 495 #endif |
496 | |
497 static Lisp_Object | |
498 postgresql_connect (Lisp_Object conninfo, int USED_IF_V7 (async)) | |
487 { | 499 { |
488 PGconn *P; | 500 PGconn *P; |
489 Lisp_PGconn *lisp_pgconn; | 501 Lisp_PGconn *lisp_pgconn; |
490 const Ascbyte *error_message = "Out of Memory?"; | |
491 Extbyte *c_conninfo; | |
492 | 502 |
493 CHECK_STRING (conninfo); | 503 CHECK_STRING (conninfo); |
494 | 504 |
495 LISP_STRING_TO_EXTERNAL (conninfo, c_conninfo, PG_OS_CODING); | 505 P = ( |
496 P = PQconnectdb (c_conninfo); | 506 #ifdef HAVE_POSTGRESQLV7 |
507 async ? PQconnectStart : | |
508 #endif | |
509 PQconnectdb) | |
510 (LISP_STRING_TO_EXTERNAL (conninfo, PG_OS_CODING)); | |
497 if (P && (PQstatus (P) == CONNECTION_OK)) | 511 if (P && (PQstatus (P) == CONNECTION_OK)) |
498 { | 512 { |
499 (void)PQsetNoticeProcessor (P, xemacs_notice_processor, NULL); | 513 (void) PQsetNoticeProcessor (P, xemacs_notice_processor, NULL); |
500 lisp_pgconn = allocate_pgconn (); | 514 lisp_pgconn = allocate_pgconn (); |
501 lisp_pgconn->pgconn = P; | 515 lisp_pgconn->pgconn = P; |
502 return make_pgconn (lisp_pgconn); | 516 return make_pgconn (lisp_pgconn); |
503 } | 517 } |
504 else | 518 else |
505 { | 519 { |
506 /* Connection failed. Destroy the connection and signal an error. */ | 520 /* Connection failed. Destroy the connection and signal an error. */ |
507 Ibyte *errmsg = (Ibyte *) error_message; | 521 |
522 Lisp_Object errmsg; | |
508 if (P) | 523 if (P) |
509 { | 524 { |
510 /* storage for the error message gets erased when call PQfinish */ | 525 errmsg = build_extstring (PQerrorMessage (P), PG_OS_CODING); |
511 /* so we must temporarily stash it somewhere -- make alloca() copy */ | |
512 errmsg = NEW_EXTERNAL_TO_C_STRING (PQerrorMessage (P), PG_OS_CODING); | |
513 IBYTE_STRING_TO_ALLOCA (errmsg, errmsg); | |
514 PQfinish (P); | 526 PQfinish (P); |
515 } | 527 } |
516 signal_ferror (Qprocess_error, "libpq: %s", errmsg); | 528 else |
529 errmsg = build_msg_string ("Out of Memory?"); | |
530 signal_error (Qprocess_error, "Connecting to PostGreSQL backend", | |
531 errmsg); | |
517 } | 532 } |
533 } | |
534 | |
535 /* ###autoload */ | |
536 DEFUN ("pq-connectdb", Fpq_connectdb, 1, 1, 0, /* | |
537 Make a new connection to a PostgreSQL backend. | |
538 */ | |
539 (conninfo)) | |
540 { | |
541 return postgresql_connect (conninfo, 0); | |
518 } | 542 } |
519 | 543 |
520 /* PQconnectStart Makes a new asynchronous connection to a backend. | 544 /* PQconnectStart Makes a new asynchronous connection to a backend. |
521 PGconn *PQconnectStart(const char *conninfo) | 545 PGconn *PQconnectStart(const char *conninfo) |
522 */ | 546 */ |
526 DEFUN ("pq-connect-start", Fpq_connect_start, 1, 1, 0, /* | 550 DEFUN ("pq-connect-start", Fpq_connect_start, 1, 1, 0, /* |
527 Make a new asynchronous connection to a PostgreSQL backend. | 551 Make a new asynchronous connection to a PostgreSQL backend. |
528 */ | 552 */ |
529 (conninfo)) | 553 (conninfo)) |
530 { | 554 { |
531 PGconn *P; | 555 return postgresql_connect (conninfo, 1); |
532 Lisp_PGconn *lisp_pgconn; | |
533 const Ascbyte *error_message = "Out of Memory?"; | |
534 Extbyte *c_conninfo; | |
535 | |
536 CHECK_STRING (conninfo); | |
537 | |
538 LISP_STRING_TO_EXTERNAL (conninfo, c_conninfo, PG_OS_CODING); | |
539 P = PQconnectStart (c_conninfo); | |
540 | |
541 if (P && (PQstatus (P) != CONNECTION_BAD)) | |
542 { | |
543 (void)PQsetNoticeProcessor (P, xemacs_notice_processor, NULL); | |
544 lisp_pgconn = allocate_pgconn (); | |
545 lisp_pgconn->pgconn = P; | |
546 | |
547 return make_pgconn (lisp_pgconn); | |
548 } | |
549 else | |
550 { | |
551 /* capture the error message before destroying the object */ | |
552 char buf[BLCKSZ]; | |
553 strcpy (buf, error_message); | |
554 if (P) | |
555 { | |
556 strncpy (buf, PQerrorMessage (P), sizeof (buf)); | |
557 buf[sizeof (buf) - 1] = '\0'; | |
558 PQfinish (P); | |
559 } | |
560 signal_ferror (Qprocess_error, "libpq: %s", buf); | |
561 } | |
562 } | 556 } |
563 | 557 |
564 DEFUN ("pq-connect-poll", Fpq_connect_poll, 1, 1, 0, /* | 558 DEFUN ("pq-connect-poll", Fpq_connect_poll, 1, 1, 0, /* |
565 Poll an asynchronous connection for completion | 559 Poll an asynchronous connection for completion |
566 */ | 560 */ |
577 polling_status = PQconnectPoll (P); | 571 polling_status = PQconnectPoll (P); |
578 switch (polling_status) | 572 switch (polling_status) |
579 { | 573 { |
580 case PGRES_POLLING_FAILED: | 574 case PGRES_POLLING_FAILED: |
581 /* Something Bad has happened */ | 575 /* Something Bad has happened */ |
582 { | 576 SIGNAL_ERROR (P, "Polling asynchronous connection"); |
583 char *e = PQerrorMessage (P); | |
584 signal_ferror (Qprocess_error, "libpq: %s", e); | |
585 } | |
586 case PGRES_POLLING_OK: | 577 case PGRES_POLLING_OK: |
587 return Qpgres_polling_ok; | 578 return Qpgres_polling_ok; |
588 case PGRES_POLLING_READING: | 579 case PGRES_POLLING_READING: |
589 return Qpgres_polling_reading; | 580 return Qpgres_polling_reading; |
590 case PGRES_POLLING_WRITING: | 581 case PGRES_POLLING_WRITING: |
743 CHECK_PGCONN (conn); | 734 CHECK_PGCONN (conn); |
744 P = (XPGCONN (conn))->pgconn; | 735 P = (XPGCONN (conn))->pgconn; |
745 CHECK_LIVE_CONNECTION (P); | 736 CHECK_LIVE_CONNECTION (P); |
746 | 737 |
747 if (PQresetStart (P)) return Qt; | 738 if (PQresetStart (P)) return Qt; |
748 { | 739 SIGNAL_ERROR (P, "Resetting connection"); |
749 char *e = PQerrorMessage (P); | |
750 signal_ferror (Qprocess_error, "libpq: %s", e); | |
751 } | |
752 } | 740 } |
753 | 741 |
754 DEFUN ("pq-reset-poll", Fpq_reset_poll, 1, 1, 0, /* | 742 DEFUN ("pq-reset-poll", Fpq_reset_poll, 1, 1, 0, /* |
755 Poll an asynchronous reset for completion. | 743 Poll an asynchronous reset for completion. |
756 */ | 744 */ |
766 | 754 |
767 polling_status = PQresetPoll (P); | 755 polling_status = PQresetPoll (P); |
768 switch (polling_status) | 756 switch (polling_status) |
769 { | 757 { |
770 case PGRES_POLLING_FAILED: | 758 case PGRES_POLLING_FAILED: |
771 /* Something Bad has happened */ | 759 SIGNAL_ERROR (P, "Polling asynchronous reset"); |
772 { | |
773 char *e = PQerrorMessage (P); | |
774 signal_ferror (Qprocess_error, "libpq: %s", e); | |
775 } | |
776 case PGRES_POLLING_OK: | 760 case PGRES_POLLING_OK: |
777 return Qpgres_polling_ok; | 761 return Qpgres_polling_ok; |
778 case PGRES_POLLING_READING: | 762 case PGRES_POLLING_READING: |
779 return Qpgres_polling_reading; | 763 return Qpgres_polling_reading; |
780 case PGRES_POLLING_WRITING: | 764 case PGRES_POLLING_WRITING: |
982 | 966 |
983 TO_EXTERNAL_FORMAT (LISP_STRING, query, | 967 TO_EXTERNAL_FORMAT (LISP_STRING, query, |
984 C_STRING_ALLOCA, c_query, Qnative); | 968 C_STRING_ALLOCA, c_query, Qnative); |
985 | 969 |
986 if (PQsendQuery (P, c_query)) return Qt; | 970 if (PQsendQuery (P, c_query)) return Qt; |
987 else signal_ferror (Qprocess_error, "async query: %s", PQerrorMessage (P)); | 971 else SIGNAL_ERROR (P, "Sending asynchronous query"); |
988 } | 972 } |
989 | 973 |
990 DEFUN ("pq-get-result", Fpq_get_result, 1, 1, 0, /* | 974 DEFUN ("pq-get-result", Fpq_get_result, 1, 1, 0, /* |
991 Retrieve an asynchronous result from a query. | 975 Retrieve an asynchronous result from a query. |
992 NIL is returned when no more query work remains. | 976 NIL is returned when no more query work remains. |
1420 CHECK_STRING (filename); | 1404 CHECK_STRING (filename); |
1421 | 1405 |
1422 P = (XPGCONN (conn))->pgconn; | 1406 P = (XPGCONN (conn))->pgconn; |
1423 CHECK_LIVE_CONNECTION (P); | 1407 CHECK_LIVE_CONNECTION (P); |
1424 | 1408 |
1425 TO_EXTERNAL_FORMAT (LISP_STRING, filename, | 1409 LISP_PATHNAME_CONVERT_OUT (filename, c_filename); |
1426 C_STRING_ALLOCA, c_filename, | |
1427 Qfile_name); | |
1428 | 1410 |
1429 return make_int ((int)lo_import (P, c_filename)); | 1411 return make_int ((int)lo_import (P, c_filename)); |
1430 } | 1412 } |
1431 | 1413 |
1432 DEFUN ("pq-lo-export", Fpq_lo_export, 3, 3, 0, /* | 1414 DEFUN ("pq-lo-export", Fpq_lo_export, 3, 3, 0, /* |
1441 CHECK_STRING (filename); | 1423 CHECK_STRING (filename); |
1442 | 1424 |
1443 P = (XPGCONN (conn))->pgconn; | 1425 P = (XPGCONN (conn))->pgconn; |
1444 CHECK_LIVE_CONNECTION (P); | 1426 CHECK_LIVE_CONNECTION (P); |
1445 | 1427 |
1446 TO_EXTERNAL_FORMAT (LISP_STRING, filename, | 1428 LISP_PATHNAME_CONVERT_OUT (filename, c_filename); |
1447 C_STRING_ALLOCA, c_filename, Qfile_name); | |
1448 | 1429 |
1449 return make_int ((int)lo_export (P, XINT (oid), c_filename)); | 1430 return make_int ((int)lo_export (P, XINT (oid), c_filename)); |
1450 } | 1431 } |
1451 | 1432 |
1452 DEFUN ("pq-make-empty-pgresult", Fpq_make_empty_pgresult, 2, 2, 0, /* | 1433 DEFUN ("pq-make-empty-pgresult", Fpq_make_empty_pgresult, 2, 2, 0, /* |