blob: 4d1dafca64e74e08f6efd40e9e778baa022fbb1f [file] [log] [blame]
/**********************************************************************
// @@@ 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: ExBitMuxFunction.cpp
* RCS: $Id
* Description: ExBitMuxFunction class Implementation
* Created: 6/15/97
* Modified: $Author
* Language: C++
* Status: $State
*
*
*
******************************************************************************
*/
#include "Platform.h"
// Includes
//
#include "exp_clause.h"
#include "exp_attrs.h"
#include "ExpPCode.h"
#include "ExpBitMuxFunction.h" // <--- See here for comments.
// ExpBitMuxFunction::ExpBitMuxFunction
//
// Constructs an ExpBitMuxFunction object
//
// IN : oper_type - The type of clause, must be ITM_BITMUX
// IN : arity - The number of input arguments
// IN : space - Memory allocator.
// EFFECTS: Calls the base class constructor
// PRECOND: The oper_type is equal to ITM_BITMUX.
// : The arity doesn't exceed MAX_OPERANDS.
// : The attributes pointer is valid.
// : The space object is valid.
// PSTCOND: ExpBitMuxFunction is constructed.
//
ExpBitMuxFunction::ExpBitMuxFunction(OperatorTypeEnum oper_type, Int32 arity,
Attributes ** attr, Space * space)
: ex_function_clause(oper_type, arity, attr, space) {
// Test preconditions. It may already be too late ...
//
#if 0
ex_assert(oper_type == ITM_BITMUX,
"ExpBitMuxFunction - bad OperatorTypeEnum");
ex_assert((arity > 0) && (arity <= ex_clause::MAX_OPERANDS),
"ExpBitMuxFunction - bad arity");
ex_assert(attr,
"ExpBitMuxFunction - NULL attr pointer");
ex_assert(space,
"ExpBitMuxFunction - NULL space pointer");
#endif
};
// ExpBitMuxFunction::~ExpBitMuxFunction
//
// Destructs an ExpBitMuxFunction object
//
// EFFECTS: None
//
ExpBitMuxFunction::ExpBitMuxFunction() {;};
// ExpBitMuxFunction::pack
//
// Packs an ExpBitMuxFunction object
//
// IN : space - The memory allocator.
// RETURN : the offset withing space of the packed object.
// EFFECTS: Pointers are changed to offsets within space.
// PRECOND: Space is a valid space object.
Long ExpBitMuxFunction::pack(void * space) {
// Test preconditions.
//
#if 0
ex_assert(space, "ExpBitMuxFunction::pack - Invalid space object");
#endif
// Since ExpBitMuxFunction has no private data, the pack_clause
// helper of the ex_clause class can be used to pack this
// class.
//
return packClause(space, sizeof(ExpBitMuxFunction));
}
// 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;
};
// 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;
};