rem: ErrorCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv, int cmd)
add: ErrorCmd(ClientData arg, Tcl_Interp *interp, int argc, CONST char **argv, int cmd)
context: static Tcl_CmdProc DbCmd, QuoteListToListCmd, GetCsvCmd, DbErrorCodeCmd,	DbErrorMsgCmd, GetCsvCmd, DbConfigPathCmd, PoolDescriptionCmd;static Ns_TclDeferProc ReleaseDbs;static char *datakey = "nsdb:data";/* *---------------------------------------------------------------------- * Ns_TclDbGetHandle -- * *      Get database handle from its handle id. * * Results: *      See DbGetHandle(). * * Side effects: *      None. * *---------------------------------------------------------------------- */intNs_TclDbGetHandle(Tcl_Interp *interp, char *id, Ns_DbHandle **handlePtr){    InterpData *idataPtr;    idataPtr = Tcl_GetAssocData(interp, datakey, NULL);    if (idataPtr == NULL) {	return TCL_ERROR;    }    return DbGetHandle(idataPtr, interp, id, handlePtr, NULL);}/* *---------------------------------------------------------------------- * * NsDbAddCmds -- * *      Add the nsdb commands. * * Results: *      None. * * Side effects: *      None. * *---------------------------------------------------------------------- */intNsDbAddCmds(Tcl_Interp *interp, void *arg){    InterpData *idataPtr;    /*     * Initialize the per-interp data.     */    idataPtr = ns_malloc(sizeof(InterpData));    idataPtr->server = arg;    idataPtr->cleanup = 0;    Tcl_InitHashTable(&idataPtr->dbs, TCL_STRING_KEYS);    Tcl_SetAssocData(interp, datakey, FreeData, idataPtr);    Tcl_CreateCommand(interp, "ns_db", DbCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_quotelisttolist", QuoteListToListCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_getcsv", GetCsvCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_dberrorcode", DbErrorCodeCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_dberrormsg", DbErrorMsgCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_getcsv", GetCsvCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_dbconfigpath", DbConfigPathCmd, idataPtr, NULL);    Tcl_CreateCommand(interp, "ns_pooldescription", PoolDescriptionCmd, idataPtr, NULL);    return TCL_OK;}/* *---------------------------------------------------------------------- * * DbCmd -- * *      Implement the AOLserver ns_db Tcl command. * * Results: *      Return TCL_OK upon success and TCL_ERROR otherwise. * * Side effects: *      Depends on the command. * *---------------------------------------------------------------------- */static intDbCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv){    InterpData	   *idataPtr = arg;    Ns_DbHandle    *handlePtr;    Ns_Set         *rowPtr;    char           *cmd;    char           *pool;    if (argc < 2) {        Tcl_AppendResult(interp, "wrong # of args: should be \"",            argv[0], " command ?args ...?", NULL);        return TCL_ERROR;    }    cmd = argv[1];    if (STREQ(cmd, "open") || STREQ(cmd, "close")) {    	Tcl_AppendResult(interp, "unsupported ns_db command: ", cmd, NULL);    	return TCL_ERROR;    } else if (STREQ(cmd, "pools")) {        if (argc != 2) {            return BadArgs(interp, argv, NULL);        }	pool = Ns_DbPoolList(idataPtr->server);	if (pool != NULL) {	    while (*pool != '\0') {		Tcl_AppendElement(interp, pool);		pool = pool + strlen(pool) + 1;	    }	}    } else if (STREQ(cmd, "bouncepool")) {	if (argc != 3) {	    return BadArgs(interp, argv, "pool");	}	if (Ns_DbBouncePool(argv[2]) == NS_ERROR) {	    Tcl_AppendResult(interp, "could not bounce: ", argv[2], NULL);	    return TCL_ERROR;	}    } else if (STREQ(cmd, "gethandle")) {	int timeout, nhandles, result;	Ns_DbHandle **handlesPtrPtr;	timeout = 0;	if (argc >= 4) {	    if (STREQ(argv[2], "-timeout")) {		if (Tcl_GetInt(interp, argv[3], &timeout) != TCL_OK) {		    return TCL_ERROR;		}		argv += 2;		argc -= 2;	    } else if (argc > 4) {		return BadArgs(interp, argv,		    "?-timeout timeout? ?pool? ?nhandles?");	    }	}	argv += 2;	argc -= 2;	/*	 * Determine the pool and requested number of handles	 * from the remaining args.	 */       	pool = argv[0];	if (pool == NULL) {	    pool = Ns_DbPoolDefault(idataPtr->server);            if (pool == NULL) {                Tcl_SetResult(interp, "no defaultpool configured", TCL_STATIC);                return TCL_ERROR;            }        }        if (Ns_DbPoolAllowable(idataPtr->server, pool) == NS_FALSE) {            Tcl_AppendResult(interp, "no access to pool: \"", pool, "\"",			     NULL);            return TCL_ERROR;        }        if (argc < 2) {	    nhandles = 1;	} else {            if (Tcl_GetInt(interp, argv[1], &nhandles) != TCL_OK) {                return TCL_ERROR;            }	    if (nhandles <= 0) {                Tcl_AppendResult(interp, "invalid nhandles \"", argv[1],                    "\": should be greater than 0.", NULL);                return TCL_ERROR;            }	}    	/*         * Allocate handles and enter them into Tcl.         */	if (nhandles == 1) {    	    handlesPtrPtr = &handlePtr;	} else {	    handlesPtrPtr = ns_malloc(nhandles * sizeof(Ns_DbHandle *));	}	result = Ns_DbPoolTimedGetMultipleHandles(handlesPtrPtr, pool,     	    	                                  nhandles, timeout);    	if (result == NS_OK) {	    int i;	    	    for (i = 0; i < nhandles; ++i) {                EnterDbHandle(idataPtr, interp, handlesPtrPtr[i]);            }	}	if (handlesPtrPtr != &handlePtr) {	    ns_free(handlesPtrPtr);	}	if (result != NS_TIMEOUT && result != NS_OK) {            Tcl_AppendResult(interp, "could not allocate ",	    	nhandles > 1 ? argv[1] : "1", " handle",		nhandles > 1 ? "s" : "", " from pool \"",		pool, "\"", NULL);            return TCL_ERROR;        }    } else if (STREQ(cmd, "exception")) {        if (argc != 3) {            return BadArgs(interp, argv, "dbId");        }        if (DbGetHandle(idataPtr, interp, argv[2], &handlePtr, NULL) != TCL_OK) {            return TCL_ERROR;        }        Tcl_AppendElement(interp, handlePtr->cExceptionCode);        Tcl_AppendElement(interp, handlePtr->dsExceptionMsg.string);    } else {	Tcl_HashEntry  *hPtr;    	/*         * All remaining commands require a valid database         * handle.  The exception message is cleared first.         */	        if (argc < 3) {            return BadArgs(interp, argv, "dbId ?args?");        }        if (DbGetHandle(idataPtr, interp, argv[2], &handlePtr, &hPtr) != TCL_OK) {            return TCL_ERROR;        }        Ns_DStringFree(&handlePtr->dsExceptionMsg);        handlePtr->cExceptionCode[0] = '\0';    	/*         * The following commands require just the handle.         */        if (STREQ(cmd, "poolname") ||	    STREQ(cmd, "password") ||	    STREQ(cmd, "user") ||	    STREQ(cmd, "datasource") ||	    STREQ(cmd, "disconnect") ||	    STREQ(cmd, "dbtype") ||	    STREQ(cmd, "driver") ||	    STREQ(cmd, "cancel") ||	    STREQ(cmd, "bindrow") ||	    STREQ(cmd, "flush") ||	    STREQ(cmd, "releasehandle") ||	    STREQ(cmd, "resethandle") ||	    STREQ(cmd, "connected") ||	    STREQ(cmd, "sp_exec") ||	    STREQ(cmd, "sp_getparams") ||	    STREQ(cmd, "sp_returncode")) {	                if (argc != 3) {                return BadArgs(interp, argv, "dbId");            }	    if (STREQ(cmd, "poolname")) {                Tcl_SetResult(interp, handlePtr->poolname, TCL_VOLATILE);	    } else if (STREQ(cmd, "password")) {                Tcl_SetResult(interp, handlePtr->password, TCL_VOLATILE);	    } else if (STREQ(cmd, "user")) {		                    Tcl_SetResult(interp, handlePtr->user, TCL_VOLATILE);	    } else if (STREQ(cmd, "dbtype")) {                Tcl_SetResult(interp, Ns_DbDriverDbType(handlePtr), 			      TCL_STATIC);	    } else if (STREQ(cmd, "driver")) {                Tcl_SetResult(interp, Ns_DbDriverName(handlePtr), TCL_STATIC);	    } else if (STREQ(cmd, "datasource")) {		Tcl_SetResult(interp, handlePtr->datasource, TCL_STATIC);	    } else if (STREQ(cmd, "disconnect")) {		NsDbDisconnect(handlePtr);	    } else if (STREQ(cmd, "flush")) {                if (Ns_DbFlush(handlePtr) != NS_OK) {                    return DbFail(interp, handlePtr, cmd);                }    	    } else if (STREQ(cmd, "bindrow")) {                rowPtr = Ns_DbBindRow(handlePtr);                if (rowPtr == NULL) {                    return DbFail(interp, handlePtr, cmd);                }                Ns_TclEnterSet(interp, rowPtr, NS_TCL_SET_STATIC);    	    } else if (STREQ(cmd, "releasehandle")) {		Tcl_DeleteHashEntry(hPtr);    		Ns_DbPoolPutHandle(handlePtr);    	    } else if (STREQ(cmd, "resethandle")) {		if (Ns_DbResetHandle(handlePtr) != NS_OK) {		  return DbFail(interp, handlePtr, cmd);		}		Tcl_SetObjResult(interp, Tcl_NewIntObj(NS_OK));    	    } else if (STREQ(cmd, "cancel")) {                if (Ns_DbCancel(handlePtr) != NS_OK) {                    return DbFail(interp, handlePtr, cmd);                }	    } else if (STREQ(cmd, "connected")) {		Tcl_SetObjResult(interp, Tcl_NewIntObj(handlePtr->connected));	    } else if (STREQ(cmd, "sp_exec")) {		switch (Ns_DbSpExec(handlePtr)) {		case NS_DML:		    Tcl_SetResult(interp, "NS_DML", TCL_STATIC);		    break;		case NS_ROWS:		    Tcl_SetResult(interp, "NS_ROWS", TCL_STATIC);		    break;		default:		    return DbFail(interp, handlePtr, cmd);		    break;		}	    } else if (STREQ(cmd, "sp_returncode")) {		char *tmpbuf;		tmpbuf = ns_malloc(32);		if (Ns_DbSpReturnCode(handlePtr, tmpbuf, 32) != NS_OK) {		    ns_free(tmpbuf);		    return DbFail(interp, handlePtr, cmd);		} else {		    Tcl_SetResult(interp, tmpbuf, TCL_VOLATILE);		    ns_free(tmpbuf);		}	    } else if (STREQ(cmd, "sp_getparams")) {		rowPtr = Ns_DbSpGetParams(handlePtr);		if (rowPtr == NULL) {		    return DbFail(interp, handlePtr, cmd);		}		Ns_TclEnterSet(interp, rowPtr, NS_TCL_SET_DYNAMIC);	    }		    	/*         * The following commands require a 3rd argument.      	 */        } else if (STREQ(cmd, "getrow") ||		   STREQ(cmd, "dml") ||		   STREQ(cmd, "1row") ||		   STREQ(cmd, "0or1row") ||		   STREQ(cmd, "exec") ||		   STREQ(cmd, "select") ||		   STREQ(cmd, "sp_start") ||		   STREQ(cmd, "interpretsqlfile")) {            if (argc != 4) {    	    	if (STREQ(cmd, "interpretsqlfile")) {                    return BadArgs(interp, argv, "dbId sqlfile");		} else if (STREQ(cmd, "getrow")) {		    return BadArgs(interp, argv, "dbId row");		} else {		    return BadArgs(interp, argv, "dbId sql");		}	    }    	    if (STREQ(cmd, "dml")) {                if (Ns_DbDML(handlePtr, argv[3]) != NS_OK) {                    return DbFail(interp, handlePtr, cmd);                }    	    } else if (STREQ(cmd, "1row")) {                rowPtr = Ns_Db1Row(handlePtr, argv[3]);                if (rowPtr == NULL) {                    return DbFail(interp, handlePtr, cmd);                }                Ns_TclEnterSet(interp, rowPtr, NS_TCL_SET_DYNAMIC);    	    } else if (STREQ(cmd, "0or1row")) {    	    	int nrows;                rowPtr = Ns_Db0or1Row(handlePtr, argv[3], &nrows);                if (rowPtr == NULL) {                    return DbFail(interp, handlePtr, cmd);                }                if (nrows == 0) {                    Ns_SetFree(rowPtr);                } else {                    Ns_TclEnterSet(interp, rowPtr, NS_TCL_SET_DYNAMIC);                }    	    } else if (STREQ(cmd, "select")) {                rowPtr = Ns_DbSelect(handlePtr, argv[3]);                if (rowPtr == NULL) {                    return DbFail(interp, handlePtr, cmd);                }                Ns_TclEnterSet(interp, rowPtr, NS_TCL_SET_STATIC);    	    } else if (STREQ(cmd, "exec")) {                switch (Ns_DbExec(handlePtr, argv[3])) {                case NS_DML:                    Tcl_SetResult(interp, "NS_DML", TCL_STATIC);                    break;                case NS_ROWS:                    Tcl_SetResult(interp, "NS_ROWS", TCL_STATIC);                    break;                default:                    return DbFail(interp, handlePtr, cmd);                    break;                }    	    } else if (STREQ(cmd, "interpretsqlfile")) {                if (Ns_DbInterpretSqlFile(handlePtr, argv[3]) != NS_OK) {                    return DbFail(interp, handlePtr, cmd);                }	    } else if (STREQ(cmd, "sp_start")) {		if (Ns_DbSpStart(handlePtr, argv[3]) != NS_OK) {		    return DbFail(interp, handlePtr, cmd);		}		Tcl_SetResult(interp, "0", TCL_STATIC);		    	    } else { /* getrow */                if (Ns_TclGetSet2(interp, argv[3], &rowPtr) != TCL_OK) {                    return TCL_ERROR;                }                switch (Ns_DbGetRow(handlePtr, rowPtr)) {                case NS_OK:                    Tcl_SetResult(interp, "1", TCL_STATIC);                    break;                case NS_END_DATA:                    Tcl_SetResult(interp, "0", TCL_STATIC);                    break;                default:                    return DbFail(interp, handlePtr, cmd);                    break;                }            }        } else if (STREQ(cmd, "verbose")) {	    int verbose;            if (argc != 3 && argc != 4) {                return BadArgs(interp, argv, "dbId ?on|off?");            }            if (argc == 4) {                if (Tcl_GetBoolean(interp, argv[3], &verbose) != TCL_OK) {                    return TCL_ERROR;                }                handlePtr->verbose = verbose;            }	    Tcl_SetObjResult(interp, Tcl_NewIntObj(handlePtr->verbose));        } else if (STREQ(cmd, "setexception")) {            if (argc != 5) {                return BadArgs(interp, argv, "dbId code message");            }            if (strlen(argv[3]) > 5) {                Tcl_AppendResult(interp, "code \"", argv[3],		    "\" more than 5 characters", NULL);                return TCL_ERROR;            }            Ns_DbSetException(handlePtr, argv[3], argv[4]);	} else if (STREQ(cmd, "sp_setparam")) {	    if (argc != 7) {		return BadArgs(interp, argv,			       "dbId paramname type in|out value");	    }	    if (!STREQ(argv[5], "in") && !STREQ(argv[5], "out")) {		Tcl_SetResult(interp, "inout parameter of setparam must "			      "be \"in\" or \"out\"", TCL_STATIC);		return TCL_ERROR;	    }	    if (Ns_DbSpSetParam(handlePtr, argv[3], argv[4], argv[5],				argv[6]) != NS_OK) {		return DbFail(interp, handlePtr, cmd);	    } else {		Tcl_SetResult(interp, "1", TCL_STATIC);	    }        } else {            Tcl_AppendResult(interp, argv[0], ":  Unknown command \"",			     argv[1], "\":  should be "			     "0or1row, "			     "1row, "			     "bindrow, "			     "cancel, "			     "connected, "			     "datasource, "			     "dbtype, "			     "disconnect, "			     "dml, "			     "driver, "			     "exception, "			     "exec, "			     "flush, "			     "gethandle, "			     "getrow, "			     "interpretsqlfile, "			     "password, "			     "poolname, "			     "pools, "			     "releasehandle, "			     "select, "			     "setexception, "			     "sp_start, "			     "sp_setparam, "			     "sp_exec, "			     "sp_returncode, "			     "sp_getparams, "			     "user, "			     "bouncepool"			     " or verbose", NULL);            return TCL_ERROR;        }    }    return TCL_OK;}/* *---------------------------------------------------------------------- * DbErrorCodeCmd -- * *      Get database exception code for the database handle. * * Results: *      Returns TCL_OK and database exception code is set as Tcl result *	or TCL_ERROR if failure. * * Side effects: *      None. * *---------------------------------------------------------------------- */static intErrorCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv, int cmd){    InterpData *idataPtr = arg;    Ns_DbHandle *handle;    if (argc != 2) {        Tcl_AppendResult(interp, "wrong # args:  should be \"",            argv[0], " dbId\"", NULL);        return TCL_ERROR;    }    if (DbGetHandle(idataPtr, interp, argv[1], &handle, NULL) != TCL_OK) {        return TCL_ERROR;    }    if (cmd == 'c') {    	Tcl_SetResult(interp, handle->cExceptionCode, TCL_VOLATILE);    } else {    	Tcl_SetResult(interp, handle->dsExceptionMsg.string, TCL_VOLATILE);    }    return TCL_OK;}static intDbErrorCodeCmd(ClientData arg, Tcl_Interp *interp, int argc,		    char **argv){    return ErrorCmd(arg, interp, argc, argv, 'c');}