// 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
void ErrorMessage::insertParams(NAError * errcb) { if (errcb->getErrParamCount() > 0) { // Note that we allocate twice the size for tmp, in order to forestall // array overrun problems (i.e. memory corruption) NAWchar tmp[MSG_BUF_SIZE * 2]; NAWchar paramName[MSG_BUF_SIZE]; NAWchar paramVal[MSG_BUF_SIZE]; // regular char, not TCHAR Int32 paramLen; Lng32 paramPos; Int32 tmpLen = 0; Int32 truncation = FALSE; #pragma nowarn(1506) // warning elimination Int32 msgBufOrigLen = NAWstrlen(msgBuf_); #pragma warn(1506) // warning elimination for (Int32 i = 0; i < msgBufOrigLen; i++) { if (msgBuf_[i] == ERRORPARAM_BEGINMARK) { // Get the formal parameter name, excluding the leading '$' mark NAWchar *p = paramName; while (++i < msgBufOrigLen && (isalnum(msgBuf_[i]) || msgBuf_[i] == ERRORPARAM_TYPESEP)) *p++ = msgBuf_[i]; *p = NAWchar('\0'); i--; // let's not lose a character! paramPos = FixupMessageParam(paramName, POSITIONAL_PARAM); if (paramPos >= 0) { paramVal[0] = NAWchar('\0'); // default is empty param NAErrorParam * param = errcb->getNAErrorParam(paramPos); if (param) switch (param->getNAErrorParamType()) { case NAErrorParam::NAERROR_PARAM_TYPE_INTEGER: NAWsprintf(paramVal,WIDE_("%d"),param->getIntegerNAErrorParam()); break; case NAErrorParam::NAERROR_PARAM_TYPE_CHAR_STRING: NAWsprintf(paramVal,WIDE_("%s"),param->getStringNAErrorParam()); break; } #pragma nowarn(1506) // warning elimination paramLen = NAWstrlen(paramVal); #pragma warn(1506) // warning elimination NAWstrncpy(&tmp[tmpLen], paramVal, paramLen); } else // invalid formal param (e.g. "$ab" "$9~" "$~9" "$9x") { tmp[tmpLen++] = ERRORPARAM_BEGINMARK; #pragma nowarn(1506) // warning elimination paramLen = NAWstrlen(paramName); #pragma warn(1506) // warning elimination NAWstrncpy(&tmp[tmpLen], paramName, paramLen); } tmpLen += paramLen; } else { tmp[tmpLen++] = msgBuf_[i]; } // If necessary, truncate the message and exit loop early. // The -1 is for the terminating '\0' below the loop. if (tmpLen > MSG_BUF_SIZE - 1) { tmpLen = MSG_BUF_SIZE - 1; truncation = TRUE; break; } } // for // Indicate truncation by overwriting last three characters with '...' if (truncation) tmp[tmpLen-3] = tmp[tmpLen-2] = tmp[tmpLen-1] = NAWchar('.'); NAWstrncpy(msgBuf_, tmp, tmpLen); msgBuf_[tmpLen] = NAWchar('\0'); } } // ErrorMessage::insertParams()
Lng32 FormatRow(const HSColumnStruct *srcDesc, const char *src, HSDataBuffer &target) { const Lng32 REC_INTERVAL = REC_MIN_INTERVAL; Lng32 retcode = 0; const Lng32 workBufLen = 4096; NAWchar workBuf[workBufLen]; Lng32 type = srcDesc->datatype; NAWString wStr; //The input source buffer will always be in the following form and will //contain unicode format. We need to separate the buffer accordingly. // |-------|--------------| // SRC -->| LEN | DATA | // |-------|--------------| short inDataLen; memcpy((char*)&inDataLen, src, sizeof(short)); const NAWchar *inData = (NAWchar*)(src + sizeof(short)); if (DFS2REC::isInterval(type)) type = REC_INTERVAL; if (DFS2REC::isAnyCharacter(type)) { wStr = WIDE_("'"); for (short i = 0; i < inDataLen/sizeof(NAWchar); i++) { if (inData[i] == NAWchar('\0')) wStr += NAWchar('\1'); /* convert x00 to x01 */ else { wStr += inData[i]; if (inData[i] == NAWchar('\'')) wStr.append(WIDE_("'")); } } wStr.append(WIDE_("'")); target = wStr.data(); } else { switch (type) { case REC_DATETIME: { switch (srcDesc->precision) { case REC_DTCODE_DATE: { wStr = WIDE_("DATE '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("'")); break; } case REC_DTCODE_TIME: { wStr = WIDE_("TIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("'")); break; } case REC_DTCODE_TIMESTAMP: { wStr = WIDE_("TIMESTAMP '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("'")); break; } // Here begin a number of cases that are only possible with MP datetime types. // LCOV_EXCL_START :mp case REC_DTCODE_YEAR: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' YEAR")); break; } case REC_DTCODE_YEAR_MONTH: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' YEAR TO MONTH")); break; } case REC_DTCODE_YEAR_HOUR: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' YEAR TO HOUR")); break; } case REC_DTCODE_YEAR_MINUTE: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' YEAR TO MINUTE")); break; } case REC_DTCODE_MONTH: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' MONTH")); break; } case REC_DTCODE_MONTH_DAY: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' MONTH TO DAY")); break; } case REC_DTCODE_MONTH_HOUR: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' MONTH TO HOUR")); break; } case REC_DTCODE_MONTH_MINUTE: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' MONTH TO MINUTE")); break; } case REC_DTCODE_MONTH_SECOND: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); if (srcDesc->scale == 0) wStr.append(WIDE_("' MONTH TO SECOND")); else { wStr.append(WIDE_("' MONTH TO ")); wStr.append(appendFraction(srcDesc->scale)); } break; } case REC_DTCODE_DAY: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' DAY")); break; } case REC_DTCODE_DAY_HOUR: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' DAY TO HOUR")); break; } case REC_DTCODE_DAY_MINUTE: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' DAY TO MINUTE")); break; } case REC_DTCODE_DAY_SECOND: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); if (srcDesc->scale == 0) wStr.append(WIDE_("' DAY TO SECOND")); else { wStr.append(WIDE_("' DAY TO ")); wStr.append(appendFraction(srcDesc->scale)); } break; } case REC_DTCODE_HOUR: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' HOUR")); break; } case REC_DTCODE_HOUR_MINUTE: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' HOUR TO MINUTE")); break; } case REC_DTCODE_MINUTE: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); wStr.append(WIDE_("' MINUTE")); break; } case REC_DTCODE_MINUTE_SECOND: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); if (srcDesc->scale == 0) wStr.append(WIDE_("' MINUTE TO SECOND")); else { wStr.append(WIDE_("' MINUTE TO ")); wStr.append(appendFraction(srcDesc->scale)); } break; } case REC_DTCODE_SECOND: { wStr = WIDE_("DATETIME '"); wStr.append(inData, inDataLen/sizeof(NAWchar)); if (srcDesc->scale == 0) wStr.append(WIDE_("' SECOND")); else { wStr.append(WIDE_("' SECOND TO ")); wStr.append(appendFraction(srcDesc->scale)); } break; } // LCOV_EXCL_STOP // LCOV_EXCL_START :rfi default: { HS_ASSERT(FALSE); break; } // LCOV_EXCL_STOP } target = wStr.data(); break; } case REC_INTERVAL: { //The INTERVAL may contain spaces and the negative sign //in front of the number. //We must capture the sign, but do not copy the extra character. Int32 spaceLen = 0; NABoolean signPresent = FALSE; spaceLen = wcsspn(inData, L" "); if (inData[spaceLen] == L'-') { signPresent = TRUE; wStr = WIDE_("INTERVAL -'"); } else wStr = WIDE_("INTERVAL '"); for (short i=0; i < spaceLen; i++) wStr.append(L" "); wStr.append( (inData+((signPresent) ? 1 : 0)+spaceLen), (inDataLen/sizeof(NAWchar)-((signPresent) ? 1 : 0)-spaceLen)); wStr.append(WIDE_("'")); switch (srcDesc->datatype) { case REC_INT_YEAR: { na_wsprintf(workBuf, WIDE_("%s YEAR(%d)"), wStr.data(), srcDesc->precision); break; } case REC_INT_YEAR_MONTH: { na_wsprintf(workBuf, WIDE_("%s YEAR(%d) TO MONTH"), wStr.data(), srcDesc->precision); break; } case REC_INT_MONTH: { na_wsprintf(workBuf, WIDE_("%s MONTH(%d)"), wStr.data(), srcDesc->precision); break; } case REC_INT_DAY: { na_wsprintf(workBuf, WIDE_("%s DAY(%d)"), wStr.data(), srcDesc->precision); break; } case REC_INT_DAY_HOUR: { na_wsprintf(workBuf, WIDE_("%s DAY(%d) TO HOUR"), wStr.data(), srcDesc->precision); break; } case REC_INT_DAY_MINUTE: { na_wsprintf(workBuf, WIDE_("%s DAY(%d) TO MINUTE"), wStr.data(), srcDesc->precision); break; } case REC_INT_DAY_SECOND: { na_wsprintf(workBuf, WIDE_("%s DAY(%d) TO SECOND(%d)"), wStr.data(), srcDesc->precision, srcDesc->scale); break; } case REC_INT_HOUR: { na_wsprintf(workBuf, WIDE_("%s HOUR(%d)"), wStr.data(), srcDesc->precision); break; } case REC_INT_HOUR_MINUTE: { na_wsprintf(workBuf, WIDE_("%s HOUR(%d) TO MINUTE"), wStr.data(), srcDesc->precision); break; } case REC_INT_HOUR_SECOND: { na_wsprintf(workBuf, WIDE_("%s HOUR(%d) TO SECOND(%d)"), wStr.data(), srcDesc->precision, srcDesc->scale); break; } case REC_INT_MINUTE: { na_wsprintf(workBuf, WIDE_("%s MINUTE(%d)"), wStr.data(), srcDesc->precision); break; } case REC_INT_MINUTE_SECOND: { na_wsprintf(workBuf, WIDE_("%s MINUTE(%d) TO SECOND(%d)"), wStr.data(), srcDesc->precision, srcDesc->scale); break; } case REC_INT_SECOND: { na_wsprintf(workBuf, WIDE_("%s SECOND(%d, %d)"), wStr.data(), srcDesc->precision, srcDesc->scale); break; } // LCOV_EXCL_START :rfi default: { HS_ASSERT(FALSE); break; } // LCOV_EXCL_STOP } target = workBuf; break; } default: { wStr.replace(0, wStr.length(), inData, inDataLen/sizeof(NAWchar)); target = wStr.data(); break; } } } return retcode; }
void ErrorMessage::printErrorMessage(NAError * errcb) { NAWchar* tmp = msgBuf_; // This is always a positive number (but make sure of it!) NAErrorCode erc_abs = errcb->getErrCode(); if (erc_abs < 0) erc_abs = -erc_abs; // A warning is positive, an error negative -- // GetErrorMessage generates the proper text for each. NAErrorCode erc_signed = (errcb->getErrType() == NAError::NAERROR_WARNING) ? erc_abs : -erc_abs; NABoolean msgNotFound = GetErrorMessage(erc_signed, tmp); NABoolean forceParamSubst = msgNotFound && errcb->getErrParamCount() > 0; /* // if tmp was assigned to a different (e.g. a static) string, we need to copy // its contents into this msgBuf_ so that insertParams overwrites our copy // and not the original. */ NAWstrcpy(msgBuf_, tmp); if (forceParamSubst) { // msgBuf_ will contain a suitable msg-not-found message, so now we just // append substitution parameters to at least make debugging easier. // // This mirrors what ComCondition::getMessageText does. NAWstrcat(msgBuf_, WIDE_(" $0 $1 $2 $3 $4 $5 $6 $7 $8 $9")); //dbg: NAWstrcat(msgBuf_, WIDE_(" $ $$ $ab $9 $~ $~~ $~0 $0~ $~a $a~ $0x $0x~int0 $int0~x # $0~int0 $int0~0 $0 $00 $0$0")); //dbg: NAWstrcat(msgBuf_, WIDE_(" $Int0~0$int0~1 $0~Int0$1~int0 #")); //dbg: NAWstrcat(msgBuf_, WIDE_(" $Int0~0$int0~0 $0~Int0$0~int0 #")); //dbg: NAWstrcat(msgBuf_, WIDE_(" $Int0~0$0~int0 $0~Int0$int0~0 #")); } ErrorMessageOverflowCheckW(msgBuf_, MSG_BUF_SIZE); insertParams(errcb); if (forceParamSubst) { // remove trailing blanks and unsubstituted substitution marks #pragma nowarn(1506) // warning elimination Int32 tmpLen = NAWstrlen(msgBuf_); #pragma warn(1506) // warning elimination while (--tmpLen >= 0 && (msgBuf_[tmpLen] == NAWchar(' ') || msgBuf_[tmpLen] == NAWchar('\t') || msgBuf_[tmpLen] == ERRORPARAM_BEGINMARK)) ; msgBuf_[++tmpLen] = NAWchar('\0'); } char msgBuf8bit[2*MSG_BUF_SIZE]; UnicodeStringToLocale(CharInfo::ISO88591, msgBuf_, MSG_BUF_SIZE, msgBuf8bit, 2*MSG_BUF_SIZE); printf("%s\n", msgBuf8bit); fflush(stdout); } // ErrorMessage::printErrorMessage()
Lng32 LocaleStringToUnicode(Lng32 charset, const char* str, Lng32 strLen, NAWchar* wstrBuf, Lng32 wstrBufLen, NABoolean addNullAtEnd) { // Changed the algorithm to call the new LocaleToUTF16() but keep // the old call to old ISO88591ToUnicode() when the character set is // ISO88591. We want to keep the old "pass through" behavior so // Use of ISO 8859-15 characters (a.k.a., Latin-9) in // CHARACTER SET ISO88591 target column continues to work. if (charset == (Lng32) CharInfo::ISO88591) { NAWcharBuf wcbuf(wstrBuf, wstrBufLen); NAWcharBuf* wcbufPtr = &wcbuf; NAWcharBuf* res = 0; res = ISO88591ToUnicode( charBuf((unsigned char*)str, strLen), 0, wcbufPtr, addNullAtEnd ); return (res) ? res->getStrLen() : 0; } // // else (charset != (Lng32) CharInfo::ISO88591) // enum cnv_charset convCS = convertCharsetEnum(charset); if (convCS == cnv_UnknownCharSet) return 0; // nothing we can do; exit the routine UInt32 outBufSizeInBytes = wstrBufLen*sizeof(NAWchar); char * pFirstUntranslatedChar = NULL; UInt32 outputDataLenInBytes = 0; UInt32 translatedtCharCount = 0; Int32 convStatus = LocaleToUTF16(cnv_version1, // const enum cnv_version version str, // const char *in_bufr strLen, // const int in_len in # of bytes (const char *)wstrBuf, // const char *out_bufr (const Int32)outBufSizeInBytes, convCS, // enum cnv_charset charset -- output charset pFirstUntranslatedChar, // char * & first_untranslated_char &outputDataLenInBytes, // unsigned int *output_data_len_p 0, // const int cnv_flags (default is 0) (const Int32)addNullAtEnd, &translatedtCharCount); // unsigned int *translated_char_cnt_p UInt32 outLenInW = outputDataLenInBytes/sizeof(NAWchar); if (convStatus == 0) // success return outLenInW; // include the NULL terminator if (addNullAtEnd == TRUE) // If convStatus != 0, LocaleToUTF16 will not add the NULL terminator if (addNullAtEnd && wstrBuf && wstrBufLen > 0) { if (outLenInW < (UInt32)wstrBufLen) wstrBuf[outLenInW] = WIDE_('\0'); else { // assume the specified wstrBufLen includes room for the NULL terminator // when the passed-in addNullAtEnd parameter is set to TRUE wstrBuf[wstrBufLen-1] = WIDE_('\0'); } } return 0; // tell the caller not to use data in wstrBuf }