void ElemDDLColViewDef::setColumnAttribute(ElemDDLNode * pColAttr) { switch(pColAttr->getOperatorType()) { case ELM_COL_HEADING_ELEM : if (isHeadingSpec_) { // Duplicate HEADING clauses in column definition. *SqlParser_Diags << DgSqlCode(-3051) << DgColumnName(ToAnsiIdentifier(getColumnName())); } ComASSERT(pColAttr->castToElemDDLColHeading() NEQ NULL); heading_ = pColAttr->castToElemDDLColHeading()->getColumnHeading(); isHeadingSpec_ = TRUE; // Report an error if heading_ is too long. if (heading_.length() > ElemDDLColHeading::maxHeadingLength) { *SqlParser_Diags << DgSqlCode(-3132) << DgColumnName(ToAnsiIdentifier(getColumnName())); } break; default : ABORT("internal logic error"); break; } // switch }
// ----------------------------------------------------------------------- // Method for creating NAType from desc_struct. // ----------------------------------------------------------------------- NABoolean NAColumn::createNAType(columns_desc_struct *column_desc /*IN*/, const NATable *table /*IN*/, NAType *&type /*OUT*/, NAMemory *heap /*IN*/, Lng32 * errorCode ) { // // Compute the NAType for this column // #define REC_INTERVAL REC_MIN_INTERVAL DataType datatype = column_desc->datatype; if (REC_MIN_INTERVAL <= datatype && datatype <= REC_MAX_INTERVAL) datatype = REC_INTERVAL; Lng32 charCount = column_desc->length; if ( DFS2REC::isAnyCharacter(column_desc->datatype) ) { if ( CharInfo::isCharSetSupported(column_desc->character_set) == FALSE ) { if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4082) << DgTableName(makeTableName(table, column_desc)); } else { *errorCode = 4082; } return TRUE; // error } if ( CharInfo::is_NCHAR_MP(column_desc->character_set) ) charCount /= SQL_DBCHAR_SIZE; } switch (datatype) { case REC_BPINT_UNSIGNED : type = new (heap) SQLBPInt(column_desc->precision, column_desc->null_flag, FALSE, heap); break; case REC_BIN8_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLTiny(TRUE, column_desc->null_flag, heap ); break; case REC_BIN8_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLTiny(FALSE, column_desc->null_flag, heap ); break; case REC_BIN16_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLSmall(TRUE, column_desc->null_flag, heap ); break; case REC_BIN16_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLSmall(FALSE, column_desc->null_flag, heap ); break; case REC_BIN32_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLInt(TRUE, column_desc->null_flag, heap ); break; case REC_BIN32_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLInt(FALSE, column_desc->null_flag, heap ); break; case REC_BIN64_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLLargeInt(TRUE, column_desc->null_flag, heap ); break; case REC_BIN64_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLLargeInt(FALSE, column_desc->null_flag, heap ); break; case REC_DECIMAL_UNSIGNED: type = new (heap) SQLDecimal(column_desc->length, column_desc->scale, FALSE, column_desc->null_flag, heap ); break; case REC_DECIMAL_LSE: type = new (heap) SQLDecimal(column_desc->length, column_desc->scale, TRUE, column_desc->null_flag, heap ); break; case REC_NUM_BIG_UNSIGNED: type = new (heap) SQLBigNum(column_desc->precision, column_desc->scale, TRUE, // is a real bignum FALSE, column_desc->null_flag, heap ); break; case REC_NUM_BIG_SIGNED: type = new (heap) SQLBigNum(column_desc->precision, column_desc->scale, TRUE, // is a real bignum TRUE, column_desc->null_flag, heap ); break; case REC_FLOAT32: type = new (heap) SQLReal(column_desc->null_flag, heap, column_desc->precision); break; case REC_FLOAT64: type = new (heap) SQLDoublePrecision(column_desc->null_flag, heap, column_desc->precision); break; case REC_BYTE_F_DOUBLE: charCount /= SQL_DBCHAR_SIZE; // divide the storage length by 2 type = new (heap) SQLChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_F_ASCII: if (column_desc->character_set == CharInfo::UTF8 || (column_desc->character_set == CharInfo::SJIS && column_desc->encoding_charset == CharInfo::SJIS)) { Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set); Lng32 sizeInChars = charCount ; // Applies when CharLenUnit == BYTES if ( column_desc->precision > 0 ) sizeInChars = column_desc->precision; type = new (heap) SQLChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/), column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, // varLenFlag column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT, // Coercibility column_desc->encoding_charset ); } else // keep the old behavior type = new (heap) SQLChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_V_DOUBLE: charCount /= SQL_DBCHAR_SIZE; // divide the storage length by 2 // fall thru case REC_BYTE_V_ASCII: if (column_desc->character_set == CharInfo::SJIS || column_desc->character_set == CharInfo::UTF8) { Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set); Lng32 sizeInChars = charCount ; // Applies when CharLenUnit == BYTES if ( column_desc->precision > 0 ) sizeInChars = column_desc->precision; type = new (heap) SQLVarChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/), column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT, // Coercibility column_desc->encoding_charset ); } else // keep the old behavior type = new (heap) SQLVarChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_V_ASCII_LONG: type = new (heap) SQLLongVarChar(charCount, FALSE, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_DATETIME: type = DatetimeType::constructSubtype( column_desc->null_flag, column_desc->datetimestart, column_desc->datetimeend, column_desc->datetimefractprec, heap ); CMPASSERT(type); if (!type->isSupportedType()) { column_desc->defaultClass = COM_NO_DEFAULT; // can't set a default for these, either. // 4030 Column is an unsupported combination of datetime fields if (!errorCode) { *CmpCommon::diags() << DgSqlCode(4030) << DgColumnName(makeColumnName(table, column_desc)) << DgInt0(column_desc->datetimestart) << DgInt1(column_desc->datetimeend) << DgInt2(column_desc->datetimefractprec); } else { *errorCode = 4030; } } break; case REC_INTERVAL: type = new (heap) SQLInterval(column_desc->null_flag, column_desc->datetimestart, column_desc->intervalleadingprec, column_desc->datetimeend, column_desc->datetimefractprec, heap ); CMPASSERT(type); if (! ((SQLInterval *)type)->checkValid(CmpCommon::diags())) return TRUE; // error if (!type->isSupportedType()) { column_desc->defaultClass = COM_NO_DEFAULT; // can't set a default for these, either. if (!errorCode) *CmpCommon::diags() << DgSqlCode(3044) << DgString0(column_desc->colname); else *errorCode = 3044; } break; case REC_BLOB : type = new (heap) SQLBlob(column_desc->precision, Lob_Invalid_Storage, column_desc->null_flag); break; case REC_CLOB : type = new (heap) SQLClob(column_desc->precision, Lob_Invalid_Storage, column_desc->null_flag); break; default: { // 4031 Column %s is an unknown data type, %d. if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4031) << DgColumnName(makeColumnName(table, column_desc)) << DgInt0(column_desc->datatype); } else { *errorCode = 4031; } return TRUE; // error } } // end switch (column_desc->datatype) CMPASSERT(type); if (type->getTypeQualifier() == NA_CHARACTER_TYPE) { CharInfo::Collation co = ((CharType *)type)->getCollation(); // a "mini-cache" to avoid proc call, for perf static THREAD_P CharInfo::Collation cachedCO = CharInfo::UNKNOWN_COLLATION; static THREAD_P Int32 cachedFlags = CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS; if (cachedCO != co) { cachedCO = co; cachedFlags = CharInfo::getCollationFlags(co); } if (cachedFlags & CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS) { // //## The NCHAR/COLLATE NSK-Rel1 project is forced to disallow all user- // defined collations here. What we can't handle is: // - full support! knowledge of how to really collate! // - safe predicate-ability of collated columns, namely // . ORDER/SEQUENCE/SORT BY // MIN/MAX // < <= > >= // These *would* have been disallowed by the // CollationInfo::ORDERED_CMP_ILLEGAL flag. // . DISTINCT // GROUP BY // = <> // These *would* have been disallowed by the // CollationInfo::EQ_NE_CMP_ILLEGAL flag. // . SELECTing a collated column which is a table or index key // We *would* have done full table scan only, based on flag // . INS/UPD/DEL involving a collated column which is a key // We *would* have had to disallow this, based on flag; // otherwise we would position in wrong and corrupt either // our partitioning or b-trees or both. // See the "MPcollate.doc" document, and // see sqlcomp/DefaultValidator.cpp ValidateCollationList comments. // { // 4069 Column TBL.COL uses unsupported collation COLLAT. if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4069) << DgColumnName(makeColumnName(table, column_desc)); } else { *errorCode= 4069; } return TRUE; // error } } } return FALSE; // no error } // createNAType()
// constructor ElemDDLColDef::ElemDDLColDef( const NAString *columnFamily, const NAString *columnName, NAType * pColumnDataType, ElemDDLNode * pColAttrList, CollHeap * heap) : ElemDDLNode(ELM_COL_DEF_ELEM), columnName_(*columnName, heap), columnDataType_(pColumnDataType), defaultClauseStatus_(DEFAULT_CLAUSE_NOT_SPEC), isNewAdjustedDefaultConstValueNode_(FALSE), pDefault_(NULL), isHeadingSpec_(FALSE), heading_(heap), columnClass_(COM_USER_COLUMN), isNotNullSpec_(FALSE), isNotNullNondroppable_(FALSE), isLoggableSpec_(FALSE), isLoggable_(TRUE), pConstraintNotNull_(NULL), isPrimaryKeySpec_(FALSE), pConstraintPK_(NULL), columnConstraintArray_(heap), primaryKeyColRefArray_(heap), direction_(COM_OUTPUT_COLUMN), pSGOptions_(NULL), pSGLocation_(NULL), isDivisionColumn_(FALSE), divisionColumnSeqNum_(-1), isLobAttrsSpec_(FALSE), lobStorage_(Lob_HDFS_File), isSeabaseSerializedSpec_(FALSE), seabaseSerialized_(FALSE), isColDefaultSpec_(FALSE) { // ComASSERT(pColumnDataType NEQ NULL); if (columnFamily) columnFamily_ = *columnFamily; if (pColumnDataType NEQ NULL) { const NAString dataTypeName = pColumnDataType->getTypeName(); // Create table with data type DATETIME not supported. Must check for DATE, // TIME, and TIMESTAMP as well since DATETIME might be converted into these, if( dataTypeName == "DATETIME" || dataTypeName == "DATE" || dataTypeName == "TIME" || dataTypeName == "TIMESTAMP" ) { // Check flag to see if DATETIME originally specified if( ((DatetimeIntervalCommonType *)pColumnDataType)-> getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE)) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("DATETIME"); } return; } } // Create table with data type INTERVAL with FRACTION field(s) not supported else if (dataTypeName == "INTERVAL") { // Check flag to see if FRACTION was originally specified if( ((DatetimeIntervalCommonType *)pColumnDataType)-> getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE)) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("INTERVAL with FRACTION field(s)"); } return; } // Check to see if interval second is specified with leading // precision of 0 if(!((SQLInterval *)pColumnDataType)->isSupportedType()) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("INTERVAL SECOND with leading precision 0"); } return; } } } setChild(INDEX_ELEM_DDL_COL_ATTR_LIST, pColAttrList); // initialize data member pDefault_ ComBoolean isIdentityColumn = FALSE; // // Traverse the list of column attributes to check for duplicate // HEADING clause and duplicate NOT NULL column constraint definition // if (pColAttrList NEQ NULL) { for (CollIndex index = 0; index < pColAttrList->entries(); index++) { setColumnAttribute((*pColAttrList)[index]); } } // At this point we will know if the user // has specified NOT NULL NOT DROPPABLE for IDENTITY // column. If not specified, then automatically add // it. if (pSGOptions_) //isIdentityColumn { // if NOT NULL not specified, then specify it here. if(NOT getIsConstraintNotNullSpecified()) isNotNullSpec_ = TRUE; // [NOT] DROPPABLE is the only attribute for NOT NULL. if (pConstraintNotNull_) { // if DROPPABLE was specified explicity then raise an error. if (pConstraintNotNull_->isDroppableSpecifiedExplicitly()) { *SqlParser_Diags << DgSqlCode(-3413) << DgColumnName(ToAnsiIdentifier(getColumnName())); return; } else { // add the NOT DROPPABLE attribute to the NOT NULL . pConstraintNotNull_->setConstraintAttributes (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); } } else { // by default NOT NULLs are NOT DROPPABLEs as well in SQL/MX pConstraintNotNull_ = new (PARSERHEAP()) ElemDDLConstraintNotNull(PARSERHEAP()); pConstraintNotNull_->setConstraintAttributes (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); } } //if isIdentityColumn // // All column attributes has been checked and saved. // If there exists a NOT NULL NONDROPPABLE constraint // associating with the currently defined column, makes // sure that the associating NAType (data type) parse // node does not allow null values. // if (getIsConstraintNotNullSpecified() AND NOT getConstraintNotNull()->isDroppable()) { isNotNullNondroppable_ = TRUE; if (columnDataType_) columnDataType_->setNullable(FALSE); } } // ElemDDLColDef()
void ElemDDLColDef::setColumnAttribute(ElemDDLNode * pColAttr) { switch(pColAttr->getOperatorType()) { case ELM_COL_HEADING_ELEM : if (isHeadingSpec_) { // Duplicate HEADING clauses in column definition. *SqlParser_Diags << DgSqlCode(-3051) << DgColumnName(ToAnsiIdentifier(getColumnName())); } ComASSERT(pColAttr->castToElemDDLColHeading() NEQ NULL); heading_ = pColAttr->castToElemDDLColHeading()->getColumnHeading(); isHeadingSpec_ = TRUE; // Report an error if heading_ is too long. if (heading_.length() > ElemDDLColHeading::maxHeadingLength) { *SqlParser_Diags << DgSqlCode(-3132) << DgColumnName(ToAnsiIdentifier(getColumnName())); } break; case ELM_CONSTRAINT_CHECK_ELEM : ComASSERT(pColAttr->castToElemDDLConstraintCheck() NEQ NULL); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); break; case ELM_CONSTRAINT_NOT_NULL_ELEM : ComASSERT(pColAttr->castToElemDDLConstraintNotNull() NEQ NULL); if (isNotNullSpec_) { // Duplicate NOT NULL clauses in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("NOT NULL") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isNotNullSpec_ = TRUE; pConstraintNotNull_ = pColAttr->castToElemDDLConstraintNotNull(); if (NOT pConstraintNotNull_->isDroppable()) { isNotNullNondroppable_ = TRUE; if (columnDataType_) columnDataType_->setNullable(FALSE); } // Note that we do not insert pConstraintNotNull_ into // columnConstraintArray_ even though Not Null constraint is // also a column constraint. The user can use the accessors // getIsConstraintNotNullSpecified and getConstraintNotNull // instead. break; case ELM_LOGGABLE: ComASSERT( NULL NEQ pColAttr->castToElemDDLLoggable()) if(TRUE == isLoggableSpec_) { // Duplicate LOGGABLE in column definition. *SqlParser_Diags << DgSqlCode(-12064) << DgColumnName(ToAnsiIdentifier(getColumnName())); } isLoggableSpec_ = TRUE; isLoggable_ = pColAttr->castToElemDDLLoggable()->getIsLoggable(); break; case ELM_CONSTRAINT_PRIMARY_KEY_COLUMN_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintPKColumn() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintPKColumn() ->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); if (isPrimaryKeySpec_) { // Duplicate PRIMARY KEY clauses in column definition. *SqlParser_Diags << DgSqlCode(-3053) << DgColumnName(ToAnsiIdentifier(getColumnName())); } isPrimaryKeySpec_ = TRUE; ElemDDLConstraintPKColumn * pColPKConstraint = pColAttr->castToElemDDLConstraintPKColumn(); // // Copies the pointer to the parse node representing the column // primary key constraint to pConstraintPK_ so the user (caller) // can access the information easier. Note that this pointer is // not inserted into columnConstraintArray_ because primary key // constraint is special. (There can only be one primary key // constraint associating with a table.) The user (caller) can // use method getIsConstraintPKSpecified() and getConstraintPK() // to get the primary key constraint information. // pConstraintPK_ = pColPKConstraint; // The column name is not specified in the column primary key // constraint definition. To make the user (caller) to access // to this information easier, creates a parse node containing // the column name. ComASSERT(pColPKConstraint->getColumnRefList() EQU NULL); ElemDDLColRef * pColRef = new(PARSERHEAP()) ElemDDLColRef(getColumnName(), pColPKConstraint-> getColumnOrdering(), PARSERHEAP()); pColPKConstraint->setColumnRefList(pColRef); primaryKeyColRefArray_.insert(pColRef); } break; case ELM_CONSTRAINT_REFERENTIAL_INTEGRITY_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintRI() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintRI()->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); // // The column name is not specified in the column referential // integrity constraint definition. To make the user (caller) // to access to this information easier, creates a parse node // containing the column name. // ElemDDLConstraintRI * pColRIConstraint = pColAttr->castToElemDDLConstraintRI(); ComASSERT(pColRIConstraint->getReferencingColumnNameList() EQU NULL); ElemDDLColName * pColName = new(PARSERHEAP()) ElemDDLColName(getColumnName()); pColRIConstraint->setReferencingColumnNameList(pColName); } break; case ELM_CONSTRAINT_UNIQUE_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintUnique() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintUnique()->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); // // The column name is not specified in the column unique // constraint definition. To make the user (caller) to access // to this information easier, creates a parse node containing // the column name. // ElemDDLConstraintUnique * pColUniqueConstraint = pColAttr->castToElemDDLConstraintUnique(); ComASSERT(pColUniqueConstraint->getColumnRefList() EQU NULL); ElemDDLColRef * pColRef = new(PARSERHEAP()) ElemDDLColRef(getColumnName(), COM_ASCENDING_ORDER, PARSERHEAP()); pColUniqueConstraint->setColumnRefList(pColRef); } break; case ELM_LOBATTRS: { ComASSERT( NULL NEQ pColAttr->castToElemDDLLobAttrs()) if(TRUE == isLobAttrsSpec_) { // Duplicate LOB attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("LOB") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isLobAttrsSpec_ = TRUE; lobStorage_ = pColAttr->castToElemDDLLobAttrs()->getLobStorage(); } break; case ELM_SEABASE_SERIALIZED: { ComASSERT( NULL NEQ pColAttr->castToElemDDLSeabaseSerialized()) if(TRUE == isSeabaseSerializedSpec_) { // Duplicate SERIALIZED attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("SERIALIZED") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isSeabaseSerializedSpec_ = TRUE; seabaseSerialized_ = pColAttr->castToElemDDLSeabaseSerialized()->serialized(); } break; case ELM_COL_DEFAULT_ELEM: { ComASSERT( NULL NEQ pColAttr->castToElemDDLColDefault()); if(TRUE == isColDefaultSpec_) { // Duplicate DEFAULT attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("DEFAULT") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isColDefaultSpec_ = TRUE; setDefaultAttribute(pColAttr->castToElemDDLColDefault()); } break; default : ABORT("internal logic error"); break; } // switch }
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; } } }
// ***************************************************************************** // * * // * Function: checkAccessPrivileges * // * * // * This function determines if a user has the requesite privileges to * // * access the referenced objects that comprise the view. * // * * // ***************************************************************************** // * * // * Parameters: * // * * // * <vtul> const ParTableUsageList & In * // * is a reference to a list of objects used by the view. * // * * // * <vctcul> const ParViewColTableColsUsageList & In * // * is a reference to the list of columns used by the view. * // * * // * <privilegesBitmap> PrivMgrBitmap & Out * // * passes back the union of privileges the user has on the referenced * // * objects. * // * * // * <grantableBitmap> PrivMgrBitmap & Out * // * passes back the union of the with grant option authority the user has * // * on the referenced objects. * // * * // ***************************************************************************** // * * // * Returns: bool * // * * // * true: User has requisite privileges; bitmap unions returned. * // * false: Could not retrieve privileges or user does not have requesite * // * privileges; see diags area for error details. * // * * // ***************************************************************************** static bool checkAccessPrivileges( const ParTableUsageList & vtul, const ParViewColTableColsUsageList & vctcul, PrivMgrBitmap & privilegesBitmap, PrivMgrBitmap & grantableBitmap) { BindWA bindWA(ActiveSchemaDB(),CmpCommon::context(),FALSE/*inDDL*/); bool missingPrivilege = false; NAString extUsedObjName; // generate the lists of privileges and grantable privileges // a side effect is to return an error if basic privileges are not granted for (CollIndex i = 0; i < vtul.entries(); i++) { if (vtul[i].getSpecialType() == ExtendedQualName::SG_TABLE) continue; ComObjectName usedObjName(vtul[i].getQualifiedNameObj().getQualifiedNameAsAnsiString(), vtul[i].getAnsiNameSpace()); const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE); const NAString extUsedObjName = usedObjName.getExternalName(TRUE); CorrName cn(objectNamePart,STMTHEAP, schemaNamePart,catalogNamePart); NATable *naTable = bindWA.getNATable(cn); if (naTable == NULL) { SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges"); return false; } // Grab privileges from the NATable structure PrivMgrUserPrivs *privs = naTable->getPrivInfo(); if (privs == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); return false; } // Requester must have at least select privilege if ( !privs->hasSelectPriv() ) missingPrivilege = true; // Summarize privileges privilegesBitmap &= privs->getObjectBitmap(); grantableBitmap &= privs->getGrantableBitmap(); } if (!missingPrivilege) return true; missingPrivilege = false; PrivColumnBitmap colPrivBitmap; PrivColumnBitmap colGrantableBitmap; PrivMgrPrivileges::setColumnPrivs(colPrivBitmap); PrivMgrPrivileges::setColumnPrivs(colGrantableBitmap); for (size_t i = 0; i < vctcul.entries(); i++) { const ParViewColTableColsUsage &vctcu = vctcul[i]; int32_t usingColNum = vctcu.getUsingViewColumnNumber(); const ColRefName &usedColRef = vctcu.getUsedObjectColumnName(); ComObjectName usedObjName; usedObjName = usedColRef.getCorrNameObj().getQualifiedNameObj(). getQualifiedNameAsAnsiString(); const NAString catalogNamePart = usedObjName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = usedObjName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = usedObjName.getObjectNamePartAsAnsiString(TRUE); extUsedObjName = usedObjName.getExternalName(TRUE); CorrName cn(objectNamePart,STMTHEAP,schemaNamePart,catalogNamePart); NATable *naTable = bindWA.getNATable(cn); if (naTable == NULL) { SEABASEDDL_INTERNAL_ERROR("Bad NATable pointer in checkAccessPrivileges"); return -1; } const NAColumnArray &nacolArr = naTable->getNAColumnArray(); ComString usedObjColName(usedColRef.getColName()); const NAColumn * naCol = nacolArr.getColumn(usedObjColName); if (naCol == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_COLUMN_DOES_NOT_EXIST_ERROR) << DgColumnName(usedObjColName); return false; } int32_t usedColNumber = naCol->getPosition(); // Grab privileges from the NATable structure PrivMgrUserPrivs *privs = naTable->getPrivInfo(); if (privs == NULL) { *CmpCommon::diags() << DgSqlCode(-CAT_UNABLE_TO_RETRIEVE_PRIVS); return false; } // If the user is missing SELECT on at least one column-level privilege, // view cannot be created. No need to proceed. if (!privs->hasColSelectPriv(usedColNumber)) { missingPrivilege = true; break; } colPrivBitmap &= privs->getColumnPrivBitmap(usedColNumber); colGrantableBitmap &= privs->getColumnGrantableBitmap(usedColNumber); } if (missingPrivilege || vctcul.entries() == 0) { *CmpCommon::diags() << DgSqlCode(-4481) << DgString0("SELECT") << DgString1(extUsedObjName.data()); return false; } for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ ) { if (colPrivBitmap.test(PrivType(i))) privilegesBitmap.set(PrivType(i)); if (colGrantableBitmap.test(PrivType(i))) grantableBitmap.set(PrivType(i)); } return true; }