/* * 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, QtVariable: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtvariable.cc,v 1.24 2003/12/27 20:40:52 rasdev Exp $"; #include #include #include using namespace std; #include "raslib/rmdebug.hh" #include "qlparser/qtvariable.hh" #include "qlparser/qtmdd.hh" #include "mddmgr/mddobj.hh" const QtNode::QtNodeType QtVariable::nodeType = QT_MDD_VAR; QtVariable::QtVariable( const string& initName ) : iteratorName( initName ), loadDomain(), oldLoadDomain(), dataIndex(-1) { domainFlag = new vector(); } QtVariable::QtVariable( const string& initName, const r_Minterval& initDomain ) : iteratorName( initName ), loadDomain( initDomain ), oldLoadDomain(), dataIndex(-1) { domainFlag = new vector(); } QtVariable::~QtVariable() { // delete STL vector including its elements delete domainFlag; domainFlag=NULL; } bool QtVariable::equalMeaning( QtNode* node ) { RMDBCLASS( "QtVariable", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) bool result = false; if( nodeType == node->getNodeType() ) { QtVariable* mddVarNode; mddVarNode = (QtVariable*) node; // by force if( iteratorName.compare ( mddVarNode->getIteratorName()) == 0 ) if( ( loadDomain.dimension() == 0 ) || ( (mddVarNode->getLoadDomain()).dimension() == 0 ) ) result = true; else if( loadDomain.dimension() == (mddVarNode->getLoadDomain()).dimension() ) result = loadDomain.intersects_with( mddVarNode->getLoadDomain() ); }; // equalMeaning() depends only on the loadDomain and not on the domainFlag! return result; } string QtVariable::getSpelling() { r_Point point; r_Dimension d; char tempStr[20]; ostringstream os; sprintf(tempStr, "%ud", (unsigned long)getNodeType()); string result = string(tempStr); result.append( iteratorName ); if( loadDomain.dimension() > 0) { os << loadDomain << ends; result.append(os.str()); }; return result; } QtNode::QtAreaType QtVariable::getAreaType() { return QT_AREA_MDD; } void QtVariable::optimizeLoad( QtTrimList* trimList ) { RMDBCLASS( "QtVariable", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) if( !trimList->empty() ) { // get the highest specified dimension r_Dimension maxDimension=0; QtTrimList::iterator i; for( i=trimList->begin(); i!=trimList->end(); i++ ) // get the maximum maxDimension = maxDimension > (*i)->dimension ? maxDimension : (*i)->dimension; // create a new loadDomain object and initialize it with open bounds loadDomain = r_Minterval(maxDimension+1); delete domainFlag; // delete the old array domainFlag = new vector(maxDimension+1); for( int j=0; jbegin(); i!=trimList->end(); i++ ) { loadDomain[(*i)->dimension] = (*i)->interval; (*domainFlag)[(*i)->dimension] = (*i)->intervalFlag; } // delete heap based elements // release( trimList->begin(), trimList->end() ); for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) { delete *iter; *iter=NULL; } // changed from RMInit:logOut -- PB 2003-nov-20 RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtVariable", "optimizeLoad: geometric load optimization: " << iteratorName << loadDomain ); } // delete list delete trimList; trimList=NULL; } QtData* QtVariable::evaluate( QtDataList* inputList ) throw (ParseInfo) { RMDBCLASS( "QtVariable", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) RMDBGENTER( 2, RMDebug::module_qlparser, "QtVariable", "QtVariable::evaluate() - " << iteratorName.c_str() << endl ) vector::iterator i; //default QtData* returnValue = NULL; if( inputList /* && inputList->size() > dataIndex*/ ) { QtData* dataObject = 0; if( dataIndex == -1 ) { // Search for the data object matching the iterator name int pos = 0; for( QtDataList::iterator iter=inputList->begin(); iter!=inputList->end() && !dataObject; iter++ ) { if( iteratorName == (*iter)->getIteratorName() ) dataObject = *iter; else pos++; } if( dataObject ) dataIndex = pos; } else // For performance reasons, take the data element from position determined in the first run. dataObject = (*inputList)[dataIndex]; if( !dataObject ) { RMInit::logOut << "Error: QtVariable::evaluate() - collection iterator " << iteratorName.c_str() << " is unknwon." << endl; parseInfo.setErrorNo(357); throw parseInfo; } if( dataObject->getDataType() == QT_MDD ) { if( loadDomain.dimension() == 0 ) { // If no domain is specified, the load domain equals the current domain. // This means that the data object is passed with an incremented reference. // This mainly occurs with point accesses. dataObject->incRef(); returnValue = dataObject; } else { QtMDD* qtMDD = (QtMDD*)dataObject; MDDObj* currentMDDObj = qtMDD->getMDDObject(); RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtVariable", " definitionDomain: " << currentMDDObj->getDefinitionDomain() ) RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtVariable", " currentDomain...: " << currentMDDObj->getCurrentDomain() ) // load domain for the actual MDDObj r_Minterval actLoadDomain; // intersect actLoadDomain with defined domain try{ actLoadDomain.intersection_of( loadDomain, currentMDDObj->getCurrentDomain() ); } catch( r_Edim_mismatch& ) { RMInit::logOut << "Error: QtVariable::evaluate() - specified domain dimensionality does not equal defined dimensionality." << endl; parseInfo.setErrorNo(362); throw parseInfo; } catch( r_Eno_interval ) { RMInit::logOut << "Error: QtVariable::evaluate() - Specified domain does not intersect with spatial domain of MDD." << endl; parseInfo.setErrorNo(356); throw parseInfo; } catch( r_Error& err ) { RMInit::logOut << "Error: QtVariable::evaluate() - general error." << endl; parseInfo.setErrorNo(350); throw parseInfo; } RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtVariable", " loadDomain......: " << actLoadDomain ) if( qtMDD->getLifetime() == QtData::QT_PERSISTENT ) { // // Create a new QtMDD object as carrier object for the persistent MDD object // and attach the load domain. Now there are more than one MDD objects pointing // to the same persistent MDD object which should not cause any problem. // // Note: Taking the same MDD object would mean sharing also the load domain which // is not possible if the iterator variable occurs with different spatial operations. // QtMDD* result = new QtMDD( (MDDObj*)currentMDDObj ); result->setLoadDomain( actLoadDomain ); returnValue = result; } else { // Take the transient data object and increase its reference. // // Note: For a transient MDD object just one QtMDD carrier object is allowed. qtMDD->incRef(); returnValue = qtMDD; } } } else { // Take the atomic data object and increase its reference. dataObject->incRef(); returnValue = dataObject; } } else { RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtVariable", "Error: QtVariable::evaluate() - the input list is empty." ) } return returnValue; } void QtVariable::printTree( int tab, ostream& s, QtChildType /*mode*/ ) { s << SPACE_STR(tab).c_str() << "QtVariable Object: type " << flush; dataStreamType.printStatus( s ); s << " name |" << iteratorName.c_str() << "|" /* << " pos " << dataIndex */ << endl; if( loadDomain.dimension() > 0 ) { s << SPACE_STR(tab).c_str() << "load domain: "; loadDomain.print_status( s ); s << " - Trimflag: "; for( int i=0; isize(); i++) s << (*domainFlag)[i]; s << endl; } if( oldLoadDomain.dimension() > 0 ) { s << SPACE_STR(tab).c_str() << "old domain: "; oldLoadDomain.print_status( s ); s << endl; }; } void QtVariable::printAlgebraicExpression( ostream& s ) { s << iteratorName.c_str() << flush; } const QtTypeElement& QtVariable::checkType( QtTypeTuple* typeTuple ) throw (ParseInfo) { RMDBCLASS( "QtVariable", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) dataStreamType.setDataType( QT_TYPE_UNKNOWN ); if( typeTuple ) { vector::iterator iter; // search for the type matching the variable name for( iter=typeTuple->tuple.begin(); iter!=typeTuple->tuple.end() && dataStreamType.getDataType() == QT_TYPE_UNKNOWN; iter++ ) { if( (*iter).getName() && iteratorName == string( (*iter).getName() ) ) dataStreamType = *iter; } } if( (dataStreamType.getDataType() == QT_TYPE_UNKNOWN) ) { RMInit::logOut << "Error: QtVariable::checkType() - variable " << iteratorName.c_str() << " is unknwon." << endl; parseInfo.setErrorNo(357); throw parseInfo; } return dataStreamType; }