NAWcharBuf* ISO88591ToUnicode(const charBuf& input, CollHeap *heap, NAWcharBuf*& unicodeString, NABoolean addNullAtEnd) { NAWcharBuf* output = checkSpace(heap, input.getStrLen(), unicodeString, addNullAtEnd); if ( output == 0 ) return 0; NAWchar* target = output->data(); Int32 i; for ( i=0; i<input.getStrLen(); i++ ) { target[i] = (NAWchar)(input.data()[i]); } if ( addNullAtEnd ) target[i] = 0; output->setStrLen(input.getStrLen()); return output; }
Int32 main(Int32 argc, char** argv) { charBuf* latin1 = 0; NAWchar wbuf[1]; NAWcharBuf uni(wbuf, 1); for ( NAWchar i=0; i<0xff; i++ ) { wbuf[0] = i; latin1 = unicodeToISO88591(uni, 0, latin1); if ( latin1 && latin1->data()[0] != i ) { printf("u2l1 test failed\n"); return 1; } } unsigned char buf[1]; charBuf ascii(buf, 1); NAWcharBuf* unicode = 0; for ( unsigned char j=0; j<0xff; j++ ) { buf[0] = j; unicode = ISO88591ToUnicode(ascii, 0, unicode); if ( unicode && unicode->data()[0] != j ) { printf("l12u test failed\n"); return 1; } } wbuf[0] = 0xC0F3; // negative test latin1 = unicodeToISO88591(uni, 0, latin1); if ( latin1 ) printf("negative u2l1 test failed\n"); printf("test pass\n"); return 0; }
short Param::convertValue(SqlciEnv * sqlci_env, short targetType, Lng32 &targetLen, Lng32 targetPrecision, Lng32 targetScale, Lng32 vcIndLen, ComDiagsArea* diags) { // get rid of the old converted value if (converted_value) { delete [] converted_value; converted_value = 0; }; short sourceType; Lng32 sourceLen; // set up the source and its length based on the how the value is passed-in. if ( isInSingleByteForm() == FALSE ) { sourceLen = (Lng32)(NAWstrlen((NAWchar*)value) * BYTES_PER_NAWCHAR); switch (getCharSet()) { case CharInfo::UNICODE: sourceType = REC_NCHAR_F_UNICODE; break; case CharInfo::KANJI_MP: case CharInfo::KSC5601_MP: sourceType = REC_BYTE_F_ASCII; // KANJI/KSC passed in as NAWchar* break; default: return SQL_Error; // error case } } else { sourceLen = (Lng32)strlen(value); // for any source in single-byte format sourceType = REC_BYTE_F_ASCII; } char * pParamValue = value; if ( DFS2REC::isAnyCharacter(targetType) ) { if (termCS_ == CharInfo::UnknownCharSet) termCS_ = sqlci_env->getTerminalCharset(); if (cs == CharInfo::UnknownCharSet) { isQuotedStrWithoutCharSetPrefix_ = TRUE; cs = termCS_; } // If the target is CHARACTER and param is set as [_cs_prefix]'...', then // make sure the source is assignment compatible with the target. CharInfo::CharSet targetCharSet = (CharInfo::CharSet)targetScale; if ( targetCharSet == CharInfo::UNICODE ) { if (getUTF16StrLit() == (NAWchar*)NULL) { utf16StrLit_ = new NAWchar [ sourceLen * 2 + 1 ]; // plenty of room Lng32 utf16StrLenInNAWchars = LocaleStringToUnicode(cs/*sourceCS*/, /*sourceStr*/value, sourceLen, utf16StrLit_/*outputBuf*/, sourceLen+1/*outputBufSizeInNAWchars*/, TRUE /* in - NABoolean addNullAtEnd*/); if (sourceLen > 0 && utf16StrLenInNAWchars == 0) return SQL_Error; // ComASSERT(utf16StrLenInNAWchars == NAWstrlen(getUTF16StrLit())); // Resize the NAWchar buffer to save space NAWchar *pNAWcharBuf = new NAWchar [ utf16StrLenInNAWchars + 1 ]; NAWstrncpy (pNAWcharBuf, utf16StrLit_, utf16StrLenInNAWchars + 1); pNAWcharBuf[utf16StrLenInNAWchars] = NAWCHR('\0'); // play it safe delete [] utf16StrLit_; utf16StrLit_ = pNAWcharBuf; // do not deallocate pNAWcharBuf } sourceLen = (Lng32)(NAWstrlen(getUTF16StrLit()) * BYTES_PER_NAWCHAR); // check to see if the parameter utf16 string fits in the target if ( sourceLen > targetLen ) return SQL_Error; pParamValue = (char *)getUTF16StrLit(); sourceType = REC_NCHAR_F_UNICODE; } } else { // MP NCHAR (KANJI/KSC) can not be converted to non-character objects if ( CharInfo::is_NCHAR_MP(cs) ) return SQL_Error; } switch(targetType) { case REC_BIN16_SIGNED: case REC_BIN16_UNSIGNED: case REC_BPINT_UNSIGNED: case REC_BIN32_SIGNED: case REC_BIN32_UNSIGNED: case REC_BIN64_SIGNED: case REC_DECIMAL_UNSIGNED: case REC_DECIMAL_LSE: case REC_FLOAT32: case REC_FLOAT64: case REC_TDM_FLOAT32: case REC_TDM_FLOAT64: case REC_BYTE_F_ASCII: case REC_BYTE_V_ASCII: case REC_BYTE_V_ASCII_LONG: case REC_NCHAR_F_UNICODE: case REC_NCHAR_V_UNICODE: { char *VCLen = NULL; short VCLenSize = 0; // 5/27/98: added VARNCHAR cases if ((targetType == REC_BYTE_V_ASCII) || (targetType == REC_BYTE_V_ASCII_LONG) || (targetType == REC_NCHAR_V_UNICODE)) { // add bytes for variable length field VCLenSize = vcIndLen; //sizeof(short); VCLen = converted_value = new char[targetLen + VCLenSize]; } else converted_value = new char[targetLen]; #pragma nowarn(1506) // warning elimination ex_expr::exp_return_type ok; CharInfo::CharSet TCS = sqlci_env->getTerminalCharset(); CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset(); NAString* tempstr; if ( DFS2REC::isAnyCharacter(sourceType) && DFS2REC::isAnyCharacter(targetType) && !(getUTF16StrLit() != NULL && sourceType == REC_NCHAR_F_UNICODE && targetScale == CharInfo::UCS2) && /*source*/cs != targetScale/*i.e., targetCharSet*/ ) { charBuf cbuf((unsigned char*)pParamValue, sourceLen); NAWcharBuf* wcbuf = 0; Int32 errorcode = 0; wcbuf = csetToUnicode(cbuf, 0, wcbuf, cs/*sourceCharSet*/ , errorcode); if (errorcode != 0) return SQL_Error; tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), targetScale/*i.e., targetCharSet*/ ); if (tempstr == NULL) return SQL_Error; //Avoid NULL ptr reference if conversion error sourceType = targetType; // we just converted it to the target type sourceLen = tempstr->length(); pParamValue = (char *)tempstr->data(); if ( sourceLen > targetLen ) return SQL_Error; } ok = convDoIt(pParamValue, sourceLen, sourceType, 0, // source Precision targetScale, // new charset we converted to &converted_value[VCLenSize], targetLen, targetType, targetPrecision, targetScale, VCLen, VCLenSize, 0, &diags); if ( ok != ex_expr::EXPR_OK) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_DATETIME: { char *VCLen = NULL; short VCLenSize = 0; converted_value = new char[targetLen + 1]; #pragma nowarn(1506) // warning elimination ex_expr::exp_return_type ok = convDoIt(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, VCLen, VCLenSize, 0, &diags); if ( ok != ex_expr::EXPR_OK) { return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_INT_YEAR: case REC_INT_MONTH: case REC_INT_YEAR_MONTH: case REC_INT_DAY: case REC_INT_HOUR: case REC_INT_DAY_HOUR: case REC_INT_MINUTE: case REC_INT_HOUR_MINUTE: case REC_INT_DAY_MINUTE: case REC_INT_SECOND: case REC_INT_MINUTE_SECOND: case REC_INT_HOUR_SECOND: case REC_INT_DAY_SECOND: { // convert target back to string. converted_value = new char[targetLen]; Lng32 convFlags = CONV_ALLOW_SIGN_IN_INTERVAL; #pragma nowarn(1506) // warning elimination short ok = convDoItMxcs(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, convFlags); if ( ok != 0 ) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_NUM_BIG_UNSIGNED: case REC_NUM_BIG_SIGNED: { converted_value = new char[targetLen]; #pragma nowarn(1506) // warning elimination short ok = convDoItMxcs(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, 0); if ( ok != 0 ) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; default: break; }; return 0; }
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 }
NAWcharBuf* csetToUnicode(const charBuf& input, CollHeap *heap, NAWcharBuf*& unicodeString, Int32 cset, Int32 &errorcode, NABoolean addNullAtEnd, Int32 *charCount, Int32 *errorByteOff) { char * err_ptr = NULL; UInt32 byteCount = 0, lv_charCount = 0, computedMaxBufSizeInNAWchars = 0; NABoolean outputBufferAllocatedByThisRoutine = (unicodeString == NULL) ? TRUE : FALSE; enum cnv_charset cnvSet = convertCharsetEnum (cset); computedMaxBufSizeInNAWchars = (input.getStrLen()+1)*2; // in NAWchar elements for the worst case NAWcharBuf* output = checkSpace(heap, computedMaxBufSizeInNAWchars, unicodeString, addNullAtEnd); if ( output == NULL ) {errorcode = CNV_ERR_BUFFER_OVERRUN; return NULL;} NAWchar* target = output->data(); errorcode = LocaleToUTF16( cnv_version1, (const char *)input.data(), input.getStrLen(), (const char *)target, output->getBufSize()*BYTES_PER_NAWCHAR /* in bytes */, cnvSet, err_ptr, &byteCount, 0, addNullAtEnd, &lv_charCount); if (errorcode == CNV_ERR_NOINPUT) errorcode=0; // empty string is OK if (errorByteOff) *errorByteOff = err_ptr - (char *)input.data(); if (charCount) *charCount = (Int32)lv_charCount; // If errorcode != 0, LocaleToUTF16 will not add the NULL terminator if (errorcode == 0 && addNullAtEnd && byteCount > 0) { // Exclude the size (in bytes) of the NULL terminator from the byte count. if (byteCount > BYTES_PER_NAWCHAR) byteCount -= BYTES_PER_NAWCHAR; else byteCount = 0; } output->setStrLen/*in_NAWchar_s*/(byteCount/BYTES_PER_NAWCHAR); // excluding the NULL terminator if (outputBufferAllocatedByThisRoutine && output->getBufSize() > output->getStrLen() + 500) // allocated too much space { // Try to save space in the heap but still allocate 50 extra NAWchars so we do not need // to resize the buffer if there is a need to append a few more characters later on. // The additional 1 NAWchar is for the NULL terminator. NAWcharBuf * outNAWcharBuf2 = new (heap) NAWcharBuf ( output->getStrLen() + 51 // in NAWchars , heap ); if (outNAWcharBuf2 != NULL) // successful allocation { // Copy data to the newly allocated, smaller buffer. NAWstrncpy(outNAWcharBuf2->data(), output->data(), output->getStrLen()); outNAWcharBuf2->setStrLen/*in_NAWchar_s*/(output->getStrLen()); // Always append a UCS-2 NULL terminator but exclude it from the string length count. outNAWcharBuf2->data()[outNAWcharBuf2->getStrLen()] = 0; // Remove the old buffer and set up for the returned value and out parameter. unicodeString = outNAWcharBuf2; // return via the out parameter NAWcharBuf*& unicodeString NADELETE(output, NAWcharBuf, heap); output = outNAWcharBuf2; } } return output; }
short Env::process(SqlciEnv *sqlci_env) { // ## Should any of this text come from the message file, // ## i.e. from a translatable file for I18N? // When adding new variables, please keep the information in // alphabetic order Logfile *log = sqlci_env->get_logfile(); log->WriteAll("----------------------------------"); log->WriteAll("Current Environment"); log->WriteAll("----------------------------------"); bool authenticationEnabled = false; bool authorizationEnabled = false; bool authorizationReady = false; bool auditingEnabled = false; Int32 rc = sqlci_env->getAuthState(authenticationEnabled, authorizationEnabled, authorizationReady, auditingEnabled); // TDB: add auditing state log->WriteAllWithoutEOL("AUTHENTICATION "); if (authenticationEnabled) log->WriteAll("enabled"); else log->WriteAll("disabled"); log->WriteAllWithoutEOL("AUTHORIZATION "); if (authorizationEnabled) log->WriteAll("enabled"); else log->WriteAll("disabled"); log->WriteAllWithoutEOL("CURRENT DIRECTORY "); // NT_PORT (bv 10/24/96) Added NA_MAX_PATH here and in common/Platform.h log->WriteAll(getcwd((char *)NULL, NA_MAX_PATH)); log->WriteAllWithoutEOL("LIST_COUNT "); char buf[100]; Int32 len = sprintf(buf, "%u", sqlci_env->getListCount()); if (len-- > 0) if (buf[len] == 'L' || buf[len] == 'l') buf[len] = '\0'; log->WriteAll(buf); if (log->IsOpen()) { log->WriteAllWithoutEOL("LOG FILE "); log->WriteAll(log->Logname()); } else { log->WriteAll("LOG FILE"); } log->WriteAllWithoutEOL("MESSAGEFILE "); const char *mf = GetErrorMessageFileName(); log->WriteAll(mf ? mf : ""); #if 0 log->WriteAllWithoutEOL("ISO88591 MAPPING "); log->WriteAll(CharInfo::getCharSetName(sqlci_env->getIsoMappingCharset())); log->WriteAllWithoutEOL("DEFAULT CHARSET "); log->WriteAll(CharInfo::getCharSetName(sqlci_env->getDefaultCharset())); log->WriteAllWithoutEOL("INFER CHARSET "); log->WriteAll((sqlci_env->getInferCharset())?"ON":"OFF"); #endif // ## These need to have real values detected from the env and written out: // "US English" is more "politically correct" than "American English". // log->WriteAllWithoutEOL("MESSAGEFILE LANG US English\n"); log->WriteAllWithoutEOL("MESSAGEFILE VRSN "); char vmsgcode[10]; sprintf(vmsgcode, "%d", SQLERRORS_MSGFILE_VERSION_INFO); #pragma nowarn(1506) // warning elimination Error vmsg(vmsgcode, strlen(vmsgcode), Error::ENVCMD_); #pragma warn(1506) // warning elimination vmsg.process(sqlci_env); ComAnsiNamePart defaultCat; ComAnsiNamePart defaultSch; sqlci_env->getDefaultCatAndSch (defaultCat, defaultSch); CharInfo::CharSet TCS = sqlci_env->getTerminalCharset(); CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset(); if(TCS != CharInfo::UTF8 ) { NAString dCat = defaultCat.getExternalName(); NAString dSch = defaultSch.getExternalName(); charBuf cbufCat((unsigned char*)dCat.data(), dCat.length()); charBuf cbufSch((unsigned char*)dSch.data(), dSch.length()); NAWcharBuf* wcbuf = 0; Int32 errorcode = 0; wcbuf = csetToUnicode(cbufCat, 0, wcbuf, CharInfo::UTF8, errorcode); NAString* tempstr; if (errorcode != 0){ tempstr = new NAString(defaultCat.getExternalName().data()); } else { tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), TCS, NULL, TRUE); TrimNAStringSpace(*tempstr, FALSE, TRUE); // trim trailing blanks } log->WriteAllWithoutEOL("SQL CATALOG "); log->WriteAll(tempstr->data()); // Default Schema wcbuf = 0; // must 0 out to get next call to allocate memory. wcbuf = csetToUnicode(cbufSch, 0, wcbuf, CharInfo::UTF8, errorcode); if (errorcode != 0){ tempstr = new NAString(defaultSch.getExternalName().data()); } else { tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), TCS, NULL, TRUE); TrimNAStringSpace(*tempstr, FALSE, TRUE); // trim trailing blanks } log->WriteAllWithoutEOL("SQL SCHEMA "); log->WriteAll(tempstr->data()); } else { log->WriteAllWithoutEOL("SQL CATALOG "); log->WriteAll(defaultCat.getExternalName()); log->WriteAllWithoutEOL("SQL SCHEMA "); log->WriteAll(defaultSch.getExternalName()); } // On Linux we include the database user name and user ID in the // command output NAString username; rc = sqlci_env->getExternalUserName(username); log->WriteAllWithoutEOL("SQL USER CONNECTED "); if (rc >= 0) log->WriteAll(username.data()); else log->WriteAll("?"); rc = sqlci_env->getDatabaseUserName(username); log->WriteAllWithoutEOL("SQL USER DB NAME "); if (rc >= 0) log->WriteAll(username.data()); else log->WriteAll("?"); Int32 uid = 0; rc = sqlci_env->getDatabaseUserID(uid); log->WriteAllWithoutEOL("SQL USER ID "); if (rc >= 0) sprintf(buf, "%d", (int) uid); else strcpy(buf, "?"); log->WriteAll(buf); log->WriteAllWithoutEOL("TERMINAL CHARSET "); log->WriteAll(CharInfo::getCharSetName(sqlci_env->getTerminalCharset())); Int64 transid; if (sqlci_env->statusTransaction(&transid)) { // transaction is active. char transid_str[20]; convertInt64ToAscii(transid, transid_str); log->WriteAllWithoutEOL("TRANSACTION ID "); log->WriteAll(transid_str); log->WriteAll("TRANSACTION STATE in progress"); } else { log->WriteAll("TRANSACTION ID "); log->WriteAll("TRANSACTION STATE not in progress"); } if (log->isVerbose()) log->WriteAll("WARNINGS on"); else log->WriteAll("WARNINGS off"); return 0; }