Index: mod_nsd/postgres.c =================================================================== RCS file: /usr/local/cvsroot/mod_nsd/postgres.c,v diff -u -r1.2 -r1.3 --- mod_nsd/postgres.c 14 Apr 2001 07:17:26 -0000 1.2 +++ mod_nsd/postgres.c 16 Apr 2001 14:40:26 -0000 1.3 @@ -136,6 +136,17 @@ /* 2000-12-30: Added bind variable emulation to support acs 4.0 porting. dcwickstrom@earthlink.net*/ +/* 2001-03-??: Added automatic quoting of emulated bind variables in order + to make it compatible with the analogous routine in the Oracle driver. + dhogaza@pacifier.com*/ + +/* 2001-04-14: Added Henry Minsky's patch which echoes changes in the + Oracle driver to stream blob data directly to the connection + rather than first spool to a temp file. Since the call to return + the file to the user doesn't return until after the operation is + complete, spooling was a waste of time and resource. + dhogaza@pacifier.com*/ + /* Contributors to this file include: Don Baccus @@ -1077,121 +1088,38 @@ } +/** + * Write the contents of BUFP to a file descriptor or to + * the network connection directly. + * + * Lifted from Oracle driver. + */ static int -blob_write(Tcl_Interp *interp, Ns_DbHandle *handle, char* lob_id) +stream_actually_write (int fd, Ns_Conn *conn, void *bufp, int length, int to_conn_p) { - NsPgConn *nsConn = (NsPgConn *) handle->connection; - char *filename; - int result; - Ns_Conn *conn; - int segment; - char query[100]; - int fd; - char *segment_pos; - int nbytes = 0; + int bytes_written = 0; - /* spool to a tmp file, then return that out the conn - * note that tmpnam returns malloc'd memory. - */ - - filename = tempnam (NULL, "tadgp"); - - if (filename == NULL) - { - Tcl_AppendResult (interp, "could not create temporary file to spool " - "BLOB/CLOB result", NULL); - return TCL_ERROR; - } - - - fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); - - if (fd < 0) - { - Ns_Log (Error, "Can't open %s for writing. error %d(%s)", - filename, errno, strerror(errno)); - Tcl_AppendResult (interp, "can't open file ", filename, - " for writing. ", - "received error ", strerror(errno), NULL); - return TCL_ERROR; - } - - segment = 1; - - strcpy(query, "SELECT BYTE_LEN, DATA FROM LOB_DATA WHERE LOB_ID = "); - strcat(query, lob_id); - strcat(query, " AND SEGMENT = "); - - segment_pos = query + strlen(query); - - for (;;) { - char *data_column; - char *byte_len_column; - int i, j, n, byte_len; - char buf[6000]; - - sprintf(segment_pos, "%d", segment); - if (Ns_PgExec(handle, query) != NS_ROWS) { - Tcl_AppendResult(interp, "Error selecting data from BLOB", NULL); - return TCL_ERROR; - } - - if (PQntuples(nsConn->res) == 0) break; - - byte_len_column = PQgetvalue(nsConn->res, 0, 0); - data_column = PQgetvalue(nsConn->res, 0, 1); - sscanf(byte_len_column, "%d", &byte_len); - nbytes += byte_len; - n = byte_len; - for (i=0, j=0; n > 0; i += 4, j += 3, n -= 3) { - decode3(&data_column[i], &buf[j], n); - } - write(fd, buf, byte_len); - segment++; + if (to_conn_p) + { + if (Ns_WriteConn (conn, bufp, length) == NS_OK) + { + bytes_written = length; + } + else + { + bytes_written = 0; + } } + else + { + bytes_written = write (fd, bufp, length); + } - close(fd); + return bytes_written; + +} /* stream_actually_write */ - PQclear(nsConn->res); - nsConn->res = NULL; - conn = Ns_TclGetConn (interp); - - if (conn == NULL) - { - Tcl_AppendResult (interp, "no connection", NULL); - free (filename); - return TCL_ERROR; - } - - fd = open (filename, O_RDONLY); - - if (fd == -1) - { - Ns_Log (Error, "Error opening file %s: %d(%s)", - filename, errno, strerror(errno)); - Tcl_AppendResult (interp, "can't open file ", filename, - " for reading. ", "received error ", strerror(errno), NULL); - return TCL_ERROR; - } - - result = Ns_ConnSendFd (conn, fd, nbytes); - - close (fd); - - if (result != NS_OK) - { - Tcl_AppendResult (interp, "could not return file ", filename, NULL); - free (filename); - return TCL_ERROR; - } - - unlink (filename); - free (filename); - - return TCL_OK; -} - /* ns_pg blob_put blob_id value * Stuff the contents of value into the pseudo-blob blob_id */ @@ -1285,83 +1213,103 @@ * DanW - This is just blob_write, except it doesn't send anything out the * connection. * . + * Combined blob_select_file and blob_write: + * If you want to write to the network connection, set TO_CONN_P to TRUE + * and pass a null filename. + * + * If you want to write the blob to a file, set TO_CONN_P = FALSE, and + * pass the filename in. */ static int -blob_select_file(Tcl_Interp *interp, Ns_DbHandle *handle, char* lob_id, - char* filename) +blob_send_to_stream(Tcl_Interp *interp, Ns_DbHandle *handle, char* lob_id, + int to_conn_p, char* filename) { - NsPgConn *nsConn = (NsPgConn *) handle->connection; - int segment; - char query[100]; - int fd; - char *segment_pos; - int nbytes = 0; + NsPgConn *nsConn = (NsPgConn *) handle->connection; + int segment; + char query[100]; + int fd; + char *segment_pos; + Ns_Conn *conn; - /* spool to a tmp file, then return that out the conn - * note that tmpnam returns malloc'd memory. - */ + if (to_conn_p) + { + conn = Ns_TclGetConn(interp); + + /* this Shouldn't Happen, but spew an error just in case */ + if (conn == NULL) + { + Ns_Log (Error, "blob_send_to_stream: No AOLserver conn available"); - if (filename == NULL) + Tcl_AppendResult (interp, "No AOLserver conn available", NULL); + goto bailout; + } + } else { + if (filename == NULL) { - Tcl_AppendResult (interp, "could not create temporary file to spool " - "BLOB/CLOB result", NULL); - return TCL_ERROR; + Tcl_AppendResult (interp, "could not create temporary file to spool " + "BLOB/CLOB result", NULL); + return TCL_ERROR; } - fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); + fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); - if (fd < 0) + if (fd < 0) { - Ns_Log (Error, "Can't open %s for writing. error %d(%s)", - filename, errno, strerror(errno)); - Tcl_AppendResult (interp, "can't open file ", filename, - " for writing. ", - "received error ", strerror(errno), NULL); - return TCL_ERROR; + Ns_Log (Error, "Can't open %s for writing. error %d(%s)", + filename, errno, strerror(errno)); + Tcl_AppendResult (interp, "can't open file ", filename, + " for writing. ", + "received error ", strerror(errno), NULL); + return TCL_ERROR; } + } - segment = 1; + segment = 1; - strcpy(query, "SELECT BYTE_LEN, DATA FROM LOB_DATA WHERE LOB_ID = "); - strcat(query, lob_id); - strcat(query, " AND SEGMENT = "); + strcpy(query, "SELECT BYTE_LEN, DATA FROM LOB_DATA WHERE LOB_ID = "); + strcat(query, lob_id); + strcat(query, " AND SEGMENT = "); - segment_pos = query + strlen(query); + segment_pos = query + strlen(query); - for (;;) { - char *data_column; - char *byte_len_column; - int i, j, n, byte_len; - char buf[6000]; + for (;;) { + char *data_column; + char *byte_len_column; + int i, j, n, byte_len; + char buf[6000]; - sprintf(segment_pos, "%d", segment); - if (Ns_PgExec(handle, query) != NS_ROWS) { - Tcl_AppendResult(interp, "Error selecting data from BLOB", NULL); - return TCL_ERROR; - } + sprintf(segment_pos, "%d", segment); + if (Ns_PgExec(handle, query) != NS_ROWS) { + Tcl_AppendResult(interp, "Error selecting data from BLOB", NULL); + return TCL_ERROR; + } - if (PQntuples(nsConn->res) == 0) break; + if (PQntuples(nsConn->res) == 0) break; - byte_len_column = PQgetvalue(nsConn->res, 0, 0); - data_column = PQgetvalue(nsConn->res, 0, 1); - sscanf(byte_len_column, "%d", &byte_len); - nbytes += byte_len; - n = byte_len; - for (i=0, j=0; n > 0; i += 4, j += 3, n -= 3) { - decode3(&data_column[i], &buf[j], n); - } - write(fd, buf, byte_len); - segment++; - } + byte_len_column = PQgetvalue(nsConn->res, 0, 0); + data_column = PQgetvalue(nsConn->res, 0, 1); + sscanf(byte_len_column, "%d", &byte_len); + n = byte_len; + for (i=0, j=0; n > 0; i += 4, j += 3, n -= 3) { + decode3(&data_column[i], &buf[j], n); + } - close(fd); + stream_actually_write (fd, conn, buf, byte_len, to_conn_p); + segment++; + } - PQclear(nsConn->res); - nsConn->res = NULL; + bailout: + if (!to_conn_p) + { + close (fd); + } - return TCL_OK; + PQclear(nsConn->res); + nsConn->res = NULL; + + return TCL_OK; } @@ -1836,7 +1784,7 @@ argv[0], " command dbId blobId\"", NULL); return TCL_ERROR; } - return blob_write(interp, handle, argv[3]); + return blob_send_to_stream(interp, handle, argv[3], TRUE, NULL); } else if (!strcmp(argv[1], "blob_get")) { if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -1879,7 +1827,7 @@ argv[0], " command dbId blobId filename\"", NULL); return TCL_ERROR; } - return blob_select_file(interp, handle, argv[3], argv[4]); + return blob_send_to_stream(interp, handle, argv[3], FALSE, argv[4]); } #endif /* FOR_ACS_USE */