diff options
author | Bruce Momjian | 1998-09-03 02:10:56 +0000 |
---|---|---|
committer | Bruce Momjian | 1998-09-03 02:10:56 +0000 |
commit | f71d0cf64ebd53fc277adddfd81c9913badb92ba (patch) | |
tree | dfb56c71e84e52703f11c5c233461369baad2d0d /src/interfaces/libpgtcl | |
parent | bcc15f15e10630b2624a1610d61bedb88e4c4901 (diff) |
Attached is a patch to remove the definitions of libpq's internal
structs from libpq-fe.h, as we previously discussed.
There turned out to be sloppy coding practices in more places than
I had realized :-(, but all in all I think it was a well-worth-while
exercise.
I ended up adding several routines to libpq's API in order to respond
to application requirements that were exposed by this work. I owe the
docs crew updates for libpq.sgml to describe these changes. I'm way too
tired to work on the docs tonight, however.
This is the last major change I intend to submit for 6.4. I do want
to see if I can make libpgtcl work with Tcl 8.0 before we go final,
but hopefully that will be a minor bug fix.
Diffstat (limited to 'src/interfaces/libpgtcl')
-rw-r--r-- | src/interfaces/libpgtcl/pgtclCmds.c | 60 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtclId.c | 104 |
2 files changed, 65 insertions, 99 deletions
diff --git a/src/interfaces/libpgtcl/pgtclCmds.c b/src/interfaces/libpgtcl/pgtclCmds.c index bd6641554d2..a8d828c0167 100644 --- a/src/interfaces/libpgtcl/pgtclCmds.c +++ b/src/interfaces/libpgtcl/pgtclCmds.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.31 1998/09/01 04:39:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.32 1998/09/03 02:10:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -358,15 +358,15 @@ Pg_connect(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); } - if (conn->status == CONNECTION_OK) + if (PQstatus(conn) == CONNECTION_OK) { { PgSetConnectionId(interp, conn); return TCL_OK; } else { - Tcl_AppendResult(interp, "Connection to database failed\n", 0); - Tcl_AppendResult(interp, conn->errorMessage, 0); + Tcl_AppendResult(interp, "Connection to database failed\n", + PQerrorMessage(conn), 0); PQfinish(conn); return TCL_ERROR; } @@ -423,7 +423,6 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) Pg_ConnectionId *connid; PGconn *conn; PGresult *result; - int connStatus; if (argc != 3) { @@ -442,7 +441,6 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) return TCL_ERROR; } - connStatus = conn->status; result = PQexec(conn, argv[2]); /* Transfer any notify events from libpq to Tcl event queue. */ @@ -452,8 +450,8 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { int rId = PgSetResultId(interp, argv[1], result); - if (result->resultStatus == PGRES_COPY_IN || - result->resultStatus == PGRES_COPY_OUT) + ExecStatusType rStat = PQresultStatus(result); + if (rStat == PGRES_COPY_IN || rStat == PGRES_COPY_OUT) { connid->res_copyStatus = RES_COPY_INPROGRESS; connid->res_copy = rId; @@ -463,7 +461,7 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) else { /* error occurred during the query */ - Tcl_SetResult(interp, conn->errorMessage, TCL_VOLATILE); + Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE); return TCL_ERROR; } } @@ -481,9 +479,12 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) -conn the connection that produced the result -assign arrayName - assign the results to an array - -assignbyidx arrayName - assign the results to an array using the first field as a key + assign the results to an array, using subscripts of the form + (tupno,attributeName) + -assignbyidx arrayName ?appendstr? + assign the results to an array using the first field's value as a key. + All but the first field of each tuple are stored, using subscripts of the form + (field0value,attributeNameappendstr) -numTuples the number of tuples in the query -attributes @@ -509,6 +510,7 @@ Pg_result(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) int tupno; char *arrVar; char nameBuffer[256]; + const char *appendstr; if (argc < 3 || argc > 5) { @@ -564,8 +566,9 @@ Pg_result(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) /* * 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). Note we expect field names not to + * array with the name given in the argument. + * The indices of the array are of the form (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. */ @@ -589,28 +592,32 @@ Pg_result(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) } else if (strcmp(opt, "-assignbyidx") == 0) { - if (argc != 4) + if (argc != 4 && argc != 5) { - Tcl_AppendResult(interp, "-assignbyidx option must be followed by a variable name", 0); + Tcl_AppendResult(interp, "-assignbyidx option requires an array name and optionally an append string",0); return TCL_ERROR; } arrVar = argv[3]; + appendstr = (argc == 5) ? (const char *) argv[4] : ""; /* * 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). Here, we still assume PQfname won't - * exceed 200 characters, but we dare not make the same assumption - * about the data in field 0. + * array with the name given in the argument. The indices of the array + * are of the form (field0Value,attrNameappendstr). + * Here, we still assume PQfname won't exceed 200 characters, + * but we dare not make the same assumption about the data in field 0 + * nor the append string. */ for (tupno = 0; tupno < PQntuples(result); tupno++) { const char *field0 = PQgetvalue(result, tupno, 0); - char *workspace = malloc(strlen(field0) + 210); + char * workspace = malloc(strlen(field0) + strlen(appendstr) + 210); for (i = 1; i < PQnfields(result); i++) { - sprintf(workspace, "%s,%.200s", field0, PQfname(result, i)); + sprintf(workspace, "%s,%.200s%s", field0, PQfname(result,i), + appendstr); + sprintf(workspace, "%s,%.200s", field0, PQfname(result,i)); if (Tcl_SetVar2(interp, arrVar, workspace, PQgetvalue(result, tupno, i), TCL_LEAVE_ERR_MSG) == NULL) @@ -701,7 +708,7 @@ Pg_result_errReturn: "\t-status\n", "\t-conn\n", "\t-assign arrayVarName\n", - "\t-assignbyidx arrayVarName\n", + "\t-assignbyidx arrayVarName ?appendstr?\n", "\t-numTuples\n", "\t-numAttrs\n" "\t-attributes\n" @@ -1238,7 +1245,7 @@ Pg_select(ClientData cData, Tcl_Interp * interp, int argc, char **argv) if ((result = PQexec(conn, argv[2])) == 0) { /* error occurred during the query */ - Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); + Tcl_SetResult(interp, PQerrorMessage(conn), TCL_STATIC); return TCL_ERROR; } @@ -1406,11 +1413,10 @@ Pg_listen(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) ckfree(cmd); /* Transfer any notify events from libpq to Tcl event queue. */ PgNotifyTransferEvents(connid); - if (!result || (result->resultStatus != PGRES_COMMAND_OK)) + if (PQresultStatus(result) != PGRES_COMMAND_OK) { { /* Error occurred during the execution of command */ - if (result) - PQclear(result); + PQclear(result); ckfree(callback); ckfree(caserelname); Tcl_DeleteHashEntry(entry); diff --git a/src/interfaces/libpgtcl/pgtclId.c b/src/interfaces/libpgtcl/pgtclId.c index 9377e322e7e..8853c1fdbea 100644 --- a/src/interfaces/libpgtcl/pgtclId.c +++ b/src/interfaces/libpgtcl/pgtclId.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.14 1998/09/01 04:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.15 1998/09/03 02:10:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -33,98 +33,62 @@ PgEndCopy(Pg_ConnectionId * connid, int *errorCodePtr) connid->res_copyStatus = RES_COPY_NONE; if (PQendcopy(connid->conn)) { - connid->results[connid->res_copy]->resultStatus = PGRES_BAD_RESPONSE; + PQclear(connid->results[connid->res_copy]); + connid->results[connid->res_copy] = + PQmakeEmptyPGresult(connid->conn, PGRES_BAD_RESPONSE); connid->res_copy = -1; *errorCodePtr = EIO; return -1; } else { - connid->results[connid->res_copy]->resultStatus = PGRES_COMMAND_OK; + PQclear(connid->results[connid->res_copy]); + connid->results[connid->res_copy] = + PQmakeEmptyPGresult(connid->conn, PGRES_COMMAND_OK); connid->res_copy = -1; return 0; } } /* - * 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. + * Called when reading data (via gets) for a copy <rel> to stdout. */ -int -PgInputProc(DRIVER_INPUT_PROTO) +int PgInputProc(DRIVER_INPUT_PROTO) { - Pg_ConnectionId *connid; - PGconn *conn; - char c; - int avail; + Pg_ConnectionId *connid; + PGconn *conn; + int avail; - connid = (Pg_ConnectionId *) cData; - conn = connid->conn; + connid = (Pg_ConnectionId *)cData; + conn = connid->conn; - if (connid->res_copy < 0 || - connid->results[connid->res_copy]->resultStatus != PGRES_COPY_OUT) + if (connid->res_copy < 0 || + PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_OUT) { *errorCodePtr = EBUSY; return -1; - } + } - /* Try to load any newly arrived data */ - conn->errorMessage[0] = '\0'; - PQconsumeInput(conn); - if (conn->errorMessage[0]) + /* Read any newly arrived data into libpq's buffer, + * thereby clearing the socket's read-ready condition. + */ + if (! PQconsumeInput(conn)) { *errorCodePtr = EIO; return -1; - } + } - /* - * Move data from libpq's buffer to Tcl's. We want to accept data only - * in units of whole lines, not partial lines. This ensures that we - * can recognize the terminator line "\\.\n". (Otherwise, if it - * happened to cross a packet/buffer boundary, we might hand the first - * one or two characters off to Tcl, which we shouldn't.) - */ + /* Move data from libpq's buffer to Tcl's. */ - conn->inCursor = conn->inStart; + avail = PQgetlineAsync(conn, buf, bufSize); - avail = bufSize; - while (avail > 0 && conn->inCursor < conn->inEnd) + if (avail < 0) { - c = conn->inBuffer[conn->inCursor++]; - *buf++ = c; - --avail; - if (c == '\n') - { - /* Got a complete line; mark the data removed from libpq */ - conn->inStart = conn->inCursor; - /* Is it the endmarker line? */ - if (bufSize - avail == 3 && buf[-3] == '\\' && buf[-2] == '.') - { - /* Yes, change state and return 0 */ - return PgEndCopy(connid, errorCodePtr); - } - /* No, return the data to Tcl */ - /* fprintf(stderr, "returning %d chars\n", bufSize - avail); */ - return bufSize - avail; - } - } + /* Endmarker detected, change state and return 0 */ + return PgEndCopy(connid, errorCodePtr); + } - /* - * We don't have a complete line. We'd prefer to leave it in libpq's - * buffer until the rest arrives, but there is a special case: what if - * the line is longer than the buffer Tcl is offering us? In that - * case we'd better hand over a partial line, else we'd get into an - * infinite loop. Do this in a way that ensures we can't misrecognize - * a terminator line later: leave last 3 characters in libpq buffer. - */ - if (avail == 0 && bufSize > 3) - { - conn->inStart = conn->inCursor - 3; - return bufSize - 3; - } - return 0; + return avail; } /* @@ -140,17 +104,13 @@ PgOutputProc(DRIVER_OUTPUT_PROTO) conn = connid->conn; if (connid->res_copy < 0 || - connid->results[connid->res_copy]->resultStatus != PGRES_COPY_IN) + PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_IN) { *errorCodePtr = EBUSY; return -1; } - conn->errorMessage[0] = '\0'; - - PQputnbytes(conn, buf, bufSize); - - if (conn->errorMessage[0]) + if (PQputnbytes(conn, buf, bufSize)) { *errorCodePtr = EIO; return -1; @@ -398,7 +358,7 @@ getresid(Tcl_Interp * interp, char *id, Pg_ConnectionId ** connid_p) connid = (Pg_ConnectionId *) Tcl_GetChannelInstanceData(conn_chan); - if (resid < 0 || resid > connid->res_max || connid->results[resid] == NULL) + if (resid < 0 || resid >= connid->res_max || connid->results[resid] == NULL) { Tcl_SetResult(interp, "Invalid result handle", TCL_STATIC); return -1; |