/*
* 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, QtNode: $Id: qtnode.cc,v 1.27 2002/06/05 18:18:17 coman Exp $";
#include "qlparser/qtnode.hh"
#include "catalogmgr/typefactory.hh"
#include "relcatalogif/type.hh"
#include "relcatalogif/basetype.hh"
#include
#include
const QtNode::QtNodeType QtNode::nodeType = QT_UNDEFINED_NODE;
const int QtNode::QtNodes = 80;
const QtNode::QtNodeType QtNode::QtRoot = QT_UNDEFINED_NODE;
const QtNode::QtNodeType QtNode::QtInheritance[][2] = {
{QT_UNDEFINED_NODE, QT_EXECUTE},
{QT_EXECUTE, QT_COMMAND},
{QT_EXECUTE, QT_DELETE},
{QT_EXECUTE, QT_INSERT},
{QT_EXECUTE, QT_PYRAMID},
{QT_EXECUTE, QT_UPDATE},
{QT_UNDEFINED_NODE, QT_ONC_STREAM},
{QT_ONC_STREAM, QT_ITERATOR},
{QT_ITERATOR, QT_JOIN_ITERATOR},
{QT_ITERATOR, QT_OPERATION_ITERATOR},
{QT_ITERATOR, QT_SELECTION_ITERATOR},
{QT_ONC_STREAM, QT_MDD_ACCESS},
{QT_UNDEFINED_NODE, QT_OPERATION},
{QT_OPERATION, QT_BINARY_OPERATION},
{QT_BINARY_OPERATION, QT_BINARY_INDUCE},
{QT_BINARY_INDUCE, QT_AND},
{QT_BINARY_INDUCE, QT_BIT},
{QT_BINARY_INDUCE, QT_DIV},
{QT_BINARY_INDUCE, QT_EQUAL},
{QT_BINARY_INDUCE, QT_IS},
{QT_BINARY_INDUCE, QT_LESS},
{QT_BINARY_INDUCE, QT_LESS_EQUAL},
{QT_BINARY_INDUCE, QT_MINUS},
{QT_BINARY_INDUCE, QT_MULT},
{QT_BINARY_INDUCE, QT_NOT_EQUAL},
{QT_BINARY_INDUCE, QT_OR},
{QT_BINARY_INDUCE, QT_OVERLAY},
{QT_BINARY_INDUCE, QT_PLUS},
{QT_BINARY_INDUCE, QT_XOR},
{QT_BINARY_OPERATION, QT_CONDENSEOP},
{QT_BINARY_OPERATION, QT_EXTEND},
{QT_BINARY_OPERATION, QT_INTERVALOP},
{QT_BINARY_OPERATION, QT_MARRAYOP},
{QT_BINARY_OPERATION, QT_SCALE},
{QT_BINARY_OPERATION, QT_SHIFT},
{QT_OPERATION, QT_CONST},
{QT_OPERATION, QT_GROUP_ITERATOR},
{QT_OPERATION, QT_IDENT},
{QT_OPERATION, QT_MDD_STREAM},
{QT_OPERATION, QT_NARY_OPERATION},
{QT_NARY_OPERATION, QT_MINTERVALOP},
{QT_NARY_OPERATION, QT_POINTOP},
{QT_OPERATION, QT_UNARY_OPERATION},
{QT_UNARY_OPERATION, QT_CONDENSE},
{QT_CONDENSE, QT_ADDCELLS},
{QT_CONDENSE, QT_ALL},
{QT_CONDENSE, QT_AVGCELLS},
{QT_CONDENSE, QT_COUNTCELLS},
{QT_CONDENSE, QT_MAXCELLS},
{QT_CONDENSE, QT_MINCELLS},
{QT_CONDENSE, QT_SOME},
{QT_UNARY_OPERATION, QT_CONVERSION},
{QT_UNARY_OPERATION, QT_CSE_ROOT},
{QT_UNARY_OPERATION, QT_DOMAIN_OPERATION},
{QT_UNARY_OPERATION, QT_HI},
{QT_UNARY_OPERATION, QT_LO},
{QT_UNARY_OPERATION, QT_OID},
{QT_UNARY_OPERATION, QT_SDOM},
{QT_UNARY_OPERATION, QT_UNARY_INDUCE},
{QT_UNARY_INDUCE, QT_CAST},
{QT_UNARY_INDUCE, QT_DOT},
{QT_UNARY_INDUCE, QT_IMAGINARPART},
{QT_UNARY_INDUCE, QT_NOT},
{QT_UNARY_INDUCE, QT_REALPART},
{QT_UNARY_INDUCE, QT_ABS},
{QT_UNARY_INDUCE, QT_SQRT},
{QT_UNARY_INDUCE, QT_EXP},
{QT_UNARY_INDUCE, QT_LOG},
{QT_UNARY_INDUCE, QT_LN},
{QT_UNARY_INDUCE, QT_SIN},
{QT_UNARY_INDUCE, QT_COS},
{QT_UNARY_INDUCE, QT_TAN},
{QT_UNARY_INDUCE, QT_SINH},
{QT_UNARY_INDUCE, QT_COSH},
{QT_UNARY_INDUCE, QT_TANH},
{QT_UNARY_INDUCE, QT_ARCSIN},
{QT_UNARY_INDUCE, QT_ARCCOS},
{QT_UNARY_INDUCE, QT_ARCTAN},
{QT_OPERATION, QT_MDD_VAR}
};
int QtNode::minim[QtNodes];
int QtNode::maxim[QtNodes];
int QtNode::child_range[QtNodes+1];
bool QtNode::MinMaxDone = false;
QtNode::QtNode()
: parent(NULL)
{
if (!MinMaxDone) {
MinMaxDone = true;
SetMinMax();
}
}
QtNode::QtNode( QtNode* node )
: parent( node )
{
if (!MinMaxDone) {
MinMaxDone = true;
SetMinMax();
}
}
QtNode::~QtNode()
{
}
bool
QtNode::subtype( enum QtNodeType a, enum QtNodeType b )
{
return (minim[a]<=minim[b] && maxim[b]<=maxim[a]);
}
QtNode::QtNodeList*
QtNode::getChilds( QtChildType flag )
{
RMDBCLASS( "QtNode", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ )
// Default definition is used for all leaf nodes.
// Algorithm:
//
// In mode QT_ALL_NODES each node calls getChild() of every son,
// merges these lists and inserts direct childs but not the node
// itself.
// In mode QT_DIRECT_CHILDS each node inserts just direct childs.
// In mode QT_LEAF_NODES the method call is passed to the sons
// and just the leaf nodes insert themselves.
QtNodeList* resultList=NULL;
resultList = new QtNodeList();
if( flag == QT_LEAF_NODES )
resultList->push_back( this );
return resultList;
}
QtNode::QtNodeList*
QtNode::getChild( const QtNodeType node, QtChildType flag )
{
RMDBCLASS( "QtNode", "getChild( QtChildType )", "qlparser", __FILE__, __LINE__ )
QtNodeList* resultList=NULL;
QtNodeList::iterator iter;
resultList = getChilds( flag );
for( iter=resultList->begin(); iter!=resultList->end(); iter++ )
if( node != (*iter)->getNodeType() )
resultList->erase( iter-- );
return resultList;
}
bool
QtNode::equalMeaning( QtNode* /*node*/ )
{
return false;
}
std::string
QtNode::getSpelling()
{
return "";
}
QtNode::QtAreaType
QtNode::getAreaType()
{
return QT_AREA_SCALAR;
}
void
QtNode::simplify()
{
RMDBCLASS( "QtNode", "simplify()", "qlparser", __FILE__, __LINE__ )
// Default method for all classes that have no implementation.
// Method is used bottom up.
QtNodeList* resultList=NULL;
QtNodeList::iterator iter;
try
{
resultList = getChilds( QT_DIRECT_CHILDS );
for( iter=resultList->begin(); iter!=resultList->end(); iter++ )
(*iter)->simplify();
}
catch(...)
{
if( resultList )
{
delete resultList;
resultList=NULL;
}
throw;
}
delete resultList;
resultList=NULL;
}
/*
void
QtNode::rewriteOps()
{
RMDBGONCE( 1, RMDebug::module_qlparser, "QtNode", " QtNode::rewriteOps() " )
// Default method for all classes that have no implementation.
// Method is used top down.
QtNodeList* resultList=NULL;
QtNodeList::iterator iter;
resultList = getChilds( QT_DIRECT_CHILDS );
for( iter=resultList->begin(); iter!=resultList->end(); iter++ )
(*iter)->rewriteOps();
delete resultList;
resultList=NULL;
}
*/
/*
void
QtNode::sortAssociativeOps()
{
RMDBGONCE( 1, RMDebug::module_qlparser, "QtScale", " QtNode::sortAssociativeOps()" )
// Default method for all nodes that have no own method
// method is used top down
QtNodeList* resultList=NULL;
QtNodeList::iterator iter;
resultList = getChilds( QT_DIRECT_CHILDS );
for( iter=resultList->begin(); iter!=resultList->end(); iter++ )
(*iter)->sortAssociativeOps();
delete resultList;
resultList=NULL;
}
*/
/*
void
QtNode::checkIdempotency()
{
RMDBGONCE( 1, RMDebug::module_qlparser, "QtNode", " QtNode::checkIdempotency()" )
// method is used bottom up
// default method for all nodes that have no own method
}
*/
QtNode::QtNodeType
QtNode::getQtNodeTypeParent (QtNode::QtNodeType node) {
int i = 0;
for (i=0; i=0; i--)
if (arr[i].base != arr[i+1].base) child_range[arr[i+1].base] = i+1;
child_range[arr[0].base] = 0;
for (i=QtNodes-1; i>0; i--)
if (child_range[i] == 0) child_range[i] = child_range[i+1];
}
void
QtNode::SetMinMax()
{
int i;
QtNodePair arr[QtNodes-1];
for (i=0; i<(QtNodes-1); i++) {
arr[i].base = QtInheritance[i][0];
arr[i].deriv = QtInheritance[i][1];
}
std::sort(arr,arr+QtNodes-1);
//creating child_range
set_child_range(arr);
//numbering the nodes
num_node(arr, QtRoot);
}
QtTypeElement::QtTypeElement()
: dataType( QT_TYPE_UNKNOWN ),
type(NULL),
name(NULL)
{
}
QtTypeElement::QtTypeElement( const QtDataType initDataType,
const char* initName )
: dataType( QT_TYPE_UNKNOWN ),
type( NULL ),
name( NULL )
{
setDataType( initDataType );
if( initName ) name = strdup( initName );
}
QtTypeElement::QtTypeElement( const Type* initType,
const char* initName )
: dataType( QT_TYPE_UNKNOWN ),
type( NULL ),
name( NULL )
{
setType( initType );
if( initName ) name = strdup( initName );
}
QtTypeElement::QtTypeElement( const QtTypeElement& typeElement )
: dataType( typeElement.dataType ),
type( typeElement.type ),
name(NULL)
{
if( typeElement.name ) name = strdup( typeElement.name );
}
QtTypeElement::~QtTypeElement()
{
// Note: Types are free by the type factory.
if( name )
{
free( name );
name=NULL;
}
}
const QtTypeElement&
QtTypeElement::operator=( const QtTypeElement& obj )
{
if( this != &obj )
{
if( name )
{
free( name );
name = NULL;
}
dataType = obj.dataType;
type = obj.type;
if( obj.name ) name = strdup( obj.name );
}
return *this;
}
void
QtTypeElement::printStatus( std::ostream& s ) const
{
if( type )
{
char* typeStructure = type->getTypeStructure();
s << typeStructure << std::flush;
free( typeStructure );
typeStructure=NULL;
}
else
{
switch( dataType )
{
case QT_STRING:
s << "string" << std::flush;
break;
case QT_INTERVAL:
s << "interval" << std::flush;
break;
case QT_MINTERVAL:
s << "minterval" << std::flush;
break;
case QT_POINT:
s << "point" << std::flush;
break;
default:
// including case QT_TYPE_UNKNOWN
s << "" << std::flush;
break;
}
}
if( name )
s << ":" << name << std::flush;
}
void
QtTypeElement::setDataType( const QtDataType newDataType )
{
dataType = newDataType;
// reset type information
type = NULL;
switch( dataType )
{
case QT_TYPE_UNKNOWN:
break;
case QT_BOOL:
type = TypeFactory::mapType("Bool");
break;
case QT_CHAR:
type = TypeFactory::mapType("Char");
break;
case QT_OCTET:
type = TypeFactory::mapType("Octet");
break;
case QT_USHORT:
type = TypeFactory::mapType("UShort");
break;
case QT_SHORT:
type = TypeFactory::mapType("Short");
break;
case QT_ULONG:
type = TypeFactory::mapType("ULong");
break;
case QT_LONG:
type = TypeFactory::mapType("Long");
break;
case QT_FLOAT:
type = TypeFactory::mapType("Float");
break;
case QT_DOUBLE:
type = TypeFactory::mapType("Double");
break;
case QT_COMPLEXTYPE1:
type = TypeFactory::mapType("Complex1");
break;
case QT_COMPLEXTYPE2:
type = TypeFactory::mapType("Complex2");
break;
case QT_MDD:
case QT_COMPLEX:
RMInit::logOut << "QtTypeElement::setDataType() - MDD and complex types need to be specified further." << std::endl;
break;
case QT_STRING:
case QT_INTERVAL:
case QT_MINTERVAL:
case QT_POINT:
default:
// transient types
break;
}
}
void
QtTypeElement::setType(const Type* newType )
{
type = NULL;
dataType = QT_TYPE_UNKNOWN;
if( newType )
switch( newType->getType() )
{
case BOOLTYPE: dataType = QT_BOOL; break;
case CHAR: dataType = QT_CHAR; break;
case OCTET: dataType = QT_OCTET; break;
case USHORT: dataType = QT_USHORT; break;
case SHORT: dataType = QT_SHORT; break;
case ULONG: dataType = QT_ULONG; break;
case LONG: dataType = QT_LONG; break;
case FLOAT: dataType = QT_FLOAT; break;
case DOUBLE: dataType = QT_DOUBLE; break;
case COMPLEXTYPE1: dataType = QT_COMPLEXTYPE1; break;
case COMPLEXTYPE2: dataType = QT_COMPLEXTYPE2; break;
case MDDTYPE: dataType = QT_MDD; break;
case STRUCT: dataType = QT_COMPLEX; break;
default: dataType = QT_TYPE_UNKNOWN; break;
}
// if type is supported
if( dataType != QT_TYPE_UNKNOWN )
type = newType;
}
QtTypeTuple::QtTypeTuple( unsigned int length )
: tuple( length )
{
}
void
QtTypeTuple::concat( const QtTypeTuple& typeTuple )
{
// reserve space for concatenated type
tuple.reserve( tuple.size() + typeTuple.tuple.size() );
// concatenate tuples
for( std::vector::const_iterator iter = typeTuple.tuple.begin();
iter != typeTuple.tuple.end(); iter++ )
tuple.push_back( *iter );
}
void
QtTypeTuple::concat( const QtTypeElement& typeElement )
{
tuple.push_back( typeElement );
}
void
QtTypeTuple::printStatus( std::ostream& s ) const
{
s << "<" << std::flush;
for( std::vector::const_iterator iter = tuple.begin();
iter != tuple.end();
iter++ )
{
if( iter != tuple.begin() )
s << ", " << std::flush;
(*iter).printStatus( s );
}
s << ">" << std::flush;
}