/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
/*************************************************************
*
*
* PURPOSE:
*
*
* COMMENTS:
*
************************************************************/
static const char rcsid[] = "@(#)qlparser, QtCondenseOp: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtcondenseop.cc,v 1.18 2003/12/27 20:51:28 rasdev Exp $";
#include "raslib/rmdebug.hh"
#include "qlparser/qtcondenseop.hh"
#include "qlparser/qtdata.hh"
#include "qlparser/qtmdd.hh"
#include "qlparser/qtpointdata.hh"
#include "qlparser/qtmintervaldata.hh"
#include "qlparser/qtatomicdata.hh"
#include "qlparser/qtcomplexdata.hh"
#include "mddmgr/mddobj.hh"
#include "catalogmgr/typefactory.hh"
#include "catalogmgr/algebraops.hh"
#include
#ifndef CPPSTDLIB
#include // STL
#else
#include
using namespace std;
#endif
const QtNode::QtNodeType QtCondenseOp::nodeType = QT_CONDENSEOP;
QtCondenseOp::QtCondenseOp( Ops::OpType newOperation,
const string &initIteratorName,
QtOperation* mintervalExp,
QtOperation* cellExp,
QtOperation* condExp )
: operation( newOperation ),
iteratorName( initIteratorName ),
QtBinaryOperation( mintervalExp, cellExp ),
condOp( condExp )
{
}
QtCondenseOp::~QtCondenseOp()
{
if( condOp )
{
delete condOp;
condOp=NULL;
}
}
QtNode::QtNodeList*
QtCondenseOp::getChilds( QtChildType flag )
{
RMDBCLASS( "QtCondenseOp", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ )
QtNodeList* resultList;
resultList = QtBinaryOperation::getChilds( flag );
if( condOp )
{
if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES )
{
QtNodeList* subList=NULL;
subList = condOp->getChilds( flag );
// remove all elements in subList and insert them at the beginning in resultList
resultList->splice( resultList->begin(), *subList );
// delete temporary subList
delete subList;
subList=NULL;
}
// add the nodes of the current level
if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES )
resultList->push_back( condOp );
}
return resultList;
}
bool
QtCondenseOp::equalMeaning( QtNode* node )
{
RMDBCLASS( "QtCondenseOp", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ )
bool result = false;
if( nodeType == node->getNodeType() )
{
QtCondenseOp* condNode;
condNode = (QtCondenseOp*) node; // by force
// check domain and cell expression
result = QtBinaryOperation::equalMeaning( condNode );
// check condition expression
result &= ( !condOp && !condNode->getCondOp() ) ||
condOp->equalMeaning( condNode->getCondOp() );
};
return ( result );
}
string
QtCondenseOp::getSpelling()
{
char tempStr[20];
sprintf(tempStr, "%ud", (unsigned long)getNodeType());
string result = string(tempStr);
result.append( "(" );
result.append( QtBinaryOperation::getSpelling() );
result.append( "," );
if( condOp )
result.append( condOp->getSpelling() );
else
result.append( "" );
result.append( ")" );
return result;
}
void
QtCondenseOp::setInput( QtOperation* inputOld, QtOperation* inputNew )
{
QtBinaryOperation::setInput( inputOld, inputNew );
if( condOp == inputOld )
{
condOp = inputNew;
if( inputNew )
inputNew->setParent( this );
}
};
void
QtCondenseOp::optimizeLoad( QtTrimList* trimList )
{
RMDBCLASS( "QtCondenseOp", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ )
// delete the trimList and optimize subtrees
// release( trimList->begin(), trimList->end() );
for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ )
{
delete *iter;
*iter=NULL;
}
delete trimList;
trimList=NULL;
QtBinaryOperation::optimizeLoad( new QtNode::QtTrimList() );
if( condOp )
condOp->optimizeLoad( new QtNode::QtTrimList() );
}
void
QtCondenseOp::simplify()
{
RMDBCLASS( "QtCondenseOp", "simplify()", "qlparser", __FILE__, __LINE__ )
RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtCondenseOp", "simplify() warning: QtCondenseOp itself is not simplified yet")
// Default method for all classes that have no implementation.
// Method is used bottom up.
QtNodeList* resultList=NULL;
QtNodeList::iterator iter;
resultList = getChilds( QT_DIRECT_CHILDS );
for( iter=resultList->begin(); iter!=resultList->end(); iter++ )
(*iter)->simplify();
delete resultList;
resultList=NULL;
}
bool
QtCondenseOp::isCommutative() const
{
return false; // NOT commutative
}
QtData*
QtCondenseOp::evaluate( QtDataList* inputList )
{
RMDBCLASS( "QtCondenseOp", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ )
QtData* returnValue = NULL;
QtData* operand1 = NULL;
if( getOperand( inputList, operand1, 1 ) )
{
#ifdef QT_RUNTIME_TYPE_CHECK
if( operand1->getDataType() != QT_MINTERVAL )
RMInit::logOut << "Internal error in QtMarrayOp::evaluate() - "
<< "runtime type checking failed (Minterval)." << endl;
// delete old operand
if( operand1 ) operand1->deleteRef();
return 0;
}
#endif
r_Minterval domain = ((QtMintervalData*)operand1)->getMintervalData();
RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtCondenseOp", "Marray domain " << domain)
// determine aggregation type
BaseType* cellType = (BaseType*) input2->getDataStreamType().getType();
// get operation object
BinaryOp* cellBinOp = Ops::getBinaryOp( operation, cellType, cellType, cellType );
// create execution object QLCondenseOp
QLCondenseOp* qlCondenseOp = new QLCondenseOp( input2, condOp, inputList, iteratorName,
cellType, 0, cellBinOp );
// result buffer
char* result=NULL;
try
{
// execute query engine marray operation
result = Tile::execGenCondenseOp( qlCondenseOp, domain );
}
catch(...)
{
// free ressources
delete qlCondenseOp;
qlCondenseOp=NULL;
delete cellBinOp;
cellBinOp=NULL;
if( operand1 ) operand1->deleteRef();
throw;
}
// allocate cell buffer
char* resultBuffer = new char[ cellType->getSize() ];
// copy cell content
memcpy( (void*)resultBuffer, (void*)result, cellType->getSize() );
delete qlCondenseOp;
qlCondenseOp=NULL;
delete cellBinOp;
cellBinOp=NULL;
// create data object for the cell
QtScalarData* scalarDataObj = NULL;
if( cellType->getType() == STRUCT )
scalarDataObj = new QtComplexData();
else
scalarDataObj = new QtAtomicData();
scalarDataObj->setValueType ( cellType );
scalarDataObj->setValueBuffer( resultBuffer );
// set return data object
returnValue = scalarDataObj;
// delete old operands
if( operand1 ) operand1->deleteRef();
}
return returnValue;
}
void
QtCondenseOp::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtCondenseOp Object " << getNodeType() << endl;
s << SPACE_STR(tab).c_str() << "Iterator Name: " << iteratorName.c_str() << endl;
QtBinaryOperation::printTree( tab, s, mode );
}
void
QtCondenseOp::printAlgebraicExpression( ostream& s )
{
s << "(";
s << iteratorName.c_str() << ",";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << ",";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtTypeElement&
QtCondenseOp::checkType( QtTypeTuple* typeTuple )
{
RMDBCLASS( "QtCondenseOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ )
dataStreamType.setDataType( QT_TYPE_UNKNOWN );
// check operand branches
if( input1 && input2 )
{
// check domain expression
const QtTypeElement& domainExp = input1->checkType( typeTuple );
if( domainExp.getDataType() != QT_MINTERVAL )
{
RMInit::logOut << "Error: QtMarrayOp::checkType() - Can not evaluate domain expression to an minterval" << endl;
parseInfo.setErrorNo(401);
throw parseInfo;
}
// add domain iterator to the list of bounded variables
bool newList = false;
if( !typeTuple )
{
typeTuple = new QtTypeTuple();
newList = true;
}
typeTuple->tuple.push_back( QtTypeElement( QT_POINT, iteratorName.c_str() ) );
//
// check value expression
//
// get value expression type
const QtTypeElement& valueExp = input2->checkType( typeTuple );
// check type
if( valueExp.getDataType() != QT_BOOL && valueExp.getDataType() != QT_COMPLEX &&
valueExp.getDataType() != QT_CHAR && valueExp.getDataType() != QT_OCTET &&
valueExp.getDataType() != QT_USHORT && valueExp.getDataType() != QT_SHORT &&
valueExp.getDataType() != QT_ULONG && valueExp.getDataType() != QT_LONG &&
valueExp.getDataType() != QT_FLOAT && valueExp.getDataType() != QT_DOUBLE )
{
RMInit::logOut << "Error: QtMarrayOp::checkType() - Value expression must be either of type atomic or complex" << endl;
parseInfo.setErrorNo(412);
throw parseInfo;
}
dataStreamType = valueExp;
//
// check condition expression
//
if( condOp )
{
// get value expression type
const QtTypeElement& condExp = condOp->checkType( typeTuple );
// check type
if( condExp.getDataType() != QT_BOOL )
{
RMInit::logOut << "Error: QtMarrayOp::checkType() - Condition expression must be of type boolean" << endl;
parseInfo.setErrorNo(413);
throw parseInfo;
}
}
// remove iterator again
typeTuple->tuple.pop_back();
if( newList )
{
delete typeTuple;
typeTuple = NULL;
}
}
else
RMInit::logOut << "Error: QtCondenseOp::checkType() - operand branch invalid." << endl;
return dataStreamType;
}