// paramName must be passed in WITHOUT leading '$' (ERRORPARAM_BEGINMARK). // paramName returns stripped of any internal '~' (ERRORPARAM_TYPESEP) and the // chars either preceding it or following it, if paramName is at all valid. // E.g., "0~string0" returns as "0" if positional but "string0" if named; // "int0~1" returns as "1" if pos but "int0" if named; // "2" returns as "2" either way; // "b" returns as "b" either way (if pos, function result is -1, invalid); // "intx~y" returns as "y" if pos (and function result is -1, invalid) // but "intx~y" if named (with a successful result, and the ComDiagsMsg.C // caller will reject it as not matching a string table lookup and then // display the entire bogus name). // Function returns -1 for invalid paramName, // 0 for valid NAMED_PARAM, // n>=0 for valid POSITIONAL_PARAM (n = the position, 0th, 1st, 2nd, ...) // // Why do we need to do this? Well, we have two kinds of messages -- // ComDiagsMsg.C ComCondition ones with named params, and // ErrorMessage.C ErrorMessage ones with positional. // The positional params need to have position numbers so that messages can // be translated (I18N of text often requires reordering params). // Tagging each param with both name and position info means that the same // msg code can be used from anywhere (either ComDiags or E'Msg), // i.e. we can share messages and not have a confusing welter of nearly // identical ones. // Lng32 FixupMessageParam(NAWchar *paramName, MsgParamType paramType) { ComASSERT(paramName); if (!*paramName) return -1; // invalid (empty) paramName NAWchar *p; NAWchar* sep = NAWstrchr(paramName, ERRORPARAM_TYPESEP); NABoolean begend = sep ? (sep == paramName || sep[1] == NAWchar('\0')) : FALSE; switch (paramType) { case NAMED_PARAM: if (begend) return 0; // "~x" and "9~" `legal' names if (sep) if (isdigit(*paramName)) NAWstrcpy(paramName, ++sep); // "9~x" -> "x" else if (isdigit(sep[1])) *sep = NAWchar('\0'); // "x~9" -> "x" //else {} // "x~y" `legal' return 0; // (Dubious legal names will be // flagged by our caller.) case POSITIONAL_PARAM: if (begend) return -1; // "~x" and "9~" invalid nums if (!isdigit(*paramName)) if (!sep) return -1; // "x" invalid num else NAWstrcpy(paramName, ++sep); // "x~9" -> "9" else if (sep) *sep = NAWchar('\0'); // "9~x" -> "9" //else {} // "9" valid for (p=paramName; *p; p++) if (!isdigit(*p)) return -1; // "9x" invalid num Lng32 pos; NAWsscanf(paramName, WIDE_("%d"), &pos); return pos; default: return -1; // invalid (unknown paramType) } } // FixupMessageParam
////////////////////////////////////////////// // Begin ERROR //////////////////////////////////////////////// short Error::process(SqlciEnv * sqlci_env) { NAWchar *error_msg; Int32 codeE, codeW; char stateE[10], stateW[10]; NABoolean msgNotFound; ostringstream omsg; #define GETERRORMESS(in, out, typ) GetErrorMessage(in, (NAWchar *&)out, typ) codeW = ABS(atoi(get_argument())); // >= 0, i.e. warning codeE = -codeW; // <= 0, i.e. error // These calls must be done before any of the GETERRORMESS(), // as they all use (overwrite) the same static buffer in GetErrorMessage.cpp. ComSQLSTATE(codeE, stateE); ComSQLSTATE(codeW, stateW); msgNotFound = GETERRORMESS(codeE, error_msg, ERROR_TEXT); if (type == ENVCMD_) { if (msgNotFound) { error_msg[0] = NAWchar('\n'); error_msg[1] = NAWchar('\0'); } else { // Extract the {braces-enclosed version string} // that msgfileVrsn.ksh (called by GenErrComp.bat) // has put into this ENVCMD_ message. NAWchar *v = NAWstrchr(error_msg, NAWchar(']')); if (v) error_msg = v; v = NAWstrchr(error_msg, NAWchar('{')); if (v) error_msg = v; v = NAWstrchr(error_msg, NAWchar('}')); if (v++ && *v == NAWchar('.')) *v = NAWchar(' '); } NAWriteConsole(error_msg, omsg, FALSE); } else if (!msgNotFound || codeE == 0) // SQL "success", special case { omsg << "\n*** SQLSTATE (Err): " << stateE << " SQLSTATE (Warn): " << stateW; omsg << endl; NAWriteConsole(error_msg,omsg, TRUE); } else { // Msg not found. ComDiagsArea diags; diags << DgSqlCode(codeW); NADumpDiags(omsg, &diags, TRUE/*newline*/); } #if 0 // CAUSE/EFFECT/RECOVERY text not implemented yet! if (!msgNotFound && type == DETAIL_) { GETERRORMESS(codeE, error_msg, CAUSE_TEXT); NAWriteConsole(error_msg,omsg, TRUE); GETERRORMESS(codeE, error_msg, EFFECT_TEXT); NAWriteConsole(error_msg,omsg, TRUE); GETERRORMESS(codeE, error_msg, RECOVERY_TEXT); NAWriteConsole(error_msg,omsg, TRUE); } #endif // 0 // CAUSE/EFFECT/RECOVERY text not implemented yet! omsg << ends; // to tack on a null-terminator sqlci_env->get_logfile()->WriteAllWithoutEOL(omsg.str().c_str()); return 0; }