/* * 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, QtInsert: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtinsert.cc,v 1.27 2003/12/27 20:40:21 rasdev Exp $"; #include "qlparser/qtinsert.hh" #include "qlparser/qtdata.hh" #include "qlparser/qtmdd.hh" #include "tilemgr/tile.hh" #include "mddmgr/mddcoll.hh" #include "mddmgr/mddobj.hh" #include #include "servercomm/servercomm.hh" extern ServerComm::ClientTblElt* currentClientTblElt; const QtNode::QtNodeType QtInsert::nodeType = QtNode::QT_INSERT; QtInsert::QtInsert( const std::string& initCollectionName, QtOperation* initSource ) : QtExecute(), collectionName( initCollectionName ), source( initSource ) { source->setParent( this ); } QtInsert::~QtInsert() { if( source ) { delete source; source=NULL; } } int QtInsert::evaluate() { RMDBCLASS( "QtInsert", "evaluate()", "qlparser", __FILE__, __LINE__ ) // empty data list for evaluation of insert expression including constant QtNode::QtDataList* nextTupel = new QtNode::QtDataList(0); // get the operands QtData* sourceData = source->evaluate( nextTupel ); if( sourceData ) { QtMDD* sourceMDD = (QtMDD*) sourceData; MDDObj* sourceObj = sourceMDD->getMDDObject(); MDDColl* persColl = NULL; MDDColl* almost = NULL; try { almost = MDDColl::getMDDCollection( collectionName.c_str() ); } catch(...) { RMInit::logOut << "Error: QtInsert::evaluate() - collection name not found" << std::endl; // delete the operand if( sourceData ) sourceData->deleteRef(); parseInfo.setErrorNo(355); throw parseInfo; } if (!almost->isPersistent()) { RMInit::logOut << "QtInsert: User tries to insert into system table" << std::endl; if( sourceData ) sourceData->deleteRef(); parseInfo.setErrorNo(355); throw parseInfo; } else { persColl = (MDDColl*)almost; } // // check MDD and collection type for compatibility // RMDBGIF(3, RMDebug::module_qlparser, "QtInsert", \ char* collTypeStructure = persColl->getCollectionType()->getTypeStructure(); \ char* mddTypeStructure = sourceObj->getMDDBaseType()->getTypeStructure(); \ RMInit::dbgOut << std::endl << "Collection type structure.: " << collTypeStructure << std::endl \ << "MDD type structure........: " << mddTypeStructure << std::endl \ << "MDD domain................: " << sourceObj->getDefinitionDomain() << std::endl; \ free( collTypeStructure ); collTypeStructure=NULL; \ free( mddTypeStructure ); mddTypeStructure=NULL; ) // bug fix: "insert into" found claimed non-existing type mismatch -- PB 2003-aug-25, based on fix by K.Hahn // if( !persColl->getCollectionType()->compatibleWith( (Type*) sourceObj->getMDDBaseType() ) ) if( !((MDDType*) sourceObj->getMDDBaseType())->compatibleWith( persColl->getCollectionType()->getMDDType() ) ) { // free resources persColl->releaseAll(); delete persColl; persColl=NULL; if( sourceData ) sourceData->deleteRef(); // delete the operand // return error RMInit::logOut << "Error: QtInsert::evaluate() - MDD and collection types are incompatible" << std::endl; parseInfo.setErrorNo(959); throw parseInfo; } if( !persColl->getCollectionType()->getMDDType()->compatibleWithDomain( &(sourceObj->getDefinitionDomain()) ) ) { // free resources persColl->releaseAll(); delete persColl; persColl=NULL; if( sourceData ) sourceData->deleteRef(); // delete the operand // return error RMInit::logOut << "Error: QtInsert::evaluate() - MDD and collection domains are incompatible" << std::endl; parseInfo.setErrorNo(959); throw parseInfo; } // // convert a transient MDD object to a persistent one // // allocate a new oid within the current db OId oid; #ifdef BASEDB_O2 if( !OId::allocateMDDOId( &oid ) ) { #else OId::allocateOId( oid, OId::MDDOID ); #endif // get all tiles vector* sourceTiles = sourceObj->getTiles(); // get a persistent type pointer MDDBaseType* persMDDType = (MDDBaseType*)TypeFactory::ensurePersistence( (Type*)sourceObj->getMDDBaseType() ); if( !persMDDType ) { RMInit::logOut << "Error: QtInsert::evaluate() - type not persistent" << std::endl; // delete dynamic data if( sourceData ) sourceData->deleteRef(); delete sourceTiles; sourceTiles=NULL; delete nextTupel; nextTupel=NULL; persColl->releaseAll(); delete persColl; persColl=NULL; parseInfo.setErrorNo(964); throw parseInfo; } // create a persistent MDD object // need a StorageLayout here StorageLayout tempStorageLayout; tempStorageLayout.setTileSize(StorageLayout::DefaultTileSize); tempStorageLayout.setIndexType(StorageLayout::DefaultIndexType); tempStorageLayout.setTilingScheme(StorageLayout::DefaultTilingScheme); if (sourceObj->getDefinitionDomain().dimension() == StorageLayout::DefaultTileConfiguration.dimension()) tempStorageLayout.setTileConfiguration(StorageLayout::DefaultTileConfiguration); MDDObj* persMDDObj = new MDDObj( persMDDType, sourceObj->getDefinitionDomain(), oid, tempStorageLayout ); // iterate over source tiles for( vector::iterator sourceIt = sourceTiles->begin(); sourceIt != sourceTiles->end(); sourceIt++ ) { // create a new persistent tile, copy the transient data, and insert it into the target mdd object Tile* newPersTile = new Tile( (*sourceIt)->getDomain(), persMDDType->getBaseType(), (*sourceIt)->getDataFormat() ); newPersTile->copyTile( (*sourceIt)->getDomain(), *sourceIt, (*sourceIt)->getDomain() ); persMDDObj->insertTile( newPersTile ); } // delete tile vector delete sourceTiles; sourceTiles=NULL; persColl->insert( persMDDObj ); #ifdef BASEDB_O2 } else { RMInit::logOut << "Error: QtInsert::evaluate() - allocation of oid failed" << std::endl; // delete dynamic data if( sourceData ) sourceData->deleteRef(); delete nextTupel; nextTupel=NULL; persColl->releaseAll(); delete persColl; persColl=NULL; parseInfo.setErrorNo(958); throw parseInfo; } #else #endif // free transient memory persColl->releaseAll(); delete persColl; persColl=NULL; } else RMInit::logOut << "Error: QtInsert::evaluate() - insert data is invalid." << std::endl; // delete source operand if( sourceData ) sourceData->deleteRef(); // delete dummy tupel vector delete nextTupel; nextTupel=NULL; return 0; } QtNode::QtNodeList* QtInsert::getChilds( QtChildType flag ) { QtNodeList* resultList=NULL; RMDBGENTER(0, RMDebug::module_qlparser, "QtInsert", "QtInsert::getChilds()") if( source ) { // allocate resultList if( flag == QT_DIRECT_CHILDS ); resultList = new QtNodeList(); if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) resultList = source->getChilds( flag ); // add the nodes of the current level if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) resultList->push_back( source ); } else resultList = new QtNodeList(); RMDBGEXIT(0, RMDebug::module_qlparser, "QtInsert", "QtInsert::getChilds()") return resultList; } void QtInsert::printTree( int tab, std::ostream& s, QtChildType mode ) { s << SPACE_STR(tab).c_str() << "QtInsert Object" << std::endl; if( mode != QtNode::QT_DIRECT_CHILDS ) { if( source ) { s << SPACE_STR(tab).c_str() << "source : " << std::endl; source->printTree( tab + 2, s ); } else s << SPACE_STR(tab).c_str() << "no source" << std::endl; s << std::endl; } } void QtInsert::printAlgebraicExpression( std::ostream& s ) { s << "insert<"; if( source ) source->printAlgebraicExpression( s ); else s << ""; s << ">"; } QtOperation* QtInsert::getSource() { return source; } /* void QtInsert::preOptimize() { if( source ) source->optimizeLoad( new QtNode::QtTrimList ); } */ void QtInsert::checkType() { RMDBCLASS( "QtInsert", "checkType()", "qlparser", __FILE__, __LINE__ ) // check operand branches if( source ) { // get input type const QtTypeElement& inputType = source->checkType(); if( inputType.getDataType() != QT_MDD ) { RMInit::logOut << "Error: QtInsert::checkType() - insert expression must be of type r_Marray" << std::endl; parseInfo.setErrorNo(960); throw parseInfo; } } else RMInit::logOut << "Error: QtInsert::checkType() - operand branch invalid." << std::endl; }