/* * 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, QtMarrayOp: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtmarrayop.cc,v 1.19 2003/12/27 20:51:28 rasdev Exp $"; #include "raslib/rmdebug.hh" #include "qlparser/qtmarrayop.hh" #include "qlparser/qtdata.hh" #include "qlparser/qtmdd.hh" #include "qlparser/qtpointdata.hh" #include "qlparser/qtmintervaldata.hh" #include "mddmgr/mddobj.hh" #include "tilemgr/tile.hh" #include "catalogmgr/typefactory.hh" #include "catalogmgr/algebraops.hh" #include #ifndef CPPSTDLIB #include // STL #else #include using namespace std; #endif const QtNode::QtNodeType QtMarrayOp::nodeType = QT_MARRAYOP; QtMarrayOp::QtMarrayOp( const string &initIteratorName, QtOperation* mintervalExp, QtOperation* cellExp ) : iteratorName( initIteratorName ), QtBinaryOperation( mintervalExp, cellExp ) { } void QtMarrayOp::optimizeLoad( QtTrimList* trimList ) { RMDBCLASS( "QtMarrayOp", "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() ); } bool QtMarrayOp::isCommutative() const { return false; // NOT commutative } QtData* QtMarrayOp::evaluate( QtDataList* inputList ) { RMDBCLASS( "QtMarrayOp", "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(); RMDBGONCE( 4, RMDebug::module_qlparser, "QtMarrayOp", "Marray domain " << domain ) // // add point data with its iterator name to the input list // // create a QtPointData object with corner point QtPointData* point = new QtPointData( domain.get_origin() ); // set its iterator name point->setIteratorName( iteratorName ); // if the list of binding variables is empty, create a new one and delete it afterwards bool newInputList = false; if( !inputList ) { inputList = new QtDataList(); newInputList = true; } // add it to the list inputList->push_back( point ); // determine types BaseType* cellType = (BaseType*) input2->getDataStreamType().getType(); MDDBaseType* mddBaseType = (MDDBaseType*)dataStreamType.getType(); // create tile for result Tile* resTile = new Tile( domain, cellType ); // create execution object QLArrayOp QLMarrayOp* qlMarrayOp = new QLMarrayOp( input2, inputList, iteratorName, cellType ); try { // execute query engine marray operation resTile->execMarrayOp( qlMarrayOp, domain, domain ); } catch(...) { // free ressources delete qlMarrayOp; qlMarrayOp=NULL; delete resTile; resTile=NULL; // remove point data object from inputList again inputList->back()->deleteRef(); inputList->pop_back(); if( newInputList ) { delete inputList; inputList=NULL; } if( operand1 ) operand1->deleteRef(); throw; } // delete execution object again delete qlMarrayOp; qlMarrayOp=NULL; // remove point data object from inputList again inputList->back()->deleteRef(); inputList->pop_back(); if( newInputList ) { delete inputList; inputList=NULL; } // create MDDObj for result MDDObj* mddres = new MDDObj( mddBaseType, domain ); // insert Tile in result mdd mddres->insertTile( resTile ); // create a new QtMDD object as carrier object for the transient MDD object returnValue = new QtMDD( (MDDObj*)mddres ); // delete old operands if( operand1 ) operand1->deleteRef(); } return returnValue; } void QtMarrayOp::printTree( int tab, ostream& s, QtChildType mode ) { s << SPACE_STR(tab).c_str() << "QtMarrayOp Object " << getNodeType() << endl; s << SPACE_STR(tab).c_str() << "Iterator Name: " << iteratorName.c_str() << endl; QtBinaryOperation::printTree( tab, s, mode ); } void QtMarrayOp::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& QtMarrayOp::checkType( QtTypeTuple* typeTuple ) { RMDBCLASS( "QtMarrayOp", "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; } // // check value expression // // 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() ) ); // get type const QtTypeElement& valueExp = input2->checkType( typeTuple ); // remove iterator again typeTuple->tuple.pop_back(); if( newList ) { delete typeTuple; typeTuple = NULL; } // 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 && valueExp.getDataType() != QT_COMPLEXTYPE1 && valueExp.getDataType() != QT_COMPLEXTYPE2 ) { RMInit::logOut << "Error: QtMarrayOp::checkType() - Value expression must be either of type atomic or complex." << endl; parseInfo.setErrorNo(412); throw parseInfo; } // create MDD type BaseType* cellType = (BaseType*)valueExp.getType(); MDDBaseType* mddBaseType = new MDDBaseType( "tmp", cellType ); TypeFactory::addTempType( mddBaseType ); dataStreamType.setType( mddBaseType ); } else RMInit::logOut << "Error: QtMarrayOp::checkType() - operand branch invalid." << endl; return dataStreamType; }