Int32 ComAnsiNameToUTF8 ( const NAWchar * inAnsiNameInUCS2 // in - valid ANSI SQL name in UCS2 , char * outBuf4AnsiNameInMBCS // out - out buffer , const Int32 outBufSizeInBytes // in - out buffer max len in bytes ) { if (outBuf4AnsiNameInMBCS == NULL || outBufSizeInBytes <= 0) return -2; // CNV_ERR_BUFFER_OVERRUN - No output buffer or not big enough if (inAnsiNameInUCS2 == NULL) return -3; // CNV_ERR_NOINPUT - No input buffer or input cnt <= 0 else if (NAWstrlen(inAnsiNameInUCS2) == 0) { outBuf4AnsiNameInMBCS[0] = 0; return 0; // success } const Int32 inAnsiNameInBytes = NAWstrlen(inAnsiNameInUCS2) * BYTES_PER_NAWCHAR; Int32 ansiNameCharSet = (Int32)ComGetNameInterfaceCharSet(); Int32 convAnsiNameCS = (Int32)/*cnv_charset*/convertCharsetEnum (ansiNameCharSet); char * pFirstByteOfTheUntranslatedChar = NULL; UInt32 iOutStrLenInBytesIncludingNull = 0; UInt32 iNumTranslatedChars = 0; Int32 iConvErrorCode = UTF16ToLocale ( cnv_version1 // in - const enum cnv_version , (const char *) inAnsiNameInUCS2 // in - const char * in_bufr , (Int32) inAnsiNameInBytes // in - const Int32 in_len_in_bytes , (const char *) outBuf4AnsiNameInMBCS // in/out - const char * out_bufr , (Int32) outBufSizeInBytes // in - const Int32 out_bufr_max_len_in bytes , (cnv_charset) convAnsiNameCS // in - enum cnv_charset conv_charset , pFirstByteOfTheUntranslatedChar // out - char * & first_untranslated_char , &iOutStrLenInBytesIncludingNull // out - UInt32 * output_data_len_p , 0 // in - const Int32 conv_flags , (Int32) TRUE // in - const Int32 add_null_at_end_Flag , (Int32) FALSE // in - const int32 allow_invalids , &iNumTranslatedChars // out - UInt32 * translated_char_cnt_p , (const char *) NULL /* i.e. "?" */ // in - const char * substitution_char = NULL ); return iConvErrorCode; }
charBuf* unicodeTocset(const NAWcharBuf& input, CollHeap *heap, charBuf*& csetString, Int32 cset, Int32 &errorcode, NABoolean addNullAtEnd, NABoolean allowInvalidCodePoint, Int32 *charCount, Int32 *errorByteOff) { char * err_ptr; UInt32 byteCount, lvCharCount; enum cnv_charset cnvSet = convertCharsetEnum (cset); Int32 cwidth = CharInfo::maxBytesPerChar((CharInfo::CharSet)cset); charBuf* output = NULL; if ( input.data() != NULL && input.getStrLen() > 0) { Int32 cSetTargetBufferSizeInBytes = input.getStrLen/*in_NAWchars*/()*cwidth+16; // memory is cheap UInt32 cSetTargetStrLenInBytes = 0; char *pTempTargetBuf = new(heap) char[cSetTargetBufferSizeInBytes]; errorcode = UTF16ToLocale ( cnv_version1 , (const char *)input.data() // source string , input.getStrLen()*BYTES_PER_NAWCHAR // source string length in bytes , (const char *)pTempTargetBuf // buffer for the converted string , cSetTargetBufferSizeInBytes // target buffer size in bytes , cnvSet // convert from UTF16 to cnvSet , err_ptr , &cSetTargetStrLenInBytes // out - length in bytes of the converted string , 0 , addNullAtEnd , allowInvalidCodePoint ); NADELETEBASICARRAY(pTempTargetBuf, heap); pTempTargetBuf = NULL; if (errorcode == 0 && cSetTargetStrLenInBytes > 0) output = checkSpace(heap, cSetTargetStrLenInBytes, csetString, addNullAtEnd); else // invoke the old code (i.e., keep the old behavior) output = checkSpace(heap, input.getStrLen()*cwidth, csetString, addNullAtEnd); } else // invoke the old code (i.e., keep the old behavior) output = checkSpace(heap, input.getStrLen()*cwidth, csetString, addNullAtEnd); if ( output == 0 ) {errorcode = CNV_ERR_BUFFER_OVERRUN; return 0;} unsigned char* target = output->data(); errorcode = UTF16ToLocale( cnv_version1, (const char *)input.data(), input.getStrLen()*BYTES_PER_NAWCHAR, (const char *)target, output->getBufSize(), cnvSet , err_ptr, &byteCount , 0, addNullAtEnd, allowInvalidCodePoint, &lvCharCount); if (errorcode == CNV_ERR_NOINPUT) errorcode=0; // empty string is OK if (errorByteOff) *errorByteOff = err_ptr - (char *)input.data(); if (charCount) *charCount = (Int32)lvCharCount; // 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. UInt32 nullLen = CharInfo::minBytesPerChar((CharInfo::CharSet) cset); if (byteCount > nullLen) byteCount -= nullLen; else byteCount = 0; } output -> setStrLen(byteCount/*in_bytes*/); // excluding the null terminator from the count return output; }
void ElemDDLColDef::setDefaultAttribute(ElemDDLNode * pColDefaultNode) { ElemDDLColDefault * pColDefault = NULL; ComBoolean isIdentityColumn = FALSE; NAType * pColumnDataType = columnDataType_; if (pColDefaultNode NEQ NULL) { ComASSERT(pColDefaultNode->castToElemDDLColDefault() NEQ NULL); pColDefault = pColDefaultNode->castToElemDDLColDefault(); } if (pColDefault NEQ NULL) { switch (pColDefault->getColumnDefaultType()) { case ElemDDLColDefault::COL_NO_DEFAULT: defaultClauseStatus_ = NO_DEFAULT_CLAUSE_SPEC; break; case ElemDDLColDefault::COL_DEFAULT: { defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC; if (pColDefault->getSGOptions()) { isIdentityColumn = TRUE; pSGOptions_ = pColDefault->getSGOptions(); pSGLocation_ = pColDefault->getSGLocation(); } else { ComASSERT(pColDefault->getDefaultValueExpr() NEQ NULL); pDefault_ = pColDefault->getDefaultValueExpr(); } // The cast ItemExpr to ConstValue for (ConstValue *)pDefault_; // statement below sets arbitary value for the isNULL_. // Bypass these checks for ID column (basically ITM_IDENTITY). ConstValue *cvDef = (ConstValue *)pDefault_; if ((cvDef && !cvDef->isNull()) && (!isIdentityColumn)) { const NAType *cvTyp = cvDef->getType(); NABoolean isAnErrorAlreadyIssued = FALSE; if ( cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE ) { CharInfo::CharSet defaultValueCS = ((const CharType *)cvTyp)->getCharSet(); // Always check for INFER_CHARSET setting before the ICAT setting. NAString inferCharSetFlag; if (getCharSetInferenceSetting(inferCharSetFlag) == TRUE && NOT cvDef->isStrLitWithCharSetPrefixSpecified()) { if (pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE && ((const CharType *)pColumnDataType)->getCharSet() == CharInfo::UCS2 && SqlParser_DEFAULT_CHARSET == CharInfo::UCS2 && defaultValueCS == CharInfo::ISO88591 ) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } else { cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE); } } else if (CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON && NOT cvDef->isStrLitWithCharSetPrefixSpecified() && cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE && SqlParser_DEFAULT_CHARSET == CharInfo::ISO88591 && defaultValueCS == CharInfo::UnknownCharSet) { cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE); } } // column default value has character data type if (NOT isAnErrorAlreadyIssued && pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE && cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE && ( CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON || NOT cvDef->isStrLitWithCharSetPrefixSpecified())) { const CharType *cdCharType = (const CharType *)pColumnDataType; const CharType *cvCharType = (const CharType *)cvTyp; CharInfo::CharSet cdCharSet = cdCharType->getCharSet(); // cd = column definition CharInfo::CharSet cvCharSet = cvCharType->getCharSet(); // cv = constant value if (cvCharSet == CharInfo::ISO88591) // default value is a _ISO88591 str lit { } else if ( (cvCharSet == CharInfo::UNICODE || // default value is a _UCS2 string literal cvCharSet == CharInfo::UTF8) && // or a _UTF8 string literal cdCharSet != cvCharSet ) { // // Check to see if all characters in the specified column default // string literal value can be successfully converted/translated // to the actual character set of the column. // char buf[2032]; // the output buffer - should be big enough buf[0] = '\0'; enum cnv_charset eCnvCS = convertCharsetEnum( cdCharSet ); const char * pInStr = cvDef->getRawText()->data(); Int32 inStrLen = cvDef->getRawText()->length(); char * p1stUnstranslatedChar = NULL; UInt32 outStrLenInBytes = 0; unsigned charCount = 0; // number of characters translated/converted Int32 cnvErrStatus = 0; char *pSubstitutionChar = NULL; Int32 convFlags = 0; if ( cvCharSet == CharInfo::UNICODE ) { cnvErrStatus = UTF16ToLocale ( cnv_version1 // in - const enum cnv_version version , pInStr // in - const char *in_bufr , inStrLen // in - const int in_len , buf // out - const char *out_bufr , 2016 // in - const int out_len , eCnvCS // in - enum cnv_charset charset , p1stUnstranslatedChar // out - char * & first_untranslated_char , &outStrLenInBytes // out - unsigned int *output_data_len_p , convFlags // in - const int cnv_flags , (Int32)TRUE // in - const int addNullAtEnd_flag , (Int32)FALSE // in - const int allow_invalids , &charCount // out - unsigned int * translated_char_cnt_p , pSubstitutionChar // in - const char *substitution_char ); } else // cvCharSet must be CharInfo::UTF8 { cnvErrStatus = UTF8ToLocale ( cnv_version1 // in - const enum cnv_version version , pInStr // in - const char *in_bufr , inStrLen // in - const int in_len , buf // out - const char *out_bufr , 2016 // in - const int out_len , eCnvCS // in - enum cnv_charset charset , p1stUnstranslatedChar // out - char * & first_untranslated_char , &outStrLenInBytes // out - unsigned int *output_data_len_p , (Int32)TRUE // in - const int addNullAtEnd_flag , (Int32)FALSE // in - const int allow_invalids , &charCount // out - unsigned int * translated_char_cnt_p , pSubstitutionChar // in - const char *substitution_char ); } switch (cnvErrStatus) { case 0: // success case CNV_ERR_NOINPUT: // an empty input string will get this error code { ConstValue *pMBStrLitConstValue ; // convert the string literal saved in cvDef (column default value) // from UNICODE (e.g. UTF16) to the column character data type if ( cdCharSet != CharInfo::UNICODE) { NAString mbs2(buf, PARSERHEAP()); // note that buf is NULL terminated pMBStrLitConstValue = new(PARSERHEAP()) ConstValue ( mbs2 , cdCharSet // use this for str lit prefix , CharInfo::DefaultCollation , CharInfo::COERCIBLE , PARSERHEAP() ); } else { NAWString mbs2((NAWchar*)buf, PARSERHEAP()); // note that buf is NULL terminated pMBStrLitConstValue = new(PARSERHEAP()) ConstValue ( mbs2 , cdCharSet // use this for str lit prefix , CharInfo::DefaultCollation , CharInfo::COERCIBLE , PARSERHEAP() ); } delete pDefault_; // deallocate the old ConstValue object cvDef = NULL; // do not use cvDef anymore pDefault_ = pMBStrLitConstValue; pColDefault->setDefaultValueExpr(pDefault_); } break; case CNV_ERR_INVALID_CHAR: { // 1401 == CAT_UNABLE_TO_CONVERT_COLUMN_DEFAULT_VALUE_TO_CHARSET *SqlParser_Diags << DgSqlCode(-1401) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(CharInfo::getCharSetName(cdCharSet)); } break; case CNV_ERR_BUFFER_OVERRUN: // output buffer not big enough case CNV_ERR_INVALID_CS: default: CMPABORT_MSG("Parser internal logic error"); break; } // switch } else if(!pColumnDataType->isCompatible(*cvTyp)) { if (NOT isAnErrorAlreadyIssued) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } } } // column has character data type else // if interval data type, the default value must have the same // interval qualifier as the column. if (NOT isAnErrorAlreadyIssued && (!pColumnDataType->isCompatible(*cvTyp) || (pColumnDataType->getTypeQualifier() == NA_INTERVAL_TYPE && pColumnDataType->getFSDatatype() != cvTyp->getFSDatatype()))) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } } } break; case ElemDDLColDefault::COL_COMPUTED_DEFAULT: { defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC; computedDefaultExpr_ = pColDefault->getComputedDefaultExpr(); } break; default: CMPABORT_MSG("Parser internal logic error"); break; } } }