Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8fb0ac8

Browse files
author
Bryan Henderson
committed
Make error messages more explicit, PQtrace() output more readable.
1 parente2da92f commit8fb0ac8

File tree

2 files changed

+186
-138
lines changed

2 files changed

+186
-138
lines changed

‎src/interfaces/libpq/fe-exec.c

Lines changed: 171 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.25 1996/12/28 01:57:13 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.26 1996/12/31 07:29:15 bryanh Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -348,6 +348,170 @@ makePGresult(PGconn* conn, char* pname)
348348
}
349349

350350

351+
/*
352+
* Assuming that we just sent a query to the backend, read the backend's
353+
* response from stream <pfin> and respond accordingly.
354+
*
355+
* If <pfdebug> is non-null, write to that stream whatever we receive
356+
* (it's a debugging trace).
357+
*
358+
* Return as <result> a pointer to a proper final PGresult structure,
359+
* newly allocated, for the query based on the response we get. If the
360+
* response we get indicates that the query didn't execute, return a
361+
* null pointer and don't allocate any space, but also place a text
362+
* string explaining the problem at <*reason>.
363+
*/
364+
365+
staticvoid
366+
process_response_from_backend(FILE*pfin,FILE*pfout,FILE*pfdebug,
367+
PGconn*conn,
368+
PGresult**result_p,char*constreason) {
369+
370+
charid;
371+
/* The protocol character received from the backend. The protocol
372+
character is the first character in the backend's response to our
373+
query. It defines the nature of the response.
374+
*/
375+
PGnotify*newNotify;
376+
booldone;
377+
/* We're all done with the query and ready to return the result. */
378+
intemptiesSent;
379+
/* Number of empty queries we have sent in order to flush out multiple
380+
responses, less the number of corresponding responses we have
381+
received.
382+
*/
383+
charcmdStatus[MAX_MESSAGE_LEN];
384+
charpname[MAX_MESSAGE_LEN];/* portal name */
385+
386+
/* loop because multiple messages, especially NOTICES,
387+
can come back from the backend. NOTICES are output directly to stderr
388+
*/
389+
390+
emptiesSent=0;/* No empty queries sent yet */
391+
pname[0]='\0';
392+
393+
done= false;/* initial value */
394+
while (!done) {
395+
/* read the result id */
396+
id=pqGetc(pfin,pfdebug);
397+
if (id==EOF) {
398+
/* hmm, no response from the backend-end, that's bad */
399+
(void)sprintf(reason,
400+
"PQexec() -- Request was sent to backend, but backend "
401+
"closed the channel before "
402+
"responding. This probably means the backend "
403+
"terminated abnormally before or while processing "
404+
"the request.\n");
405+
conn->status=CONNECTION_BAD;/* No more connection to backend */
406+
*result_p= (PGresult*)NULL;
407+
done= true;
408+
}else {
409+
switch (id) {
410+
case'A':
411+
newNotify= (PGnotify*)malloc(sizeof(PGnotify));
412+
pqGetInt(&(newNotify->be_pid),4,pfin,pfdebug);
413+
pqGets(newNotify->relname,NAMEDATALEN,pfin,pfdebug);
414+
DLAddTail(conn->notifyList,DLNewElem(newNotify));
415+
/* async messages are piggy'ed back on other messages,
416+
so we stay in the while loop for other messages */
417+
break;
418+
case'C':/* portal query command, no rows returned */
419+
if (pqGets(cmdStatus,MAX_MESSAGE_LEN,pfin,pfdebug)==1) {
420+
sprintf(reason,
421+
"PQexec() -- query command completed, "
422+
"but return message from backend cannot be read.");
423+
*result_p= (PGresult*)NULL;
424+
done= true;
425+
}else {
426+
/*
427+
// since backend may produce more than one result for some
428+
// commands need to poll until clear
429+
// send an empty query down, and keep reading out of the pipe
430+
// until an 'I' is received.
431+
*/
432+
pqPuts("Q ",pfout,pfdebug);/* send an empty query */
433+
/*
434+
* Increment a flag and process messages in the usual way because
435+
* there may be async notifications pending. DZ - 31-8-1996
436+
*/
437+
emptiesSent++;
438+
}
439+
break;
440+
case'E':/* error return */
441+
if (pqGets(conn->errorMessage,ERROR_MSG_LENGTH,pfin,pfdebug)==1) {
442+
(void)sprintf(reason,
443+
"PQexec() -- error return detected from backend, "
444+
"but attempt to read the error message failed.");
445+
}
446+
*result_p= (PGresult*)NULL;
447+
done= true;
448+
break;
449+
case'I': {/* empty query */
450+
/* read and throw away the closing '\0' */
451+
intc;
452+
if ((c=pqGetc(pfin,pfdebug))!='\0') {
453+
fprintf(stderr,"error!, unexpected character %c following 'I'\n",c);
454+
}
455+
if (emptiesSent) {
456+
if (--emptiesSent==0) {/* is this the last one? */
457+
/*
458+
* If this is the result of a portal query command set the
459+
* command status and message accordingly. DZ - 31-8-1996
460+
*/
461+
*result_p=makeEmptyPGresult(conn,PGRES_COMMAND_OK);
462+
strncpy((*result_p)->cmdStatus,cmdStatus,CMDSTATUS_LEN-1);
463+
done= true;
464+
}
465+
}
466+
else {
467+
*result_p=makeEmptyPGresult(conn,PGRES_EMPTY_QUERY);
468+
done= true;
469+
}
470+
}
471+
break;
472+
case'N':/* notices from the backend */
473+
if (pqGets(reason,ERROR_MSG_LENGTH,pfin,pfdebug)==1) {
474+
sprintf(reason,
475+
"PQexec() -- Notice detected from backend, "
476+
"but attempt to read the notice failed.");
477+
*result_p= (PGresult*)NULL;
478+
done= true;
479+
}else
480+
/* Should we really be doing this? These notices are not important
481+
enough for us to presume to put them on stderr. Maybe the caller
482+
should decide whether to put them on stderr or not. BJH 96.12.27
483+
*/
484+
fprintf(stderr,"%s",reason);
485+
break;
486+
case'P':/* synchronous (normal) portal */
487+
pqGets(pname,MAX_MESSAGE_LEN,pfin,pfdebug);/* read in portal name*/
488+
break;
489+
case'T':/* actual row results: */
490+
*result_p=makePGresult(conn,pname);
491+
done= true;
492+
break;
493+
case'D':/* copy command began successfully */
494+
*result_p=makeEmptyPGresult(conn,PGRES_COPY_IN);
495+
done= true;
496+
break;
497+
case'B':/* copy command began successfully */
498+
*result_p=makeEmptyPGresult(conn,PGRES_COPY_OUT);
499+
done= true;
500+
break;
501+
default:
502+
sprintf(reason,
503+
"unknown protocol character '%c' read from backend. "
504+
"(The protocol character is the first character the "
505+
"backend sends in response to a query it receives).\n",
506+
id);
507+
*result_p= (PGresult*)NULL;
508+
done= true;
509+
}/* switch on protocol character */
510+
}/* if character was received */
511+
}/* while not done */
512+
}
513+
514+
351515

352516
/*
353517
* PQexec
@@ -364,27 +528,14 @@ PGresult*
364528
PQexec(PGconn*conn,constchar*query)
365529
{
366530
PGresult*result;
367-
intid;
368531
charbuffer[MAX_MESSAGE_LEN];
369-
charcmdStatus[MAX_MESSAGE_LEN];
370-
charpname[MAX_MESSAGE_LEN];/* portal name */
371-
PGnotify*newNotify;
372-
FILE*pfin,*pfout,*pfdebug;
373-
staticintemptiesPending=0;
374-
boolemptySent= false;
375-
376-
pname[0]='\0';
377532

378533
if (!conn)returnNULL;
379534
if (!query) {
380535
sprintf(conn->errorMessage,"PQexec() -- query pointer is null.");
381536
returnNULL;
382537
}
383538

384-
pfin=conn->Pfin;
385-
pfout=conn->Pfout;
386-
pfdebug=conn->Pfdebug;
387-
388539
/*clear the error string */
389540
conn->errorMessage[0]='\0';
390541

@@ -406,129 +557,20 @@ PQexec(PGconn* conn, const char* query)
406557
sprintf(buffer,"Q%s",query);
407558

408559
/* send the query to the backend; */
409-
if (pqPuts(buffer,pfout,pfdebug)==1) {
560+
if (pqPuts(buffer,conn->Pfout,conn->Pfdebug)==1) {
410561
(void)sprintf(conn->errorMessage,
411562
"PQexec() -- while sending query: %s\n"
412563
"-- fprintf to Pfout failed: errno=%d\n%s\n",
413-
query,errno,strerror(errno));
564+
query,errno,strerror(errno));
414565
returnNULL;
415566
}
416567

417-
/* loop forever because multiple messages, especially NOTICES,
418-
can come back from the backend
419-
NOTICES are output directly to stderr
420-
*/
421-
422-
while (1) {
568+
process_response_from_backend(conn->Pfin,conn->Pfout,conn->Pfdebug,conn,
569+
&result,conn->errorMessage);
570+
return(result);
571+
}
423572

