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; }
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; }
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; }