Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
8fb0ac88
Commit
8fb0ac88
authored
Dec 31, 1996
by
Bryan Henderson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make error messages more explicit, PQtrace() output more readable.
parent
e2da92f1
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
186 additions
and
138 deletions
+186
-138
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/fe-exec.c
+171
-129
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/fe-misc.c
+15
-9
No files found.
src/interfaces/libpq/fe-exec.c
View file @
8fb0ac88
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.2
5 1996/12/28 01:57:13 momjian
Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.2
6 1996/12/31 07:29:15 bryanh
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -348,93 +348,64 @@ makePGresult_badResponse_return:
...
@@ -348,93 +348,64 @@ makePGresult_badResponse_return:
}
}
/*
/*
*
PQexec
*
Assuming that we just sent a query to the backend, read the backend's
*
send a query to the backend and package up the result in a Pgresult
*
response from stream <pfin> and respond accordingly.
*
*
* if the query failed, return NULL, conn->errorMessage is set to
* If <pfdebug> is non-null, write to that stream whatever we receive
* a relevant message
* (it's a debugging trace).
* if query is successful, a new PGresult is returned
* the use is responsible for freeing that structure when done with it
*
*
* Return as <result> a pointer to a proper final PGresult structure,
* newly allocated, for the query based on the response we get. If the
* response we get indicates that the query didn't execute, return a
* null pointer and don't allocate any space, but also place a text
* string explaining the problem at <*reason>.
*/
*/
PGresult
*
static
void
PQexec
(
PGconn
*
conn
,
const
char
*
query
)
process_response_from_backend
(
FILE
*
pfin
,
FILE
*
pfout
,
FILE
*
pfdebug
,
{
PGconn
*
conn
,
PGresult
*
result
;
PGresult
**
result_p
,
char
*
const
reason
)
{
int
id
;
char
buffer
[
MAX_MESSAGE_LEN
];
char
id
;
/* The protocol character received from the backend. The protocol
character is the first character in the backend's response to our
query. It defines the nature of the response.
*/
PGnotify
*
newNotify
;
bool
done
;
/* We're all done with the query and ready to return the result. */
int
emptiesSent
;
/* Number of empty queries we have sent in order to flush out multiple
responses, less the number of corresponding responses we have
received.
*/
char
cmdStatus
[
MAX_MESSAGE_LEN
];
char
cmdStatus
[
MAX_MESSAGE_LEN
];
char
pname
[
MAX_MESSAGE_LEN
];
/* portal name */
char
pname
[
MAX_MESSAGE_LEN
];
/* portal name */
PGnotify
*
newNotify
;
FILE
*
pfin
,
*
pfout
,
*
pfdebug
;
static
int
emptiesPending
=
0
;
bool
emptySent
=
false
;
pname
[
0
]
=
'\0'
;
if
(
!
conn
)
return
NULL
;
if
(
!
query
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- query pointer is null."
);
return
NULL
;
}
pfin
=
conn
->
Pfin
;
/* loop because multiple messages, especially NOTICES,
pfout
=
conn
->
Pfout
;
can come back from the backend. NOTICES are output directly to stderr
pfdebug
=
conn
->
Pfdebug
;
/*clear the error string */
conn
->
errorMessage
[
0
]
=
'\0'
;
/* check to see if the query string is too long */
if
(
strlen
(
query
)
>
MAX_MESSAGE_LEN
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- query is too long. "
"Maximum length is %d
\n
"
,
MAX_MESSAGE_LEN
-
2
);
return
NULL
;
}
/* Don't try to send if we know there's no live connection. */
if
(
conn
->
status
!=
CONNECTION_OK
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- There is no connection "
"to the backend.
\n
"
);
return
NULL
;
}
/* the frontend-backend protocol uses 'Q' to designate queries */
sprintf
(
buffer
,
"Q%s"
,
query
);
/* send the query to the backend; */
if
(
pqPuts
(
buffer
,
pfout
,
pfdebug
)
==
1
)
{
(
void
)
sprintf
(
conn
->
errorMessage
,
"PQexec() -- while sending query: %s
\n
"
"-- fprintf to Pfout failed: errno=%d
\n
%s
\n
"
,
query
,
errno
,
strerror
(
errno
));
return
NULL
;
}
/* loop forever because multiple messages, especially NOTICES,
can come back from the backend
NOTICES are output directly to stderr
*/
*/
while
(
1
)
{
emptiesSent
=
0
;
/* No empty queries sent yet */
pname
[
0
]
=
'\0'
;
done
=
false
;
/* initial value */
while
(
!
done
)
{
/* read the result id */
/* read the result id */
id
=
pqGetc
(
pfin
,
pfdebug
);
id
=
pqGetc
(
pfin
,
pfdebug
);
if
(
id
==
EOF
)
{
if
(
id
==
EOF
)
{
/* hmm, no response from the backend-end, that's bad */
/* hmm, no response from the backend-end, that's bad */
(
void
)
sprintf
(
conn
->
errorMessage
,
(
void
)
sprintf
(
reason
,
"PQexec() -- Request was sent to backend, but backend "
"PQexec() -- Request was sent to backend, but backend "
"closed the channel before "
"closed the channel before "
"responding. This probably means the backend "
"responding. This probably means the backend "
"terminated abnormally before or while processing "
"terminated abnormally before or while processing "
"the request.
\n
"
);
"the request.
\n
"
);
conn
->
status
=
CONNECTION_BAD
;
/* No more connection to backend */
conn
->
status
=
CONNECTION_BAD
;
/* No more connection to backend */
return
(
PGresult
*
)
NULL
;
*
result_p
=
(
PGresult
*
)
NULL
;
}
done
=
true
;
}
else
{
switch
(
id
)
{
switch
(
id
)
{
case
'A'
:
case
'A'
:
newNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
));
newNotify
=
(
PGnotify
*
)
malloc
(
sizeof
(
PGnotify
));
...
@@ -446,90 +417,161 @@ PQexec(PGconn* conn, const char* query)
...
@@ -446,90 +417,161 @@ PQexec(PGconn* conn, const char* query)
break
;
break
;
case
'C'
:
/* portal query command, no rows returned */
case
'C'
:
/* portal query command, no rows returned */
if
(
pqGets
(
cmdStatus
,
MAX_MESSAGE_LEN
,
pfin
,
pfdebug
)
==
1
)
{
if
(
pqGets
(
cmdStatus
,
MAX_MESSAGE_LEN
,
pfin
,
pfdebug
)
==
1
)
{
sprintf
(
conn
->
errorMessage
,
sprintf
(
reason
,
"PQexec() -- query command completed, "
"PQexec() -- query command completed, "
"but return message from backend cannot be read."
);
"but return message from backend cannot be read."
);
return
(
PGresult
*
)
NULL
;
*
result_p
=
(
PGresult
*
)
NULL
;
}
done
=
true
;
else
{
}
else
{
/*
/*
// since backend may produce more than one result for some commands
// since backend may produce more than one result for some
//
need to poll until clear
// commands
need to poll until clear
// send an empty query down, and keep reading out of the pipe
// send an empty query down, and keep reading out of the pipe
// until an 'I' is received.
// until an 'I' is received.
*/
*/
pqPuts
(
"Q"
,
pfout
,
pfdebug
);
/* send an empty query */
pqPuts
(
"Q "
,
pfout
,
pfdebug
);
/* send an empty query */
/*
/*
* Increment a flag and process messages in the usual way because
* Increment a flag and process messages in the usual way because
* there may be async notifications pending. DZ - 31-8-1996
* there may be async notifications pending. DZ - 31-8-1996
*/
*/
emptiesPending
++
;
emptiesSent
++
;
emptySent
=
true
;
}
}
break
;
break
;
case
'E'
:
/* error return */
case
'E'
:
/* error return */
if
(
pqGets
(
conn
->
errorMessage
,
ERROR_MSG_LENGTH
,
pfin
,
pfdebug
)
==
1
)
{
if
(
pqGets
(
conn
->
errorMessage
,
ERROR_MSG_LENGTH
,
pfin
,
pfdebug
)
==
1
)
{
(
void
)
sprintf
(
conn
->
errorMessage
,
(
void
)
sprintf
(
reason
,
"PQexec() -- error return detected from backend, "
"PQexec() -- error return detected from backend, "
"but attempt to read the error message failed."
);
"but attempt to read the error message failed."
);
}
}
return
(
PGresult
*
)
NULL
;
*
result_p
=
(
PGresult
*
)
NULL
;
done
=
true
;
break
;
break
;
case
'I'
:
/* empty query */
case
'I'
:
{
/* empty query */
/* read the throw away the closing '\0' */
/* read and throw away the closing '\0' */
{
int
c
;
int
c
;
if
((
c
=
pqGetc
(
pfin
,
pfdebug
))
!=
'\0'
)
{
if
((
c
=
pqGetc
(
pfin
,
pfdebug
))
!=
'\0'
)
{
fprintf
(
stderr
,
"error!, unexpected character %c following 'I'
\n
"
,
c
);
fprintf
(
stderr
,
"error!, unexpected character %c following 'I'
\n
"
,
c
);
}
}
if
(
empties
Pending
)
{
if
(
empties
Sent
)
{
if
(
--
emptiesPending
==
0
&&
emptySent
)
{
/* is this the last one? */
if
(
--
emptiesSent
==
0
)
{
/* is this the last one? */
/*
/*
* If this is the result of a portal query command set the
* If this is the result of a portal query command set the
* command status and message accordingly. DZ - 31-8-1996
* command status and message accordingly. DZ - 31-8-1996
*/
*/
result
=
makeEmptyPGresult
(
conn
,
PGRES_COMMAND_OK
);
*
result_p
=
makeEmptyPGresult
(
conn
,
PGRES_COMMAND_OK
);
strncpy
(
result
->
cmdStatus
,
cmdStatus
,
CMDSTATUS_LEN
-
1
);
strncpy
((
*
result_p
)
->
cmdStatus
,
cmdStatus
,
CMDSTATUS_LEN
-
1
);
return
result
;
done
=
true
;
}
}
}
}
else
{
else
{
result
=
makeEmptyPGresult
(
conn
,
PGRES_EMPTY_QUERY
);
*
result_p
=
makeEmptyPGresult
(
conn
,
PGRES_EMPTY_QUERY
);
return
result
;
done
=
true
;
}
}
}
}
break
;
break
;
case
'N'
:
/* notices from the backend */
case
'N'
:
/* notices from the backend */
if
(
pqGets
(
conn
->
errorMessage
,
ERROR_MSG_LENGTH
,
pfin
,
pfdebug
)
==
1
)
{
if
(
pqGets
(
reason
,
ERROR_MSG_LENGTH
,
pfin
,
pfdebug
)
==
1
)
{
sprintf
(
conn
->
errorMessage
,
sprintf
(
reason
,
"PQexec() -- Notice detected from backend, "
"PQexec() -- Notice detected from backend, "
"but attempt to read the notice failed."
);
"but attempt to read the notice failed."
);
return
(
PGresult
*
)
NULL
;
*
result_p
=
(
PGresult
*
)
NULL
;
}
done
=
true
;
else
}
else
fprintf
(
stderr
,
"%s"
,
conn
->
errorMessage
);
/* Should we really be doing this? These notices are not important
enough for us to presume to put them on stderr. Maybe the caller
should decide whether to put them on stderr or not. BJH 96.12.27
*/
fprintf
(
stderr
,
"%s"
,
reason
);
break
;
break
;
case
'P'
:
/* synchronous (normal) portal */
case
'P'
:
/* synchronous (normal) portal */
pqGets
(
pname
,
MAX_MESSAGE_LEN
,
pfin
,
pfdebug
);
/* read in portal name*/
pqGets
(
pname
,
MAX_MESSAGE_LEN
,
pfin
,
pfdebug
);
/* read in portal name*/
break
;
break
;
case
'T'
:
/* actual row results: */
case
'T'
:
/* actual row results: */
return
makePGresult
(
conn
,
pname
);
*
result_p
=
makePGresult
(
conn
,
pname
);
done
=
true
;
break
;
break
;
case
'D'
:
/* copy command began successfully */
case
'D'
:
/* copy command began successfully */
return
makeEmptyPGresult
(
conn
,
PGRES_COPY_IN
);
*
result_p
=
makeEmptyPGresult
(
conn
,
PGRES_COPY_IN
);
done
=
true
;
break
;
break
;
case
'B'
:
/* copy command began successfully */
case
'B'
:
/* copy command began successfully */
return
makeEmptyPGresult
(
conn
,
PGRES_COPY_OUT
);
*
result_p
=
makeEmptyPGresult
(
conn
,
PGRES_COPY_OUT
);
done
=
true
;
break
;
break
;
default:
default:
sprintf
(
conn
->
errorMessage
,
sprintf
(
reason
,
"unknown protocol character %c read from backend
\n
"
,
"unknown protocol character '%c' read from backend. "
"(The protocol character is the first character the "
"backend sends in response to a query it receives).
\n
"
,
id
);
id
);
return
(
PGresult
*
)
NULL
;
*
result_p
=
(
PGresult
*
)
NULL
;
}
/* switch */
done
=
true
;
}
/* while (1)*/
}
/* switch on protocol character */
}
/* if character was received */
}
/* while not done */
}
}
/*
* PQexec
* send a query to the backend and package up the result in a Pgresult
*
* if the query failed, return NULL, conn->errorMessage is set to
* a relevant message
* if query is successful, a new PGresult is returned
* the use is responsible for freeing that structure when done with it
*
*/
PGresult
*
PQexec
(
PGconn
*
conn
,
const
char
*
query
)
{
PGresult
*
result
;
char
buffer
[
MAX_MESSAGE_LEN
];
if
(
!
conn
)
return
NULL
;
if
(
!
query
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- query pointer is null."
);
return
NULL
;
}
/*clear the error string */
conn
->
errorMessage
[
0
]
=
'\0'
;
/* check to see if the query string is too long */
if
(
strlen
(
query
)
>
MAX_MESSAGE_LEN
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- query is too long. "
"Maximum length is %d
\n
"
,
MAX_MESSAGE_LEN
-
2
);
return
NULL
;
}
/* Don't try to send if we know there's no live connection. */
if
(
conn
->
status
!=
CONNECTION_OK
)
{
sprintf
(
conn
->
errorMessage
,
"PQexec() -- There is no connection "
"to the backend.
\n
"
);
return
NULL
;
}
/* the frontend-backend protocol uses 'Q' to designate queries */
sprintf
(
buffer
,
"Q%s"
,
query
);
/* send the query to the backend; */
if
(
pqPuts
(
buffer
,
conn
->
Pfout
,
conn
->
Pfdebug
)
==
1
)
{
(
void
)
sprintf
(
conn
->
errorMessage
,
"PQexec() -- while sending query: %s
\n
"
"-- fprintf to Pfout failed: errno=%d
\n
%s
\n
"
,
query
,
errno
,
strerror
(
errno
));
return
NULL
;
}
process_response_from_backend
(
conn
->
Pfin
,
conn
->
Pfout
,
conn
->
Pfdebug
,
conn
,
&
result
,
conn
->
errorMessage
);
return
(
result
);
}
/*
/*
* PQnotifies
* PQnotifies
* returns a PGnotify* structure of the latest async notification
* returns a PGnotify* structure of the latest async notification
...
...
src/interfaces/libpq/fe-misc.c
View file @
8fb0ac88
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.
3 1996/11/03 07:14:32 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.
4 1996/12/31 07:29:17 bryanh
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -35,7 +35,7 @@ pqGetc(FILE* fin, FILE* debug)
...
@@ -35,7 +35,7 @@ pqGetc(FILE* fin, FILE* debug)
c
=
getc
(
fin
);
c
=
getc
(
fin
);
if
(
debug
&&
c
!=
EOF
)
if
(
debug
&&
c
!=
EOF
)
putc
(
c
,
debug
);
fprintf
(
debug
,
"From backend> %c
\n
"
,
c
);
return
c
;
return
c
;
}
}
...
@@ -52,6 +52,7 @@ pqPutnchar(const char* s, int len, FILE *f, FILE *debug)
...
@@ -52,6 +52,7 @@ pqPutnchar(const char* s, int len, FILE *f, FILE *debug)
if
(
f
==
NULL
)
if
(
f
==
NULL
)
return
1
;
return
1
;
if
(
debug
)
fputs
(
"To backend>"
,
debug
);
while
(
len
--
)
{
while
(
len
--
)
{
status
=
fputc
(
*
s
,
f
);
status
=
fputc
(
*
s
,
f
);
if
(
debug
)
if
(
debug
)
...
@@ -60,6 +61,7 @@ pqPutnchar(const char* s, int len, FILE *f, FILE *debug)
...
@@ -60,6 +61,7 @@ pqPutnchar(const char* s, int len, FILE *f, FILE *debug)
if
(
status
==
EOF
)
if
(
status
==
EOF
)
return
1
;
return
1
;
}
}
if
(
debug
)
fputc
(
'\n'
,
debug
);
return
0
;
return
0
;
}
}
...
@@ -79,7 +81,7 @@ pqGetnchar(char* s, int len, FILE *f, FILE *debug)
...
@@ -79,7 +81,7 @@ pqGetnchar(char* s, int len, FILE *f, FILE *debug)
*
s
=
'\0'
;
*
s
=
'\0'
;
if
(
debug
)
{
if
(
debug
)
{
fp
uts
(
s
,
debug
);
fp
rintf
(
debug
,
"From backend> %s
\n
"
,
s
);
}
}
return
0
;
return
0
;
}
}
...
@@ -100,7 +102,7 @@ pqGets(char* s, int len, FILE *f, FILE *debug)
...
@@ -100,7 +102,7 @@ pqGets(char* s, int len, FILE *f, FILE *debug)
*
s
=
'\0'
;
*
s
=
'\0'
;
if
(
debug
)
{
if
(
debug
)
{
fp
uts
(
s
,
debug
);
fp
rintf
(
debug
,
"From backend> %s
\n
"
,
s
);
}
}
return
0
;
return
0
;
}
}
...
@@ -114,22 +116,24 @@ pqGets(char* s, int len, FILE *f, FILE *debug)
...
@@ -114,22 +116,24 @@ pqGets(char* s, int len, FILE *f, FILE *debug)
returns 0 if successful, 1 otherwise
returns 0 if successful, 1 otherwise
*/
*/
int
int
pqPutInt
(
int
i
,
int
bytes
,
FILE
*
f
,
FILE
*
debug
)
pqPutInt
(
const
int
integer
,
int
bytes
,
FILE
*
f
,
FILE
*
debug
)
{
{
int
i
;
int
status
;
int
status
;
i
=
integer
;
if
(
bytes
>
4
)
if
(
bytes
>
4
)
bytes
=
4
;
bytes
=
4
;
while
(
bytes
--
)
{
while
(
bytes
--
)
{
status
=
fputc
(
i
&
0xff
,
f
);
status
=
fputc
(
i
&
0xff
,
f
);
if
(
debug
)
fputc
(
i
&
0xff
,
debug
);
i
>>=
8
;
i
>>=
8
;
if
(
status
==
EOF
)
{
if
(
status
==
EOF
)
{
return
1
;
return
1
;
}
}
}
}
if
(
debug
)
fprintf
(
debug
,
"To backend (#)> %d
\n
"
,
integer
);
return
0
;
return
0
;
}
}
...
@@ -163,7 +167,7 @@ pqGetInt(int* result, int bytes, FILE* f, FILE *debug)
...
@@ -163,7 +167,7 @@ pqGetInt(int* result, int bytes, FILE* f, FILE *debug)
*
result
=
n
;
*
result
=
n
;
if
(
debug
)
if
(
debug
)
fprintf
(
debug
,
"
%d
"
,
*
result
);
fprintf
(
debug
,
"
From backend (#)> %d
\n
"
,
*
result
);
return
0
;
return
0
;
}
}
...
@@ -181,7 +185,7 @@ pqPuts(const char* s, FILE *f, FILE *debug)
...
@@ -181,7 +185,7 @@ pqPuts(const char* s, FILE *f, FILE *debug)
fflush
(
f
);
fflush
(
f
);
if
(
debug
)
{
if
(
debug
)
{
fp
uts
(
s
,
debug
);
fp
rintf
(
debug
,
"To backend> %s
\n
"
,
s
);
}
}
return
0
;
return
0
;
}
}
...
@@ -195,3 +199,5 @@ pqFlush(FILE *f, FILE *debug)
...
@@ -195,3 +199,5 @@ pqFlush(FILE *f, FILE *debug)
if
(
debug
)
if
(
debug
)
fflush
(
debug
);
fflush
(
debug
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment