mirror of
https://github.com/postgres/postgres.git
synced 2025-10-31 10:30:33 +03:00
Date: Sun, 16 Aug 1998 14:56:48 -0400
From: Tom Lane <tgl@sss.pgh.pa.us> Attached is a patch for this weekend's work on libpq. I've dealt with several issues: <for details: see message, in pgsql-patches archive for above data>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.28 1998/07/09 03:32:09 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.29 1998/08/17 03:50:22 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -485,9 +485,8 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
char *opt;
|
||||
int i;
|
||||
int tupno;
|
||||
char prearrayInd[MAX_MESSAGE_LEN];
|
||||
char arrayInd[MAX_MESSAGE_LEN];
|
||||
char *arrVar;
|
||||
char nameBuffer[256];
|
||||
|
||||
if (argc < 3 || argc > 5) {
|
||||
Tcl_AppendResult(interp, "Wrong # of arguments\n",0);
|
||||
@@ -522,6 +521,10 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
sprintf(interp->result, "%d", PQntuples(result));
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-numAttrs") == 0) {
|
||||
sprintf(interp->result, "%d", PQnfields(result));
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-assign") == 0) {
|
||||
if (argc != 4) {
|
||||
Tcl_AppendResult(interp, "-assign option must be followed by a variable name",0);
|
||||
@@ -530,17 +533,21 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
arrVar = argv[3];
|
||||
/* this assignment assigns the table of result tuples into a giant
|
||||
array with the name given in the argument,
|
||||
the indices of the array or (tupno,attrName)*/
|
||||
the indices of the array or (tupno,attrName).
|
||||
Note we expect field names not to exceed a few dozen characters,
|
||||
so truncating to prevent buffer overflow shouldn't be a problem.
|
||||
*/
|
||||
for (tupno = 0; tupno<PQntuples(result); tupno++) {
|
||||
for (i=0;i<PQnfields(result);i++) {
|
||||
sprintf(arrayInd, "%d,%s", tupno, PQfname(result,i));
|
||||
Tcl_SetVar2(interp, arrVar, arrayInd,
|
||||
sprintf(nameBuffer, "%d,%.200s", tupno, PQfname(result,i));
|
||||
if (Tcl_SetVar2(interp, arrVar, nameBuffer,
|
||||
#ifdef TCL_ARRAYS
|
||||
tcl_value(PQgetvalue(result,tupno,i)),
|
||||
tcl_value(PQgetvalue(result,tupno,i)),
|
||||
#else
|
||||
PQgetvalue(result,tupno,i),
|
||||
PQgetvalue(result,tupno,i),
|
||||
#endif
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
TCL_LEAVE_ERR_MSG) == NULL)
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_AppendResult(interp, arrVar, 0);
|
||||
@@ -554,15 +561,23 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
arrVar = argv[3];
|
||||
/* this assignment assigns the table of result tuples into a giant
|
||||
array with the name given in the argument,
|
||||
the indices of the array or (tupno,attrName)*/
|
||||
the indices of the array or (tupno,attrName).
|
||||
Here, we still assume PQfname won't exceed 200 characters,
|
||||
but we dare not make the same assumption about the data in field 0.
|
||||
*/
|
||||
for (tupno = 0; tupno<PQntuples(result); tupno++) {
|
||||
sprintf(prearrayInd,"%s",PQgetvalue(result,tupno,0));
|
||||
const char *field0 = PQgetvalue(result,tupno,0);
|
||||
char * workspace = malloc(strlen(field0) + 210);
|
||||
for (i=1;i<PQnfields(result);i++) {
|
||||
sprintf(arrayInd, "%s,%s", prearrayInd, PQfname(result,i));
|
||||
Tcl_SetVar2(interp, arrVar, arrayInd,
|
||||
PQgetvalue(result,tupno,i),
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
sprintf(workspace, "%s,%.200s", field0, PQfname(result,i));
|
||||
if (Tcl_SetVar2(interp, arrVar, workspace,
|
||||
PQgetvalue(result,tupno,i),
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
free(workspace);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
free(workspace);
|
||||
}
|
||||
Tcl_AppendResult(interp, arrVar, 0);
|
||||
return TCL_OK;
|
||||
@@ -573,25 +588,13 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tupno = atoi(argv[3]);
|
||||
|
||||
if (tupno >= PQntuples(result)) {
|
||||
if (tupno < 0 || tupno >= PQntuples(result)) {
|
||||
Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1",0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
#ifdef TCL_ARRAYS
|
||||
for (i=0; i<PQnfields(result); i++) {
|
||||
Tcl_AppendElement(interp, tcl_value(PQgetvalue(result,tupno,i)));
|
||||
Tcl_AppendElement(interp, PQgetvalue(result,tupno,i));
|
||||
}
|
||||
#else
|
||||
/* Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */
|
||||
Tcl_AppendElement(interp, PQgetvalue(result,tupno,0));
|
||||
for (i=1;i<PQnfields(result);i++) {
|
||||
/* Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/
|
||||
Tcl_AppendElement(interp, PQgetvalue(result,tupno,i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-tupleArray") == 0) {
|
||||
@@ -600,41 +603,42 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
return TCL_ERROR;
|
||||
}
|
||||
tupno = atoi(argv[3]);
|
||||
|
||||
if (tupno >= PQntuples(result)) {
|
||||
if (tupno < 0 || tupno >= PQntuples(result)) {
|
||||
Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1",0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
for ( i = 0; i < PQnfields(result); i++) {
|
||||
if (Tcl_SetVar2(interp, argv[4], PQfname(result, i), PQgetvalue(result, tupno, i), TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
|
||||
PQgetvalue(result, tupno, i),
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-attributes") == 0) {
|
||||
Tcl_AppendResult(interp, PQfname(result,0),NULL);
|
||||
for (i=1;i<PQnfields(result);i++) {
|
||||
Tcl_AppendResult(interp, " ", PQfname(result,i), NULL);
|
||||
for (i=0;i<PQnfields(result);i++) {
|
||||
Tcl_AppendElement(interp, PQfname(result,i));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-lAttributes") == 0) {
|
||||
char buf[512];
|
||||
Tcl_ResetResult(interp);
|
||||
for (i = 0; i < PQnfields(result); i++) {
|
||||
sprintf(buf, "{%s} %ld %d", PQfname(result, i),
|
||||
(long) PQftype(result, i),
|
||||
PQfsize(result, i));
|
||||
Tcl_AppendElement(interp, buf);
|
||||
/* start a sublist */
|
||||
if (i > 0)
|
||||
Tcl_AppendResult(interp, " {", 0);
|
||||
else
|
||||
Tcl_AppendResult(interp, "{", 0);
|
||||
Tcl_AppendElement(interp, PQfname(result, i));
|
||||
sprintf(nameBuffer, "%ld", (long) PQftype(result, i));
|
||||
Tcl_AppendElement(interp, nameBuffer);
|
||||
sprintf(nameBuffer, "%ld", (long) PQfsize(result, i));
|
||||
Tcl_AppendElement(interp, nameBuffer);
|
||||
/* end the sublist */
|
||||
Tcl_AppendResult(interp, "}", 0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if (strcmp(opt, "-numAttrs") == 0) {
|
||||
sprintf(interp->result, "%d", PQnfields(result));
|
||||
return TCL_OK;
|
||||
}
|
||||
else {
|
||||
Tcl_AppendResult(interp, "Invalid option",0);
|
||||
goto Pg_result_errReturn;
|
||||
@@ -649,9 +653,9 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
||||
"\t-assign arrayVarName\n",
|
||||
"\t-assignbyidx arrayVarName\n",
|
||||
"\t-numTuples\n",
|
||||
"\t-numAttrs\n"
|
||||
"\t-attributes\n"
|
||||
"\t-lAttributes\n"
|
||||
"\t-numAttrs\n"
|
||||
"\t-getTuple tupleNumber\n",
|
||||
"\t-tupleArray tupleNumber arrayVarName\n",
|
||||
"\t-clear\n",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.11 1998/06/16 04:10:17 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.12 1998/08/17 03:50:26 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -43,7 +43,10 @@ static int PgEndCopy(Pg_ConnectionId *connid, int *errorCodePtr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when reading data (via gets) for a copy <rel> to stdout
|
||||
* Called when reading data (via gets) for a copy <rel> to stdout.
|
||||
*
|
||||
* NOTE: this routine knows way more than it ought to about libpq's
|
||||
* internal buffering mechanisms.
|
||||
*/
|
||||
int PgInputProc(DRIVER_INPUT_PROTO)
|
||||
{
|
||||
@@ -62,10 +65,10 @@ int PgInputProc(DRIVER_INPUT_PROTO)
|
||||
}
|
||||
|
||||
/* Try to load any newly arrived data */
|
||||
errno = 0;
|
||||
|
||||
if (pqReadData(conn) < 0) {
|
||||
*errorCodePtr = errno ? errno : EIO;
|
||||
conn->errorMessage[0] = '\0';
|
||||
PQconsumeInput(conn);
|
||||
if (conn->errorMessage[0]) {
|
||||
*errorCodePtr = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -80,8 +83,8 @@ int PgInputProc(DRIVER_INPUT_PROTO)
|
||||
conn->inCursor = conn->inStart;
|
||||
|
||||
avail = bufSize;
|
||||
while (avail > 0 &&
|
||||
pqGetc(&c, conn) == 0) {
|
||||
while (avail > 0 && conn->inCursor < conn->inEnd) {
|
||||
c = conn->inBuffer[conn->inCursor++];
|
||||
*buf++ = c;
|
||||
--avail;
|
||||
if (c == '\n') {
|
||||
@@ -130,10 +133,12 @@ int PgOutputProc(DRIVER_OUTPUT_PROTO)
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
conn->errorMessage[0] = '\0';
|
||||
|
||||
if (pqPutnchar(buf, bufSize, conn)) {
|
||||
*errorCodePtr = errno ? errno : EIO;
|
||||
PQputnbytes(conn, buf, bufSize);
|
||||
|
||||
if (conn->errorMessage[0]) {
|
||||
*errorCodePtr = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -141,7 +146,6 @@ int PgOutputProc(DRIVER_OUTPUT_PROTO)
|
||||
* in a single operation; maybe not such a good assumption?
|
||||
*/
|
||||
if (bufSize >= 3 && strncmp(&buf[bufSize-3], "\\.\n", 3) == 0) {
|
||||
(void) pqFlush(conn);
|
||||
if (PgEndCopy(connid, errorCodePtr) == -1)
|
||||
return -1;
|
||||
}
|
||||
@@ -423,7 +427,7 @@ PgGetConnByResultId(Tcl_Interp *interp, char *resid_c)
|
||||
*mark = '\0';
|
||||
conn_chan = Tcl_GetChannel(interp, resid_c, 0);
|
||||
*mark = '.';
|
||||
if(conn_chan && Tcl_GetChannelType(conn_chan) != &Pg_ConnType) {
|
||||
if(conn_chan && Tcl_GetChannelType(conn_chan) == &Pg_ConnType) {
|
||||
Tcl_SetResult(interp, Tcl_GetChannelName(conn_chan), TCL_VOLATILE);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user