ex_expr::exp_return_type ex_function_substring_doublebyte::eval(char *op_data[],
						 CollHeap* heap,
						 ComDiagsArea** diagsArea)
{
#pragma nowarn(1506)   // warning elimination 
  Lng32 len1 = getOperand(1)->getLength(op_data[-MAX_OPERANDS+1]);
#pragma warn(1506)  // warning elimination 

  len1 /= sizeof(NAWchar); // len1 now counts in terms of number of NCHARs.
  
  // Get the starting position from operand 2.
  Int64 start = *(Lng32 *)op_data[2];  
  
  // If operand 3 exists, get the length of substring from operand 3.
  // Otherwise, length of the substring is (len1 - start + 1).
  Int64 len = 0;
  Int64 temp = 0;
  if (getNumOperands() == 4)
    {
      len = *(Lng32 *)op_data[3];
      temp = start + len;
    }
  else
    {
      if (start > (len1 + 1)) 
	temp = start;
      else
	temp = len1 + 1;
    }
  
  // Check for error conditions.
  if (temp < start)
    {
      ExRaiseSqlError(heap, diagsArea, EXE_SUBSTRING_ERROR);
      return ex_expr::EXPR_ERROR;
    }
  
  Lng32 len0 = 0;
  if ((start <= len1) && (temp > 0)) 
    {
      if (start < 1)
        start = 1;
      if (temp > (len1 + 1))
        temp = len1 + 1;
      len0 = int64ToInt32(temp - start);     
    }

  len0 *= sizeof(NAWchar);  // convert the length back into the number of octets.
  
  // Result is always a varchar, so store the length of substring 
  // in the varlen indicator.
  getOperand(0)->setVarLength(len0, op_data[-MAX_OPERANDS]);
  
  // Now, copy the substring of operand 1 from the starting position into
  // operand 0, if len0 is greater than 0.
  if (len0 > 0) 
    str_cpy_all(op_data[0], &op_data[1][sizeof(NAWchar)*(int64ToInt32(start) - 1)], len0); 
  
  return ex_expr::EXPR_OK;
}
Exemple #2
0
void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
  assert(HasHungOffUses && "realloc must have hung off uses");

  unsigned OldNumUses = getNumOperands();

  // We don't support shrinking the number of uses.  We wouldn't have enough
  // space to copy the old uses in to the new space.
  assert(NewNumUses > OldNumUses && "realloc must grow num uses");

  Use *OldOps = getOperandList();
  allocHungoffUses(NewNumUses, IsPhi);
  Use *NewOps = getOperandList();

  // Now copy from the old operands list to the new one.
  std::copy(OldOps, OldOps + OldNumUses, NewOps);

  // If this is a Phi, then we need to copy the BB pointers too.
  if (IsPhi) {
    auto *OldPtr =
        reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef);
    auto *NewPtr =
        reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef);
    std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
  }
  Use::zap(OldOps, OldOps + OldNumUses, true);
}
ex_expr::exp_return_type ExpLOBfuncSubstring::eval(char *op_data[],
						   CollHeap *heap,
						   ComDiagsArea** diagsArea)
{

  Int32 len1_bytes = getOperand(1)->getLength(op_data[-MAX_OPERANDS+1]);
  Int32 startPos = *(Lng32 *)op_data[2];
  
  Int32 specifiedLen = len1_bytes;
  if (getNumOperands() == 4)
    specifiedLen = *(Lng32 *)op_data[3]; 

  return ex_expr::EXPR_OK;
}
Exemple #4
0
void User::replaceUsesOfWith(Value *From, Value *To) {
  if (From == To) return;   // Duh what?

  assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
         "Cannot call User::replaceUsesOfWith on a constant!");

  for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
    if (getOperand(i) == From) {  // Is This operand is pointing to oldval?
      // The side effects of this setOperand call include linking to
      // "To", adding "this" to the uses list of To, and
      // most importantly, removing "this" from the use list of "From".
      setOperand(i, To); // Fix it now...
    }
}
// ExpBitMuxFunction::eval
//
// Evaluate the BitMux function.
//
// IN     : op_data      - output/input vector
// IN     : heap         - not used
// IN     : comDiagsArea - not used
// RETURN : ex_expr::EXPR_OK is no errors
// EFFECTS: Writes byte equality comparable output to
//          result attribute based on input attributes.
// PRECOND: The op_data vector points to the NULL/VARCHAR and data.
// PSTCONT: The BitMuxing result is stored in the result attribute.
//
ex_expr::exp_return_type ExpBitMuxFunction::eval(char *op_data[],
						 CollHeap*,
						 ComDiagsArea**) {
  
  // Get the pointer to the start of the result data.
  //
  char *dstData = op_data[0];

  // Get a handle on the operands so they can be queried for
  // NULL and VARCHAR ness.
  //
  AttributesPtr *attrs = getOperand();

  // Loop over each input attribute and convert the attribute data into
  // BitMux form.
  //
  for(Int32 i=1; i<getNumOperands(); i++) {

    // Query the attribute to the size of the data. This size does not
    // include NULL or VARCHAR information.
    //
    Int32 length = attrs[i]->getLength();

    // Start by assumming that the attribute is not NULL and uses the
    // entire allocate space. Change below if necessary.
    //
    Int32 isNull = 0;
    Int32 dataLength = length;

    // Remember the pointer to the attribute data.
    //
    const char *srcData = op_data[i];

    // If the attribute is nullable, then add two bytes indicating
    // the nullness. If the attribute is NULL, also set the isNULL flag.
    //
    if(attrs[i]->getNullFlag()) {
      if(!op_data[-2 * MAX_OPERANDS + i]) {
	*(dstData++) = (char)0xFF;
	*(dstData++) = (char)0xFF;
	isNull = 1;
      } else {
	*(dstData++) = (char)0x00;
	*(dstData++) = (char)0x00;
      }
    }

    // If the attribute is a VARCHAR, then add two bytes indicating
    // the VARCHAR length and set dataLength to be the actual length
    // of the VARCHAR.
    //
    if(attrs[i]->getVCIndicatorLength() > 0) {
      if (isNull) // a null value, make datalength 0.
	dataLength = 0;
      else
	{
	  dataLength = *(short*)op_data[- ex_clause::MAX_OPERANDS + i];
	  
	  // skip trailing blanks, they do not count as far as ANSI SQL 
	  // comparison rules go.
	  while ((dataLength > 0) && (srcData[dataLength-1] == ' '))
	    dataLength--;
	}

      *((short*)dstData) = dataLength;
      dstData += 2;
    } // source is a VARCHAR

    // If the attribute is NULL, then NULL out the data space.
    //
    if(isNull) {
      for(Int32 j=0; j<length; j++)
	dstData[j] = 0;
    } 
    // Otherwise, copy the data to the data space and pad with
    // zeros if necessary.
    //
    else {
      Int32 j=0;
      for(; j<dataLength; j++)
	dstData[j] = srcData[j]; 
      while(j<length)
	dstData[j++] = 0;
    }

    // Adjust the result pointer ahead length bytes to compensate for the
    // data added in the last loop above.
    //
    dstData += length;
  }

  // Return all OK...
  //
  return ex_expr::EXPR_OK;
};
// ExpBitMuxFunction::pCodeGenerate
//
// Generate PCI's for the BitMux operation. For now, only handle certain
// cases which give signifigant speedup. Otherwise, use CLAUSE_EVAL.
//
// IN     : space - memory allocator
// RETURN : ex_expr::EXPR_OK is no errors
// EFFECTS: stores pointer to PCodeObject in clause
//
ex_expr::exp_return_type ExpBitMuxFunction::pCodeGenerate(Space *space, UInt32 f) {
  // What is the arity?
  //
  Int32 numOperands = getNumOperands();

  // Get a handle on the operands.
  //
  AttributesPtr *attrs = getOperand();

  // Only support operations to/from ATPs with INT's or CHAR datatype.
  //
  // Dst must be ATP
  //
  if(attrs[0]->getAtpIndex() < 2)
    return ex_clause::pCodeGenerate(space, f);

  Int32 i=1;
  for(; i<numOperands; i++) 
    {
      // Src must be ATP
      //
      if(attrs[i]->getAtpIndex() < 2)
	return ex_clause::pCodeGenerate(space, f);

      // No varchars
      //
      if(attrs[i]->getVCIndicatorLength() > 0) 
	return ex_clause::pCodeGenerate(space, f);

      // No nulls. Fix for genesis case 10-980114-7618 : AS 01/22/98
      //
      if(attrs[i]->getNullIndicatorLength() > 0) 
	return ex_clause::pCodeGenerate(space, f);

      // Only ints or chars.
      //
      switch(attrs[i]->getDatatype())
	{
	case REC_BPINT_UNSIGNED:
	case REC_BIN16_SIGNED: case REC_BIN16_UNSIGNED:
	case REC_BIN32_SIGNED: case REC_BIN32_UNSIGNED:
	case REC_BIN64_SIGNED:
	case REC_BYTE_F_ASCII:
	  break;

      default:
	return ex_clause::pCodeGenerate(space, f);
	break;
	}
    }

  // Allocate the code list.
  //
  PCIList code(space);

  // Generate pre clause PCI's.
  // 
  PCode::preClausePCI(this, code);

  // Load and store each input value.
  //
  Int32 offset = attrs[0]->getOffset();
  AML aml(PCIT::MBIN8, PCIT::MBIN8, PCIT::IBIN32S);
  for(i=1; i<numOperands; i++) {
    if(attrs[i]->getNullFlag())
      {
	OL ol(attrs[0]->getAtp(), attrs[0]->getAtpIndex(), offset,
	      attrs[i]->getAtp(), attrs[i]->getAtpIndex(), 
	      attrs[i]->getNullIndOffset(), 2);

        PCI pci(PCIT::Op_MOVE, aml, ol); 
	code.append(pci);
	offset += 2;
      }

    OL ol(attrs[0]->getAtp(), attrs[0]->getAtpIndex(), offset,
	  attrs[i]->getAtp(), attrs[i]->getAtpIndex(), attrs[i]->getOffset(),
	  attrs[i]->getLength());
    PCI pci(PCIT::Op_MOVE, aml, ol);
    code.append(pci);
    offset += attrs[i]->getLength();
  }

  // Generate post clause PCI's
  //
  PCode::postClausePCI(this, code);

  setPCIList(code.getList());
  return ex_expr::EXPR_OK;
};
// LCOV_EXCL_STOP
ex_expr::exp_return_type ExFunctionMath::eval(char *op_data[],
					      CollHeap *heap,
					      ComDiagsArea** diagsArea)
{
  ex_expr::exp_return_type retcode = ex_expr::EXPR_OK;

  short err = 0;
  errno = 0;

  if ((getOperand()) &&
      (getOperand(0)->getDatatype() != REC_FLOAT64))
    {
      return evalUnsupportedOperations(op_data, heap, diagsArea);
    }

  switch (getOperType())
    {
    case ITM_DEGREES:
      // radians to degrees
      *(double *)op_data[0] = (*(double *)op_data[1] * 180E0) / PIVALUE;
      break;

    case ITM_PI:
      *(double *)op_data[0] = PIVALUE;
      break;

    case ITM_RADIANS:
      // degrees to radians
      *(double *)op_data[0] = (*(double *)op_data[1] / 180E0) * PIVALUE;
      break;

    case ITM_ROUND:
    {
      double op, res;
      short err1 = 0, err2 = 0, err3 = 0;
      Int32 roundTo;

      roundTo = (getNumOperands() > 2) ? (Int32)(*((double*)op_data[2])) : 0;

      switch (getOperand(1)->getDatatype()) {
        case REC_IEEE_FLOAT32:
          op = *((float*)op_data[1]);
          break;
        case REC_IEEE_FLOAT64:
          op = *((double*)op_data[1]);
          break;
        default:
            // LCOV_EXCL_START
          ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
          **diagsArea << DgString0("ROUND");
          return ex_expr::EXPR_ERROR;
          // LCOV_EXCL_STOP
      }

      //
      // For commenting purposes, assume the following:
      //
      // op      = -12.58
      // roundTo = 0
      //
      //

      double pow1 = MathPow(10.0, roundTo, err1);             // = 1
      double pow2 = MathPow(10.0, -roundTo, err2);            // = 1
      double pow3 = MathPow(10.0, roundTo+1, err3);           // = 10


      double abs1 = (op < 0.0) ? -op : op;                    // = 12.58
      double sign = (op < 0.0) ? -1.0 : 1.0;                  // = -1.0

      double floor1 = MathFloor(abs1*pow3, err);              // = 125
      double floor2 = 10.0 * MathFloor(floor1 / 10.0, err);   // = 120
      double floor3 = floor1 - floor2;                        // = 5

      double floor4 = MathFloor(abs1*pow1, err);              // = 12
      double floor5 = pow2 * sign;                            // = -1.0

      // Is digit at rounding position less than 5?
      if (floor3 < 5.0) {
        res = floor4 * floor5;                                // = -12.0
      }
      // Is digit at rounding position greater than 5?
      else if (floor3 > 5.0) {
        res = (floor4 + 1.0) * floor5;                        // = -13.0
      }
      else {
        // Are digits after rounding position greater than 0?
        if (((abs1*pow3) - floor1) > 0.0)
          res = (floor4 + 1.0) * floor5;                      // = -13.0
        else {
          double floor6 = 2.0 * MathFloor(floor4 / 2.0, err); // = 12.0

          // Now round to even
          if ((floor4 - floor6) == 1.0)
            res = (floor4 + 1.0) * floor5;                    // = -13.0
          else
            res = floor4 * floor5;                            // = -12.0
        }
      }

      *(double *)op_data[0] = res;

      break;
    }

    case ITM_SCALE_TRUNC:
      {
          // LCOV_EXCL_START
	ExRaiseSqlError(heap, diagsArea, EXE_MATH_FUNC_NOT_SUPPORTED);
	if (getOperType() == ITM_ROUND)
	  **diagsArea << DgString0("ROUND");
	else
	  **diagsArea << DgString0("TRUNCATE");
	  
	retcode = ex_expr::EXPR_ERROR;
      }
     break;
     // LCOV_EXCL_STOP

    case ITM_ACOS:
      if ((*(double *)op_data[1] < -1) ||
	  (*(double *)op_data[1] > 1))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("ACOS");
	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathAcos(*(double *)op_data[1], err);
      break;

    case ITM_ASIN:
      if ((*(double *)op_data[1] < -1) ||
	  (*(double *)op_data[1] > 1))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("ASIN");

	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathAsin(*(double *)op_data[1], err);
      break;

    case ITM_ATAN:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathAtan(*(double *)op_data[1], err);
      break;
      
    case ITM_ATAN2:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathAtan2(*(double *)op_data[1],
				    *(double *)op_data[2], err);
      break;

    case ITM_CEIL:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathCeil(*(double *)op_data[1], err);
      break;

    case ITM_COS:

       *(double *)op_data[0] = MathCos(*(double *)op_data[1], err);
      break;

    case ITM_COSH:
      *(double *)op_data[0] = MathCosh(*(double *)op_data[1], err);
      if (*(double *)op_data[0] == HUGE_VAL)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("COSH");
	  return ex_expr::EXPR_ERROR;
	}
      break;

    case ITM_EXP:
      *(double *)op_data[0] = MathExp(*(double *)op_data[1], err);

      // Check for overflow. 
      if (err) 
	// if  (*(double *)op_data[0] == HUGE_VAL_REAL64)
	{
	  // Overflow

	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("EXP");
	  return ex_expr::EXPR_ERROR;
	}

      break;

    case ITM_FLOOR:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathFloor(*(double *)op_data[1], err);
      break;

    case ITM_LOG:
      if (*(double *)op_data[1] <= 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("LOG");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathLog(*(double *)op_data[1], err);
      break;

    case ITM_LOG10:
      if (*(double *)op_data[1] <= 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("LOG10");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathLog10(*(double *)op_data[1], err);
      break;

    case ITM_SIN:

      *(double *)op_data[0] = MathSin(*(double *)op_data[1], err);
      break;

    case ITM_SINH:
      *(double *)op_data[0] = MathSinh(*(double *)op_data[1], err);
      if (*(double *)op_data[0] == HUGE_VAL)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("SINH");
	  return ex_expr::EXPR_ERROR;
	}
	
      break;

    case ITM_SQRT:
      if (*(double *)op_data[1] < 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("SQRT");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathSqrt(*(double *)op_data[1], err);
      break;

    case ITM_TAN:

      *(double *)op_data[0] = MathTan(*(double *)op_data[1], err);
      break;

    case ITM_TANH:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathTanh(*(double *)op_data[1], err);
      break;
     
    case ITM_EXPONENT:
    case ITM_POWER:
      if (((*(double *)op_data[1] == 0) &&
	   (*(double *)op_data[2] <= 0)) ||
	  ((*(double *)op_data[1] < 0) &&
	   (MathFloor(*(double *)op_data[2], err) != *(double *)op_data[2])))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("POWER");
	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathPow(*(double *)op_data[1],
				  *(double *)op_data[2], err);
        if (errno == ERANGE)	
	{
	  // Overflow

	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("POWER");
	  return ex_expr::EXPR_ERROR;
	}
	

      break;

    default:
      {
	ExRaiseSqlError(heap, diagsArea, EXE_INTERNAL_ERROR);
	retcode = ex_expr::EXPR_ERROR;
      }
      break;
     }
  
  return retcode;
}
// LCOV_EXCL_START
ex_expr::exp_return_type ExFunctionMath::evalUnsupportedOperations(
     char *op_data[],
     CollHeap *heap,
     ComDiagsArea** diagsArea)
{
  if (getOperand(0)->getDatatype() == REC_TDM_FLOAT64)
    {
      // convert all child operands to double.
      // Do the math function operation and convert result back to the
      // type of result operand.
      double op1Double;
      double op2Double;
      double op0Double; // result

      char * opDoubleData[3];
      opDoubleData[0] = (char *)&op0Double;
      opDoubleData[1] = (char *)&op1Double;
      opDoubleData[2] = (char *)&op2Double;

      SimpleType op1DoubleAttr(REC_FLOAT64, sizeof(double), 0, 0,
			       ExpTupleDesc::SQLMX_FORMAT,
			       8, 0, 0, 0, Attributes::NO_DEFAULT, 0);
      SimpleType op2DoubleAttr(REC_FLOAT64, sizeof(double), 0, 0,
			       ExpTupleDesc::SQLMX_FORMAT,
			       8, 0, 0, 0, Attributes::NO_DEFAULT, 0);
      SimpleType op0DoubleAttr(REC_FLOAT64, sizeof(double), 0, 0,
			       ExpTupleDesc::SQLMX_FORMAT,
			       8, 0, 0, 0, Attributes::NO_DEFAULT, 0);

      for (Int32 i = 1; i < getNumOperands(); i++)
	{
#pragma nowarn(1506)   // warning elimination 
	  if (convDoIt(op_data[i],
		       getOperand(i)->getLength(),
		       getOperand(i)->getDatatype(),
		       getOperand(i)->getPrecision(),
		       getOperand(i)->getScale(),
		       opDoubleData[i],
		       (Lng32)sizeof(double),
		       REC_FLOAT64,
		       0,
		       0, NULL, 0, heap, diagsArea,
		       CONV_UNKNOWN) != ex_expr::EXPR_OK)
	    return ex_expr::EXPR_ERROR;
#pragma warn(1506)  // warning elimination 
	}

      ExFunctionMath tempMath(getOperType(), getNumOperands(), NULL, NULL);
      if (tempMath.eval(opDoubleData, heap, diagsArea) != ex_expr::EXPR_OK)
	return ex_expr::EXPR_ERROR;

      // convert double result to the actual result type.
      if (convDoIt(opDoubleData[0],
		   (Lng32)sizeof(double),
		   REC_FLOAT64,
		   0, 0,
		   op_data[0],
		   getOperand(0)->getLength(),
		   getOperand(0)->getDatatype(),
		   getOperand(0)->getPrecision(),
		   getOperand(0)->getScale(),
		   NULL, 0, heap, diagsArea,
		   CONV_UNKNOWN) != ex_expr::EXPR_OK)
	return ex_expr::EXPR_ERROR;
    }
  else
    {
      ExRaiseSqlError(heap, diagsArea, EXE_INTERNAL_ERROR);
      return ex_expr::EXPR_ERROR;
    }

  return ex_expr::EXPR_OK;
}