예제 #1
0
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()
예제 #3
0
// 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()
예제 #4
0
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
}
예제 #5
0
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;

}