| /********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **********************************************************************/ |
| /* -*-C++-*- |
| ***************************************************************************** |
| * |
| * File: <file> |
| * Description: |
| * |
| * |
| * Created: 7/10/95 |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| #include "Platform.h" |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "exp_stdh.h" |
| #include "exp_expr.h" |
| #include "ExpPCode.h" |
| #include "ExpPCodeOptimizations.h" |
| |
| void setVCLength(char * VCLen, Lng32 VCLenSize, ULng32 value); |
| |
| |
| // ----------------------------------------------------------------------- |
| // This method returns the virtual function table pointer for an object |
| // with the given class ID; used by NAVersionedObject::driveUnpack(). |
| // ----------------------------------------------------------------------- |
| char *ex_expr::findVTblPtr(short classID) |
| { |
| char *vtblPtr; |
| switch (classID) |
| { |
| case exp_INPUT_OUTPUT: |
| GetVTblPtr(vtblPtr, InputOutputExpr); |
| break; |
| case exp_AGGR: |
| GetVTblPtr(vtblPtr, AggrExpr); |
| break; |
| case exp_LEAN_EXPR: |
| GetVTblPtr(vtblPtr, ex_expr_lean); |
| break; |
| default: |
| GetVTblPtr(vtblPtr, ex_expr); |
| break; |
| } |
| return vtblPtr; |
| } |
| |
| Lng32 ex_expr::initExpr() |
| { |
| Lng32 rc = 0; |
| |
| ex_clause *currClause = clauses_; |
| |
| while( currClause != NULL ) |
| { |
| rc = currClause->initClause(); |
| if (rc) |
| return rc; |
| |
| currClause = currClause->getNextClause(); |
| } |
| |
| return rc; |
| } |
| |
| // lean expressions are not used not tested |
| void ex_expr_lean::displayContents(Space * space, short mode, |
| const char * displayStr, |
| ULng32 flag) |
| { |
| char buf[200]; |
| |
| str_sprintf(buf, "Expression: %s", displayStr); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, " Total Expr Len: %d, Consts Area Len: %d", getLength(), getConstsLength()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, " Temps Area Len: %d, Persistent Area Len: %d", getTempsLength(), persistentLength()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, " PCode Expr Length: %d\n", getPCodeSize()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if (flag & 0x00000002) |
| { |
| // Clear the fixup flag, since the expression has not been fixed up |
| // (pCodeGenerate undoes, the fixup of Const and Temp offsets.) |
| // |
| setFixupConstsAndTemps(0); |
| |
| if (getPCodeBinary()) |
| { |
| str_sprintf(buf, " PCode:\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| // PCode::displayContents(getPCodeObject()->getPCIList(), space); |
| |
| PCodeBinary *pCode = getPCodeBinary(); |
| |
| // skip over the ATP's |
| Int32 length = *(pCode++); |
| pCode += (2 * length); |
| |
| while (pCode[0] != PCIT::END) |
| { |
| Int32 opcode = *(pCode++); |
| |
| str_sprintf(buf, " %s ", PCIT::instructionString(PCIT::Instruction(opcode))); |
| |
| Lng32 pcodeLength = PCode::getInstructionLength(pCode-1) - 1; |
| |
| char tbuf[256]; |
| char operandBuf[32]; |
| for (Int32 i=0; i<pcodeLength; i++) |
| { |
| PCIT::operandString(pCode[i], operandBuf); |
| str_sprintf(tbuf, "%s ", operandBuf); |
| str_cat(buf, tbuf, buf); |
| } |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| pCode += pcodeLength; |
| } // while |
| |
| str_sprintf(buf, "\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| } |
| } |
| // make a 'lean' copy of 'this' and point it back to itself. Supports all |
| // expressions. Do not copy clauses_ or pCodeObject_. Caller is responsible |
| // for proper deallocation of memory. |
| void ex_expr::makeLeanCopyAll(Space * space) |
| { |
| if (getPCodeSegment() != NULL) { |
| Int32 pCodeSize = getPCodeSize(); |
| NABoolean evalFlag = pCode_->containsClauseEval(); |
| PCodeBinary* pCode = getPCodeBinary(); |
| PCodeBinary* code; |
| |
| pCode_ = new(space) PCodeSegment(); |
| code = (PCodeBinary*) (new(space) char[pCodeSize]); |
| |
| str_cpy_all((char*)code, (char*)pCode, pCodeSize); |
| |
| pCode_.getPointer()->setPCodeSegmentSize(pCodeSize); |
| pCode_.getPointer()->setContainsClauseEval(evalFlag); |
| |
| setPCodeBinary(code); |
| } |
| |
| if (constantsArea_) { |
| char* area = space->allocateAlignedSpace(constantsAreaLength_); |
| str_cpy_all(area, constantsArea_, constantsAreaLength_); |
| setConstantsArea(area); |
| } |
| |
| if (tempsArea_) { |
| char* area = space->allocateAlignedSpace(tempsAreaLength_); |
| setTempsArea(area); |
| } |
| |
| if (persistentArea_) { |
| char* area = space->allocateAlignedSpace(persistentLength_); |
| persistentArea_ = area; |
| } |
| |
| if (persistentInitializationArea_) { |
| char* area = space->allocateAlignedSpace(persistentLength_); |
| str_cpy_all(area, persistentInitializationArea_, persistentLength_); |
| persistentInitializationArea_ = area; |
| } |
| } |
| |
| // make a 'lean' copy of 'this' to 'other'. |
| // Do not copy clauses_ or pCodeObject_. |
| void ex_expr::makeLeanCopy(ex_expr_lean * other, Space * space) |
| { |
| // *((ex_expr_base*)other) = *((ex_expr_base*)this); |
| |
| PCodeBinary * pCodeS = (PCodeBinary*) |
| space->allocateAlignedSpace(sizeof(PCodeBinary) + |
| pCode_->getPCodeSegmentSize()); |
| str_cpy_all((char*)&pCodeS[1], (char*)pCode_->getPCodeBinary(), |
| pCode_->getPCodeSegmentSize()); |
| pCodeS[0] = pCode_->getPCodeSegmentSize(); |
| other->setPCodeLean(pCodeS); |
| // other->setPCodeSize(pCode_->getPCodeSegmentSize()); |
| |
| other->constantsAreaLength_ = constantsAreaLength_; |
| other->tempsAreaLength_ = tempsAreaLength_; |
| other->persistentLength_ = persistentLength_; |
| |
| if (constantsArea_) |
| { |
| other->setConstantsArea(space->allocateAlignedSpace(constantsAreaLength_)); |
| str_cpy_all(other->getConstantsArea(), constantsArea_, |
| constantsAreaLength_); |
| } |
| |
| if (tempsArea_) |
| { |
| other->setTempsArea(space->allocateAlignedSpace(tempsAreaLength_)); |
| } |
| |
| if (persistentArea_) |
| { |
| other->persistentArea_ = space->allocateAlignedSpace(persistentLength_); |
| } |
| } |
| void ex_expr::displayContents(Space * space, short mode, const char * displayStr,ULng32 flag) |
| { |
| char buf[100] = {0}; // Soln 10-041117-1848 |
| |
| ULng32 exprLen = getLength(); |
| |
| str_sprintf(buf, "Expression: %s", displayStr); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, "Expr Len: %d, Consts Len: %d", exprLen, getConstsLength()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, "flags_ = %x ",flags_ ); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if (flag & 0x00000004) |
| { |
| Int32 i = 1; |
| ex_clause * clause = getClauses(); |
| while (clause) |
| { |
| clause->displayContents(space, 0, i, constantsArea_); |
| |
| clause = clause->getNextClause(); |
| i++; |
| } |
| } |
| |
| if (flag & 0x00000002) |
| { |
| if (getPCodeBinary()) |
| { |
| str_sprintf(buf, " PCode:\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf),sizeof(short)); |
| str_sprintf(buf, "PCode Expr Length: %d", getPCodeSize()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf),sizeof(short)); |
| |
| PCodeCfg* cfg = new(heap_) PCodeCfg(this, heap_); |
| cfg->generateShowPlan(getPCodeBinary(), space); |
| NADELETE(cfg, PCodeCfg, heap_); |
| } |
| else if ((flag & 0x00000010) && |
| (getPCodeBinary())) |
| { |
| str_sprintf(buf, " PCode:\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, "PCode Expr Length: %d", getPCodeSize()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| PCode::displayContents(getPCodeBinary(), space); |
| } |
| else |
| { |
| // Clear the fixup flag, since the expression has not been fixed up |
| // (pCodeGenerate undoes, the fixup of Const and Temp offsets.) |
| // |
| setFixupConstsAndTemps(0); |
| |
| // re-generate pcode for showplan |
| setPCodeGenCompile(0); |
| setPCodeObject(0); |
| pCode_ = 0; |
| Space tempSpace; //create pcode stuff in a different space |
| //the space in PCode::displayContents is used for |
| //creating text for the showplan |
| UInt32 f = 0; |
| ex_expr_base::setForShowplan(f, TRUE); |
| pCodeGenerate(&tempSpace, &tempSpace, f); |
| |
| if(getPCodeObject()) |
| { |
| str_sprintf(buf, " PCode:\n"); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, "PCode Expr Length: %d", getPCodeSize()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| PCode::displayContents(getPCodeObject()->getPCIList(), space); |
| } |
| } |
| } |
| } |
| |
| char *ex_expr::getPersistentData(Int32 offset) |
| { |
| return persistentArea_ + offset; |
| } |
| |
| // error denoted by negative return code |
| int ex_expr::formatARow2(const char** srcFldsPtr, |
| const int* srcFldsLength, |
| const int * srcFieldsConvIndex, |
| char* formattedRow, |
| int& formattedRowLength, |
| int numAttrs, |
| AttributesPtr * attrs, |
| ExpTupleDesc *tupleDesc, |
| UInt16 firstFixedOffset, |
| UInt16 bitmapEntryOffset, |
| UInt16 bitmapOffset, |
| NABoolean sysKeyTable, |
| CollHeap *heap, |
| ComDiagsArea **diags) |
| { |
| |
| formattedRowLength = tupleDesc->tupleDataLength(); //need to fix this later for other types |
| //char *sourceData = (char*)asciiRow; |
| //char *sourceDataEnd =(char*)asciiRow + rowLength; |
| //assert (sourceDataEnd); |
| |
| |
| //set the headers in tuple. |
| ExpTupleDesc::setFirstFixedOffset(formattedRow, |
| firstFixedOffset, |
| tupleDesc->getTupleDataFormat()); |
| |
| //Bitmap offset value is zero if bitmap is not preset. But bitmap offset |
| //still exists. |
| ExpAlignedFormat::setBitmapOffset(formattedRow + bitmapEntryOffset, |
| - bitmapOffset); |
| |
| |
| char *targetData = NULL; |
| |
| //for varchars |
| UInt32 vcActualLen = 0; |
| UInt32 voaOffset = 0; |
| UInt32 vOffset = 0; |
| Int32 vcLenIndOffset = 0; |
| bool firstvc = true; |
| char paddedTimestampVal[27] = "2000-01-01 00:00:00.000000" ; |
| |
| |
| int startCol = 0; |
| if (sysKeyTable) |
| { |
| startCol =1; |
| } |
| for(int index= startCol; index < numAttrs ; index++) |
| { |
| //Attributes * attr = myTdb().getOutputAttr(index); |
| Attributes * attr = attrs[index]; |
| //loop thru all the columns in the row. For each column, |
| //find its corresponding offset in ascii row. Corresponding |
| //offset is identified and converted. |
| |
| char * srcColData = (char*)srcFldsPtr[index - startCol]; |
| int srcColLen = srcFldsLength[index - startCol]; |
| |
| //set null bit map if column is nullable. |
| //if ( attr->getDefaultClass() == Attributes::DEFAULT_NULL ) |
| // ExpAlignedFormat::setNullValue( formattedRow, attr->getNullBitIndex() ); |
| |
| if (! srcColLen ) |
| { |
| ExpAlignedFormat::setNullValue( formattedRow, attr->getNullBitIndex() ); |
| continue; |
| } |
| |
| if((!firstvc) && attr->getVCIndicatorLength() > 0) |
| targetData = (char*) formattedRow + vOffset; |
| else |
| targetData = (char*) formattedRow + attr->getOffset(); |
| |
| if (attr->getDatatype() == REC_DATETIME && srcColLen == 10) |
| { |
| srcColData = &(paddedTimestampVal[0]); |
| srcColLen = 26; |
| } |
| |
| ex_expr::exp_return_type err = convDoIt(srcColData, |
| srcColLen, |
| REC_BYTE_F_ASCII, |
| 0,0, |
| targetData, |
| attr->getLength(), |
| attr->getDatatype(), |
| attr->getPrecision(), |
| attr->getScale(), |
| (char*)&vcActualLen, |
| sizeof(vcActualLen), |
| heap, |
| diags, |
| (ConvInstruction)srcFieldsConvIndex[index] |
| ); |
| |
| if(err == ex_expr::EXPR_ERROR) return -1; |
| |
| //update var fields parameters and adjust for subsequent var columns. |
| if(attr->getVCIndicatorLength() > 0) |
| { |
| if(firstvc) |
| { |
| voaOffset = attr->getVoaOffset(); |
| vOffset = attr->getOffset(); |
| vcLenIndOffset = attr->getVCLenIndOffset(); |
| } |
| //obtain actual len of varchar field and update VCIndicatorLength |
| setVCLength(formattedRow + vcLenIndOffset, |
| attr->getVCIndicatorLength(), vcActualLen); |
| |
| //update voa offset location with value of offset |
| ExpTupleDesc::setVoaValue(formattedRow, voaOffset, |
| vcLenIndOffset, tupleDesc->getTupleDataFormat()); |
| |
| //update all offset vars for next varchar column |
| ExpAlignedFormat::incrVoaOffset(voaOffset); |
| vcLenIndOffset += (vcActualLen + attr->getVCIndicatorLength()); |
| vOffset = vcLenIndOffset + attr->getVCIndicatorLength(); //vcIndLen remains same. |
| firstvc = false; |
| |
| //update formatted row length to reflect actual len |
| formattedRowLength = vcLenIndOffset; |
| } |
| |
| } |
| |
| //finally adjust the data length to alignment size. See header file for more info. |
| formattedRowLength = ExpAlignedFormat::adjustDataLength(formattedRow, |
| formattedRowLength, |
| ExpAlignedFormat::ALIGNMENT, |
| TRUE); |
| return 0; |
| }; |
| |
| void AggrExpr::displayContents(Space * space, short mode, const char * displayStr, |
| ULng32 flag) |
| { |
| char buf[100]; |
| |
| if (initExpr_) |
| { |
| str_sprintf(buf, "%s::initExpr_", displayStr); |
| |
| initExpr_->displayContents(space, mode, buf, flag); |
| } |
| |
| if (finalNullExpr_) |
| { |
| str_sprintf(buf, "%s::finalNullExpr_", displayStr); |
| |
| finalNullExpr_->displayContents(space, mode, buf, flag); |
| } |
| |
| if (finalExpr_) |
| { |
| str_sprintf(buf, "%s::finalExpr_", displayStr); |
| |
| finalExpr_->displayContents(space, mode, buf, flag); |
| } |
| |
| if (groupingExpr_) |
| { |
| str_sprintf(buf, "%s::groupingExpr_", displayStr); |
| |
| groupingExpr_->displayContents(space, mode, buf, flag); |
| } |
| |
| if (perrecExpr_) |
| { |
| str_sprintf(buf, "%s::perrecExpr_", displayStr); |
| |
| perrecExpr_->displayContents(space, mode, buf, flag); |
| } |
| |
| } |
| |
| |