// change literals of a cacheable query into ConstantParameters ItemExpr* Assign::normalizeForCache(CacheWA& cwa, BindWA& bindWA) { if (nodeIsNormalizedForCache()) { return this; } if (cwa.getPhase() == CmpMain::PARSE) { child(1) = child(1)->normalizeForCache(cwa, bindWA); } else if (cwa.getPhase() >= CmpMain::BIND) { ItemExpr *leftC=child(0), *rightC=child(1); OperatorTypeEnum leftO = leftC->getOperatorType(); OperatorTypeEnum rightO = rightC->getOperatorType(); ConstantParameter *cParam; if (leftO == ITM_BASECOLUMN && rightO == ITM_CONSTANT // normalizeForCache only constants that can be safely backpatched. // part of fix to CR 10-010726-4109. && isSafelyCoercible(cwa) // normalizeForCache only constants that are contained in the original // SQL query so that each parameter can be backpatched by the // corresponding constant from the query. This is to fix regression // failure MP core/test055 where a SystemLiteral was inserted when the // Keytag for a MP table column is not zero. see LeafInsert::bindNode(). // The offending query in MP core/test055 is // update t055t9v set b = b + 1 where current of c10; && NOT ((ConstValue*)rightC)->isSystemProvided() ) { ConstValue *val = (ConstValue*)rightC; if (!val->isNull()) { cParam = new (cwa.wHeap()) ConstantParameter ((ConstValue*)rightC, cwa.wHeap(), ((BaseColumn*)leftC)->getNAColumn()->getType()); cwa.addConstParam(cParam, bindWA); child(1) = cParam; } // else val is null; keep null as is. // this is part of a fix to genesis case: 10-010618-3484. } else { child(1) = child(1)->normalizeForCache(cwa, bindWA); } } markAsNormalizedForCache(); return this; }
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; } } }
NABoolean CmpSPOutputFormat::ElemDDLColDef2ColumnDescStruct (ElemDDLColDef* elem, const char* tableName, columns_desc_struct* colDesc) { // Just copy the pointer for this name -- // no need to alloc + strcpy a la copyString colDesc->tablename = (char *)tableName; colDesc->colname = copyString(elem->getColumnName()); // colDesc->colnumber, filled outside NAType* genericType = elem->getColumnDataType(); colDesc->datatype = (DataType) genericType->getFSDatatype(); colDesc->length = genericType->getNominalSize(); colDesc->pictureText = (char *)emptyString; // The logic for converting from an NAType to column_desc is also // in the catman code -- readRealArk.cpp::convertColumn(). Any changes // there must be reflected here as well and vice versa. if ( genericType->getTypeQualifier() == NA_NUMERIC_TYPE ) { NumericType & nt = *((NumericType*)genericType); colDesc->scale = nt.getScale(); // if this is a float (real or double) datatype, // then get the precision. Otherwise, for other // numeric type, get the precision only if it // is not binary precision. if(nt.isExact() && nt.binaryPrecision() && (nt.getFSDatatype() != REC_BPINT_UNSIGNED)) { colDesc->precision = 0; } else { colDesc->precision = nt.getPrecision(); } } else { colDesc->scale = 0; colDesc->precision = 0; } #pragma nowarn(1506) // warning elimination if ( genericType->getTypeQualifier() == NA_CHARACTER_TYPE ) { CharType & charType = (CharType &) *genericType; colDesc->character_set = charType.getCharSet(); colDesc->encoding_charset = charType.getEncodingCharSet(); colDesc->collation_sequence = charType.getCollation(); colDesc->upshift = charType.isUpshifted(); } if ( genericType->getTypeQualifier() == NA_DATETIME_TYPE || genericType->getTypeQualifier() == NA_INTERVAL_TYPE ) { DatetimeIntervalCommonType& dti = (DatetimeIntervalCommonType& )*genericType; colDesc->datetimestart = dti.getStartField(); colDesc->datetimeend = dti.getEndField(); colDesc->datetimefractprec = dti.getFractionPrecision(); colDesc->intervalleadingprec = dti.getLeadingPrecision(); } #pragma warn(1506) // warning elimination // offset, to be done (do we need it?) colDesc->null_flag = NOT elem->isNotNullConstraintSpecified(); colDesc->colclass = 'U'; colDesc->addedColumn = 0; colDesc->uec = (Cardinality)0; colDesc->highval = colDesc->lowval = 0; // defaultclass, to be done? (not referenced, not needed) ConstValue *pDefVal = (ConstValue*)elem->getDefaultValueExpr(); if (!pDefVal || pDefVal->isNull()) colDesc->defaultvalue = NULL; else colDesc->defaultvalue = copyString(pDefVal->getConstStr()); return TRUE; }