424-
/* read the result id */
425-
id=pqGetc(pfin,pfdebug);
426-
if (id==EOF) {
427-
/* hmm, no response from the backend-end, that's bad */
428-
(void)sprintf(conn->errorMessage,
429-
"PQexec() -- Request was sent to backend, but backend "
430-
"closed the channel before "
431-
"responding. This probably means the backend "
432-
"terminated abnormally before or while processing "
433-
"the request.\n");
434-
conn->status=CONNECTION_BAD;/* No more connection to backend */
435-
return (PGresult*)NULL;
436-
}
437573

438-
switch (id) {
439-
case'A':
440-
newNotify= (PGnotify*)malloc(sizeof(PGnotify));
441-
pqGetInt(&(newNotify->be_pid),4,pfin,pfdebug);
442-
pqGets(newNotify->relname,NAMEDATALEN,pfin,pfdebug);
443-
DLAddTail(conn->notifyList,DLNewElem(newNotify));
444-
/* async messages are piggy'ed back on other messages,
445-
so we stay in the while loop for other messages */
446-
break;
447-
case'C':/* portal query command, no rows returned */
448-
if (pqGets(cmdStatus,MAX_MESSAGE_LEN,pfin,pfdebug)==1) {
449-
sprintf(conn->errorMessage,
450-
"PQexec() -- query command completed, "
451-
"but return message from backend cannot be read.");
452-
return (PGresult*)NULL;
453-
}
454-
else {
455-
/*
456-
// since backend may produce more than one result for some commands
457-
// need to poll until clear
458-
// send an empty query down, and keep reading out of the pipe
459-
// until an 'I' is received.
460-
*/
461-
pqPuts("Q",pfout,pfdebug);/* send an empty query */
462-
/*
463-
* Increment a flag and process messages in the usual way because
464-
* there may be async notifications pending. DZ - 31-8-1996
465-
*/
466-
emptiesPending++;
467-
emptySent= true;
468-
}
469-
break;
470-
case'E':/* error return */
471-
if (pqGets(conn->errorMessage,ERROR_MSG_LENGTH,pfin,pfdebug)==1) {
472-
(void)sprintf(conn->errorMessage,
473-
"PQexec() -- error return detected from backend, "
474-
"but attempt to read the error message failed.");
475-
}
476-
return (PGresult*)NULL;
477-
break;
478-
case'I':/* empty query */
479-
/* read the throw away the closing '\0' */
480-
{
481-
intc;
482-
if ((c=pqGetc(pfin,pfdebug))!='\0') {
483-
fprintf(stderr,"error!, unexpected character %c following 'I'\n",c);
484-
}
485-
if (emptiesPending) {
486-
if (--emptiesPending==0&&emptySent) {/* is this the last one? */
487-
/*
488-
* If this is the result of a portal query command set the
489-
* command status and message accordingly. DZ - 31-8-1996
490-
*/
491-
result=makeEmptyPGresult(conn,PGRES_COMMAND_OK);
492-
strncpy(result->cmdStatus,cmdStatus,CMDSTATUS_LEN-1);
493-
returnresult;
494-
}
495-
}
496-
else {
497-
result=makeEmptyPGresult(conn,PGRES_EMPTY_QUERY);
498-
returnresult;
499-
}
500-
}
501-
break;
502-
case'N':/* notices from the backend */
503-
if (pqGets(conn->errorMessage,ERROR_MSG_LENGTH,pfin,pfdebug)==1) {
504-
sprintf(conn->errorMessage,
505-
"PQexec() -- Notice detected from backend, "
506-
"but attempt to read the notice failed.");
507-
return (PGresult*)NULL;
508-
}
509-
else
510-
fprintf(stderr,"%s",conn->errorMessage);
511-
break;
512-
case'P':/* synchronous (normal) portal */
513-
pqGets(pname,MAX_MESSAGE_LEN,pfin,pfdebug);/* read in portal name*/
514-
break;
515-
case'T':/* actual row results: */
516-
returnmakePGresult(conn,pname);
517-
break;
518-
case'D':/* copy command began successfully */
519-
returnmakeEmptyPGresult(conn,PGRES_COPY_IN);
520-
break;
521-
case'B':/* copy command began successfully */
522-
returnmakeEmptyPGresult(conn,PGRES_COPY_OUT);
523-
break;
524-
default:
525-
sprintf(conn->errorMessage,
526-
"unknown protocol character %c read from backend\n",
527-
id);
528-
return (PGresult*)NULL;
529-
}/* switch */
530-
}/* while (1)*/
531-
}
532574

533575
/*
534576
* PQnotifies

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp